364 lines
15 KiB
JavaScript
Executable File
364 lines
15 KiB
JavaScript
Executable File
class BypassPluginDashboard 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: 'Country', 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/BypassPluginManagementContent',
|
|
{ title: 'Accelerator configuration', subtitle: 'Users access & token management' },
|
|
{ profile: this.profile, models: { users: this.users, tokens: this.tokens } }
|
|
).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, [
|
|
`<a href="#" data-id="${item.itemData.id}" data-pic="${item.itemData.enterprise.pic}" data-legalname="${item.itemData.enterprise.legalname}" title="View token details">${item.itemData.enterprise.pic}</a>`,
|
|
item.itemData.enterprise.legalname,
|
|
app.meta.toString('accelerator-tracks', item.itemData.domain),
|
|
item.itemData.granted,
|
|
`<span ${priority}>${item.itemData.status}</span>`,
|
|
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(`<div class="cols-2"></div>`)
|
|
let revokeButton = ui.create(`<button eicbutton xsmall danger title="revoke this token" data-pic="${item.itemData.enterprise.pic}" data-legalname="${item.itemData.enterprise.legalname}" data-track="${item.itemData.track}" data-domain="${item.itemData.domain}" >Revoke</button>`);
|
|
revokeButton.addEventListener('click', this.onTokenRevoke.bind(this));
|
|
buttonBar.appendChild(revokeButton);
|
|
|
|
let useButton = ui.create(`<button eicbutton xsmall info title="Activate the coaching" data-id="${item.itemData.id}" data-pic="${item.itemData.enterprise.pic}" data-legalname="${item.itemData.enterprise.legalname}" data-track="${item.itemData.track}" data-domain="${item.itemData.domain}" >Consume</button>`);
|
|
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(`<span>Consuming...</span>`));
|
|
}
|
|
}
|
|
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,
|
|
`<span ${priority}>${item.action}</span>`,
|
|
`${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',
|
|
'Program',
|
|
'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.program || '',
|
|
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 },
|
|
mode: 'edit',
|
|
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 },
|
|
mode: 'edit',
|
|
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('BypassPluginDashboard', BypassPluginDashboard); |