unclean SPARC
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
class ContactMgrModel extends EICModel {
|
||||
|
||||
constructor(privileges) {
|
||||
super('/contactMgr', privileges)
|
||||
Object.assign(this, app.helpers.validators)
|
||||
}
|
||||
|
||||
async list() {
|
||||
if(!this.hasPrivilege('list')) return( new Promise((resolve, reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('list')
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async get(qcid){
|
||||
if(!this.hasPrivilege('get')) return( new Promise((resolve, reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('get')
|
||||
endpoint.uri = endpoint.uri.replace('{qcid}', qcid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async getField(qcid, fieldid){
|
||||
if(!this.hasPrivilege('getFields')) return( new Promise((resolve, reject) => reject()))
|
||||
const endpoint = this.getApiEndpoint('getFields')
|
||||
endpoint.uri = endpoint.uri.replace('{qcid}', qcid)
|
||||
const payload = {
|
||||
fieldid: fieldid
|
||||
}
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, payload)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async getSample(qcid, values){
|
||||
if(!this.hasPrivilege('execute')) return( new Promise((resolve, reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('execute')
|
||||
endpoint.uri = endpoint.uri.replace('{qcid}', qcid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, {
|
||||
sample: true,
|
||||
sampleSize: 10,
|
||||
values: values,
|
||||
})
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async execute(qcid, values){
|
||||
if(!this.hasPrivilege('execute')) return( new Promise((resolve, reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('execute')
|
||||
endpoint.uri = endpoint.uri.replace('{qcid}', qcid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, {
|
||||
sample: false,
|
||||
values: values,
|
||||
})
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async probe(qcid, values, probe){
|
||||
if(!this.hasPrivilege('execute')) return( new Promise((resolve, reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('execute')
|
||||
endpoint.uri = endpoint.uri.replace('{qcid}', qcid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, {
|
||||
sample: false,
|
||||
probe: probe,
|
||||
values: values,
|
||||
})
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
app.registerClass('ContactMgrModel', ContactMgrModel);
|
||||
@@ -0,0 +1,427 @@
|
||||
class MailingsModel extends EICModel {
|
||||
|
||||
constructor(privileges) {
|
||||
super('/mailing', privileges)
|
||||
this.ffs = new FakeFileSystem()
|
||||
Object.assign(this, app.helpers.validators)
|
||||
}
|
||||
|
||||
async search(query, status=[]) {
|
||||
if(!this.hasPrivilege('search')) return( new Promise((resolve, reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('search')
|
||||
let payload = {
|
||||
query: query,
|
||||
status: status,
|
||||
}
|
||||
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, payload) // Separate filesystem info from true mailings
|
||||
.then( async serverData => serverData.payload)
|
||||
.then( data => { // And feed ffs
|
||||
this.ffs.loadStructure(
|
||||
data.ffs,
|
||||
data.mailings.map(item=>(
|
||||
{
|
||||
fullPath: (item.path+'/'+item.name).replace(/\/+/g, '/'),
|
||||
object : item
|
||||
}
|
||||
))
|
||||
)
|
||||
return(data.mailings)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
async get(mid) {
|
||||
if(!this.hasPrivilege('read')) return( new Promise((resolve, reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('read')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async getRecipients(mid){
|
||||
if(!this.hasPrivilege('read')) return( new Promise((resolve, reject) => reject())) // if can read mailing => can read recipients
|
||||
let endpoint = this.getApiEndpoint('read', '/mailing/{mid}/recipients')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async getBounces(mid){
|
||||
if(!this.hasPrivilege('read')) return( new Promise((resolve, reject) => reject())) // if can read mailing => can read bounces
|
||||
let endpoint = this.getApiEndpoint('read', '/mailing/{mid}/bounces')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async save(mailingInfo) {
|
||||
// Local copy where we'll remove display (non-save-able) mailingInfo stuff, and join-in ext stuff into the request.
|
||||
let localMmailingInfo = JSON.parse(JSON.stringify(mailingInfo))
|
||||
|
||||
// template struct => templateId
|
||||
if(localMmailingInfo.template && localMmailingInfo.template.id){
|
||||
localMmailingInfo.templateId = localMmailingInfo.template.id
|
||||
delete(localMmailingInfo.template)
|
||||
}
|
||||
|
||||
delete(localMmailingInfo.imports)
|
||||
delete(localMmailingInfo.sources)
|
||||
delete(localMmailingInfo.statusHistory)
|
||||
delete(localMmailingInfo.kpis)
|
||||
delete(localMmailingInfo.nbSources)
|
||||
delete(localMmailingInfo.nbRecipients)
|
||||
|
||||
let endpoint = this.getApiEndpoint('save')
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, localMmailingInfo)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async delete(mid) {
|
||||
if(!this.hasPrivilege('delete')) return( new Promise((resolve, reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('delete')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async schedule(mid, scheduleDate) {
|
||||
if(!this.hasPrivilege('schedule')) return( new Promise((resolve, reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('schedule')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, { scheduleDate: scheduleDate })
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async test(mid, templateId, recipientEmail, mappings={}) {
|
||||
if((!this.hasPrivilege('edit')) && (!this.hasPrivilege('approve')) && (!this.hasPrivilege('reject'))) return( new Promise((resolve, reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('test')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, {
|
||||
templateId: templateId,
|
||||
recipientEmail: recipientEmail,
|
||||
parameters: mappings
|
||||
})
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async getImports(mid) {
|
||||
let endpoint = this.getApiEndpoint('list', '/mailing/{mid}/imports')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async saveImport(mid, data) {
|
||||
data.refresh = false
|
||||
let endpoint = this.getApiEndpoint('save', '/mailing/{mid}/imports')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, data)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async saveExclusion(mid, data) {
|
||||
data.refresh = false
|
||||
data.exclusionList = true
|
||||
data.availableColumns = data.availableColumns.filter(item=>item.isEmail)
|
||||
const emailIdx = data.availableColumns[0].value
|
||||
data.data = data.data.map(row=>row[emailIdx])
|
||||
let endpoint = this.getApiEndpoint('save', '/mailing/{mid}/imports')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, data)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async refreshImport(mid, data, importId) {
|
||||
if(data.sourceType=='Excel') return({})
|
||||
data.refresh = true
|
||||
data.importId = importId
|
||||
let endpoint = this.getApiEndpoint('save', '/mailing/{mid}/imports')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, data)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async readImport(mid, iid) {
|
||||
let endpoint = this.getApiEndpoint('read', '/mailing/{mid}/imports/{iid}')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid).replace('{iid}', iid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async deleteImport(mid, id) {
|
||||
let endpoint = this.getApiEndpoint('delete', '/mailing/{mid}/imports')
|
||||
endpoint.uri = endpoint.uri.replace('{mid}', mid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, { id: id })
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async getReadableFolders() {
|
||||
try {
|
||||
const endpoint = this.getApiEndpoint('list', '/mailing/folders')
|
||||
const payload = { path: '/', withFiles: true }
|
||||
|
||||
const serverData = await this.request(endpoint.uri, endpoint.method, payload)
|
||||
return serverData.payload || {}
|
||||
} catch (err) {
|
||||
console.error("Error in getReadableFolders", err)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async makeDir(path=null, dirName){
|
||||
let ffs = this.ffs
|
||||
if(path && (!ffs.pathExists(path))) return(Promise.resolve(null))
|
||||
if(!path) path=ffs.currentPath
|
||||
dirName = dirName.replace(/\//g,'').replace(/"/g,'').replace('\\','').replace(/\./g,'')
|
||||
|
||||
let endpoint = this.getApiEndpoint('add', '/mailing/folders')
|
||||
let uri = endpoint.uri
|
||||
return (
|
||||
this.request(uri, endpoint.method, {
|
||||
appId: 2,
|
||||
path: path,
|
||||
newFolder: dirName
|
||||
})
|
||||
.then( async serverData => {
|
||||
return(serverData.payload)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
async removeDir(appId, path = null) {
|
||||
let ffs = this.ffs
|
||||
if (!path) return Promise.resolve(null)
|
||||
|
||||
path = ffs.normalizePath(path)
|
||||
|
||||
let endpoint = this.getApiEndpoint('delete', '/mailing/folders')
|
||||
let uri = endpoint.uri
|
||||
|
||||
|
||||
return this.request(uri, endpoint.method, {
|
||||
appId: appId,
|
||||
path: path
|
||||
}).then(async serverData => {
|
||||
return serverData.payload
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/********************************* Data helpers **************************************/
|
||||
getStatusLabel() {
|
||||
return({
|
||||
created : 'Created',
|
||||
draft : 'Draft',
|
||||
submitted : app.User.roles.includes('MAIL_Reviewer') ? 'To review' : 'Being reviewed',
|
||||
approved : 'Approved',
|
||||
rejected : 'Rejected',
|
||||
scheduled : 'Scheduled',
|
||||
sent : 'Sent',
|
||||
})
|
||||
}
|
||||
|
||||
findDupes(allImports){
|
||||
let dupes = {} //Key email, value: array of where it is found
|
||||
let allEmails = []
|
||||
for(let oneImport of allImports){
|
||||
const emailCol = oneImport.availableColumns.find(item => item.isEmail)
|
||||
if(!emailCol) continue
|
||||
for(let[rownb, row] of oneImport.data.entries()){
|
||||
let inAllEmails = allEmails.find(item => ( item.email == row[emailCol.value]))
|
||||
if(inAllEmails) { // that's a dupe
|
||||
if(!(row[emailCol.value] in dupes)) { // First time we come across this one, add the original entry
|
||||
dupes[row[emailCol.value]] = [{
|
||||
sourceName: inAllEmails.sourceName,
|
||||
sourceType: inAllEmails.sourceType,
|
||||
rownb: inAllEmails.rownb,
|
||||
}]
|
||||
}
|
||||
dupes[row[emailCol.value]].push({ // Add the dupe
|
||||
sourceName: oneImport.sourceName,
|
||||
sourceType: oneImport.sourceType,
|
||||
rownb: rownb,
|
||||
})
|
||||
} else {
|
||||
allEmails.push({
|
||||
email: row[emailCol.value],
|
||||
sourceName: oneImport.sourceName,
|
||||
sourceType : oneImport.sourceType,
|
||||
rownb: rownb,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return(dupes)
|
||||
}
|
||||
|
||||
getLatestStatus(mailingInfo, status=null){
|
||||
if(!mailingInfo || !mailingInfo.statusHistory || (mailingInfo.statusHistory.length<1)) return('')
|
||||
const latest = mailingInfo.statusHistory.reduce((max, obj) =>
|
||||
(obj.dateTime > max.dateTime) && ((!status) || (status==obj.value)) ? obj : max
|
||||
)
|
||||
return( (!status) ? latest : (status == latest.value) ? latest : null )
|
||||
}
|
||||
|
||||
getStepActivations(mailing, templateTokens){
|
||||
const stepActivations = { }
|
||||
stepActivations['start'] = {
|
||||
disabled: (!this.hasPrivilege('edit')) || ((mailing.status != 'created') && (mailing.status != 'draft')),
|
||||
severity: (mailing.status != 'created') ? 'success' : 'warning',
|
||||
done: (mailing.name && mailing.path)
|
||||
}
|
||||
stepActivations['template'] = {
|
||||
disabled: (!this.hasPrivilege('edit')) || (mailing.status != 'draft'),
|
||||
severity: (!mailing.template.id) ? (mailing.status != 'draft') ? 'secondary' : 'warning' : 'success',
|
||||
done: (mailing.template.id)
|
||||
}
|
||||
stepActivations['recipients'] = {
|
||||
disabled: (!this.hasPrivilege('edit')) || (mailing.status != 'draft'), // || (!stepActivations.template.done),
|
||||
severity: (mailing.nbRecipients == 0) ? ((mailing.status != 'draft') || (!mailing.template.id)) ? 'secondary' : 'warning' : 'success',
|
||||
done: (mailing.nbRecipients > 0)
|
||||
}
|
||||
stepActivations['mappings'] = {
|
||||
disabled: (!this.hasPrivilege('edit')) || (mailing.status != 'draft') || (!stepActivations.template.done) || (!stepActivations.recipients.done),
|
||||
severity: (stepActivations.template.done && stepActivations.recipients.done) ? (this.TotalNbMapMissing(mailing, templateTokens) > 0) ? 'warning': 'success' : 'secondary',
|
||||
done: (stepActivations['template'].done && stepActivations['recipients'].done && (this.TotalNbMapMissing(mailing, templateTokens) == 0))
|
||||
}
|
||||
stepActivations['approval'] = {
|
||||
disabled: ((!this.hasPrivilege('edit')) && (!this.hasPrivilege('approve')) && (!this.hasPrivilege('reject'))) || (!(['draft','submitted'].includes(mailing.status))) || (!stepActivations.mappings.done) ,
|
||||
severity: stepActivations.mappings.done ? ((mailing.status == 'approved') || (mailing.status == 'scheduled')) ? 'success' : 'warning' : 'secondary',
|
||||
done: (mailing.status == 'approved')
|
||||
}
|
||||
stepActivations['schedule'] = {
|
||||
disabled: (!this.hasPrivilege('schedule')) || ((mailing.status!='approved') && (mailing.status!='scheduled')),
|
||||
severity: (mailing.status!='scheduled') ? (mailing.status!='approved') ? 'secondary' : 'warning' : 'success',
|
||||
done: (mailing.status=='scheduled')
|
||||
}
|
||||
return(stepActivations)
|
||||
}
|
||||
|
||||
nbMapMissingPerSrc(mailing, templateTokens){
|
||||
let nbMissing = {}
|
||||
mailing.sources.forEach(src => {
|
||||
let srcMappings = mailing.mappings.find(mp => mp. sourceId==src.id)
|
||||
if(srcMappings) {
|
||||
nbMissing[src.id] = (templateTokens.length - Object.keys(srcMappings.mappings).length)
|
||||
} else {
|
||||
nbMissing[src.id] = templateTokens.length
|
||||
}
|
||||
})
|
||||
return(nbMissing)
|
||||
}
|
||||
|
||||
TotalNbMapMissing(mailing, templateTokens){
|
||||
const missingPerSrc = this.nbMapMissingPerSrc(mailing, templateTokens)
|
||||
return(Object.keys(missingPerSrc).reduce((acc,key) => acc+=missingPerSrc[key],0))
|
||||
}
|
||||
|
||||
getReviewBlocks(mailing){
|
||||
const latestSubmitted = this.getLatestStatus(mailing, 'submitted')
|
||||
const latestRejected = this.getLatestStatus(mailing, 'rejected')
|
||||
const latestApproved = this.getLatestStatus(mailing, 'approved')
|
||||
let blocks = []
|
||||
let contents = {}
|
||||
if(!app.User.roles.includes('MAIL_Reviewer')){
|
||||
// Only Editors & Revieers can sen test mails
|
||||
if(app.User.roles.includes('MAIL_Editor')) blocks.push('testPane')
|
||||
blocks.push('revieweePane')
|
||||
switch(mailing.status){
|
||||
case 'submitted': blocks.push('revieweeOngoing'); break
|
||||
case 'approved': blocks.push('revieweeApproved')
|
||||
contents['approUser1'] = `${latestApproved.changedBy.firstname} ${latestApproved.changedBy.lastname}`
|
||||
contents['approDate1'] = (new Intl.DateTimeFormat("fr-FR", {timeZone: "Europe/Paris", dateStyle:'medium', timeStyle:'medium'}))
|
||||
.format(new Date(latestApproved.dateTime))
|
||||
break
|
||||
case 'draft': if((latestRejected) && // no rejection ever
|
||||
// Rejection and no approval afterwards (possible because might be draft again after unscheduled)
|
||||
((!latestApproved) || (latestApproved.dateTime<latestRejected.dateTime))){
|
||||
blocks.push('revieweeRejected')
|
||||
contents['rejectionUser1'] = `${latestRejected.changedBy.firstname} ${latestRejected.changedBy.lastname}`
|
||||
contents['rejectionDate1'] = (new Intl.DateTimeFormat("fr-FR", {timeZone: "Europe/Paris", dateStyle:'medium', timeStyle:'medium'}))
|
||||
.format(new Date(latestRejected.dateTime))
|
||||
contents['rejectionReason1'] = (latestRejected.meta && latestRejected.meta.reason) ? latestRejected.meta.reason : ''
|
||||
} else if(app.User.roles.includes('MAIL_Editor')) {
|
||||
blocks.push('revieweeRequest')
|
||||
}
|
||||
break
|
||||
}
|
||||
} else {
|
||||
blocks.push('testPane')
|
||||
|
||||
switch(mailing.status){
|
||||
case 'submitted': blocks.push('reviewerPane')
|
||||
blocks.push('reviewerChoice')
|
||||
contents['requestUser2'] =`${latestSubmitted.changedBy.firstname} ${latestSubmitted.changedBy.lastname}`
|
||||
contents['requestDate2'] =(new Intl.DateTimeFormat("fr-FR", {timeZone: "Europe/Paris", dateStyle:'medium', timeStyle:'medium'}))
|
||||
.format(new Date(latestSubmitted.dateTime))
|
||||
contents['reviewComments2'] = (latestSubmitted.meta && latestSubmitted.meta.comments) ? latestSubmitted.meta.comments : ''
|
||||
break
|
||||
case 'approved': blocks.push('reviewerPane')
|
||||
blocks.push('reviewerApproved')
|
||||
contents['approUser2'] = `${latestApproved.changedBy.firstname} ${latestApproved.changedBy.lastname}`
|
||||
contents['approDate2'] = (new Intl.DateTimeFormat("fr-FR", {timeZone: "Europe/Paris", dateStyle:'medium', timeStyle:'medium'}))
|
||||
.format(new Date(latestApproved.dateTime))
|
||||
break
|
||||
case 'draft': if(app.User.roles.includes('MAIL_Editor')) {
|
||||
// For those who are both editor & reviewer, let them ask themselves (or other reviewer)
|
||||
blocks.push('revieweePane')
|
||||
blocks.push('revieweeRequest')
|
||||
}
|
||||
if((latestRejected) &&
|
||||
// Rejection and no approval afterwards (possible because might be draft again after unscheduled)
|
||||
((!latestApproved) || (latestApproved.dateTime<latestRejected.dateTime))){
|
||||
blocks.push('reviewerPane')
|
||||
blocks.push('reviewerRejected')
|
||||
contents['rejectionUser2'] = `${latestRejected.changedBy.firstname} ${latestRejected.changedBy.lastname}`
|
||||
contents['rejectionDate2'] = (new Intl.DateTimeFormat("fr-FR", {timeZone: "Europe/Paris", dateStyle:'medium', timeStyle:'medium'}))
|
||||
.format(new Date(latestRejected.dateTime))
|
||||
contents['rejectionReason2'] = (latestRejected.meta && latestRejected.meta.reason) ? latestRejected.meta.reason : ''
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return([blocks, contents])
|
||||
}
|
||||
|
||||
canImport(){
|
||||
return(true)
|
||||
}
|
||||
|
||||
canImportExclusion(){
|
||||
return(true)
|
||||
}
|
||||
|
||||
canFetch(){
|
||||
return(app.User.identity.uuid=='steinic')
|
||||
}
|
||||
}
|
||||
|
||||
app.registerClass('MailingsModel', MailingsModel);
|
||||
@@ -0,0 +1,315 @@
|
||||
class TemplatesModel extends EICModel {
|
||||
|
||||
current = null;
|
||||
|
||||
constructor(privileges) {
|
||||
super('/templates', privileges)
|
||||
this.ffs = new FakeFileSystem()
|
||||
this.tokenCache = {}
|
||||
}
|
||||
|
||||
getLatestStatus(templateInfo, status=null){
|
||||
if(!templateInfo.statusHistory || (templateInfo.statusHistory.length<1)) return('')
|
||||
return(
|
||||
templateInfo.statusHistory.reduce((max, obj) =>
|
||||
(obj.dateTime > max.dateTime) && ((!status) || (status==obj.value)) ? obj : max
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
getTokens(templateInfo){
|
||||
if((!templateInfo) || (!templateInfo.id)) return
|
||||
if(templateInfo.id in this.tokenCache) return(this.tokenCache[templateInfo.id])
|
||||
const re = new RegExp(/\{\{([\w\-\.\^\#\/]+)\}\}/,'gm')
|
||||
let txt = atob(templateInfo.html)
|
||||
let allTokens = [...txt.matchAll(re)].map(item=>item[1])
|
||||
if(templateInfo.meta.altText){
|
||||
txt = atob(templateInfo.meta.altText)
|
||||
for(let m of txt.matchAll(re)){
|
||||
if(!allTokens.includes(m[1])) allTokens.push(m[1])
|
||||
}
|
||||
}
|
||||
if(templateInfo.meta.subject){
|
||||
txt = templateInfo.meta.subject
|
||||
for(let m of txt.matchAll(re)){
|
||||
if(!allTokens.includes(m[1])) allTokens.push(m[1])
|
||||
}
|
||||
}
|
||||
this.tokenCache[templateInfo.id] = allTokens
|
||||
return(allTokens)
|
||||
}
|
||||
|
||||
countTokens(templateInfo){
|
||||
return(this.getTokens(templateInfo).length)
|
||||
}
|
||||
|
||||
async getTechDDTokens() {
|
||||
this.tokenList = Promise.resolve([
|
||||
{ name: 'personEmail' },
|
||||
{ name: 'personEuLogin' },
|
||||
{ name: 'personFirstName' },
|
||||
{ name: 'personLastName' },
|
||||
{ name: 'personFullName' },
|
||||
{ name: 'organisationFullName' },
|
||||
{ name: 'organisationShortName' },
|
||||
{ name: 'organisationPIC' },
|
||||
{ name: 'proposalId' },
|
||||
{ name: 'proposalAcronym' },
|
||||
{ name: 'proposalType' },
|
||||
{ name: 'expertFirstName' },
|
||||
{ name: 'expertLastName' },
|
||||
{ name: 'expertFullName' },
|
||||
{ name: 'FIOFirstName' },
|
||||
{ name: 'FIOLastName' },
|
||||
{ name: 'FIOFullName' },
|
||||
{ name: 'POFirstName' },
|
||||
{ name: 'POLastName' },
|
||||
{ name: 'POFullName' },
|
||||
{ name: 'TechDDFirstName' },
|
||||
{ name: 'TechDDLastName' },
|
||||
{ name: 'TechDDFullName' },
|
||||
{ name: 'reportURL' },
|
||||
{ name: 'unsubscribeURL' }
|
||||
]);
|
||||
return this.tokenList;
|
||||
}
|
||||
|
||||
/************************/
|
||||
|
||||
|
||||
/**
|
||||
* Get a template by its ID.
|
||||
* @param {string} tid - The ID of the templitor.
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
async get(tid) {
|
||||
let endpoint = this.getApiEndpoint('read')
|
||||
endpoint.uri = endpoint.uri.replace('{tid}', tid)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method)
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* List all templates.
|
||||
* @returns {Promise<any[]>}
|
||||
*/
|
||||
async search(query, status=[]) {
|
||||
if(!this.hasPrivilege('search')) return( new Promise((resolve, reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('search')
|
||||
let payload = {
|
||||
query: query,
|
||||
status: status,
|
||||
}
|
||||
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, payload)
|
||||
.then( async serverData => serverData.payload)
|
||||
.then( data => {
|
||||
this.ffs.loadStructure(
|
||||
data.ffs,
|
||||
data.templates.map(item=>(
|
||||
{
|
||||
fullPath: (item.path+'/'+item.name).replace(/\/+/g, '/'),
|
||||
object : item
|
||||
}
|
||||
))
|
||||
)
|
||||
return(data.templates)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
async save(data) {
|
||||
let endpoint = this.getApiEndpoint('save')
|
||||
console.log("Saving template with data:", data);
|
||||
return this.request(endpoint.uri, endpoint.method, data)
|
||||
}
|
||||
|
||||
async delete(tid) {
|
||||
if(!this.hasPrivilege('delete')) return( new Promise((reject) => reject('Insufficient privileges to perform delete templates')))
|
||||
let endpoint = this.getApiEndpoint('delete')
|
||||
endpoint.uri = endpoint.uri.replace('{tid}', tid)
|
||||
return this.request(endpoint.uri, endpoint.method)
|
||||
}
|
||||
|
||||
/*
|
||||
* list of predefined images can be used in template
|
||||
*/
|
||||
async getImages() {
|
||||
if(!this.hasPrivilege('read')) return( new Promise((reject) => reject('Insufficient privileges to perform get images'))) // if can read templates => can search list
|
||||
let endpoint = this.getApiEndpoint('getImages');
|
||||
return this.request(endpoint.uri, endpoint.method)
|
||||
.then(serverData => serverData.payload)
|
||||
.then(data => {
|
||||
return data.map(item => ({
|
||||
fullPath: (item.path + '/' + item.name).replace(/\/+/g, '/'),
|
||||
object: item,
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete image
|
||||
* @param {*} pid - picture id
|
||||
* @param {*} deleteUrl - aws image url
|
||||
* @returns {Promise<any[]>}
|
||||
*/
|
||||
async deleteImage(pid, deleteUrl) {
|
||||
if (!this.hasPrivilege('delete')) {
|
||||
return new Promise((reject) => reject('Insufficient privileges to perform delete images'));
|
||||
}
|
||||
|
||||
let endpoint = this.getApiEndpoint('deleteImage');
|
||||
endpoint.uri = endpoint.uri.replace('{pid}', pid);
|
||||
|
||||
const requestBody = { deleteUrl: deleteUrl };
|
||||
|
||||
return this.request(endpoint.uri, endpoint.method, requestBody)
|
||||
.then(response => {
|
||||
console.log('Image deleted successfully:', response);
|
||||
return response;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error deleting image:', error);
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
getStatusLabel() {
|
||||
return({
|
||||
created : 'Created',
|
||||
draft : 'Draft',
|
||||
submitted : app.User.roles.includes('TEMPLATE_Reviewer') ? 'To review' : 'Being reviewed',
|
||||
prod : 'Approved',
|
||||
archived : 'Archived',
|
||||
})
|
||||
}
|
||||
|
||||
async readDir(path = '/', withFiles=true ){
|
||||
if(!this.hasPrivilege('read')) return( new Promise((reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('list', '/templitor/folders')
|
||||
let uri = endpoint.uri
|
||||
return (
|
||||
this.request(uri, endpoint.method, { "path":path, withFiles: true })
|
||||
.then( async serverData => {
|
||||
if(!withFiles){
|
||||
this.ffs.changeDir('/')
|
||||
this.ffs.loadStructure(serverData.payload, this.ffs.getFiles())
|
||||
} else {
|
||||
const ffsData = serverData.payload.ffs || serverData.payload
|
||||
this.ffs.loadStructure(ffsData, serverData.payload.files || [])
|
||||
}
|
||||
return(serverData.payload)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
async getReadableFolders() {
|
||||
try {
|
||||
const endpoint = this.getApiEndpoint('list', '/templitor/folders')
|
||||
const payload = { path: '/', withFiles: true }
|
||||
|
||||
const serverData = await this.request(endpoint.uri, endpoint.method, payload)
|
||||
return serverData.payload || {}
|
||||
} catch (err) {
|
||||
console.error("Error in getReadableFolders", err)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async makeDir(path=null, dirName){
|
||||
let ffs = this.ffs //here not first param of method
|
||||
if(path && (!ffs.pathExists(path))) return(Promise.resolve(null))
|
||||
if(!path) path=ffs.currentPath
|
||||
dirName = dirName.replace(/\//g,'').replace(/"/g,'').replace('\\','').replace(/\./g,'')
|
||||
|
||||
let endpoint = this.getApiEndpoint('add', '/templitor/folders');
|
||||
let uri = endpoint.uri
|
||||
return (
|
||||
this.request(uri, endpoint.method, {
|
||||
appId: 1,
|
||||
path: path,
|
||||
newFolder: dirName
|
||||
})
|
||||
.then( async serverData => {
|
||||
return(serverData.payload)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
async removeDir(appId, path = null) {
|
||||
let ffs = this.ffs
|
||||
if (!path) return Promise.resolve(null)
|
||||
|
||||
path = ffs.normalizePath(path)
|
||||
|
||||
let endpoint = this.getApiEndpoint('delete', '/templitor/folders')
|
||||
let uri = endpoint.uri
|
||||
|
||||
|
||||
return this.request(uri, endpoint.method, {
|
||||
appId: appId,
|
||||
path: path
|
||||
}).then(async serverData => {
|
||||
return serverData.payload
|
||||
})
|
||||
}
|
||||
|
||||
async testMail(templateId, recipientEmail) {
|
||||
if(!this.hasPrivilege('edit')) return( new Promise((reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('testTemplateMail')
|
||||
endpoint.uri = endpoint.uri.replace('{tid}',templateId)
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, {
|
||||
templateId: templateId,
|
||||
recipientEmail: recipientEmail
|
||||
})
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async saveImage(data) {
|
||||
let endpoint = this.getApiEndpoint('addImage');
|
||||
return this.request(endpoint.uri, endpoint.method, data);
|
||||
}
|
||||
|
||||
async requestPub(templateId, recipientEmail) {
|
||||
if(!this.hasPrivilege('edit')) return( new Promise((reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('requestPubTemplate')
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, {
|
||||
templateId: templateId,
|
||||
recipientEmail: recipientEmail
|
||||
})
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async approvePub(templateId, recipientEmail) {
|
||||
if((!this.hasPrivilege('edit')) && (!this.hasPrivilege('approve')) && (!this.hasPrivilege('reject'))) return( new Promise((reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('approvePub')
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, {
|
||||
templateId: templateId,
|
||||
recipientEmail: recipientEmail
|
||||
})
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
async rejectPub(templateId, recipientEmail) {
|
||||
if((!this.hasPrivilege('edit')) && (!this.hasPrivilege('approve')) && (!this.hasPrivilege('reject'))) return( new Promise((reject) => reject()))
|
||||
let endpoint = this.getApiEndpoint('rejectPub')
|
||||
return (
|
||||
this.request(endpoint.uri, endpoint.method, {
|
||||
templateId: templateId,
|
||||
recipientEmail: recipientEmail
|
||||
})
|
||||
.then( async serverData => serverData.payload)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
app.registerClass('TemplatesModel', TemplatesModel);
|
||||
Reference in New Issue
Block a user