Skip to content

Commit

Permalink
Merge pull request #10 from twilliamsorel/mvc
Browse files Browse the repository at this point in the history
refactoring with MVC
  • Loading branch information
Trevor Sorel authored Apr 5, 2024
2 parents 6ac6b41 + dcebeb4 commit 706af01
Show file tree
Hide file tree
Showing 42 changed files with 81 additions and 57 deletions.
8 changes: 5 additions & 3 deletions .eleventy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ const tickerCodes = require("./tickerCodes.js")

module.exports = function (eleventyConfig) {
eleventyConfig.addPassthroughCopy("_src/assets");
eleventyConfig.addPassthroughCopy("_src/interfaces");
eleventyConfig.addPassthroughCopy("_src/controllers");
eleventyConfig.addPassthroughCopy("_src/models");
eleventyConfig.addPassthroughCopy("_src/Utils.js");
eleventyConfig.addPassthroughCopy("_src/favicon-32x32.png");
eleventyConfig.addPassthroughCopy("_src/favicon-16x16.png");

Expand Down Expand Up @@ -37,8 +39,8 @@ module.exports = function (eleventyConfig) {
return {
dir: {
input: "_src",
includes: "_includes",
layouts: "_layouts",
includes: "views/_includes",
layouts: "views/_layouts",
data: "_data"
}
}
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default class Filters {
export default class FiltersController {
constructor(selectorString) {
this.form = document.querySelector(selectorString)
this.button = document.querySelector('#filter-toggle')
Expand All @@ -9,6 +9,7 @@ export default class Filters {
const formattedData = this.#formatFiltersData(rawData)
const filterEvent = new CustomEvent('filter', { detail: { results: formattedData } })
window.dispatchEvent(filterEvent)
this.form.parentElement.classList.toggle('open')
})
this.button.addEventListener('click', () => {
this.form.parentElement.classList.toggle('open')
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Utils from "/interfaces/Utils.js"

export default class Search {
constructor(selectorString) {
this.input = document.querySelector(selectorString)
Expand All @@ -11,8 +9,7 @@ export default class Search {

#runSearch() {
!this.frozen && setTimeout(async () => {
const res = this.input.value.length > 0 ? (await Utils.getRequest(`${Utils.getBaseUrl()}/api/search-stocks?search=${this.input.value}`)) : false
const searchEvent = new CustomEvent("search", { detail: { results: JSON.parse(res), length: this.input.value.length } })
const searchEvent = new CustomEvent("search", { detail: { results: this.input.value } })
window.dispatchEvent(searchEvent)
this.frozen = false
}, this.throttleTime)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import Utils from '/interfaces/Utils.js'
import StorageManager from '/interfaces/StorageManager.js'
import StockTable from '/models/StockTable.js'
import StorageManager from '/models/StorageManager.js'
import Utils from '/Utils.js'

export default class Table {
export default class StockTableController {
constructor(selectorString) {
this.stockTable = new StockTable()
this.table = document.querySelector(selectorString)
this.tableType = this.table.getAttribute('data-type') ? this.table.getAttribute('data-type') : undefined
this.sort = 'ticker'
this.sortDirection = 'desc'
this.filters = undefined
this.page = 0
this.freezeScroll = false
this.#updateTable()
this.searchLengthRef = 0
Expand All @@ -20,36 +18,37 @@ export default class Table {
}
})
this.table.querySelector('thead').addEventListener('click', (e) => {
this.#setSort(e.target.getAttribute('data-sort'))
this.stockTable.setSort(e.target.getAttribute('data-sort'))
this.#updateTable()
})
window.addEventListener('search', (e) => {
this.#updateTable(e.detail.results)
this.searchLengthRef = e.detail.length
})
window.addEventListener('filter', (e) => {
const data = e.detail.results
this.filters = data
this.stockTable.setFilters(data)
this.#updateTable()
})
}

#header() {
return `
<tr class="label">
<td data-sort="ticker" data-tooltip="<span>ticker</span>The stock's ticker value; a shorthand code used to identify the stock." class="${this.sort === 'ticker' ? 'active' : ''} ${this.sortDirection === 'desc' ? 'desc' : 'asc'}">ticker</td>
<td class="d-none d-lg-table-cell ${this.sort === 'dividend_records' ? 'active' : ''} ${this.sortDirection === 'desc' ? 'desc' : 'asc'}" data-sort="dividend_records"
<td data-sort="ticker" data-tooltip="<span>ticker</span>The stock's ticker value; a shorthand code used to identify the stock." class="${this.stockTable.sort === 'ticker' ? 'active' : ''} ${this.stockTable.sortDirection === 'desc' ? 'desc' : 'asc'}">ticker</td>
<td class="d-none d-lg-table-cell ${this.stockTable.sort === 'dividend_records' ? 'active' : ''} ${this.stockTable.sortDirection === 'desc' ? 'desc' : 'asc'}" data-sort="dividend_records"
data-tooltip="<span>dividend records</span>The total number of historical dividend records in the database for this stock, taken at monthly intervals.">dividend records</td>
<td data-sort="dividend_volatility" class="d-none d-md-table-cell ${this.sort === 'dividend_volatility' ? 'active' : ''} ${this.sortDirection === 'desc' ? 'desc' : 'asc'}"
<td data-sort="dividend_volatility" class="d-none d-md-table-cell ${this.stockTable.sort === 'dividend_volatility' ? 'active' : ''} ${this.stockTable.sortDirection === 'desc' ? 'desc' : 'asc'}"
data-tooltip="<span>dividend volatility</span>A numeric value representing the volatility of monthly dividend payments. Compare this value to the dividend yield charts to calibrate to it.">
<span class="d-inline-block d-xl-none">div volatility</span>
<span class="d-none d-xl-inline-block">dividend volatility</span>
</td>
<td data-sort="percentage_yield" class="${this.sort === 'percentage_yield' ? 'active' : ''} ${this.sortDirection === 'desc' ? 'desc' : 'asc'}"
<td data-sort="percentage_yield" class="${this.stockTable.sort === 'percentage_yield' ? 'active' : ''} ${this.stockTable.sortDirection === 'desc' ? 'desc' : 'asc'}"
data-tooltip="<span>annual percentage yield</span>The annual percentage yield, calculated by dividing the sum of dividend payments by the current stock price. See 'Guides > Glossary and methodology' for more information.">
<span class="d-inline-block d-xl-none">APY</span>
<span class="d-none d-xl-inline-block">annual percentage yield</span>
</td>
<td data-sort="median_percentage_yield" class="${this.sort === 'median_percentage_yield' ? 'active' : ''} ${this.sortDirection === 'desc' ? 'desc' : 'asc'}"
<td data-sort="median_percentage_yield" class="${this.stockTable.sort === 'median_percentage_yield' ? 'active' : ''} ${this.stockTable.sortDirection === 'desc' ? 'desc' : 'asc'}"
data-tooltip="<span>Median APY</span>A median variation of the APY, designed to be more representative of typical returns. See 'Guides > Glossary and methodology' for more information.">Median APY</td>
</tr>
`
Expand All @@ -73,29 +72,21 @@ export default class Table {
#clearTable() {
if (!this.table) throw Error('Table is not defined. Did you try and call this before initializing one?')
const rows = this.table.querySelectorAll('tr')
this.page = 0
this.stockTable.resetPage()
rows.forEach((row) => {
row.remove()
})
}

async #updateTable() {
const thead = this.#header()
const data = await this.#getData()
this.#clearTable()
this.table.querySelector('thead').insertAdjacentHTML('beforeend', thead)
this.#paginate(data)
}

async #getData() {
async #getData(tableType) {
const requestObj = {
sort: this.sort,
sortDirection: this.sortDirection,
pagination: this.page,
sort: this.stockTable.sort,
sortDirection: this.stockTable.sortDirection,
pagination: this.stockTable.page,
}
if (this.filters) { requestObj.filters = this.filters }
if (this.stockTable.filters) { requestObj.filters = this.stockTable.filters }

if (this.tableType === 'localstorage') {
if (tableType === 'localstorage') {
const storage = new StorageManager('stocks')
const tickers = storage.read.reduce((acc, cur) => { acc.push(cur.id); return acc }, [])
requestObj.tickers = tickers
Expand All @@ -105,19 +96,25 @@ export default class Table {
}
}

#paginate(data) {
if (data.length === 0) return;
async #getSearchData(searchQuery) {
return await Utils.getRequest(`${Utils.getBaseUrl()}/api/search-stocks?search=${searchQuery}`)
}

async #updateTable(searchQuery) {
const thead = this.#header()
const data = searchQuery ? await this.#getSearchData(searchQuery) : await this.#getData()
this.#clearTable()
this.table.querySelector('thead').insertAdjacentHTML('beforeend', thead)
this.#paginate(data)
}

async #paginate() {
const data = await this.#getData(this.tableType)
data.forEach((d) => {
if (!d.percentage_yield) return;
this.table.querySelector('tbody').insertAdjacentHTML('beforeend', this.#row(d))
})
this.page++
this.stockTable.paginate()
this.freezeScroll = false
}

#setSort(sort) {
this.sort = sort
this.sortDirection = this.sortDirection === 'desc' ? 'asc' : 'desc'
this.#updateTable()
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default class Tooltips {
export default class TooltipController {
constructor() {
this.div = undefined
this.shown = false
Expand Down
2 changes: 2 additions & 0 deletions _src/models/Filters.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions _src/models/StockTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export default class StockTable {
constructor() {
this.sort = 'ticker'
this.sortDirection = 'desc'
this.filters = undefined
this.page = 0
}

setFilters(filters) {
this.filters = filters
}

paginate() {
this.page++
}

resetPage() {
this.page = 0;
}

setSort(sort) {
this.sort = sort
this.sortDirection = this.sortDirection === 'desc' ? 'asc' : 'desc'
}
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ <h2>Menu</h2>
</div>

<script type="module">
import Nav from '/interfaces/Nav.js'
new Nav('.main-nav')
import NavController from '/controllers/NavController.js'
new NavController('.main-nav')
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@
</div>

<script type="module">
import Filters from '/interfaces/Filters.js'
new Filters('form.filters-container')
import FiltersController from '/controllers/FiltersController.js'
new FiltersController('form.filters-container')
</script>
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
</div>

<script type="module">
import Search from '/interfaces/Search.js'
new Search('input.search.interface')
import SearchController from '/controllers/SearchController.js'
new SearchController('input.search.interface')
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
</div>

<script type="module">
import Table from '/interfaces/Table.js'
new Table('table.stocks');
import StockTableController from '/controllers/StockTableController.js'
new StockTableController('table.stocks');
</script>
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
{% include footer.html %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script type="module">
import Tooltips from '/interfaces/Tooltips.js'
new Tooltips()
import TooltipController from '/controllers/TooltipController.js'
new TooltipController()
</script>

{% if globals.environment == "development" %}
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 706af01

Please sign in to comment.