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} */ 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} */ 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} */ 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);