pinstripe 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commands/generate_project.js +18 -0
- package/lib/commands/list_commands.js +2 -4
- package/lib/commands/list_migrations.js +2 -4
- package/lib/commands/list_models.js +2 -4
- package/lib/commands/list_node_wrappers.js +2 -4
- package/lib/commands/list_services.js +2 -4
- package/lib/commands/list_views.js +2 -4
- package/lib/database/row.js +2 -1
- package/lib/database/table.js +2 -1
- package/lib/initialize.client.js +4 -27
- package/lib/node_wrapper.js +52 -3
- package/lib/node_wrappers/anchor.client.js +2 -0
- package/lib/node_wrappers/form.client.js +12 -1
- package/lib/node_wrappers/markdown_editor.client.js +7 -0
- package/lib/node_wrappers/overlay.client.js +13 -0
- package/lib/services/command_names.js +6 -0
- package/lib/services/config.js +0 -1
- package/lib/services/migration_names.js +6 -0
- package/lib/services/model_names.js +6 -0
- package/lib/services/node_wrapper_names.js +6 -0
- package/lib/services/render_form.js +66 -58
- package/lib/services/render_table.js +6 -5
- package/lib/services/send_mail.js +32 -0
- package/lib/services/service_names.js +6 -0
- package/lib/services/stylesheet_view_names.js +10 -0
- package/lib/services/view_names.js +6 -0
- package/lib/views/_layout.js +4 -2
- package/lib/views/sign_in.js +0 -5
- package/lib/views/stylesheets/components/button.css.js +56 -0
- package/lib/views/stylesheets/components/card.css.js +41 -0
- package/lib/views/stylesheets/components/form.css.js +11 -0
- package/lib/views/stylesheets/components/frame.css.js +10 -0
- package/lib/views/stylesheets/components/input.css.js +54 -0
- package/lib/views/stylesheets/components/label.css.js +14 -0
- package/lib/views/stylesheets/components/markdown_editor.css.js +53 -0
- package/lib/views/stylesheets/components/modal.css.js +77 -0
- package/lib/views/stylesheets/components/overlay.css.js +17 -0
- package/lib/views/stylesheets/components/pagination.css.js +80 -0
- package/lib/views/stylesheets/components/progress_bar.css.js +32 -0
- package/lib/views/stylesheets/components/textarea.css.js +17 -0
- package/lib/views/stylesheets/global.css +120 -0
- package/lib/views/stylesheets/reset.css +74 -0
- package/lib/views/stylesheets/vars.css +25 -0
- package/package.json +3 -2
- package/pinstripe_development.db +0 -0
- package/lib/views/base.css.js +0 -406
|
@@ -36,11 +36,29 @@ export default async ({
|
|
|
36
36
|
await generateFile(`lib/index.js`, () => {
|
|
37
37
|
line();
|
|
38
38
|
line(`import { importAll } from 'pinstripe';`);
|
|
39
|
+
dependencies.forEach((dependency) => {
|
|
40
|
+
if(dependency != 'pinstripe') line(`import '${dependency}';`);
|
|
41
|
+
});
|
|
39
42
|
line();
|
|
40
43
|
line(`importAll(import.meta.url);`);
|
|
41
44
|
line();
|
|
42
45
|
});
|
|
43
46
|
|
|
47
|
+
await generateFile(`README.md`, () => {
|
|
48
|
+
line();
|
|
49
|
+
line(`# ${name}`);
|
|
50
|
+
line();
|
|
51
|
+
line('## Getting started');
|
|
52
|
+
line();
|
|
53
|
+
line('```bash');
|
|
54
|
+
indent(() => {
|
|
55
|
+
line('pinstripe init-database');
|
|
56
|
+
line('pinstripe start-server');
|
|
57
|
+
});
|
|
58
|
+
line('```');
|
|
59
|
+
line();
|
|
60
|
+
});
|
|
61
|
+
|
|
44
62
|
spawnSync('yarn', [ 'add', ...dependencies ], {
|
|
45
63
|
stdio: 'inherit'
|
|
46
64
|
});
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export default () => {
|
|
4
|
+
export default ({ commandNames }) => {
|
|
7
5
|
console.log('');
|
|
8
6
|
console.log('The following commands are available:');
|
|
9
7
|
console.log('');
|
|
10
|
-
|
|
8
|
+
commandNames.forEach(commandName => {
|
|
11
9
|
console.log(` * ${chalk.green(commandName)}`);
|
|
12
10
|
});
|
|
13
11
|
console.log('');
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export default () => {
|
|
4
|
+
export default ({ migrationNames }) => {
|
|
7
5
|
console.log('');
|
|
8
6
|
console.log('The following migrations are available:');
|
|
9
7
|
console.log('');
|
|
10
|
-
|
|
8
|
+
migrationNames.forEach(migrationName => {
|
|
11
9
|
console.log(` * ${chalk.green(migrationName)}`);
|
|
12
10
|
});
|
|
13
11
|
console.log('');
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export default () => {
|
|
4
|
+
export default ({ modelNames }) => {
|
|
7
5
|
console.log('');
|
|
8
6
|
console.log('The following models are available:');
|
|
9
7
|
console.log('');
|
|
10
|
-
|
|
8
|
+
modelNames.forEach(modelName => {
|
|
11
9
|
console.log(` * ${chalk.green(modelName)}`);
|
|
12
10
|
});
|
|
13
11
|
console.log('');
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export default () => {
|
|
4
|
+
export default ({ nodeWrapperNames }) => {
|
|
7
5
|
console.log('');
|
|
8
6
|
console.log('The following node wrappers are available:');
|
|
9
7
|
console.log('');
|
|
10
|
-
|
|
8
|
+
nodeWrapperNames.forEach(nodeWrapperName => {
|
|
11
9
|
console.log(` * ${chalk.green(nodeWrapperName)}`);
|
|
12
10
|
});
|
|
13
11
|
console.log('');
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export default () => {
|
|
4
|
+
export default ({ serviceNames }) => {
|
|
7
5
|
console.log('');
|
|
8
6
|
console.log('The following services are available:');
|
|
9
7
|
console.log('');
|
|
10
|
-
|
|
8
|
+
serviceNames.forEach(serviceName => {
|
|
11
9
|
console.log(` * ${chalk.green(serviceName)}`);
|
|
12
10
|
});
|
|
13
11
|
console.log('');
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export default () => {
|
|
4
|
+
export default ({ viewNames }) => {
|
|
7
5
|
console.log('');
|
|
8
6
|
console.log('The following views are available:');
|
|
9
7
|
console.log('');
|
|
10
|
-
|
|
8
|
+
viewNames.forEach(viewName => {
|
|
11
9
|
console.log(` * ${chalk.green(viewName)}`);
|
|
12
10
|
});
|
|
13
11
|
console.log('');
|
package/lib/database/row.js
CHANGED
|
@@ -175,9 +175,10 @@ export const Row = Base.extend().include({
|
|
|
175
175
|
|
|
176
176
|
const submitTitle = 'Save Changes';
|
|
177
177
|
const cancelTitle = 'Cancel';
|
|
178
|
+
const unsavedChangesConfirm = 'There are unsaved changes are you sure you want to close?';
|
|
178
179
|
|
|
179
180
|
return {
|
|
180
|
-
title, fields, submitTitle, cancelTitle,
|
|
181
|
+
title, fields, submitTitle, cancelTitle, unsavedChangesConfirm,
|
|
181
182
|
|
|
182
183
|
submit: async (values, success) => {
|
|
183
184
|
return success(await this.update(values));
|
package/lib/database/table.js
CHANGED
|
@@ -227,9 +227,10 @@ export const Table = Base.extend().include({
|
|
|
227
227
|
|
|
228
228
|
const submitTitle = title;
|
|
229
229
|
const cancelTitle = 'Cancel';
|
|
230
|
+
const unsavedChangesConfirm = 'There are unsaved changes are you sure you want to close?';
|
|
230
231
|
|
|
231
232
|
return {
|
|
232
|
-
title, fields, submitTitle, cancelTitle,
|
|
233
|
+
title, fields, submitTitle, cancelTitle, unsavedChangesConfirm,
|
|
233
234
|
|
|
234
235
|
submit: async (values, success) => {
|
|
235
236
|
return success(await this.insert(values));
|
package/lib/initialize.client.js
CHANGED
|
@@ -2,33 +2,10 @@
|
|
|
2
2
|
import { NodeWrapper } from './node_wrapper.js';
|
|
3
3
|
|
|
4
4
|
if(typeof window != 'undefined'){
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const observer = new MutationObserver(mutations => {
|
|
12
|
-
if(ready){
|
|
13
|
-
mutations.forEach(
|
|
14
|
-
mutation => {
|
|
15
|
-
mutation.addedNodes.forEach(node => initializeTree(node));
|
|
16
|
-
}
|
|
17
|
-
)
|
|
18
|
-
}
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
observer.observe(document.documentElement, {
|
|
22
|
-
attributes: false,
|
|
23
|
-
childList: true,
|
|
24
|
-
subtree: true
|
|
5
|
+
window.addEventListener('DOMContentLoaded', (event) => {
|
|
6
|
+
const documentNodeWrapper = NodeWrapper.instanceFor(document);
|
|
7
|
+
documentNodeWrapper.observe({ add: true }, nodeWrapper => nodeWrapper.descendants);
|
|
8
|
+
documentNodeWrapper.patch(document.documentElement.outerHTML);
|
|
25
9
|
});
|
|
26
|
-
|
|
27
|
-
setTimeout(() => {
|
|
28
|
-
ready = true
|
|
29
|
-
NodeWrapper.instanceFor(document).patch(
|
|
30
|
-
document.documentElement.outerHTML
|
|
31
|
-
);
|
|
32
|
-
}, 0);
|
|
33
10
|
}
|
|
34
11
|
|
package/lib/node_wrapper.js
CHANGED
|
@@ -45,6 +45,7 @@ export const NodeWrapper = Base.extend().include({
|
|
|
45
45
|
initialize(node, skipInit = false){
|
|
46
46
|
this.node = node;
|
|
47
47
|
this._registeredEventListeners = [];
|
|
48
|
+
this._registeredObservers = [];
|
|
48
49
|
this._registeredTimers = [];
|
|
49
50
|
this._virtualNodeFilters = [];
|
|
50
51
|
|
|
@@ -54,6 +55,12 @@ export const NodeWrapper = Base.extend().include({
|
|
|
54
55
|
this.traverse(normalizeVirtualNode);
|
|
55
56
|
});
|
|
56
57
|
|
|
58
|
+
const { autofocus } = this.attributes;
|
|
59
|
+
|
|
60
|
+
if(autofocus){
|
|
61
|
+
this.setTimeout(() => this.node.focus());
|
|
62
|
+
}
|
|
63
|
+
|
|
57
64
|
const { autosubmit, trigger } = this.data;
|
|
58
65
|
|
|
59
66
|
if(autosubmit){
|
|
@@ -375,7 +382,45 @@ export const NodeWrapper = Base.extend().include({
|
|
|
375
382
|
addVirtualNodeFilter(fn){
|
|
376
383
|
this._virtualNodeFilters.push(fn);
|
|
377
384
|
return this;
|
|
378
|
-
}
|
|
385
|
+
},
|
|
386
|
+
|
|
387
|
+
observe: overload({
|
|
388
|
+
['object, function'](options, fn){
|
|
389
|
+
const { add = false, remove = false, alter = false } = options;
|
|
390
|
+
|
|
391
|
+
const observer = new MutationObserver(mutations => {
|
|
392
|
+
mutations.forEach(
|
|
393
|
+
mutation => {
|
|
394
|
+
if(mutation.type == 'childList'){
|
|
395
|
+
if(add) mutation.addedNodes.forEach(node => fn(NodeWrapper.instanceFor(node), 'add'));
|
|
396
|
+
if(remove) mutation.removedNodes.forEach(node => fn(NodeWrapper.instanceFor(node), 'remove'));
|
|
397
|
+
}
|
|
398
|
+
if(mutation.type == 'attributes' && alter){
|
|
399
|
+
fn(NodeWrapper.instanceFor(mutation.target), 'alter', mutation.attributeName);
|
|
400
|
+
}
|
|
401
|
+
if(mutation.type == 'characterData' && alter){
|
|
402
|
+
fn(NodeWrapper.instanceFor(mutation.target), 'alter', 'value');
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
)
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
observer.observe(this.node, {
|
|
409
|
+
attributes: alter,
|
|
410
|
+
characterData: 'alter',
|
|
411
|
+
childList: add || remove,
|
|
412
|
+
subtree: true
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
this._registeredObservers.push(observer);
|
|
416
|
+
|
|
417
|
+
return this;
|
|
418
|
+
},
|
|
419
|
+
|
|
420
|
+
function(fn){
|
|
421
|
+
return this.observe({ add: true, remove: true, alter: true }, fn);
|
|
422
|
+
}
|
|
423
|
+
})
|
|
379
424
|
});
|
|
380
425
|
|
|
381
426
|
function cleanChildren(){
|
|
@@ -391,6 +436,10 @@ function clean(){
|
|
|
391
436
|
this.node.removeEventListener(...this._registeredEventListeners.pop());
|
|
392
437
|
}
|
|
393
438
|
|
|
439
|
+
while(this._registeredObservers.length){
|
|
440
|
+
this._registeredObservers.pop().disconnect();
|
|
441
|
+
}
|
|
442
|
+
|
|
394
443
|
clearTimers.call(this);
|
|
395
444
|
|
|
396
445
|
if(this._overlayChild) this._overlayChild.remove();
|
|
@@ -427,8 +476,8 @@ function createVirtualNode(html){
|
|
|
427
476
|
}
|
|
428
477
|
|
|
429
478
|
function patch(attributes, virtualChildren){
|
|
430
|
-
if(this.is('.progress-bar')) return;
|
|
431
|
-
const isEmptyFrame = this.is('.frame') && virtualChildren.length == 0;
|
|
479
|
+
if(this.is('.ps-progress-bar')) return;
|
|
480
|
+
const isEmptyFrame = this.is('.ps-frame') && virtualChildren.length == 0;
|
|
432
481
|
if(isEmptyFrame && attributes['data-load-on-init'] === undefined){
|
|
433
482
|
attributes['data-load-on-init'] = 'true';
|
|
434
483
|
}
|
|
@@ -14,5 +14,7 @@ export default {
|
|
|
14
14
|
if(action == 'load') loadFrame.call(this, confirm, target, method, href);
|
|
15
15
|
if(action == 'remove') removeFrame.call(this, confirm, target);
|
|
16
16
|
});
|
|
17
|
+
|
|
18
|
+
if(this.is('input, textarea')) this.on('keyup', (event) => this.trigger('click'));
|
|
17
19
|
}
|
|
18
20
|
};
|
|
@@ -6,11 +6,22 @@ export default {
|
|
|
6
6
|
initialize(...args){
|
|
7
7
|
this.constructor.parent.prototype.initialize.call(this, ...args);
|
|
8
8
|
|
|
9
|
+
const { confirm, target = '_self', method = 'GET', action } = { ...this.attributes, ...this.data };
|
|
10
|
+
|
|
9
11
|
this.on('submit', (event) => {
|
|
10
12
|
event.preventDefault();
|
|
11
13
|
event.stopPropagation();
|
|
12
|
-
|
|
14
|
+
|
|
13
15
|
loadFrame.call(this, confirm, target, method, action);
|
|
14
16
|
});
|
|
17
|
+
|
|
18
|
+
this._initialHash = JSON.stringify(this.values);
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
isForm: true,
|
|
22
|
+
|
|
23
|
+
get hasUnsavedChanges(){
|
|
24
|
+
return this.data.hasUnsavedChanges || JSON.stringify(this.values) != this._initialHash;
|
|
15
25
|
}
|
|
26
|
+
|
|
16
27
|
};
|
|
@@ -13,6 +13,13 @@ export default {
|
|
|
13
13
|
|
|
14
14
|
const previewFrame = this.frame.descendants.find(n => n.is('.ps-markdown-editor-preview-pane'));
|
|
15
15
|
|
|
16
|
+
previewFrame.observe((current) => {
|
|
17
|
+
while(current.parent && current.parent != previewFrame) {
|
|
18
|
+
current = current.parent;
|
|
19
|
+
}
|
|
20
|
+
if(current.node.scrollIntoView) current.node.scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"});
|
|
21
|
+
})
|
|
22
|
+
|
|
16
23
|
this.on('submit', () => {
|
|
17
24
|
const { value } = this.values;
|
|
18
25
|
previewFrame.load({ _method: 'post', value });
|
|
@@ -16,7 +16,20 @@ export default {
|
|
|
16
16
|
},
|
|
17
17
|
|
|
18
18
|
remove(...args){
|
|
19
|
+
if(window.getSelection().type == 'Range') return;
|
|
20
|
+
|
|
21
|
+
let canRemove = true;
|
|
22
|
+
this.descendants.filter(n => n.isForm).forEach(({ hasUnsavedChanges, data: { unsavedChangesConfirm } }) => {
|
|
23
|
+
if(hasUnsavedChanges && unsavedChangesConfirm && !confirm(unsavedChangesConfirm)){
|
|
24
|
+
canRemove = false;
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
if(!canRemove) return;
|
|
28
|
+
|
|
19
29
|
this.constructor.parent.prototype.remove.call(this, ...args);
|
|
30
|
+
|
|
31
|
+
delete this.parent._overlayChild;
|
|
32
|
+
|
|
20
33
|
if(!this.document.descendants.find(node => node.is('body')).children.filter((child) => child.is('.ps-overlay')).length){
|
|
21
34
|
this.document.descendants.filter(node => node.is('html')).forEach(node => {
|
|
22
35
|
node.removeClass('ps-has-overlay');
|
package/lib/services/config.js
CHANGED
|
@@ -50,6 +50,7 @@ export default {
|
|
|
50
50
|
const fields = extractFields(formAdapter, options);
|
|
51
51
|
const submitTitle = options.submitTitle || formAdapter.submitTitle;
|
|
52
52
|
const cancelTitle = options.cancelTitle || formAdapter.cancelTitle;
|
|
53
|
+
const unsavedChangesConfirm = options.unsavedChangesConfirm || formAdapter.unsavedChangesConfirm;
|
|
53
54
|
|
|
54
55
|
const indexedFields = indexFieldsByName(fields);
|
|
55
56
|
const otherErrors = [];
|
|
@@ -72,67 +73,74 @@ export default {
|
|
|
72
73
|
return renderHtml`
|
|
73
74
|
<div class="ps-modal" data-node-wrapper="anchor" data-action="remove" data-ignore-events-from-children="true">
|
|
74
75
|
<button data-node-wrapper="anchor" data-action="remove"></button>
|
|
75
|
-
<form
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
<form
|
|
77
|
+
class="ps-card"
|
|
78
|
+
method="post"
|
|
79
|
+
enctype="multipart/form-data"
|
|
80
|
+
autocomplete="off"
|
|
81
|
+
${unsavedChangesConfirm ? renderHtml`data-unsaved-changes-confirm="${unsavedChangesConfirm}"` : undefined}
|
|
82
|
+
${unsavedChangesConfirm && params._method == 'POST' ? renderHtml`data-has-unsaved-changes="true"` : undefined}
|
|
83
|
+
>
|
|
84
|
+
<div class="ps-card-header">
|
|
85
|
+
<p class="ps-card-header-title">${title}</p>
|
|
86
|
+
</div>
|
|
87
|
+
<div class="ps-card-body">
|
|
88
|
+
${() => {
|
|
89
|
+
if(otherErrors.length){
|
|
90
|
+
return renderHtml`
|
|
91
|
+
<div class="ps-field">
|
|
92
|
+
${otherErrors.map(error => renderHtml`
|
|
93
|
+
<p class="ps-is-error">${error}</p>
|
|
94
|
+
`)}
|
|
95
|
+
</div>
|
|
96
|
+
`
|
|
97
|
+
}
|
|
98
|
+
}}
|
|
99
|
+
${fields.map(({ label, name, type, value, error }) => {
|
|
100
|
+
if(type == 'hidden'){
|
|
101
|
+
return renderHtml`
|
|
102
|
+
<input type="hidden" name="${name}" value="${value}">
|
|
103
|
+
`;
|
|
104
|
+
}
|
|
82
105
|
return renderHtml`
|
|
83
|
-
<div
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
106
|
+
<div>
|
|
107
|
+
<label class="ps-label">${label}</label>
|
|
108
|
+
${() => {
|
|
109
|
+
if(type == 'textarea'){
|
|
110
|
+
return renderHtml`
|
|
111
|
+
<textarea class="ps-textarea${error ? ' ps-is-error' : ''}" name="${name}">${value}</textarea>
|
|
112
|
+
`
|
|
113
|
+
}
|
|
114
|
+
if(type == 'markdown'){
|
|
115
|
+
return renderHtml`
|
|
116
|
+
<textarea class="ps-textarea${error ? ' ps-is-error' : ''}" name="${name}" data-node-wrapper="anchor" data-target="_overlay" data-href="&_part=markdown-editor">${value}</textarea>
|
|
117
|
+
`
|
|
118
|
+
}
|
|
119
|
+
if(type == 'checkbox'){
|
|
120
|
+
return renderHtml`
|
|
121
|
+
<input class="ps-input${error ? ' ps-is-error' : ''}" type="checkbox" name="${name}" type="${type}" ${value ? 'checked' : ''} />
|
|
122
|
+
`
|
|
123
|
+
}
|
|
124
|
+
return renderHtml`
|
|
125
|
+
<input class="ps-input${error ? ' ps-is-error' : ''}" name="${name}" type="${type}" value="${value}">
|
|
126
|
+
`
|
|
127
|
+
}}
|
|
128
|
+
${() => {
|
|
129
|
+
if(error){
|
|
130
|
+
return renderHtml`
|
|
131
|
+
<p class="ps-is-error">${error}</p>
|
|
132
|
+
`
|
|
133
|
+
}
|
|
134
|
+
}}
|
|
87
135
|
</div>
|
|
88
|
-
`
|
|
89
|
-
}
|
|
90
|
-
}}
|
|
91
|
-
${fields.map(({ label, name, type, value, error }) => {
|
|
92
|
-
if(type == 'hidden'){
|
|
93
|
-
return renderHtml`
|
|
94
|
-
<input type="hidden" name="${name}" value="${value}">
|
|
95
136
|
`;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<textarea class="ps-textarea${error ? ' ps-is-error' : ''}" name="${name}">${value}</textarea>
|
|
104
|
-
`
|
|
105
|
-
}
|
|
106
|
-
if(type == 'markdown'){
|
|
107
|
-
return renderHtml`
|
|
108
|
-
<textarea class="ps-textarea${error ? ' ps-is-error' : ''}" name="${name}" data-node-wrapper="anchor" data-target="_overlay" data-href="&_part=markdown-editor">${value}</textarea>
|
|
109
|
-
`
|
|
110
|
-
}
|
|
111
|
-
if(type == 'checkbox'){
|
|
112
|
-
return renderHtml`
|
|
113
|
-
<input class="ps-input${error ? ' ps-is-error' : ''}" type="checkbox" name="${name}" type="${type}" ${value ? 'checked' : ''} />
|
|
114
|
-
`
|
|
115
|
-
}
|
|
116
|
-
return renderHtml`
|
|
117
|
-
<input class="ps-input${error ? ' ps-is-error' : ''}" name="${name}" type="${type}" value="${value}">
|
|
118
|
-
`
|
|
119
|
-
}}
|
|
120
|
-
${() => {
|
|
121
|
-
if(error){
|
|
122
|
-
return renderHtml`
|
|
123
|
-
<p class="ps-is-error">${error}</p>
|
|
124
|
-
`
|
|
125
|
-
}
|
|
126
|
-
}}
|
|
127
|
-
</div>
|
|
128
|
-
`;
|
|
129
|
-
})}
|
|
130
|
-
</section>
|
|
131
|
-
<footer>
|
|
132
|
-
<button class="ps-button" type="submit">${submitTitle}</button>
|
|
133
|
-
<button class="ps-button" data-node-wrapper="anchor" data-action="remove">${cancelTitle}</button>
|
|
134
|
-
</footer>
|
|
135
|
-
</form>
|
|
137
|
+
})}
|
|
138
|
+
</div>
|
|
139
|
+
<div class="ps-card-footer">
|
|
140
|
+
<button class="ps-button" type="submit">${submitTitle}</button>
|
|
141
|
+
<button class="ps-button" data-node-wrapper="anchor" data-action="remove">${cancelTitle}</button>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
136
144
|
</div>
|
|
137
145
|
`;
|
|
138
146
|
},
|
|
@@ -26,15 +26,16 @@ export default ({ overload, renderList, renderHtml, params: { _headers = {} } })
|
|
|
26
26
|
return renderHtml`
|
|
27
27
|
<div class="ps-modal" data-node-wrapper="anchor" data-action="remove" data-ignore-events-from-children="true">
|
|
28
28
|
<button data-node-wrapper="anchor" data-action="remove"></button>
|
|
29
|
-
|
|
29
|
+
<div class="ps-card-body">
|
|
30
|
+
<div class="ps-card-title">
|
|
30
31
|
<p>${name}</p>
|
|
31
|
-
</
|
|
32
|
-
<div>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="ps-card-body">
|
|
33
34
|
${out}
|
|
34
35
|
</div>
|
|
35
|
-
<footer>
|
|
36
|
+
<div class="ps-card-footer">
|
|
36
37
|
<button class="button" data-action="remove">Close</button>
|
|
37
|
-
</
|
|
38
|
+
</div>
|
|
38
39
|
</div>
|
|
39
40
|
</div>
|
|
40
41
|
`;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
import { createTransport } from 'nodemailer';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
|
|
5
|
+
export default async ({ config }) => {
|
|
6
|
+
const { mail: mailConfig = {} } = await config;
|
|
7
|
+
const transport = createTransport(mailConfig);
|
|
8
|
+
return (mailOptions = {}) => {
|
|
9
|
+
if(process.env.NODE_ENV == 'production') return transport.sendMail(mailOptions);
|
|
10
|
+
const { text, html, ...otherMailOptions } = mailOptions;
|
|
11
|
+
console.log('');
|
|
12
|
+
console.log('----------------------------------------');
|
|
13
|
+
console.log(chalk.green('sendMail'));
|
|
14
|
+
console.log('----------------------------------------');
|
|
15
|
+
Object.keys(otherMailOptions).forEach(name => {
|
|
16
|
+
console.log(`${name}: ${JSON.stringify(otherMailOptions[name])}`)
|
|
17
|
+
});
|
|
18
|
+
if(text){
|
|
19
|
+
console.log('text:')
|
|
20
|
+
console.log(text.replace(/(^|\n)/g, '$1 '));
|
|
21
|
+
}
|
|
22
|
+
if(html){
|
|
23
|
+
console.log('html:')
|
|
24
|
+
console.log(html.replace(/(^|\n)/g, '$1 '));
|
|
25
|
+
}
|
|
26
|
+
if(!Object.keys(mailOptions).length){
|
|
27
|
+
console.log('No mail options have been provided.')
|
|
28
|
+
}
|
|
29
|
+
console.log('----------------------------------------');
|
|
30
|
+
console.log('');
|
|
31
|
+
};
|
|
32
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
export default ({ viewNames }) => {
|
|
3
|
+
const nonComponentStylesheetViewNames = [
|
|
4
|
+
'stylesheets/vars.css',
|
|
5
|
+
'stylesheets/reset.css',
|
|
6
|
+
'stylesheets/global.css',
|
|
7
|
+
];
|
|
8
|
+
const componentStylesheetViewNames = viewNames.filter(viewName => viewName.match(/\.css$/) && !nonComponentStylesheetViewNames.includes(viewName))
|
|
9
|
+
return [ ...nonComponentStylesheetViewNames, ...componentStylesheetViewNames ];
|
|
10
|
+
};
|
package/lib/views/_layout.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
|
|
2
|
-
export default async ({ params: { title, body, isSignedIn, user }, renderHtml }) => renderHtml`
|
|
2
|
+
export default async ({ params: { title, body, isSignedIn, user }, renderHtml, stylesheetViewNames }) => renderHtml`
|
|
3
3
|
<!DOCTYPE html>
|
|
4
4
|
<html>
|
|
5
5
|
<head>
|
|
6
6
|
<title>${title}</title>
|
|
7
|
-
|
|
7
|
+
${stylesheetViewNames.map(viewName => renderHtml`
|
|
8
|
+
<link rel="stylesheet" href="/${viewName}">
|
|
9
|
+
`)}
|
|
8
10
|
<script src="/bundle.js"></script>
|
|
9
11
|
</head>
|
|
10
12
|
<body>
|
package/lib/views/sign_in.js
CHANGED