Created
September 6, 2023 09:50
-
-
Save x8BitRain/3ec55df633c6277ceb8f51c5c3523743 to your computer and use it in GitHub Desktop.
ember table example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Component from '@glimmer/component'; | |
import { inject as service } from '@ember/service'; | |
/** | |
@argument currentPage | |
@argument pages | |
@argument limit | |
@argument onLimitUpdated | |
@argument onPageUpdated | |
*/ | |
export default class NwKeywordPagePaginationComponent extends Component { | |
@service userSettings; | |
limits = [50, 100, 250, 500]; | |
defaultLimit = 50; | |
get pagesList() { | |
const pagesCount = Number.parseInt(this.args.pages, 10); | |
let pages = | |
pagesCount && Number.parseInt(pagesCount, 10) > 0 | |
? [...Array(pagesCount).keys()].map((p) => ++p) | |
: []; | |
if (pages.length > 10) { | |
// show first, four pages before current, four pages after current and last | |
const currentPage = this.args.currentPage; | |
const left = [...Array(4).keys()] | |
.map((n) => currentPage - (4 - n)) | |
.filter((p) => p > 1); | |
const right = [...Array(4).keys()] | |
.map((n) => currentPage + (1 + n)) | |
.filter((p) => p < pagesCount); | |
pages = [1] | |
.concat(left) | |
.concat([currentPage]) | |
.concat(right) | |
.concat([pagesCount]) | |
.uniq(); | |
const pagesWithTruncation = []; | |
for (let index = 0; index < pages.length; index++) { | |
const page = pages[index]; | |
pagesWithTruncation.push(page); | |
if (pages[index + 1] && pages[index + 1] - page !== 1) { | |
pagesWithTruncation.push(null); //ellipsis in template | |
} | |
} | |
pages = pagesWithTruncation; | |
} | |
return pages; | |
} | |
get paginationShown() { | |
return this.pagesList.length > 1 || this.args.limit > this.defaultLimit; | |
} | |
get previousPage() { | |
const previous = Number.parseInt(this.args.currentPage, 10) - 1; | |
return this.pagesList.includes(previous) ? previous : null; | |
} | |
get nextPage() { | |
const next = Number.parseInt(this.args.currentPage, 10) + 1; | |
return this.pagesList.includes(next) ? next : null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { action } from '@ember/object'; | |
import Component from '@glimmer/component'; | |
import { tracked } from '@glimmer/tracking'; | |
import { inject as service } from '@ember/service'; | |
import { allSearchEngines } from 'nightwatch-web/constants/keyword-data'; | |
import isEmpty from 'lodash-es/isEmpty'; | |
import xor from 'lodash-es/xor'; | |
import underscorifyKeys from 'nightwatch-web/utils/underscorify-keys'; | |
import { task } from 'ember-concurrency'; | |
import isTesting from '../../utils/is-testing'; | |
import KeywordTableColumns from '../../utils/tables/keyword-table-columns'; | |
import { getOwner } from '@ember/application'; | |
/** | |
@argument scope - one of url, dynamicView, newDynamicView, urlDynamicView, newUrlDynamicView | |
@argument url | |
@argument dynamicView | |
@argument sort | |
@argument direction | |
@argument onSort | |
@argument keywords | |
*/ | |
export default class NwKeywordTableProviderComponent extends Component { | |
@service userSettings; | |
@service metrics; | |
@service router; | |
@service filterGroupHandling; | |
@service keywordColumnsData; | |
@service('persistence/keyword-list-sorting') keywordListSorting; | |
@service session; | |
@service fetch; | |
@service store; | |
@tracked selectedKeywordIds = []; | |
previousResourceId = null; | |
columns = new KeywordTableColumns({ | |
owner: getOwner(this), | |
saveColumnNames: this.saveColumnNames, | |
}); | |
@action | |
initColumns() { | |
if ( | |
this.columns.selected.length === 0 || | |
this.resource?.id !== this.previousResourceId | |
) { | |
this.columns.init(this.loadColumnNames, this.args.url?.competitors); | |
} | |
this.previousResourceId = this.resource?.id; | |
} | |
get engineTitle() { | |
return allSearchEngines.reduce((acc, { id, text }) => { | |
acc[id] = text; | |
return acc; | |
}, {}); | |
} | |
get resource() { | |
const { scope, url, dynamicView } = this.args; | |
if (scope === 'url') { | |
return url; | |
} else if (scope.toLowerCase().includes('view')) { | |
return dynamicView; | |
} else { | |
throw `NwKeywordTableProviderComponent: unknown scope (${scope})`; | |
} | |
} | |
get isNewView() { | |
return ['newDynamicView', 'newUrlDynamicView'].includes(this.args.scope); | |
} | |
get keywordsDeletable() { | |
return this.args.scope === 'url'; | |
} | |
get isLoaded() { | |
return this.args.keywords?.isLoaded || this.args.keywords?.isFulfilled; | |
} | |
get oppositeDirection() { | |
return this.args.direction === 'asc' ? 'desc' : 'asc'; | |
} | |
get selectedKeywords() { | |
if (!this.args.keywords) return []; | |
return this.args.keywords.filter((keyword) => | |
this.selectedKeywordIds.includes(keyword.id) | |
); | |
} | |
get allKeywordsSelected() { | |
const { keywords, selectedKeywords } = this.args; | |
if (!keywords || keywords?.length === 0) return false; | |
return isEmpty(xor(selectedKeywords?.mapBy('id'), keywords?.mapBy('id'))); | |
} | |
@action | |
toggleKeywordSelected(keyword) { | |
if (this.selectedKeywordIds.includes(keyword.id)) { | |
this.selectedKeywordIds.removeObject(keyword.id); | |
} else { | |
this.selectedKeywordIds.pushObject(keyword.id); | |
} | |
} | |
@action | |
selectAll() { | |
this.selectedKeywordIds = this.args.keywords.mapBy('id'); | |
} | |
@action | |
selectNone() { | |
this.selectedKeywordIds = []; | |
} | |
@action | |
onSelectAllToggleChange(checked) { | |
checked ? this.selectAll() : this.selectNone(); | |
} | |
@action | |
onSort(field, direction) { | |
if (!field) return; | |
this.args.onSort(field, direction); | |
this.saveSortParams(field, direction); | |
this.metrics.trackEvent({ event: 'Sorted Keywords' }); | |
} | |
saveSortParams(sortField, sortDirection) { | |
const { resource } = this; | |
const { scope } = this.args; | |
if (!resource) return; | |
const params = { sortField, sortDirection }; | |
if (scope.toLowerCase().includes('view')) { | |
params['viewId'] = resource.id; | |
} else if (scope.toLowerCase().includes('url')) { | |
params['urlId'] = resource.id; | |
} | |
this.keywordListSorting.persistSorting(params); | |
} | |
@action | |
openRankingUrl(url) { | |
return window.open(url); | |
} | |
@task({ drop: true }) | |
*deleteKeyword(keyword) { | |
if (!isTesting && !confirm('Are you sure you want to delete this keyword?')) | |
return; | |
yield keyword.destroyRecord(); | |
this.afterKeywordsDeleted([keyword]); | |
} | |
@task({ drop: true }) | |
*deleteSelectedKeywords() { | |
const keywords = this.selectedKeywords.slice(); | |
if ( | |
!isTesting && | |
!confirm( | |
`Are you sure you want to delete ${keywords.length} ${ | |
keywords.length === 1 ? 'keyword' : 'keywords' | |
}? All associated data will be lost.` | |
) | |
) | |
return; | |
yield this.fetch.post(`/urls/${this.args.url.id}/keywords/batch_destroy`, { | |
data: underscorifyKeys({ keywordIds: keywords.mapBy('id') }), | |
}); | |
keywords.forEach((keyword) => this.store.unloadRecord(keyword)); | |
this.afterKeywordsDeleted(keywords); | |
} | |
get loadColumnNames() { | |
const searchKeywordUrlId = this.args.url?.id; | |
const dynamicViewId = this.args.dynamicView?.id; | |
return this.userSettings.getSetting({ | |
searchKeywordUrlId, | |
dynamicViewId, | |
})?.settingsData?.keywords?.columns; | |
} | |
@action | |
saveColumnNames(columnNames) { | |
this.metrics.trackEvent({ | |
event: 'Switched Columns', | |
table: 'Keywords', | |
columns: columnNames.join(', '), | |
}); | |
if (this.isNewView) return; | |
const searchKeywordUrlId = this.args.url?.id; | |
const dynamicViewId = this.args.dynamicView?.id; | |
return this.userSettings.saveSetting({ | |
searchKeywordUrlId, | |
dynamicViewId, | |
settingsData: { | |
keywords: { | |
columns: columnNames, | |
}, | |
}, | |
}); | |
} | |
afterKeywordsDeleted(keywords) { | |
const meta = this.args.keywords.meta; | |
meta.total = meta.total - keywords.length; | |
this.session.user.reload(); // Refresh account uasge | |
this.args.url.reload(); // Refresh url usage | |
this.metrics.trackEvent({ | |
event: 'Removed Keywords', | |
keywords: keywords.mapBy('query').join(', '), | |
}); | |
this.args.fetchKeywordStats(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment