refactor
gitea/salix/1466-print_refactor This commit looks good
Details
|
@ -18,6 +18,7 @@ export default class Controller {
|
|||
this.$.balanceCreateDialog.show();
|
||||
}, name: 'Payment on account...', always: true}
|
||||
];
|
||||
console.log(this.$stateParams);
|
||||
}
|
||||
|
||||
setBalanceCreateDialog() {
|
||||
|
|
|
@ -4769,7 +4769,7 @@
|
|||
"dot-prop": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
|
||||
"integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
|
||||
"integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=",
|
||||
"requires": {
|
||||
"is-obj": "^1.0.0"
|
||||
}
|
||||
|
@ -4937,7 +4937,7 @@
|
|||
},
|
||||
"jsonfile": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
|
||||
"integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
@ -7485,7 +7485,7 @@
|
|||
},
|
||||
"kind-of": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
|
||||
"integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -9120,7 +9120,7 @@
|
|||
},
|
||||
"jasmine-core": {
|
||||
"version": "2.99.1",
|
||||
"resolved": "http://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
|
||||
"integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -11194,7 +11194,7 @@
|
|||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "http://registry.npmjs.org/commander/-/commander-1.0.4.tgz",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-1.0.4.tgz",
|
||||
"integrity": "sha1-Xt6xruI8T7VBprcNaSq+8ZZpotM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
@ -13041,7 +13041,7 @@
|
|||
},
|
||||
"readable-stream": {
|
||||
"version": "1.1.14",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
@ -13053,7 +13053,7 @@
|
|||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -13500,7 +13500,7 @@
|
|||
"dependencies": {
|
||||
"jsesc": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
|
||||
"integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
|
||||
"dev": true
|
||||
}
|
||||
|
@ -14321,7 +14321,7 @@
|
|||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
@ -15885,7 +15885,7 @@
|
|||
"touch": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
|
||||
"integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
|
||||
"integrity": "sha1-/jZfX3XsntTlaCXgu3bSSrdK+Ds=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"nopt": "~1.0.10"
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/**
|
||||
* Email only stylesheet
|
||||
*
|
||||
*/
|
||||
body {
|
||||
background-color: #EEE
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/**
|
||||
* CSS layout elements
|
||||
*
|
||||
*/
|
||||
.container {
|
||||
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
|
||||
font-size: 16px
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/**
|
||||
* CSS misc classes
|
||||
*
|
||||
*/
|
||||
.uppercase {
|
||||
text-transform: uppercase
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/**
|
||||
* Report only stylesheet
|
||||
*
|
||||
*/
|
||||
body {
|
||||
zoom: 0.55
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
[
|
||||
{"type": "email", "name": "client-welcome"},
|
||||
{"type": "email", "name": "printer-setup"},
|
||||
{"type": "email", "name": "payment-update"},
|
||||
{"type": "email", "name": "letter-debtor-st"},
|
||||
{"type": "email", "name": "letter-debtor-nd"},
|
||||
{"type": "email", "name": "claim-pickup-order"},
|
||||
{"type": "email", "name": "sepa-core"},
|
||||
{"type": "email", "name": "client-lcr"},
|
||||
{"type": "email", "name": "driver-route"},
|
||||
{"type": "email", "name": "delivery-note"},
|
||||
{"type": "report", "name": "rpt-delivery-note"},
|
||||
{"type": "report", "name": "rpt-claim-pickup-order"},
|
||||
{"type": "report", "name": "rpt-letter-debtor"},
|
||||
{"type": "report", "name": "rpt-sepa-core"},
|
||||
{"type": "report", "name": "rpt-receipt"},
|
||||
{"type": "report", "name": "rpt-zone"},
|
||||
{"type": "report", "name": "rpt-route"},
|
||||
{"type": "report", "name": "rpt-lcr"},
|
||||
{"type": "report", "name": "rpt-item-label"},
|
||||
{"type": "static", "name": "email-header"},
|
||||
{"type": "static", "name": "email-footer"},
|
||||
{"type": "static", "name": "report-header"},
|
||||
{"type": "static", "name": "report-footer"}
|
||||
]
|
|
@ -0,0 +1,103 @@
|
|||
const Vue = require('vue');
|
||||
const VueI18n = require('vue-i18n');
|
||||
const renderer = require('vue-server-renderer').createRenderer();
|
||||
Vue.use(VueI18n);
|
||||
|
||||
const fs = require('fs');
|
||||
const yaml = require('js-yaml');
|
||||
const juice = require('juice');
|
||||
const path = require('path');
|
||||
|
||||
const config = require('./config');
|
||||
|
||||
class Component {
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
get path() {
|
||||
return `./components/${this.name}`;
|
||||
}
|
||||
|
||||
get template() {
|
||||
const templatePath = `${this.path}/${this.name}.html`;
|
||||
const fullPath = path.resolve(__dirname, templatePath);
|
||||
|
||||
return fs.readFileSync(fullPath, 'utf8');
|
||||
}
|
||||
|
||||
get locale() {
|
||||
const mergedLocale = {messages: {}};
|
||||
const localePath = path.resolve(__dirname, `${this.path}/locale`);
|
||||
|
||||
if (!fs.existsSync(localePath))
|
||||
return mergedLocale;
|
||||
|
||||
const localeDir = fs.readdirSync(localePath);
|
||||
localeDir.forEach(locale => {
|
||||
const fullPath = path.join(localePath, '/', locale);
|
||||
const yamlLocale = fs.readFileSync(fullPath, 'utf8');
|
||||
const jsonLocale = yaml.safeLoad(yamlLocale);
|
||||
const localeName = locale.replace('.yml', '');
|
||||
|
||||
mergedLocale.messages[localeName] = jsonLocale;
|
||||
});
|
||||
|
||||
return mergedLocale;
|
||||
}
|
||||
|
||||
get stylesheet() {
|
||||
let mergedStyles = '';
|
||||
const stylePath = path.resolve(__dirname, `${this.path}/assets/css`);
|
||||
|
||||
if (!fs.existsSync(stylePath))
|
||||
return mergedStyles;
|
||||
|
||||
const styleDir = fs.readdirSync(stylePath);
|
||||
styleDir.forEach(fileName => {
|
||||
const fullPath = path.join(stylePath, '/', fileName);
|
||||
const contents = fs.readFileSync(fullPath, 'utf8');
|
||||
|
||||
mergedStyles += contents;
|
||||
});
|
||||
|
||||
return mergedStyles;
|
||||
}
|
||||
|
||||
get attachments() {
|
||||
const attachmentsPath = `${this.path}/attachments.json`;
|
||||
const fullPath = path.resolve(__dirname, attachmentsPath);
|
||||
|
||||
if (!fs.existsSync(fullPath))
|
||||
return [];
|
||||
|
||||
return require(fullPath);
|
||||
}
|
||||
|
||||
build() {
|
||||
const component = require(`${this.path}/${this.name}`);
|
||||
|
||||
component.i18n = this.locale;
|
||||
component.attachments = this.attachments;
|
||||
component.template = juice.inlineContent(this.template, this.stylesheet, {
|
||||
inlinePseudoElements: true
|
||||
});
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
async render() {
|
||||
const component = this.build();
|
||||
const i18n = new VueI18n(config.i18n);
|
||||
const app = new Vue({
|
||||
i18n: i18n,
|
||||
render: h => h(component, {
|
||||
props: this.args
|
||||
})
|
||||
});
|
||||
|
||||
return renderer.renderToString(app);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Component;
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
@ -0,0 +1,27 @@
|
|||
[
|
||||
{
|
||||
"filename": "facebook.png",
|
||||
"path": "/assets/images/facebook.png",
|
||||
"cid": "facebook.png"
|
||||
}, {
|
||||
"filename": "twitter.png",
|
||||
"path": "/assets/images/twitter.png",
|
||||
"cid": "twitter.png"
|
||||
}, {
|
||||
"filename": "youtube.png",
|
||||
"path": "/assets/images/youtube.png",
|
||||
"cid": "youtube.png"
|
||||
}, {
|
||||
"filename": "pinterest.png",
|
||||
"path": "/assets/images/pinterest.png",
|
||||
"cid": "pinterest.png"
|
||||
}, {
|
||||
"filename": "instagram.png",
|
||||
"path": "/assets/images/instagram.png",
|
||||
"cid": "instagram.png"
|
||||
}, {
|
||||
"filename": "linkedin.png",
|
||||
"path": "/assets/images/linkedin.png",
|
||||
"cid": "linkedin.png"
|
||||
}
|
||||
]
|
|
@ -4,13 +4,13 @@
|
|||
<a href="https://www.verdnatura.es" target="_blank">
|
||||
<div class="btn">
|
||||
<span class="text">{{ $t('buttons.webAcccess')}}</span>
|
||||
<span class="icon"><img :src="embeded['/assets/images/action.png']"/></span>
|
||||
<span class="icon"><img :src="/assets/images/action.png"/></span>
|
||||
</div>
|
||||
</a>
|
||||
<a href="https://goo.gl/forms/j8WSL151ZW6QtlT72" target="_blank">
|
||||
<div class="btn">
|
||||
<span class="text">{{ $t('buttons.info')}}</span>
|
||||
<span class="icon"><img :src="embeded['/assets/images/info.png']"/></span>
|
||||
<span class="icon"><img :src="/assets/images/info.png"/></span>
|
||||
</div>
|
||||
</a>
|
||||
</section> -->
|
||||
|
@ -19,22 +19,22 @@
|
|||
<!-- Networks block -->
|
||||
<section class="networks">
|
||||
<a href="https://www.facebook.com/Verdnatura" target="_blank">
|
||||
<img :src="embeded['/assets/images/facebook.png']" alt="Facebook"/>
|
||||
<img :src="getSrc('facebook.png')" alt="Facebook"/>
|
||||
</a>
|
||||
<a href="https://www.twitter.com/Verdnatura" target="_blank">
|
||||
<img :src="embeded['/assets/images/twitter.png']" alt="Twitter"/>
|
||||
<img :src="getSrc('twitter.png')" alt="Twitter"/>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/Verdnatura" target="_blank">
|
||||
<img :src="embeded['/assets/images/youtube.png']" alt="Youtube"/>
|
||||
<img :src="getSrc('youtube.png')" alt="Youtube"/>
|
||||
</a>
|
||||
<a href="https://www.pinterest.com/Verdnatura" target="_blank">
|
||||
<img :src="embeded['/assets/images/pinterest.png']" alt="Pinterest"/>
|
||||
<img :src="getSrc('pinterest.png')" alt="Pinterest"/>
|
||||
</a>
|
||||
<a href="https://www.instagram.com/Verdnatura" target="_blank">
|
||||
<img :src="embeded['/assets/images/instagram.png']" alt="Instagram"/>
|
||||
<img :src="getSrc('instagram.png')" alt="Instagram"/>
|
||||
</a>
|
||||
<a href="https://www.linkedin.com/company/verdnatura" target="_blank">
|
||||
<img :src="embeded['/assets/images/linkedin.png']" alt="Linkedin"/>
|
||||
<img :src="getSrc('linkedin.png')" alt="Linkedin"/>
|
||||
</a>
|
||||
</section>
|
||||
<!-- Networks block end -->
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
name: 'email-footer',
|
||||
props: ['isPreview', 'locale']
|
||||
};
|
|
@ -0,0 +1,19 @@
|
|||
buttons:
|
||||
webAcccess: Visita nuestra Web
|
||||
info: Ayúdanos a mejorar
|
||||
privacy:
|
||||
fiscalAddress: VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla
|
||||
· www.verdnatura.es · clientes@verdnatura.es
|
||||
disclaimer: '- AVISO - Este mensaje es privado y confidencial, y debe ser utilizado
|
||||
exclusivamente por la persona destinataria del mismo. Si has recibido este mensaje
|
||||
por error, te rogamos lo comuniques al remitente y borres dicho mensaje y cualquier
|
||||
documento adjunto que pudiera contener. Verdnatura Levante SL no renuncia a la
|
||||
confidencialidad ni a ningún privilegio por causa de transmisión errónea o mal
|
||||
funcionamiento. Igualmente no se hace responsable de los cambios, alteraciones,
|
||||
errores u omisiones que pudieran hacerse al mensaje una vez enviado.'
|
||||
law: En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de
|
||||
Datos de Carácter Personal, te comunicamos que los datos personales que facilites
|
||||
se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L., pudiendo en
|
||||
todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición,
|
||||
comunicándolo por escrito al domicilio social de la entidad. La finalidad del
|
||||
fichero es la gestión administrativa, contabilidad, y facturación.
|
|
@ -0,0 +1,19 @@
|
|||
buttons:
|
||||
webAcccess: Visitez notre site web
|
||||
info: Ayúdanos a mejorar
|
||||
privacy:
|
||||
fiscalAddress: VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla
|
||||
· www.verdnatura.es · clientes@verdnatura.es
|
||||
disclaimer: '- AVISO - Ce message est privé et confidentiel et doit être utilisé.exclusivamente
|
||||
por la persona destinataria del mismo. Si has recibido este mensajepor error,
|
||||
te rogamos lo comuniques al remitente y borres dicho mensaje y cualquier documentoadjunto
|
||||
que pudiera contener. Verdnatura Levante SL no renuncia a la confidencialidad
|
||||
ni aningún privilegio por causa de transmisión errónea o mal funcionamiento. Igualmente
|
||||
no se haceresponsable de los cambios, alteraciones, errores u omisiones que pudieran
|
||||
hacerse al mensaje una vez enviado.'
|
||||
law: En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de
|
||||
Datos de Carácter Personal,te comunicamos que los datos personales que facilites
|
||||
se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L.,pudiendo en
|
||||
todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición,
|
||||
comunicándolo porescrito al domicilio social de la entidad. La finalidad del fichero
|
||||
es la gestión administrativa, contabilidad, y facturación.
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
@ -0,0 +1,7 @@
|
|||
[
|
||||
{
|
||||
"filename": "email-logo.png",
|
||||
"path": "/assets/images/email-logo.png",
|
||||
"cid": "email-logo.png"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,5 @@
|
|||
<header>
|
||||
<a href="https://www.verdnatura.es" target="_blank">
|
||||
<img :src="getSrc('email-logo.png')" alt="VerdNatura"/>
|
||||
</a>
|
||||
</header>
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
name: 'email-header',
|
||||
props: ['isPreview']
|
||||
};
|
|
@ -0,0 +1,10 @@
|
|||
numPages: Página {{page}} de {{pages}}
|
||||
law:
|
||||
phytosanitary: 'VERDNATURA LEVANTE SL - Pasaporte Fitosanitario R.P. Generalitat
|
||||
Valenciana - Nº Comerciante: ES17462130'
|
||||
privacy: En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección
|
||||
de Datos de Carácter Personal, le comunicamos que los datos personales que facilite
|
||||
se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L., pudiendo en
|
||||
todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición,
|
||||
comunicándolo por escrito al domicilio social de la entidad. La finalidad del
|
||||
fichero es la gestión administrativa, contabilidad, y facturación.
|
|
@ -0,0 +1,10 @@
|
|||
numPages: Page {{page}} de {{pages}}
|
||||
law:
|
||||
phytosanitary: 'VERDNATURA LEVANTE SL - Passeport Phytosanitaire R.P. Generalitat
|
||||
Valenciana - Numéro d''opérateur: ES17462130'
|
||||
privacy: Conformément aux dispositions de la loi organique 15/1999 sur la protection
|
||||
des données personnelles, nous vous informons que les données personnelles que
|
||||
vous fournissez seront incluses dans des dossiers. VERDNATURA LEVANTE S.L., vous
|
||||
pouvez à tout moment, exercer les droits d'accès, de rectification, d'annulation
|
||||
et d'opposition, en communiquant par écrit au siège social de la société. Le dossier
|
||||
a pour objet la gestion administrative, la comptabilité et la facturation.
|
|
@ -0,0 +1,10 @@
|
|||
numPages: Página {{page}} de {{pages}}
|
||||
law:
|
||||
phytosanitary: 'VERDNATURA LEVANTE S.L - Passaporte Fitossanitário R.P. Generalitat
|
||||
Valenciana - Nº Comerciante: ES17462130'
|
||||
privacy: Em cumprimento do disposto na lei Orgânica 15/1999, de Protecção de Dados
|
||||
de Carácter Pessoal, comunicamos que os dados pessoais que facilite se incluirão
|
||||
nos ficheiros automatizados de VERDNATURA LEVANTE S.L., podendo em todo momento
|
||||
exercer os direitos de acesso, rectificação, cancelação e oposição, comunicando
|
||||
por escrito ao domicílio social da entidade. A finalidade do ficheiro é a gestão
|
||||
administrativa, contabilidade e facturação.
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
|
@ -0,0 +1,5 @@
|
|||
company:
|
||||
fiscalAddress: VERDNATURA LEVANTE S.L., B97367486 Avda. Espioca, 100, 46460 Silla
|
||||
- www.verdnatura.es - clientes@verdnatura.es
|
||||
registry: 'CIF: B97367486 Registro Mercantil de Valencia, Tomo 8041, Libro 5334,
|
||||
Folio 160, Sección 8, Hoja V 102076'
|
|
@ -0,0 +1,5 @@
|
|||
company:
|
||||
fiscalAddress: VERDNATURA LEVANTE S.L., B97367486 Avda. Espioca, 100, 46460 Silla
|
||||
- www.verdnatura.es - clientes@verdnatura.es
|
||||
registry: 'CIF: B97367486 Registro Mercantil de Valencia, Tomo 8041, Libro 5334,
|
||||
Folio 160, Sección 8, Hoja V 102076'
|
|
@ -0,0 +1 @@
|
|||
// Import global directives
|
|
@ -1,26 +1,92 @@
|
|||
const Vue = require('vue');
|
||||
const VueI18n = require('vue-i18n');
|
||||
const renderer = require('vue-server-renderer').createRenderer();
|
||||
const fs = require('fs-extra');
|
||||
const juice = require('juice');
|
||||
const path = require('path');
|
||||
const smtp = require('./smtp');
|
||||
const fallbackLocale = 'es';
|
||||
const Component = require('./component');
|
||||
const Report = require('./report');
|
||||
|
||||
if (!process.env.OPENSSL_CONF)
|
||||
process.env.OPENSSL_CONF = '/etc/ssl/';
|
||||
|
||||
Vue.use(VueI18n);
|
||||
class Email extends Component {
|
||||
constructor(name, args) {
|
||||
super(name);
|
||||
|
||||
module.exports = {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
get path() {
|
||||
return `../templates/email/${this.name}`;
|
||||
}
|
||||
|
||||
|
||||
get subject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
async send() {
|
||||
const instance = this.build();
|
||||
const rendered = await this.render();
|
||||
const attachments = [];
|
||||
const getAttachments = async(componentPath, files) => {
|
||||
for (file of files) {
|
||||
const fileCopy = Object.assign({}, file);
|
||||
if (fileCopy.cid) {
|
||||
const templatePath = `${componentPath}/${file.path}`;
|
||||
const fullFilePath = path.resolve(__dirname, templatePath);
|
||||
|
||||
fileCopy.path = path.resolve(__dirname, fullFilePath);
|
||||
} else {
|
||||
const reportName = fileCopy.filename.replace('.pdf', '');
|
||||
const report = new Report(reportName, this.args);
|
||||
fileCopy.content = await report.toPdfStream();
|
||||
}
|
||||
|
||||
attachments.push(fileCopy);
|
||||
}
|
||||
};
|
||||
|
||||
if (instance.components) {
|
||||
const components = instance.components;
|
||||
for (let componentName in components) {
|
||||
const component = components[componentName];
|
||||
const componentPath = `../components/${componentName}`;
|
||||
await getAttachments(componentPath, component.attachments);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (this.attachments)
|
||||
await getAttachments(this.path, this.attachments);
|
||||
/*
|
||||
this.attachments.forEach(file => {
|
||||
const fileCopy = Object.assign({}, file);
|
||||
if (fileCopy.path) {
|
||||
const templatePath = `${this.path}/${file.path}`;
|
||||
const fullFilePath = path.resolve(__dirname, templatePath);
|
||||
|
||||
fileCopy.path = path.resolve(__dirname, fullFilePath);
|
||||
}
|
||||
|
||||
attachments.push(fileCopy);
|
||||
}); */
|
||||
|
||||
const options = {
|
||||
to: this.args.recipient,
|
||||
subject: 'Test',
|
||||
html: rendered,
|
||||
attachments: attachments
|
||||
};
|
||||
|
||||
return smtp.send(options);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Email;
|
||||
|
||||
|
||||
/* module.exports = {
|
||||
|
||||
path: `${appPath}/report`,
|
||||
|
||||
/**
|
||||
* Renders a report component
|
||||
*
|
||||
* @param {String} name - Report name
|
||||
* @param {Object} ctx - Request context
|
||||
*/
|
||||
async render(name, ctx) {
|
||||
const component = require(`${this.path}/${name}`);
|
||||
const result = await this.preFetch(component, ctx);
|
||||
|
@ -39,12 +105,6 @@ module.exports = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Prefetch all component data from asyncData method
|
||||
*
|
||||
* @param {Object} orgComponent - Component object
|
||||
* @param {Object} ctx - Request context
|
||||
*/
|
||||
async preFetch(orgComponent, ctx) {
|
||||
let component = Object.create(orgComponent);
|
||||
let mergedData = {attachments: []};
|
||||
|
@ -150,3 +210,4 @@ module.exports = {
|
|||
return smtp.send(options);
|
||||
},
|
||||
};
|
||||
*/
|
|
@ -0,0 +1,7 @@
|
|||
const Vue = require('vue');
|
||||
const currency = {
|
||||
methods: {
|
||||
},
|
||||
};
|
||||
|
||||
Vue.mixin(currency);
|
|
@ -0,0 +1 @@
|
|||
// Import global filters
|
|
@ -0,0 +1,15 @@
|
|||
const Vue = require('vue');
|
||||
const imageSrc = {
|
||||
methods: {
|
||||
getSrc(image) {
|
||||
let src = `cid:${image}`;
|
||||
|
||||
if (this.isPreview === 'true')
|
||||
src = `/api/assets/${this.$options.name}/images/${image}`;
|
||||
|
||||
return src;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Vue.mixin(imageSrc);
|
|
@ -0,0 +1,2 @@
|
|||
// Import global mixins
|
||||
require('./image-src');
|
|
@ -1,66 +1,20 @@
|
|||
const Vue = require('vue');
|
||||
const VueI18n = require('vue-i18n');
|
||||
const renderer = require('vue-server-renderer').createRenderer();
|
||||
|
||||
const fs = require('fs');
|
||||
const pdf = require('html-pdf');
|
||||
const juice = require('juice');
|
||||
const path = require('path');
|
||||
|
||||
const config = require('./config');
|
||||
const reportsPath = '../templates/reports';
|
||||
const Component = require('./component');
|
||||
|
||||
if (!process.env.OPENSSL_CONF)
|
||||
process.env.OPENSSL_CONF = '/etc/ssl/';
|
||||
|
||||
Vue.use(VueI18n);
|
||||
|
||||
class Report {
|
||||
class Report extends Component {
|
||||
constructor(name, args) {
|
||||
this.name = name;
|
||||
super(name);
|
||||
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
get path() {
|
||||
return `${reportsPath}/${this.name}`;
|
||||
}
|
||||
|
||||
get template() {
|
||||
const templatePath = `${this.path}/${this.name}.html`;
|
||||
const fullPath = path.resolve(__dirname, templatePath);
|
||||
|
||||
return fs.readFileSync(fullPath, 'utf8');
|
||||
}
|
||||
|
||||
get locale() {
|
||||
|
||||
}
|
||||
|
||||
get style() {
|
||||
|
||||
}
|
||||
|
||||
async render() {
|
||||
const localePath = `${this.path}/locale`;
|
||||
const stylePath = `${this.path}/assets/css/index`;
|
||||
|
||||
const stylesheet = require(stylePath);
|
||||
const component = require(this.path);
|
||||
|
||||
component.i18n = require(localePath);
|
||||
component.template = juice.inlineContent(this.template, stylesheet, {
|
||||
inlinePseudoElements: true
|
||||
});
|
||||
|
||||
const i18n = new VueI18n(config.i18n);
|
||||
const app = new Vue({
|
||||
i18n: i18n,
|
||||
render: h => h(component, {
|
||||
props: this.args
|
||||
})
|
||||
});
|
||||
|
||||
return renderer.renderToString(app);
|
||||
return `../templates/reports/${this.name}`;
|
||||
}
|
||||
|
||||
async toPdfStream() {
|
|
@ -1,13 +1,25 @@
|
|||
const Report = require('./report');
|
||||
const emailEngine = require('./emailEngine');
|
||||
const express = require('express');
|
||||
const path = require('path');
|
||||
const vue = require('vue');
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const Report = require('./report');
|
||||
const Email = require('./email');
|
||||
|
||||
const templatesPath = path.resolve(__dirname, '../templates');
|
||||
const componentsPath = path.resolve(__dirname, './components');
|
||||
|
||||
module.exports = app => {
|
||||
/**
|
||||
* Serve component static files
|
||||
*/
|
||||
const componentsDir = fs.readdirSync(componentsPath);
|
||||
componentsDir.forEach(componentName => {
|
||||
const componentDir = path.join(componentsPath, '/', componentName);
|
||||
const assetsDir = `${componentDir}/assets`;
|
||||
|
||||
app.use(`/api/assets/${componentName}`, express.static(assetsDir));
|
||||
});
|
||||
|
||||
/**
|
||||
* Serve static files
|
||||
*/
|
||||
|
@ -20,7 +32,7 @@ module.exports = app => {
|
|||
const templateDir = path.join(templatesPath, '/', directory, '/', templateName);
|
||||
const assetsDir = `${templateDir}/assets`;
|
||||
|
||||
app.use(`/api/assets`, express.static(assetsDir));
|
||||
app.use(`/api/assets/${templateName}`, express.static(assetsDir));
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -28,19 +40,34 @@ module.exports = app => {
|
|||
const args = Object.assign({}, req.body, req.query);
|
||||
const report = new Report(req.params.name, args);
|
||||
const stream = await report.toPdfStream();
|
||||
|
||||
res.setHeader('Content-type', 'application/pdf');
|
||||
stream.pipe(res);
|
||||
});
|
||||
|
||||
/* app.get(`/api/email/${name}`, (request, response) => {
|
||||
emailEngine.render(name, request).then(rendered => {
|
||||
response.send(rendered.html);
|
||||
}).catch(e => {
|
||||
next(e);
|
||||
app.get(`/api/email/:name`, async(req, res) => {
|
||||
const args = req.query;
|
||||
const requiredArgs = ['userId'];
|
||||
|
||||
const hasRequiredArgs = requiredArgs.every(arg => {
|
||||
return args[arg];
|
||||
});
|
||||
|
||||
if (!hasRequiredArgs)
|
||||
res.json({message: 'userId'});
|
||||
|
||||
const email = new Email(req.params.name, args);
|
||||
if (args.isPreview === 'true') {
|
||||
const rendered = await email.render();
|
||||
|
||||
res.send(rendered);
|
||||
} else {
|
||||
await email.send();
|
||||
res.status(200).json({message: 'Sent'});
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
|
||||
app.post(`/api/email/${name}`, (request, response, next) => {
|
||||
emailEngine.toEmail(name, request).then(() => {
|
||||
response.status(200).json({status: 200});
|
|
@ -1,5 +1,5 @@
|
|||
const nodemailer = require('nodemailer');
|
||||
const config = require('./config.js');
|
||||
const config = require('./config');
|
||||
|
||||
module.exports = {
|
||||
init() {
|
||||
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
options.from = `${config.app.senderName} <${config.app.senderMail}>`;
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (!config.smtp.user)
|
||||
if (!config.smtp.auth.user)
|
||||
return Promise.resolve(true);
|
||||
|
||||
options.to = config.app.senderMail;
|
|
@ -1,7 +0,0 @@
|
|||
module.exports = {
|
||||
methods: {
|
||||
uFirst: (text) => {
|
||||
return text;
|
||||
},
|
||||
},
|
||||
};
|
|
@ -25,6 +25,14 @@
|
|||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
|
||||
},
|
||||
"argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
|
@ -309,6 +317,11 @@
|
|||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
|
@ -519,6 +532,15 @@
|
|||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
|
@ -997,6 +1019,11 @@
|
|||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
|
||||
"integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"sqlstring": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"dependencies": {
|
||||
"fs-extra": "^7.0.1",
|
||||
"html-pdf": "^2.2.0",
|
||||
"js-yaml": "^3.13.1",
|
||||
"juice": "^5.0.1",
|
||||
"mysql2": "^1.6.5",
|
||||
"nodemailer": "^4.7.0",
|
||||
|
|
|
@ -4,11 +4,16 @@ module.exports = app => {
|
|||
process.env.OPENSSL_CONF = '/etc/ssl/';
|
||||
|
||||
// Init database instance
|
||||
require('./lib/database').init();
|
||||
require('./core/database').init();
|
||||
// Init SMTP Instance
|
||||
require('./lib/smtp').init();
|
||||
require('./core/smtp').init();
|
||||
|
||||
require('./lib/router')(app);
|
||||
require('./core/router')(app);
|
||||
|
||||
require('./core/mixins');
|
||||
require('./core/filters');
|
||||
require('./core/directives');
|
||||
// require('./core/components/email-header/email-header');
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Email only stylesheet
|
||||
*
|
||||
*/
|
||||
body {
|
||||
background-color: #EEE
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 600px;
|
||||
min-width: 320px;
|
||||
margin: 0 auto;
|
||||
color: #555
|
||||
}
|
||||
|
||||
.main {
|
||||
background-color: #FFF;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.main a {
|
||||
color: #8dba25
|
||||
}
|
||||
|
||||
.main h1 {
|
||||
color: #999
|
||||
}
|
||||
|
||||
.main h3 {
|
||||
font-size: 16px
|
||||
}
|
||||
|
||||
.title {
|
||||
background-color: #95d831;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
padding: 35px 0
|
||||
}
|
||||
|
||||
.title h1 {
|
||||
font-size: 32px;
|
||||
color: #333;
|
||||
margin: 0
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
const CssReader = require(`${appPath}/lib/cssReader`);
|
||||
|
||||
module.exports = new CssReader([
|
||||
`${appPath}/common/css/layout.css`,
|
||||
`${appPath}/common/css/email.css`,
|
||||
`${appPath}/common/css/misc.css`])
|
||||
.mergeStyles();
|
|
@ -0,0 +1,233 @@
|
|||
/**
|
||||
* CSS layout elements
|
||||
*
|
||||
*/
|
||||
.container {
|
||||
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
|
||||
font-size: 16px
|
||||
}
|
||||
|
||||
.columns {
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.columns .size100 {
|
||||
width: 100%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size75 {
|
||||
width: 75%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size50 {
|
||||
width: 50%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size33 {
|
||||
width: 33.33%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size25 {
|
||||
width: 25%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.clearfix {
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
clear: both
|
||||
}
|
||||
|
||||
.panel {
|
||||
position: relative;
|
||||
margin-bottom: 15px;
|
||||
padding-top: 10px;
|
||||
break-inside: avoid;
|
||||
break-before: always;
|
||||
break-after: always;
|
||||
}
|
||||
|
||||
.panel .header {
|
||||
background-color: #FFF;
|
||||
padding: 2.5px 10px;
|
||||
position: absolute;
|
||||
font-weight: bold;
|
||||
top: 0px;
|
||||
left: 17.5px;
|
||||
}
|
||||
|
||||
.panel .body {
|
||||
border: 1px solid #CCC;
|
||||
overflow: hidden;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.panel .body h3 {
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
.panel.dark .header {
|
||||
border: 1px solid #808080;
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
.panel.dark .body {
|
||||
border: 1px solid #808080;
|
||||
background-color: #c0c0c0
|
||||
}
|
||||
|
||||
.field {
|
||||
border-bottom: 1px solid #CCC;
|
||||
border-left: 1px solid #CCC;
|
||||
border-top: 1px solid #CCC;
|
||||
float: left
|
||||
}
|
||||
|
||||
.field span {
|
||||
border-right: 1px solid #CCC;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.field.square span {
|
||||
height: 35.4px;
|
||||
width: 35.4px
|
||||
}
|
||||
|
||||
.emptyField {
|
||||
border-bottom: 1px dotted grey;
|
||||
min-height: 1em;
|
||||
display: block
|
||||
}
|
||||
|
||||
.field.rectangle span {
|
||||
height: 2em;
|
||||
width: 8em
|
||||
}
|
||||
|
||||
.pull-left {
|
||||
float: left !important
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right !important
|
||||
}
|
||||
|
||||
.vertical-text {
|
||||
-moz-transform: rotate(90deg);
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
font-size: .65em;
|
||||
right: -108px;
|
||||
width: 200px;
|
||||
top: 50%
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.row-oriented, .column-oriented {
|
||||
text-align: left;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.column-oriented {
|
||||
margin-bottom: 15px
|
||||
}
|
||||
|
||||
.column-oriented td,
|
||||
.column-oriented th {
|
||||
padding: 5px 10px
|
||||
}
|
||||
|
||||
.column-oriented thead {
|
||||
background-color: #e5e5e5
|
||||
}
|
||||
|
||||
.column-oriented thead tr {
|
||||
border-bottom: 1px solid #808080;
|
||||
border-top: 1px solid #808080;
|
||||
background-color: #e5e5e5
|
||||
}
|
||||
|
||||
.column-oriented tfoot {
|
||||
border-top: 2px solid #808080;
|
||||
}
|
||||
|
||||
.column-oriented tfoot tr:first-child td {
|
||||
padding-top: 20px !important;
|
||||
}
|
||||
|
||||
.column-oriented .description {
|
||||
border-bottom: 1px solid #DDD;
|
||||
font-size: 0.8em
|
||||
}
|
||||
|
||||
.panel .row-oriented td, .panel .row-oriented th {
|
||||
padding: 10px 0
|
||||
}
|
||||
|
||||
.row-oriented > tbody > tr > td {
|
||||
width: 30%
|
||||
}
|
||||
|
||||
.row-oriented > tbody > tr > th {
|
||||
padding-left: 30px;
|
||||
width: 70%
|
||||
}
|
||||
|
||||
.row-oriented .description {
|
||||
padding: 0 !important;
|
||||
font-size: 0.6em;
|
||||
color: #888
|
||||
}
|
||||
|
||||
.line {
|
||||
border-bottom: 1px solid #DDD;
|
||||
border-right: 1px solid #DDD;
|
||||
border-left: 1px solid #DDD;
|
||||
position: relative;
|
||||
margin-left: -1px;
|
||||
margin-right: 1px;
|
||||
margin-top: 10px;
|
||||
color: #999;
|
||||
padding: 5px 0
|
||||
}
|
||||
|
||||
.line .vertical-aligned {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
.line span {
|
||||
background-color: #FFF;
|
||||
padding: 5px
|
||||
}
|
||||
|
||||
.signature {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.signature section {
|
||||
height: 150px
|
||||
}
|
||||
|
||||
.signature p {
|
||||
margin-right: 50%;
|
||||
margin-top: 140px
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* CSS misc classes
|
||||
*
|
||||
*/
|
||||
.uppercase {
|
||||
text-transform: uppercase
|
||||
}
|
||||
|
||||
.justified {
|
||||
text-align: justify
|
||||
}
|
||||
|
||||
.centered {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left
|
||||
}
|
||||
|
||||
.number {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.font.gray {
|
||||
color: #555
|
||||
}
|
||||
|
||||
.font.light-gray {
|
||||
color: #888
|
||||
}
|
||||
|
||||
.font.small {
|
||||
font-size: 0.65em
|
||||
}
|
||||
|
||||
.font.bold {
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.non-page-break {
|
||||
page-break-inside: avoid;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
[{
|
||||
"filename": "claim-pickup-order.pdf"
|
||||
}]
|
|
@ -6,7 +6,7 @@
|
|||
<body>
|
||||
<section class="container">
|
||||
<!-- Header component -->
|
||||
<email-header></email-header>
|
||||
<email-header :is-preview="isPreview"></email-header>
|
||||
<!-- End header component -->
|
||||
<section class="main">
|
||||
<!-- Title block -->
|
||||
|
@ -15,6 +15,8 @@
|
|||
</div>
|
||||
<!-- Title block end -->
|
||||
|
||||
{{$t('testing')}}
|
||||
|
||||
<p>{{$t('description.dear')}},</p>
|
||||
<p>{{$t('description.instructions')}}</p>
|
||||
|
||||
|
@ -27,9 +29,14 @@
|
|||
</ol>
|
||||
<p>{{$t('sections.howToBuy.stock')}}</p>
|
||||
<p>{{$t('sections.howToBuy.delivery')}}</p> -->
|
||||
<section>
|
||||
<section v-for="attachment in attachments">
|
||||
<a href="/api/report/claim-pickup-order?userId=106&claimId=5" target="_blank">Ver PDF</a>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<!-- Footer component -->
|
||||
<email-footer :locale="locale"></email-footer>
|
||||
<email-footer :is-preview="isPreview" :locale="locale"></email-footer>
|
||||
<!-- End footer component -->
|
||||
</section>
|
||||
</body>
|
|
@ -0,0 +1,39 @@
|
|||
const db = require(`${appPath}/core/database`);
|
||||
const Component = require(`${appPath}/core/component`);
|
||||
const emailHeader = new Component('email-header');
|
||||
const emailFooter = new Component('email-footer');
|
||||
const attachments = require('./attachments.json');
|
||||
|
||||
module.exports = {
|
||||
name: 'claim-pickup-order',
|
||||
/* async serverPrefetch() {
|
||||
this.client = await this.fetchClient(this.clientId);
|
||||
},*/
|
||||
created() {
|
||||
if (this.locale)
|
||||
this.$i18n.locale = this.locale;
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
attachments
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
fetchClient(claimId) {
|
||||
return db.findOne(`
|
||||
SELECT
|
||||
c.id,
|
||||
u.lang locale,
|
||||
c.email recipient
|
||||
FROM claim cl
|
||||
JOIN client c ON c.id = cl.clientFk
|
||||
JOIN account.user u ON u.id = c.id
|
||||
WHERE cl.id = ?`, [claimId]);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
'email-header': emailHeader.build(),
|
||||
'email-footer': emailFooter.build()
|
||||
},
|
||||
props: ['claimId', 'isPreview']
|
||||
};
|
|
@ -1,53 +0,0 @@
|
|||
const UserException = require(`${appPath}/lib/exceptions/userException`);
|
||||
const reportEngine = require(`${appPath}/lib/reportEngine`);
|
||||
const database = require(`${appPath}/lib/database`);
|
||||
const emailHeader = require('../email-header');
|
||||
const emailFooter = require('../email-footer');
|
||||
|
||||
|
||||
module.exports = {
|
||||
name: 'claim-pickup-order',
|
||||
async asyncData(ctx, params) {
|
||||
const promises = [];
|
||||
const data = {
|
||||
isPreview: ctx.method === 'GET',
|
||||
};
|
||||
|
||||
if (!params.claimFk)
|
||||
throw new UserException('No claim id specified');
|
||||
|
||||
promises.push(reportEngine.toPdf('rpt-claim-pickup-order', ctx));
|
||||
promises.push(this.methods.fetchClient(params.claimFk));
|
||||
|
||||
return Promise.all(promises).then(result => {
|
||||
const stream = result[0];
|
||||
const [[client]] = result[1];
|
||||
|
||||
Object.assign(data, client);
|
||||
Object.assign(data, {attachments: [{filename: 'claim-pickup-order.pdf', content: stream}]});
|
||||
|
||||
return data;
|
||||
});
|
||||
},
|
||||
created() {
|
||||
if (this.locale)
|
||||
this.$i18n.locale = this.locale;
|
||||
},
|
||||
methods: {
|
||||
fetchClient(claimFk) {
|
||||
return database.pool.query(`
|
||||
SELECT
|
||||
c.id,
|
||||
u.lang locale,
|
||||
c.email recipient
|
||||
FROM claim cl
|
||||
JOIN client c ON c.id = cl.clientFk
|
||||
JOIN account.user u ON u.id = c.id
|
||||
WHERE cl.id = ?`, [claimFk]);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
emailHeader,
|
||||
emailFooter,
|
||||
},
|
||||
};
|
|
@ -1,25 +0,0 @@
|
|||
module.exports = {
|
||||
messages: {
|
||||
es: {
|
||||
subject: 'Orden de recogida',
|
||||
title: 'Orden de recogida',
|
||||
description: {
|
||||
dear: 'Estimado cliente',
|
||||
instructions: 'Aqui tienes tu orden de recogida.'
|
||||
},
|
||||
sections: {
|
||||
howToBuy: {
|
||||
title: 'Cómo hacer un pedido',
|
||||
description: `Para realizar un pedido en nuestra web,
|
||||
debes configurarlo indicando:`,
|
||||
requeriments: [
|
||||
'Si quieres recibir el pedido (por agencia o por nuestro propio reparto) o si lo prefieres recoger en alguno de nuestros almacenes.',
|
||||
'La fecha en la que quieres recibir el pedido (se preparará el día anterior).',
|
||||
'La dirección de entrega o el almacén donde quieres recoger el pedido.'],
|
||||
stock: 'En nuestra web y aplicaciones puedes visualizar el stock disponible de flor cortada, verdes, plantas, complementos y artificial. Ten en cuenta que dicho stock puede variar en función de la fecha seleccionada al configurar el pedido. Es importante CONFIRMAR los pedidos para que la mercancía quede reservada.',
|
||||
delivery: 'El reparto se realiza de lunes a sábado según la zona en la que te encuentres. Por regla general, los pedidos que se entregan por agencia, deben estar confirmados y pagados antes de las 17h del día en que se preparan (el día anterior a recibirlos), aunque esto puede variar si el pedido se envía a través de nuestro reparto y según la zona.',
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
subject: Orden de recogida
|
||||
title: Orden de recogida
|
||||
description:
|
||||
dear: Estimado cliente
|
||||
instructions: Aqui tienes tu orden de recogida.
|
||||
sections:
|
||||
howToBuy:
|
||||
title: Cómo hacer un pedido
|
||||
description: 'Para realizar un pedido en nuestra web, debes configurarlo indicando:'
|
||||
requeriments:
|
||||
- Si quieres recibir el pedido (por agencia o por nuestro propio reparto) o si
|
||||
lo prefieres recoger en alguno de nuestros almacenes.
|
||||
- La fecha en la que quieres recibir el pedido (se preparará el día anterior).
|
||||
- La dirección de entrega o el almacén donde quieres recoger el pedido.
|
||||
stock: En nuestra web y aplicaciones puedes visualizar el stock disponible de
|
||||
flor cortada, verdes, plantas, complementos y artificial. Ten en cuenta que
|
||||
dicho stock puede variar en función de la fecha seleccionada al configurar el
|
||||
pedido. Es importante CONFIRMAR los pedidos para que la mercancía quede reservada.
|
||||
delivery: El reparto se realiza de lunes a sábado según la zona en la que te encuentres.
|
||||
Por regla general, los pedidos que se entregan por agencia, deben estar confirmados
|
||||
y pagados antes de las 17h del día en que se preparan (el día anterior a recibirlos),
|
||||
aunque esto puede variar si el pedido se envía a través de nuestro reparto y
|
||||
según la zona.
|
|
@ -0,0 +1 @@
|
|||
../../../../../common/css/email.css
|
|
@ -1,7 +0,0 @@
|
|||
const CssReader = require(`${appPath}/lib/cssReader`);
|
||||
|
||||
module.exports = new CssReader([
|
||||
`${appPath}/common/css/layout.css`,
|
||||
`${appPath}/common/css/email.css`,
|
||||
`${appPath}/common/css/misc.css`])
|
||||
.mergeStyles();
|
|
@ -0,0 +1,233 @@
|
|||
/**
|
||||
* CSS layout elements
|
||||
*
|
||||
*/
|
||||
.container {
|
||||
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
|
||||
font-size: 16px
|
||||
}
|
||||
|
||||
.columns {
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.columns .size100 {
|
||||
width: 100%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size75 {
|
||||
width: 75%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size50 {
|
||||
width: 50%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size33 {
|
||||
width: 33.33%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size25 {
|
||||
width: 25%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.clearfix {
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
clear: both
|
||||
}
|
||||
|
||||
.panel {
|
||||
position: relative;
|
||||
margin-bottom: 15px;
|
||||
padding-top: 10px;
|
||||
break-inside: avoid;
|
||||
break-before: always;
|
||||
break-after: always;
|
||||
}
|
||||
|
||||
.panel .header {
|
||||
background-color: #FFF;
|
||||
padding: 2.5px 10px;
|
||||
position: absolute;
|
||||
font-weight: bold;
|
||||
top: 0px;
|
||||
left: 17.5px;
|
||||
}
|
||||
|
||||
.panel .body {
|
||||
border: 1px solid #CCC;
|
||||
overflow: hidden;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.panel .body h3 {
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
.panel.dark .header {
|
||||
border: 1px solid #808080;
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
.panel.dark .body {
|
||||
border: 1px solid #808080;
|
||||
background-color: #c0c0c0
|
||||
}
|
||||
|
||||
.field {
|
||||
border-bottom: 1px solid #CCC;
|
||||
border-left: 1px solid #CCC;
|
||||
border-top: 1px solid #CCC;
|
||||
float: left
|
||||
}
|
||||
|
||||
.field span {
|
||||
border-right: 1px solid #CCC;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.field.square span {
|
||||
height: 35.4px;
|
||||
width: 35.4px
|
||||
}
|
||||
|
||||
.emptyField {
|
||||
border-bottom: 1px dotted grey;
|
||||
min-height: 1em;
|
||||
display: block
|
||||
}
|
||||
|
||||
.field.rectangle span {
|
||||
height: 2em;
|
||||
width: 8em
|
||||
}
|
||||
|
||||
.pull-left {
|
||||
float: left !important
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right !important
|
||||
}
|
||||
|
||||
.vertical-text {
|
||||
-moz-transform: rotate(90deg);
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
font-size: .65em;
|
||||
right: -108px;
|
||||
width: 200px;
|
||||
top: 50%
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.row-oriented, .column-oriented {
|
||||
text-align: left;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.column-oriented {
|
||||
margin-bottom: 15px
|
||||
}
|
||||
|
||||
.column-oriented td,
|
||||
.column-oriented th {
|
||||
padding: 5px 10px
|
||||
}
|
||||
|
||||
.column-oriented thead {
|
||||
background-color: #e5e5e5
|
||||
}
|
||||
|
||||
.column-oriented thead tr {
|
||||
border-bottom: 1px solid #808080;
|
||||
border-top: 1px solid #808080;
|
||||
background-color: #e5e5e5
|
||||
}
|
||||
|
||||
.column-oriented tfoot {
|
||||
border-top: 2px solid #808080;
|
||||
}
|
||||
|
||||
.column-oriented tfoot tr:first-child td {
|
||||
padding-top: 20px !important;
|
||||
}
|
||||
|
||||
.column-oriented .description {
|
||||
border-bottom: 1px solid #DDD;
|
||||
font-size: 0.8em
|
||||
}
|
||||
|
||||
.panel .row-oriented td, .panel .row-oriented th {
|
||||
padding: 10px 0
|
||||
}
|
||||
|
||||
.row-oriented > tbody > tr > td {
|
||||
width: 30%
|
||||
}
|
||||
|
||||
.row-oriented > tbody > tr > th {
|
||||
padding-left: 30px;
|
||||
width: 70%
|
||||
}
|
||||
|
||||
.row-oriented .description {
|
||||
padding: 0 !important;
|
||||
font-size: 0.6em;
|
||||
color: #888
|
||||
}
|
||||
|
||||
.line {
|
||||
border-bottom: 1px solid #DDD;
|
||||
border-right: 1px solid #DDD;
|
||||
border-left: 1px solid #DDD;
|
||||
position: relative;
|
||||
margin-left: -1px;
|
||||
margin-right: 1px;
|
||||
margin-top: 10px;
|
||||
color: #999;
|
||||
padding: 5px 0
|
||||
}
|
||||
|
||||
.line .vertical-aligned {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
.line span {
|
||||
background-color: #FFF;
|
||||
padding: 5px
|
||||
}
|
||||
|
||||
.signature {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.signature section {
|
||||
height: 150px
|
||||
}
|
||||
|
||||
.signature p {
|
||||
margin-right: 50%;
|
||||
margin-top: 140px
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* CSS misc classes
|
||||
*
|
||||
*/
|
||||
.uppercase {
|
||||
text-transform: uppercase
|
||||
}
|
||||
|
||||
.justified {
|
||||
text-align: justify
|
||||
}
|
||||
|
||||
.centered {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left
|
||||
}
|
||||
|
||||
.number {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.font.gray {
|
||||
color: #555
|
||||
}
|
||||
|
||||
.font.light-gray {
|
||||
color: #888
|
||||
}
|
||||
|
||||
.font.small {
|
||||
font-size: 0.65em
|
||||
}
|
||||
|
||||
.font.bold {
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.non-page-break {
|
||||
page-break-inside: avoid;
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
<body>
|
||||
<section class="container">
|
||||
<!-- Header component -->
|
||||
<email-header></email-header>
|
||||
<email-header :is-preview="isPreview"></email-header>
|
||||
<!-- End header component -->
|
||||
<section class="main">
|
||||
<!-- Title block -->
|
||||
|
@ -19,8 +19,8 @@
|
|||
<p v-html="$t('clientData')"></p>
|
||||
|
||||
<p>
|
||||
<div>{{$t('clientId')}}: <strong>{{ id }}</strong></div>
|
||||
<div>{{$t('user')}}: <strong>{{userName}}</strong></div>
|
||||
<div>{{$t('clientId')}}: <strong>{{client.id}}</strong></div>
|
||||
<div>{{$t('user')}}: <strong>{{client.userName}}</strong></div>
|
||||
<div>{{$t('password')}}: <strong>********</strong>
|
||||
(<a href="https://verdnatura.es">{{$t('passwordResetText')}}</a>)
|
||||
</div>
|
||||
|
@ -52,20 +52,21 @@
|
|||
|
||||
<p v-html="$t('help')"></p>
|
||||
<p>
|
||||
<section v-if="salesPersonName">
|
||||
{{$t('salesPersonName')}}: <strong>{{salesPersonName}}</strong>
|
||||
<section v-if="client.salesPersonName">
|
||||
{{$t('salesPersonName')}}: <strong>{{client.salesPersonName}}</strong>
|
||||
</section>
|
||||
<section v-if="salesPersonPhone">
|
||||
{{$t('salesPersonPhone')}}: <strong>{{salesPersonPhone}}</strong>
|
||||
<section v-if="client.salesPersonPhone">
|
||||
{{$t('salesPersonPhone')}}: <strong>{{client.salesPersonPhone}}</strong>
|
||||
</section>
|
||||
<section v-if="salesPersonEmail">
|
||||
<section v-if="client.salesPersonEmail">
|
||||
{{$t('salesPersonEmail')}}:
|
||||
<strong><a v-bind:href="`mailto: ${salesPersonEmail}`" target="_blank">{{salesPersonEmail}}</strong>
|
||||
<strong><a v-bind:href="`mailto: ${client.salesPersonEmail}`" target="_blank">{{client.salesPersonEmail}}</strong>
|
||||
</section>
|
||||
</p>
|
||||
</section>
|
||||
{{isPreview}}
|
||||
<!-- Footer component -->
|
||||
<email-footer :locale="locale"></email-footer>
|
||||
<email-footer :is-preview="isPreview" :locale="client.locale"></email-footer>
|
||||
<!-- End footer component -->
|
||||
</section>
|
||||
</body>
|
|
@ -1,9 +1,15 @@
|
|||
const database = require(`${appPath}/lib/database`);
|
||||
const UserException = require(`${appPath}/lib/exceptions/userException`);
|
||||
const db = require(`${appPath}/lib/database`);
|
||||
const Component = require(`${appPath}/lib/component`);
|
||||
const emailHeader = new Component('email-header');
|
||||
const emailFooter = new Component('email-footer');
|
||||
|
||||
|
||||
module.exports = {
|
||||
name: 'client-welcome',
|
||||
async asyncData(ctx, params) {
|
||||
async serverPrefetch() {
|
||||
this.client = await this.fetchClient(this.clientId);
|
||||
},
|
||||
/* async asyncData(ctx, params) {
|
||||
const data = {
|
||||
isPreview: ctx.method === 'GET',
|
||||
};
|
||||
|
@ -17,14 +23,14 @@ module.exports = {
|
|||
throw new UserException('No client data found');
|
||||
return Object.assign(data, result[0]);
|
||||
});
|
||||
},
|
||||
}, */
|
||||
created() {
|
||||
if (this.locale)
|
||||
this.$i18n.locale = this.locale;
|
||||
},
|
||||
methods: {
|
||||
fetchClient(clientFk) {
|
||||
return database.pool.query(`
|
||||
fetchClient(clientId) {
|
||||
return db.findOne(`
|
||||
SELECT
|
||||
c.id,
|
||||
u.lang locale,
|
||||
|
@ -37,11 +43,12 @@ module.exports = {
|
|||
JOIN account.user u ON u.id = c.id
|
||||
LEFT JOIN worker w ON w.id = c.salesPersonFk
|
||||
LEFT JOIN account.user wu ON wu.id = w.userFk
|
||||
WHERE c.id = ?`, [clientFk]);
|
||||
WHERE c.id = ?`, [clientId]);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
'email-header': require('../email-header'),
|
||||
'email-footer': require('../email-footer'),
|
||||
'email-header': emailHeader.build(),
|
||||
'email-footer': emailFooter.build()
|
||||
},
|
||||
props: ['clientId', 'isPreview']
|
||||
};
|
|
@ -1,55 +0,0 @@
|
|||
module.exports = {
|
||||
messages: {
|
||||
es: {
|
||||
subject: 'Bienvenido a Verdnatura',
|
||||
title: '¡Te damos la bienvenida!',
|
||||
dearClient: 'Estimado cliente',
|
||||
clientData: `Tus datos para poder comprar en la web de Verdnatura
|
||||
(<a href="https://www.verdnatura.es" title="Visitar Verdnatura" target="_blank" style="color: #8dba25">https://www.verdnatura.es</a>)
|
||||
o en nuestras aplicaciones para <a href="https://goo.gl/3hC2mG" title="App Store" target="_blank" style="color: #8dba25">iOS</a> y
|
||||
<a href="https://goo.gl/8obvLc" title="Google Play" target="_blank" style="color: #8dba25">Android</a>
|
||||
(<a href="https://www.youtube.com/watch?v=gGfEtFm8qkw" target="_blank" style="color: #8dba25"><strong>Ver tutorial de uso</strong></a>), son`,
|
||||
clientId: 'Identificador de cliente',
|
||||
user: 'Usuario',
|
||||
password: 'Contraseña',
|
||||
passwordResetText: 'Haz clic en "¿Has olvidado tu contraseña?"',
|
||||
sections: {
|
||||
howToBuy: {
|
||||
title: 'Cómo hacer un pedido',
|
||||
description: `Para realizar un pedido en nuestra web,
|
||||
debes configurarlo indicando:`,
|
||||
requeriments: [
|
||||
'Si quieres recibir el pedido (por agencia o por nuestro propio reparto) o si lo prefieres recoger en alguno de nuestros almacenes.',
|
||||
'La fecha en la que quieres recibir el pedido (se preparará el día anterior).',
|
||||
'La dirección de entrega o el almacén donde quieres recoger el pedido.'],
|
||||
stock: 'En nuestra web y aplicaciones puedes visualizar el stock disponible de flor cortada, verdes, plantas, complementos y artificial. Ten en cuenta que dicho stock puede variar en función de la fecha seleccionada al configurar el pedido. Es importante CONFIRMAR los pedidos para que la mercancía quede reservada.',
|
||||
delivery: 'El reparto se realiza de lunes a sábado según la zona en la que te encuentres. Por regla general, los pedidos que se entregan por agencia, deben estar confirmados y pagados antes de las 17h del día en que se preparan (el día anterior a recibirlos), aunque esto puede variar si el pedido se envía a través de nuestro reparto y según la zona.',
|
||||
},
|
||||
howToPay: {
|
||||
title: 'Cómo pagar',
|
||||
description: 'Las formas de pago admitidas en Verdnatura son:',
|
||||
options: [
|
||||
'Con <strong>tarjeta</strong> a través de nuestra plataforma web (al confirmar el pedido).',
|
||||
'Mediante <strong>giro bancario mensual</strong>, modalidad que hay que solicitar y tramitar.',
|
||||
],
|
||||
},
|
||||
toConsider: {
|
||||
title: 'Cosas a tener en cuenta',
|
||||
description: `Verdnatura vende EXCLUSIVAMENTE a profesionales, por lo que debes
|
||||
remitirnos el Modelo 036 ó 037, para comprobar que está
|
||||
dado/a de alta en el epígrafe correspondiente al comercio de flores.`,
|
||||
},
|
||||
claimsPolicy: {
|
||||
title: 'POLÍTICA DE RECLAMACIONES',
|
||||
description: `Verdnatura aceptará las reclamaciones que se realicen dentro
|
||||
de los dos días naturales siguientes a la recepción del pedido (incluyendo el mismo día de la recepción).
|
||||
Pasado este plazo no se aceptará ninguna reclamación.`,
|
||||
},
|
||||
},
|
||||
help: 'Cualquier duda que te surja, no dudes en consultarla, <strong>¡estamos para atenderte!</strong>',
|
||||
salesPersonName: 'Soy tu comercial y mi nombre es',
|
||||
salesPersonPhone: 'Teléfono y whatsapp',
|
||||
salesPersonEmail: 'Dirección de e-mail',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -0,0 +1,55 @@
|
|||
subject: Bienvenido a Verdnatura
|
||||
title: "¡Te damos la bienvenida!"
|
||||
dearClient: Estimado cliente
|
||||
clientData: 'Tus datos para poder comprar en la web de Verdnatura (<a href="https://www.verdnatura.es"
|
||||
title="Visitar Verdnatura" target="_blank" style="color: #8dba25">https://www.verdnatura.es</a>)
|
||||
o en nuestras aplicaciones para <a href="https://goo.gl/3hC2mG" title="App Store"
|
||||
target="_blank" style="color: #8dba25">iOS</a> y <a href="https://goo.gl/8obvLc"
|
||||
title="Google Play" target="_blank" style="color: #8dba25">Android</a> (<a
|
||||
href="https://www.youtube.com/watch?v=gGfEtFm8qkw" target="_blank" style="color:
|
||||
#8dba25"><strong>Ver tutorial de uso</strong></a>), son'
|
||||
clientId: Identificador de cliente
|
||||
user: Usuario
|
||||
password: Contraseña
|
||||
passwordResetText: Haz clic en '¿Has olvidado tu contraseña?'
|
||||
sections:
|
||||
howToBuy:
|
||||
title: Cómo hacer un pedido
|
||||
description: 'Para realizar un pedido en nuestra web, debes configurarlo indicando:'
|
||||
requeriments:
|
||||
- Si quieres recibir el pedido (por agencia o por nuestro propio reparto) o si
|
||||
lo prefieres recoger en alguno de nuestros almacenes.
|
||||
- La fecha en la que quieres recibir el pedido (se preparará el día anterior).
|
||||
- La dirección de entrega o el almacén donde quieres recoger el pedido.
|
||||
stock: En nuestra web y aplicaciones puedes visualizar el stock disponible de
|
||||
flor cortada, verdes, plantas, complementos y artificial. Ten en cuenta que
|
||||
dicho stock puede variar en función de la fecha seleccionada al configurar el
|
||||
pedido. Es importante CONFIRMAR los pedidos para que la mercancía quede reservada.
|
||||
delivery: El reparto se realiza de lunes a sábado según la zona en la que te encuentres.
|
||||
Por regla general, los pedidos que se entregan por agencia, deben estar confirmados
|
||||
y pagados antes de las 17h del día en que se preparan (el día anterior a recibirlos),
|
||||
aunque esto puede variar si el pedido se envía a través de nuestro reparto y
|
||||
según la zona.
|
||||
howToPay:
|
||||
title: Cómo pagar
|
||||
description: 'Las formas de pago admitidas en Verdnatura son:'
|
||||
options:
|
||||
- Con <strong>tarjeta</strong> a través de nuestra plataforma web (al confirmar
|
||||
el pedido).
|
||||
- Mediante <strong>giro bancario mensual</strong>, modalidad que hay que solicitar
|
||||
y tramitar.
|
||||
toConsider:
|
||||
title: Cosas a tener en cuenta
|
||||
description: Verdnatura vende EXCLUSIVAMENTE a profesionales, por lo que debes
|
||||
remitirnos el Modelo 036 ó 037, para comprobar que está dado/a de alta en el
|
||||
epígrafe correspondiente al comercio de flores.
|
||||
claimsPolicy:
|
||||
title: POLÍTICA DE RECLAMACIONES
|
||||
description: Verdnatura aceptará las reclamaciones que se realicen dentro de los
|
||||
dos días naturales siguientes a la recepción del pedido (incluyendo el mismo
|
||||
día de la recepción). Pasado este plazo no se aceptará ninguna reclamación.
|
||||
help: Cualquier duda que te surja, no dudes en consultarla, <strong>¡estamos para
|
||||
atenderte!</strong>
|
||||
salesPersonName: Soy tu comercial y mi nombre es
|
||||
salesPersonPhone: Teléfono y whatsapp
|
||||
salesPersonEmail: Dirección de e-mail
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Email only stylesheet
|
||||
*
|
||||
*/
|
||||
body {
|
||||
background-color: #EEE
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 600px;
|
||||
min-width: 320px;
|
||||
margin: 0 auto;
|
||||
color: #555
|
||||
}
|
||||
|
||||
.main {
|
||||
background-color: #FFF;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.main a {
|
||||
color: #8dba25
|
||||
}
|
||||
|
||||
.main h1 {
|
||||
color: #999
|
||||
}
|
||||
|
||||
.main h3 {
|
||||
font-size: 16px
|
||||
}
|
||||
|
||||
.title {
|
||||
background-color: #95d831;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
padding: 35px 0
|
||||
}
|
||||
|
||||
.title h1 {
|
||||
font-size: 32px;
|
||||
color: #333;
|
||||
margin: 0
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
const CssReader = require(`${appPath}/lib/cssReader`);
|
||||
|
||||
module.exports = new CssReader([
|
||||
`${appPath}/common/css/layout.css`,
|
||||
`${appPath}/common/css/email.css`,
|
||||
`${appPath}/common/css/misc.css`])
|
||||
.mergeStyles();
|
|
@ -0,0 +1,233 @@
|
|||
/**
|
||||
* CSS layout elements
|
||||
*
|
||||
*/
|
||||
.container {
|
||||
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
|
||||
font-size: 16px
|
||||
}
|
||||
|
||||
.columns {
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.columns .size100 {
|
||||
width: 100%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size75 {
|
||||
width: 75%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size50 {
|
||||
width: 50%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size33 {
|
||||
width: 33.33%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size25 {
|
||||
width: 25%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.clearfix {
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
clear: both
|
||||
}
|
||||
|
||||
.panel {
|
||||
position: relative;
|
||||
margin-bottom: 15px;
|
||||
padding-top: 10px;
|
||||
break-inside: avoid;
|
||||
break-before: always;
|
||||
break-after: always;
|
||||
}
|
||||
|
||||
.panel .header {
|
||||
background-color: #FFF;
|
||||
padding: 2.5px 10px;
|
||||
position: absolute;
|
||||
font-weight: bold;
|
||||
top: 0px;
|
||||
left: 17.5px;
|
||||
}
|
||||
|
||||
.panel .body {
|
||||
border: 1px solid #CCC;
|
||||
overflow: hidden;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.panel .body h3 {
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
.panel.dark .header {
|
||||
border: 1px solid #808080;
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
.panel.dark .body {
|
||||
border: 1px solid #808080;
|
||||
background-color: #c0c0c0
|
||||
}
|
||||
|
||||
.field {
|
||||
border-bottom: 1px solid #CCC;
|
||||
border-left: 1px solid #CCC;
|
||||
border-top: 1px solid #CCC;
|
||||
float: left
|
||||
}
|
||||
|
||||
.field span {
|
||||
border-right: 1px solid #CCC;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.field.square span {
|
||||
height: 35.4px;
|
||||
width: 35.4px
|
||||
}
|
||||
|
||||
.emptyField {
|
||||
border-bottom: 1px dotted grey;
|
||||
min-height: 1em;
|
||||
display: block
|
||||
}
|
||||
|
||||
.field.rectangle span {
|
||||
height: 2em;
|
||||
width: 8em
|
||||
}
|
||||
|
||||
.pull-left {
|
||||
float: left !important
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right !important
|
||||
}
|
||||
|
||||
.vertical-text {
|
||||
-moz-transform: rotate(90deg);
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
font-size: .65em;
|
||||
right: -108px;
|
||||
width: 200px;
|
||||
top: 50%
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.row-oriented, .column-oriented {
|
||||
text-align: left;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.column-oriented {
|
||||
margin-bottom: 15px
|
||||
}
|
||||
|
||||
.column-oriented td,
|
||||
.column-oriented th {
|
||||
padding: 5px 10px
|
||||
}
|
||||
|
||||
.column-oriented thead {
|
||||
background-color: #e5e5e5
|
||||
}
|
||||
|
||||
.column-oriented thead tr {
|
||||
border-bottom: 1px solid #808080;
|
||||
border-top: 1px solid #808080;
|
||||
background-color: #e5e5e5
|
||||
}
|
||||
|
||||
.column-oriented tfoot {
|
||||
border-top: 2px solid #808080;
|
||||
}
|
||||
|
||||
.column-oriented tfoot tr:first-child td {
|
||||
padding-top: 20px !important;
|
||||
}
|
||||
|
||||
.column-oriented .description {
|
||||
border-bottom: 1px solid #DDD;
|
||||
font-size: 0.8em
|
||||
}
|
||||
|
||||
.panel .row-oriented td, .panel .row-oriented th {
|
||||
padding: 10px 0
|
||||
}
|
||||
|
||||
.row-oriented > tbody > tr > td {
|
||||
width: 30%
|
||||
}
|
||||
|
||||
.row-oriented > tbody > tr > th {
|
||||
padding-left: 30px;
|
||||
width: 70%
|
||||
}
|
||||
|
||||
.row-oriented .description {
|
||||
padding: 0 !important;
|
||||
font-size: 0.6em;
|
||||
color: #888
|
||||
}
|
||||
|
||||
.line {
|
||||
border-bottom: 1px solid #DDD;
|
||||
border-right: 1px solid #DDD;
|
||||
border-left: 1px solid #DDD;
|
||||
position: relative;
|
||||
margin-left: -1px;
|
||||
margin-right: 1px;
|
||||
margin-top: 10px;
|
||||
color: #999;
|
||||
padding: 5px 0
|
||||
}
|
||||
|
||||
.line .vertical-aligned {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
.line span {
|
||||
background-color: #FFF;
|
||||
padding: 5px
|
||||
}
|
||||
|
||||
.signature {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.signature section {
|
||||
height: 150px
|
||||
}
|
||||
|
||||
.signature p {
|
||||
margin-right: 50%;
|
||||
margin-top: 140px
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* CSS misc classes
|
||||
*
|
||||
*/
|
||||
.uppercase {
|
||||
text-transform: uppercase
|
||||
}
|
||||
|
||||
.justified {
|
||||
text-align: justify
|
||||
}
|
||||
|
||||
.centered {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left
|
||||
}
|
||||
|
||||
.number {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.font.gray {
|
||||
color: #555
|
||||
}
|
||||
|
||||
.font.light-gray {
|
||||
color: #888
|
||||
}
|
||||
|
||||
.font.small {
|
||||
font-size: 0.65em
|
||||
}
|
||||
|
||||
.font.bold {
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.non-page-break {
|
||||
page-break-inside: avoid;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
[{
|
||||
"filename": "delivery-note.pdf",
|
||||
"href": "http://localhost:5000/pi"
|
||||
}]
|
|
@ -6,7 +6,7 @@
|
|||
<body>
|
||||
<section class="container">
|
||||
<!-- Header component -->
|
||||
<email-header></email-header>
|
||||
<email-header :is-preview="isPreview" :locale="locale"></email-header>
|
||||
<!-- End header component -->
|
||||
<section class="main">
|
||||
<!-- Title block -->
|
||||
|
@ -20,7 +20,7 @@
|
|||
<p v-html="$t('help')"></p>
|
||||
</section>
|
||||
<!-- Footer component -->
|
||||
<email-footer :locale="locale"></email-footer>
|
||||
<email-footer :is-preview="isPreview" :locale="locale"></email-footer>
|
||||
<!-- End footer component -->
|
||||
</section>
|
||||
</body>
|
|
@ -1,6 +1,7 @@
|
|||
const database = require(`${appPath}/lib/database`);
|
||||
const reportEngine = require(`${appPath}/lib/reportEngine.js`);
|
||||
const UserException = require(`${appPath}/lib/exceptions/userException`);
|
||||
const db = require(`${appPath}/lib/database`);
|
||||
const Component = require(`${appPath}/lib/component`);
|
||||
const emailHeader = new Component('email-header');
|
||||
const emailFooter = new Component('email-footer');
|
||||
|
||||
module.exports = {
|
||||
name: 'delivery-note',
|
||||
|
@ -27,12 +28,11 @@ module.exports = {
|
|||
});
|
||||
},
|
||||
created() {
|
||||
if (this.locale)
|
||||
this.$i18n.locale = this.locale;
|
||||
this.locale = 'es';
|
||||
},
|
||||
methods: {
|
||||
fetchTicket(ticketFk) {
|
||||
return database.pool.query(`
|
||||
fetchTicket(ticketId) {
|
||||
return db.findOne(`
|
||||
SELECT
|
||||
t.id,
|
||||
u.lang locale,
|
||||
|
@ -40,11 +40,12 @@ module.exports = {
|
|||
FROM ticket t
|
||||
JOIN client c ON c.id = t.clientFk
|
||||
JOIN account.user u ON u.id = c.id
|
||||
WHERE t.id = ?`, [ticketFk]);
|
||||
WHERE t.id = ?`, [ticketId]);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
'email-header': require('../email-header'),
|
||||
'email-footer': require('../email-footer'),
|
||||
'email-header': emailHeader.build(),
|
||||
'email-footer': emailFooter.build()
|
||||
},
|
||||
props: ['ticketId', 'isPreview']
|
||||
};
|
|
@ -1,11 +0,0 @@
|
|||
module.exports = {
|
||||
messages: {
|
||||
es: {
|
||||
subject: 'Aquí tienes tu albarán',
|
||||
title: '¡Este es tu albarán!',
|
||||
dearClient: 'Estimado cliente',
|
||||
clientData: `A continuación adjuntamos tu albarán.`,
|
||||
help: 'Cualquier duda que te surja, no dudes en consultarla, <strong>¡estamos para atenderte!</strong>'
|
||||
},
|
||||
},
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
subject: Aquí tienes tu albarán
|
||||
title: "¡Este es tu albarán!"
|
||||
dearClient: Estimado cliente
|
||||
clientData: A continuación adjuntamos tu albarán.
|
||||
help: Cualquier duda que te surja, no dudes en consultarla, <strong>¡estamos para
|
||||
atenderte!</strong>
|
|
@ -1,4 +0,0 @@
|
|||
const CssReader = require(`${appPath}/lib/cssReader`);
|
||||
|
||||
module.exports = new CssReader([`${__dirname}/style.css`])
|
||||
.mergeStyles();
|
|
@ -1,34 +0,0 @@
|
|||
module.exports = {
|
||||
name: 'email-footer',
|
||||
asyncData(ctx) {
|
||||
return {
|
||||
isPreview: ctx.method === 'GET',
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (this.locale)
|
||||
this.$i18n.locale = this.locale;
|
||||
|
||||
const embeded = [];
|
||||
this.files.map(file => {
|
||||
const src = this.isPreview ? `/api/${file}` : `cid:${file}`;
|
||||
embeded[file] = src;
|
||||
});
|
||||
this.embeded = embeded;
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
files: [
|
||||
/* '/assets/images/action.png',
|
||||
'/assets/images/info.png', */
|
||||
'/assets/images/facebook.png',
|
||||
'/assets/images/twitter.png',
|
||||
'/assets/images/youtube.png',
|
||||
'/assets/images/pinterest.png',
|
||||
'/assets/images/instagram.png',
|
||||
'/assets/images/linkedin.png',
|
||||
],
|
||||
};
|
||||
},
|
||||
props: ['locale']
|
||||
};
|
|
@ -1,42 +0,0 @@
|
|||
module.exports = {
|
||||
messages: {
|
||||
es: {
|
||||
buttons: {
|
||||
webAcccess: 'Visita nuestra Web',
|
||||
info: 'Ayúdanos a mejorar',
|
||||
},
|
||||
privacy: {
|
||||
fiscalAddress: 'VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla · www.verdnatura.es · clientes@verdnatura.es',
|
||||
disclaimer: `- AVISO - Este mensaje es privado y confidencial, y debe ser utilizado
|
||||
exclusivamente por la persona destinataria del mismo. Si has recibido este mensaje
|
||||
por error, te rogamos lo comuniques al remitente y borres dicho mensaje y cualquier documento
|
||||
adjunto que pudiera contener. Verdnatura Levante SL no renuncia a la confidencialidad ni a
|
||||
ningún privilegio por causa de transmisión errónea o mal funcionamiento. Igualmente no se hace
|
||||
responsable de los cambios, alteraciones, errores u omisiones que pudieran hacerse al mensaje una vez enviado.`,
|
||||
law: `En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal,
|
||||
te comunicamos que los datos personales que facilites se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L.,
|
||||
pudiendo en todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, comunicándolo por
|
||||
escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación.`,
|
||||
},
|
||||
},
|
||||
/* fr: {
|
||||
buttons: {
|
||||
webAcccess: 'Visitez notre site web',
|
||||
info: 'Ayúdanos a mejorar',
|
||||
},
|
||||
privacy: {
|
||||
fiscalAddress: 'VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla · www.verdnatura.es · clientes@verdnatura.es',
|
||||
disclaimer: `- AVISO - Ce message est privé et confidentiel et doit être utilisé.
|
||||
exclusivamente por la persona destinataria del mismo. Si has recibido este mensaje
|
||||
por error, te rogamos lo comuniques al remitente y borres dicho mensaje y cualquier documento
|
||||
adjunto que pudiera contener. Verdnatura Levante SL no renuncia a la confidencialidad ni a
|
||||
ningún privilegio por causa de transmisión errónea o mal funcionamiento. Igualmente no se hace
|
||||
responsable de los cambios, alteraciones, errores u omisiones que pudieran hacerse al mensaje una vez enviado.`,
|
||||
law: `En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal,
|
||||
te comunicamos que los datos personales que facilites se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L.,
|
||||
pudiendo en todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, comunicándolo por
|
||||
escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación.`,
|
||||
},
|
||||
}, */
|
||||
},
|
||||
};
|
|
@ -1,4 +0,0 @@
|
|||
const CssReader = require(`${appPath}/lib/cssReader`);
|
||||
|
||||
module.exports = new CssReader([`${__dirname}/style.css`])
|
||||
.mergeStyles();
|
|
@ -1,5 +0,0 @@
|
|||
<header>
|
||||
<a href="https://www.verdnatura.es" target="_blank"/>
|
||||
<img :src="embeded['/assets/images/email-logo.png']" alt="VerdNatura"/>
|
||||
</a>
|
||||
</header>
|
|
@ -1,22 +0,0 @@
|
|||
module.exports = {
|
||||
name: 'email-header',
|
||||
asyncData(ctx) {
|
||||
return {
|
||||
isPreview: ctx.method === 'GET',
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const embeded = [];
|
||||
this.files.map(file => {
|
||||
const src = this.isPreview ? `/api/${file}` : `cid:${file}`;
|
||||
embeded[file] = src;
|
||||
});
|
||||
this.embeded = embeded;
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
files: ['/assets/images/email-logo.png'],
|
||||
};
|
||||
},
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
module.exports = {
|
||||
messages: {
|
||||
es: {},
|
||||
},
|
||||
};
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Email only stylesheet
|
||||
*
|
||||
*/
|
||||
body {
|
||||
background-color: #EEE
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 600px;
|
||||
min-width: 320px;
|
||||
margin: 0 auto;
|
||||
color: #555
|
||||
}
|
||||
|
||||
.main {
|
||||
background-color: #FFF;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.main a {
|
||||
color: #8dba25
|
||||
}
|
||||
|
||||
.main h1 {
|
||||
color: #999
|
||||
}
|
||||
|
||||
.main h3 {
|
||||
font-size: 16px
|
||||
}
|
||||
|
||||
.title {
|
||||
background-color: #95d831;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
padding: 35px 0
|
||||
}
|
||||
|
||||
.title h1 {
|
||||
font-size: 32px;
|
||||
color: #333;
|
||||
margin: 0
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
const CssReader = require(`${appPath}/lib/cssReader`);
|
||||
|
||||
module.exports = new CssReader([
|
||||
`${appPath}/common/css/layout.css`,
|
||||
`${appPath}/common/css/email.css`,
|
||||
`${appPath}/common/css/misc.css`])
|
||||
.mergeStyles();
|
|
@ -0,0 +1,233 @@
|
|||
/**
|
||||
* CSS layout elements
|
||||
*
|
||||
*/
|
||||
.container {
|
||||
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
|
||||
font-size: 16px
|
||||
}
|
||||
|
||||
.columns {
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.columns .size100 {
|
||||
width: 100%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size75 {
|
||||
width: 75%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size50 {
|
||||
width: 50%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size33 {
|
||||
width: 33.33%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.columns .size25 {
|
||||
width: 25%;
|
||||
float: left
|
||||
}
|
||||
|
||||
.clearfix {
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
clear: both
|
||||
}
|
||||
|
||||
.panel {
|
||||
position: relative;
|
||||
margin-bottom: 15px;
|
||||
padding-top: 10px;
|
||||
break-inside: avoid;
|
||||
break-before: always;
|
||||
break-after: always;
|
||||
}
|
||||
|
||||
.panel .header {
|
||||
background-color: #FFF;
|
||||
padding: 2.5px 10px;
|
||||
position: absolute;
|
||||
font-weight: bold;
|
||||
top: 0px;
|
||||
left: 17.5px;
|
||||
}
|
||||
|
||||
.panel .body {
|
||||
border: 1px solid #CCC;
|
||||
overflow: hidden;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.panel .body h3 {
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
.panel.dark .header {
|
||||
border: 1px solid #808080;
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
.panel.dark .body {
|
||||
border: 1px solid #808080;
|
||||
background-color: #c0c0c0
|
||||
}
|
||||
|
||||
.field {
|
||||
border-bottom: 1px solid #CCC;
|
||||
border-left: 1px solid #CCC;
|
||||
border-top: 1px solid #CCC;
|
||||
float: left
|
||||
}
|
||||
|
||||
.field span {
|
||||
border-right: 1px solid #CCC;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.field.square span {
|
||||
height: 35.4px;
|
||||
width: 35.4px
|
||||
}
|
||||
|
||||
.emptyField {
|
||||
border-bottom: 1px dotted grey;
|
||||
min-height: 1em;
|
||||
display: block
|
||||
}
|
||||
|
||||
.field.rectangle span {
|
||||
height: 2em;
|
||||
width: 8em
|
||||
}
|
||||
|
||||
.pull-left {
|
||||
float: left !important
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right !important
|
||||
}
|
||||
|
||||
.vertical-text {
|
||||
-moz-transform: rotate(90deg);
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
font-size: .65em;
|
||||
right: -108px;
|
||||
width: 200px;
|
||||
top: 50%
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.row-oriented, .column-oriented {
|
||||
text-align: left;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.column-oriented {
|
||||
margin-bottom: 15px
|
||||
}
|
||||
|
||||
.column-oriented td,
|
||||
.column-oriented th {
|
||||
padding: 5px 10px
|
||||
}
|
||||
|
||||
.column-oriented thead {
|
||||
background-color: #e5e5e5
|
||||
}
|
||||
|
||||
.column-oriented thead tr {
|
||||
border-bottom: 1px solid #808080;
|
||||
border-top: 1px solid #808080;
|
||||
background-color: #e5e5e5
|
||||
}
|
||||
|
||||
.column-oriented tfoot {
|
||||
border-top: 2px solid #808080;
|
||||
}
|
||||
|
||||
.column-oriented tfoot tr:first-child td {
|
||||
padding-top: 20px !important;
|
||||
}
|
||||
|
||||
.column-oriented .description {
|
||||
border-bottom: 1px solid #DDD;
|
||||
font-size: 0.8em
|
||||
}
|
||||
|
||||
.panel .row-oriented td, .panel .row-oriented th {
|
||||
padding: 10px 0
|
||||
}
|
||||
|
||||
.row-oriented > tbody > tr > td {
|
||||
width: 30%
|
||||
}
|
||||
|
||||
.row-oriented > tbody > tr > th {
|
||||
padding-left: 30px;
|
||||
width: 70%
|
||||
}
|
||||
|
||||
.row-oriented .description {
|
||||
padding: 0 !important;
|
||||
font-size: 0.6em;
|
||||
color: #888
|
||||
}
|
||||
|
||||
.line {
|
||||
border-bottom: 1px solid #DDD;
|
||||
border-right: 1px solid #DDD;
|
||||
border-left: 1px solid #DDD;
|
||||
position: relative;
|
||||
margin-left: -1px;
|
||||
margin-right: 1px;
|
||||
margin-top: 10px;
|
||||
color: #999;
|
||||
padding: 5px 0
|
||||
}
|
||||
|
||||
.line .vertical-aligned {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
.line span {
|
||||
background-color: #FFF;
|
||||
padding: 5px
|
||||
}
|
||||
|
||||
.signature {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.signature section {
|
||||
height: 150px
|
||||
}
|
||||
|
||||
.signature p {
|
||||
margin-right: 50%;
|
||||
margin-top: 140px
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* CSS misc classes
|
||||
*
|
||||
*/
|
||||
.uppercase {
|
||||
text-transform: uppercase
|
||||
}
|
||||
|
||||
.justified {
|
||||
text-align: justify
|
||||
}
|
||||
|
||||
.centered {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left
|
||||
}
|
||||
|
||||
.number {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.font.gray {
|
||||
color: #555
|
||||
}
|
||||
|
||||
.font.light-gray {
|
||||
color: #888
|
||||
}
|
||||
|
||||
.font.small {
|
||||
font-size: 0.65em
|
||||
}
|
||||
|
||||
.font.bold {
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.non-page-break {
|
||||
page-break-inside: avoid;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
[{
|
||||
"filename": "model.ezp",
|
||||
"path": "/assets/files/model.ezp",
|
||||
"cid": "model.ezp"
|
||||
},
|
||||
{
|
||||
"filename": "port.png",
|
||||
"path": "/assets/files/port.png",
|
||||
"cid": "port.png"
|
||||
}]
|
|
@ -1,55 +0,0 @@
|
|||
const database = require(`${appPath}/lib/database`);
|
||||
const UserException = require(`${appPath}/lib/exceptions/userException`);
|
||||
|
||||
module.exports = {
|
||||
name: 'printer-setup',
|
||||
async asyncData(ctx, params) {
|
||||
const data = {
|
||||
isPreview: ctx.method === 'GET',
|
||||
};
|
||||
|
||||
if (!params.clientFk)
|
||||
throw new UserException('No client id specified');
|
||||
|
||||
return this.methods.fetchClient(params.clientFk)
|
||||
.then(([result]) => {
|
||||
if (!result)
|
||||
throw new UserException('No client data found');
|
||||
return Object.assign(data, result[0]);
|
||||
});
|
||||
},
|
||||
created() {
|
||||
if (this.locale)
|
||||
this.$i18n.locale = this.locale;
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
files: [
|
||||
'/assets/files/model.ezp',
|
||||
'/assets/files/port.png'
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
fetchClient(clientFk) {
|
||||
return database.pool.query(`
|
||||
SELECT
|
||||
c.id,
|
||||
u.lang locale,
|
||||
u.name AS userName,
|
||||
c.email recipient,
|
||||
CONCAT(w.lastName, ' ', w.firstName) salesPersonName,
|
||||
w.phone AS salesPersonPhone,
|
||||
CONCAT(wu.name, '@verdnatura.es') AS salesPersonEmail
|
||||
FROM client c
|
||||
JOIN account.user u ON u.id = c.id
|
||||
LEFT JOIN worker w ON w.id = c.salesPersonFk
|
||||
LEFT JOIN account.user wu ON wu.id = w.userFk
|
||||
WHERE c.id = ?`, [clientFk]);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
'email-header': require('../email-header'),
|
||||
'email-footer': require('../email-footer'),
|
||||
},
|
||||
};
|
|
@ -1,59 +0,0 @@
|
|||
module.exports = {
|
||||
messages: {
|
||||
es: {
|
||||
subject: 'Instalación y configuración de impresora',
|
||||
title: '¡Gracias por tu confianza!',
|
||||
description: {
|
||||
dear: 'Estimado cliente',
|
||||
instructions: 'Sigue las instrucciones especificadas en este correo para llevar a cabo la instalación de la impresora.',
|
||||
followGuide: `Puedes utilizar como guía, el vídeo del montaje del ribon y la cinta
|
||||
<a href="https://www.youtube.com/watch?v=qhb0kgQF3o8" title="Youtube" target="_blank" style="color:#8dba25">https://www.youtube.com/watch?v=qhb0kgQF3o8</a>.
|
||||
También necesitarás el QLabel, el programa para imprimir las cintas.`,
|
||||
downloadFrom: `Puedes descargarlo desde este enlace
|
||||
<a href="https://godex.s3-accelerate.amazonaws.com/gGnOPoojkP6vC1lgmrbEqQ.file?v01" title="Descargar QLabel"
|
||||
target="_blank" style="color:#8dba25">https://godex.s3-accelerate.amazonaws.com/gGnOPoojkP6vC1lgmrbEqQ.file?v01</a>`,
|
||||
},
|
||||
sections: {
|
||||
QLabel: {
|
||||
title: 'Utilización de QLabel',
|
||||
description: 'Para utilizar el programa de impresión de cintas sigue estos pasos',
|
||||
steps: [
|
||||
'Abre el programa QLabel',
|
||||
'Haz clic en el icono de la barra superior con forma de "carpeta"',
|
||||
'Selecciona el archivo llamado "model.ezp" adjunto en este correo, y haz clic en abrir',
|
||||
'Ve a "File" -> "Save as" y guárdalo en el escritorio con otro nombre',
|
||||
'Cierra el Qlabel y abre el archivo que acabamos de guardar',
|
||||
'Haz clic <strong>encima del texto</strong> con el botón secundario del ratón',
|
||||
'Elige la primera opción "setup"',
|
||||
'Cambia el texto para imprimir',
|
||||
'Haz clic en el botón "Ok"',
|
||||
'Desplázate con el ratón para ver la medida máxima que ocupa el texto',
|
||||
'Haz clic <strong>encima del texto</strong> con el botón secundario del ratón',
|
||||
'Elige la segunda opción "Setup printer"',
|
||||
'Haz clic en la primera pestaña "Label Setup"',
|
||||
'Modifica la propiedad "Paper Height" con la medida máxima consultada anteriormente',
|
||||
`Comprueba el puerto de la impresora, botón de de la derecha
|
||||
"SETUP PRINTER" y en la parte derecha, igual como la imagen
|
||||
que adjuntamos, seleccionar la que ponga "USB00x: GODEX"`,
|
||||
'Haz clic en el botón "Ok"',
|
||||
'Haz clic sobre el icono de la impresora',
|
||||
'Haz clic en "Print"',
|
||||
],
|
||||
},
|
||||
help: {
|
||||
title: '¿Necesitas ayuda?',
|
||||
description: `Si necesitas ayuda, descárgate nuestro programa de soporte para poder conectarnos
|
||||
remotamente a tu equipo y hacerte la instalación. Proporciónanos un horario de contacto para atenderte, y contactaremos contigo.`,
|
||||
remoteSupport: `Puedes descargarte el programa desde este enlace
|
||||
<a href="http://soporte.verdnatura.es" title="Soporte Verdnatura" target="_blank" style="color:#8dba25">http://soporte.verdnatura.es</a>.`,
|
||||
},
|
||||
},
|
||||
help: 'Cualquier duda que te surja, no dudes en consultarla, <strong>¡estamos para atenderte!</strong>',
|
||||
salesPersonName: 'Soy tu comercial y mi nombre es',
|
||||
salesPersonPhone: 'Teléfono y whatsapp',
|
||||
salesPersonEmail: 'Dirección de e-mail',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
subject: Instalación y configuración de impresora
|
||||
title: "¡Gracias por tu confianza!"
|
||||
description:
|
||||
dear: Estimado cliente
|
||||
instructions: Sigue las instrucciones especificadas en este correo para llevar a
|
||||
cabo la instalación de la impresora.
|
||||
followGuide: Puedes utilizar como guía, el vídeo del montaje del ribon y la cinta
|
||||
<a href='https://www.youtube.com/watch?v=qhb0kgQF3o8' title='Youtube' target='_blank'
|
||||
style='color:#8dba25'>https://www.youtube.com/watch?v=qhb0kgQF3o8</a>. También
|
||||
necesitarás el QLabel, el programa para imprimir las cintas.
|
||||
downloadFrom: Puedes descargarlo desde este enlace <a href='https://godex.s3-accelerate.amazonaws.com/gGnOPoojkP6vC1lgmrbEqQ.file?v01'
|
||||
title='Descargar QLabel' target='_blank' style='color:#8dba25'>https://godex.s3-accelerate.amazonaws.com/gGnOPoojkP6vC1lgmrbEqQ.file?v01</a>
|
||||
sections:
|
||||
QLabel:
|
||||
title: Utilización de QLabel
|
||||
description: Para utilizar el programa de impresión de cintas sigue estos pasos
|
||||
steps:
|
||||
- Abre el programa QLabel
|
||||
- Haz clic en el icono de la barra superior con forma de 'carpeta'
|
||||
- Selecciona el archivo llamado 'model.ezp' adjunto en este correo, y haz clic
|
||||
en abrir
|
||||
- Ve a 'File' -> 'Save as' y guárdalo en el escritorio con otro nombre
|
||||
- Cierra el Qlabel y abre el archivo que acabamos de guardar
|
||||
- Haz clic <strong>encima del texto</strong> con el botón secundario del ratón
|
||||
- Elige la primera opción 'setup'
|
||||
- Cambia el texto para imprimir
|
||||
- Haz clic en el botón 'Ok'
|
||||
- Desplázate con el ratón para ver la medida máxima que ocupa el texto
|
||||
- Haz clic <strong>encima del texto</strong> con el botón secundario del ratón
|
||||
- Elige la segunda opción 'Setup printer'
|
||||
- Haz clic en la primera pestaña 'Label Setup'
|
||||
- Modifica la propiedad 'Paper Height' con la medida máxima consultada anteriormente
|
||||
- 'Comprueba el puerto de la impresora, botón de de la derecha ''SETUP PRINTER''
|
||||
y en la parte derecha, igual como la imagen que adjuntamos, seleccionar la que
|
||||
ponga ''USB00x: GODEX'''
|
||||
- Haz clic en el botón 'Ok'
|
||||
- Haz clic sobre el icono de la impresora
|
||||
- Haz clic en 'Print'
|
||||
help:
|
||||
title: "¿Necesitas ayuda?"
|
||||
description: Si necesitas ayuda, descárgate nuestro programa de soporte para poder
|
||||
conectarnos remotamente a tu equipo y hacerte la instalación. Proporciónanos
|
||||
un horario de contacto para atenderte, y contactaremos contigo.
|
||||
remoteSupport: Puedes descargarte el programa desde este enlace <a href='http://soporte.verdnatura.es'
|
||||
title='Soporte Verdnatura' target='_blank' style='color:#8dba25'>http://soporte.verdnatura.es</a>.
|
||||
help: Cualquier duda que te surja, no dudes en consultarla, <strong>¡estamos para
|
||||
atenderte!</strong>
|
||||
salesPersonName: Soy tu comercial y mi nombre es
|
||||
salesPersonPhone: Teléfono y whatsapp
|
||||
salesPersonEmail: Dirección de e-mail
|