Mailspring/examples/N1-Composer-Templates/lib/template-store.es6
Drew Regitsky 20c522ed39 feat(templates-plugin): Add prefs page with template editor, fix bugs.
[Composer Templates / Quick Reply plugin example]

Add a page to preferences with a basic editor for quick reply templates,
allowing add, delete, and edit (HTML and rendered text), with instructions
for how to add variable regions. Add methods to TemplatesStore to enable
these. Fix issues in plugin with quoted text handling, name conflicts,
`this` scoping.
2015-12-02 21:28:49 -08:00

209 lines
6.4 KiB
JavaScript

import {DraftStore, Actions, QuotedHTMLParser} from 'nylas-exports';
import NylasStore from 'nylas-store';
import shell from 'shell';
import path from 'path';
import fs from 'fs';
class TemplateStore extends NylasStore {
init(templatesDir = path.join(NylasEnv.getConfigDirPath(), 'templates')) {
this.items = this.items.bind(this);
this.templatesDirectory = this.templatesDirectory.bind(this);
this._setStoreDefaults = this._setStoreDefaults.bind(this);
this._registerListeners = this._registerListeners.bind(this);
this._populate = this._populate.bind(this);
this._onCreateTemplate = this._onCreateTemplate.bind(this);
this._onShowTemplates = this._onShowTemplates.bind(this);
this._displayError = this._displayError.bind(this);
this._writeTemplate = this._writeTemplate.bind(this);
this._onInsertTemplateId = this._onInsertTemplateId.bind(this);
this._setStoreDefaults();
this._registerListeners();
this._templatesDir = templatesDir;
this._welcomeName = 'Welcome to Templates.html';
this._welcomePath = path.join(__dirname, '..', 'assets', this._welcomeName);
// I know this is a bit of pain but don't do anything that
// could possibly slow down app launch
fs.exists(this._templatesDir, (exists) => {
if (exists) {
this._populate();
fs.watch(this._templatesDir, () => this._populate());
} else {
fs.mkdir(this._templatesDir, () => {
fs.readFile(this._welcomePath, (err, welcome) => {
fs.writeFile(path.join(this._templatesDir, this._welcomeName), welcome, () => {
fs.watch(this._templatesDir, () => this._populate());
});
});
});
}
});
}
items() {
return this._items;
}
templatesDirectory() {
return this._templatesDir;
}
_setStoreDefaults() {
this._items = [];
}
_registerListeners() {
this.listenTo(Actions.insertTemplateId, this._onInsertTemplateId);
this.listenTo(Actions.createTemplate, this._onCreateTemplate);
this.listenTo(Actions.showTemplates, this._onShowTemplates);
}
_populate() {
fs.readdir(this._templatesDir, (err, filenames) => {
this._items = [];
for (let i = 0, filename; i < filenames.length; i++) {
filename = filenames[i];
if (filename[0] === '.') { continue; }
const displayname = path.basename(filename, path.extname(filename));
this._items.push({
id: filename,
name: displayname,
path: path.join(this._templatesDir, filename),
});
}
this.trigger(this);
});
}
_onCreateTemplate({draftClientId, name, contents} = {}) {
if (draftClientId) {
DraftStore.sessionForClientId(draftClientId).then((session) => {
const draft = session.draft();
const draftName = name ? name : draft.subject;
const draftContents = contents ? contents : QuotedHTMLParser.removeQuotedHTML(draft.body);
if (!draftName || draftName.length === 0) {
this._displayError('Give your draft a subject to name your template.');
}
if (!draftContents || draftContents.length === 0) {
this._displayError('To create a template you need to fill the body of the current draft.');
}
this._writeTemplate(draftName, draftContents);
});
return;
}
if (!name || name.length === 0) {
this._displayError('You must provide a name for your template.');
}
if (!contents || contents.length === 0) {
this._displayError('You must provide contents for your template.');
}
this._writeTemplate(name, contents);
}
_onShowTemplates() {
const ref = this._items[0];
shell.showItemInFolder(((ref != null) ? ref.path : undefined) || this._templatesDir);
}
_displayError(message) {
const dialog = require('remote').require('dialog');
dialog.showErrorBox('Template Creation Error', message);
}
_writeTemplate(name, contents) {
this.saveTemplate(name, contents, true, (template) => {
Actions.switchPreferencesTab('Quick Replies');
Actions.openPreferences()
});
}
saveTemplate(name, contents, isNew, callback) {
const filename = `${name}.html`;
const templatePath = path.join(this._templatesDir, filename);
var template = null;
this._items.forEach((item) => {
if (item.name === name) { template = item; }
});
if(isNew && template !== null) {
this._displayError("A template with that name already exists!");
return undefined;
}
fs.writeFile(templatePath, contents, (err) => {
if (err) { this._displayError(err); }
if (template === null) {
template = {
id: filename,
name: name,
path: templatePath
};
this._items.push(template);
}
if(callback)
callback(template);
this.trigger(this);
});
}
deleteTemplate(name, callback) {
var template = null;
this._items.forEach((item) => {
if (item.name === name) { template = item; }
});
if (!template) { return undefined }
fs.unlink(template.path, () => {
this._populate();
if(callback)
callback()
});
}
renameTemplate(oldName, newName, callback) {
var template = null;
this._items.forEach((item) => {
if (item.name === oldName) { template = item; }
});
if (!template) { return undefined }
const newFilename = `${newName}.html`;
const oldPath = path.join(this._templatesDir, `${oldName}.html`);
const newPath = path.join(this._templatesDir, newFilename);
fs.rename(oldPath, newPath, () => {
template.name = newName;
template.id = newFilename;
template.path = newPath;
this.trigger(this);
callback(template)
});
}
_onInsertTemplateId({templateId, draftClientId} = {}) {
this.getTemplateContents(templateId, (body) => {
DraftStore.sessionForClientId(draftClientId).then((session)=> {
draftHtml = QuotedHTMLParser.appendQuotedHTML(body, session.draft().body);
session.changes.add({body: draftHtml});
});
});
}
getTemplateContents(templateId, callback) {
let template = null;
this._items.forEach((item) => {
if (item.id === templateId) { template = item; }
});
if (!template) { return undefined }
fs.readFile(template.path, (err, data)=> {
const body = data.toString();
callback(body);
});
}
}
module.exports = new TemplateStore();