class BypassKICDashboard extends EICDomContent { DOMContentLoaded(options) { ui.eicfy(this.el); this.profile = options.profile; for(let model in options.models) this[model] = options.models[model]; this.tabs = new Tab(); this.tabs.addTabs(this.findAll('menu li'), this.findAll('.content')) this.gridTokens = new DataGrid(this.find('.granted-tokens'), { headers: [ { label: 'PIC', type:'markup', filter: 'text', sortable: true}, { label: 'Company name', filter: 'text', sortable: true}, { label: 'Entity/programme', filter: 'list', sortable: true}, { label: 'Token granted', type: 'date', filter: 'text', sortable: true}, { label: 'Status', filter: 'list', sortable: true}, { label: 'Project', filter: 'text', sortable: true}, { label: 'Short proposal submission', type: 'date', filter: 'text', sortable: true} ], height: 'calc(100vh - 472px)', actions: [] }); this.btTokenDl = new Button(null, {icon: 'icon-download', severity: 'secondary', rounded: true, size: 'small', hint: 'Download complete list as CSV'}) this.btTokenDl.addEventListener('click', this.downloadTokensList.bind(this)); this.gridTokens.el.querySelector('header .cell.actions').append(this.btTokenDl.el); this.btTokenRefresh = new Button(null, {icon: 'icon-refresh', severity: 'primary', rounded: true, size: 'small', hint: 'Refresh the list'}) this.btTokenRefresh.addEventListener('click', this.refreshTokensList.bind(this)); this.gridTokens.el.querySelector('header .cell.actions').append(this.btTokenRefresh.el); this.gridTokens.onRowFiltered = this.refreshMetrics.bind(this); this.gridHistory = new DataGrid(this.find('.history-tokens'), { headers: [ { label: 'Date', type: 'dateTime', filter: 'text', sortable: true}, { label: 'PIC', filter: 'text', sortable: true}, { label: 'Company name', filter: 'text', sortable: true}, { label: 'Action', filter: 'list', sortable: true}, { label: 'Managed by', filter: 'text', sortable: true}, ], height: 'calc(100vh - 420px)', actions: [] }); let btGrant = this.find('.grant-token'); if(this.company.hasPrivilege('grant')) { btGrant.addEventListener('click', this.onTokenGrant.bind(this)); } else { ui.hide(btGrant); } if(this.tokens.hasPrivilege('list')) { this.refreshTokensList(); } if(this.users) { this.loadContent( 'projects/bypass/BypassKICManagementContent', { title: 'Accelerator configuration', subtitle: 'Users access & token management' }, { profile: this.profile, models: { "users": this.users } } ).then(view => this.setupUserManagement(view)) } else { ui.hide(this.find('li.settings')); } } setupUserManagement(view) { this.userManagement = view; this.find('.content.config').append(view.el); } fill() { let year = new Date().getFullYear(); let awardedPast = this.tokens.awardedTokens(year - 1); awardedPast.forEach(item => item.ref = 'assigned-past'); let awardedCurrent = this.tokens.awardedTokens(year); awardedCurrent.forEach(item => item.ref = 'assigned-current'); let consumedPast = this.tokens.consumedTokens(year - 1); consumedPast.forEach(item => item.ref = 'consumed-past'); let consumedCurrent = this.tokens.consumedTokens(year); consumedCurrent.forEach(item => item.ref = 'consumed-current'); let history = this.tokens.history(); this.find('.metrics .available span').innerText = this.tokens.freeTokens - awardedCurrent.length; this.find('.metrics .assigned-current .year').innerText = year; this.find('.metrics .consumed-current .year').innerText = year; this.find('.metrics .assigned-past .year').innerText = year - 1; this.find('.metrics .consumed-past .year').innerText = year - 1; this.gridHistory.loading = false; this.gridTokens.loading = false; this.btTokenRefresh.loading = false; this.gridTokens.clear(); let awarded = awardedCurrent.concat(awardedPast); awarded.sort((a,b) => a.itemData.granted < b.itemData.granted ? 1: -1); for (const item of awarded) { let priority = '' switch(item.itemData.status) { case 'consumed': priority = 'success'; break; } let row = this.gridTokens.addRow(item.itemData.id, [ `${item.itemData.enterprise.pic}`, item.itemData.enterprise.legalname, app.meta.toString('accelerator-tracks', item.itemData.domain), item.itemData.granted, `${item.itemData.status}`, item.itemData.project ? item.itemData.project.acronym: '', item.itemData.project ? item.itemData.project.submissionDate: '' ], true); let tokenLink = row.querySelector('.cell:nth-child(2) a') tokenLink.addEventListener('click', this.onTokenView.bind(this)); row.classList.add(item.ref); // checking if token can be revoked (meaning status is allocated and user has privilege for that action) if((item.itemData.status == "allocated") && this.company.hasPrivilege('revoke') && (!item.itemData.isAssignedToShortProposal)) { let buttonBar = ui.create(`
`) let revokeButton = ui.create(``); revokeButton.addEventListener('click', this.onTokenRevoke.bind(this)); buttonBar.appendChild(revokeButton); let useButton = ui.create(``); useButton.addEventListener('click', this.onTokenConsume.bind(this)); buttonBar.appendChild(useButton); row.querySelector('.cell.actions').appendChild(buttonBar); } else if((item.itemData.status == "allocated") && this.company.hasPrivilege('revoke') && (item.itemData.isAssignedToShortProposal)){ row.querySelector('.cell.actions').appendChild(ui.create(`Consuming...`)); } } this.gridTokens.updateFilters(); // filling the history list this.gridHistory.clear(); for (const item of history) { let priority = '' switch(item.action) { case 'revoked': priority = 'danger'; break; case 'consumed': priority = 'success'; break; } let row = this.gridHistory.addRow(item.date, [ item.date, item.pic, item.legalname, `${item.action}`, `${item.actor.firstname ? item.actor.firstname[0] + '. ': ''}${item.actor.lastname}` ], true); } this.gridHistory.updateFilters(); this.refreshMetrics(); } refreshMetrics() { let rows = Array.from(this.gridTokens.filteredRows); let assignedPast = rows.filter(item => item.classList.contains('assigned-past')); let assignedCurrent = rows.filter(item => item.classList.contains('assigned-current')); let consumedPast = rows.filter(item => item.classList.contains('consumed-past')); let consumedCurrent = rows.filter(item => item.classList.contains('consumed-current')); this.find('.metrics .assigned-past span').innerText = assignedPast.length; this.find('.metrics .assigned-current span').innerText = assignedCurrent.length; this.find('.metrics .consumed-past span').innerText = consumedPast.length; this.find('.metrics .consumed-current span').innerText = consumedCurrent.length; } refreshTokensList(event) { if(event) { event.preventDefault(); event.stopPropagation(); } this.btTokenRefresh.loading = true; this.gridTokens.loading = true; this.gridHistory.loading = true; this.tokens.list().then(this.fill.bind(this)); } downloadTokensList(event) { if(event) { event.preventDefault(); event.stopPropagation(); } this.btTokenDl.loading = true; this.tokens.export({filter: { includePersons: true }}).then(this.buildCSV.bind(this)); } buildCSV(payload) { let options = { headers: [ 'PIC', 'Organisation Name', 'Granted on', 'Scheme', 'Entity', 'Status', 'Project', 'Submission date', 'Contact name', 'Contact gender', 'Contact position', 'Contact email', 'Contact phone', 'SPOC name', 'SPOC email', ], filename: 'EIC-Bypass', delimiter: ';' } let data = []; for(let token of payload.tokens) { let row = [ token.enterprise.pic, token.enterprise.legalname, token.granted, app.meta.toString('accelerator-tracks', token.track), app.meta.toString('accelerator-tracks', token.domain), token.history[0].status, token.project ? token.project.acronym: '', token.project ? token.project.submissiondate: '', token.shortProposal ? token.shortProposal.contact.lastname + ' ' + token.shortProposal.contact.firstname: '', token.shortProposal ? token.shortProposal.contact.gender: '', token.shortProposal ? token.shortProposal.contact.position: '', token.shortProposal ? token.shortProposal.contact.email: '', token.shortProposal ? token.shortProposal.contact.phone: '', token.spoc ? token.spoc.lastname + ' ' + token.spoc.firstname: '', token.spoc ? token.spoc.email: '', ] data.push(row); } app.helpers.translator.toCSV( data, options ); this.btTokenDl.loading = false; } async onTokenGrant(event) { event.preventDefault(); event.stopPropagation(); let grantResult = await this.openDialog( await this.loadContent( 'projects/bypass/dialogs/BypassTokenGrantDialog', { title: 'Grant a token' }, { models: { 'company': this.company, 'tokens': this.tokens }, profile: this.profile } ) ); if(grantResult) { ui.growl.append('Token granted', 'success'); let ConsumeResult = await this.openDialog( await this.loadContent( 'projects/bypass/dialogs/BypassTokenGrantPropaDialog', { title: 'Activate the coaching for...', subtitle: `${this.company.itemData.legalname} (${this.company.itemData.pic})` }, { models: { users: this.users, token: this.tokens }, profile: this.profile, tokenId: this.company.itemData.token.id, pic: this.company.pic, legalname: this.company.itemData.legalname, wizard: true, } ) ); } this.refreshTokensList(); } async onTokenRevoke(event) { event.preventDefault(); event.stopPropagation(); let result = await this.openDialog( await this.loadContent( 'projects/bypass/dialogs/BypassTokenRevokeDialog', { title: 'Revoke a token for...', subtitle: `${event.currentTarget.dataset.legalname} (${event.currentTarget.dataset.pic})` }, { model: this.company, profile: this.profile, pic: event.currentTarget.dataset.pic, track: event.currentTarget.dataset.track, domain: event.currentTarget.dataset.domain, } ) ); if(result) { ui.growl.append('Token revoked', 'success'); this.refreshTokensList(); } } async onTokenView(event) { event.preventDefault(); event.stopPropagation(); let result = await this.openDialog( await this.loadContent( 'projects/bypass/dialogs/BypassTokenGrantProposalDialog', { title: 'Token granted to ', subtitle: `${event.currentTarget.dataset.legalname} (${event.currentTarget.dataset.pic})` }, { models: { users: this.users, token: this.tokens }, mode: 'read', profile: this.profile, tokenId: event.currentTarget.dataset.id, pic: event.currentTarget.dataset.pic, legalname: event.currentTarget.dataset.legalname, wizard: false, } ) ); if(result) { ui.growl.append('Token consumed', 'success'); this.refreshTokensList(); } } async onTokenConsume(event) { event.preventDefault(); event.stopPropagation(); let result = await this.openDialog( await this.loadContent( 'projects/bypass/dialogs/BypassTokenGrantProposalDialog', { title: 'Activate the coaching for...', subtitle: `${event.currentTarget.dataset.legalname} (${event.currentTarget.dataset.pic})` }, { models: { users: this.users, token: this.tokens }, profile: this.profile, tokenId: event.currentTarget.dataset.id, pic: event.currentTarget.dataset.pic, legalname: event.currentTarget.dataset.legalname, wizard: false, } ) ); if(result) { ui.growl.append('Token consumed', 'success'); this.refreshTokensList(); } } } app.registerClass('BypassKICDashboard', BypassKICDashboard);