mirror of
https://github.com/frappe/books.git
synced 2024-11-14 01:14:03 +00:00
Merge pull request #39 from pratu16x7/dev
[refactor] FormLayout for repurposing layouts, UI tree, make desk optional
This commit is contained in:
commit
3b284e9ec6
@ -74,16 +74,14 @@ module.exports = class sqliteDatabase extends Database {
|
||||
}
|
||||
|
||||
getColumnDefinition(field) {
|
||||
let def = `${field.fieldname} ${this.typeMap[field.fieldtype]}`;
|
||||
if (field.fieldname==='name') {
|
||||
def += ' PRIMARY KEY NOT NULL';
|
||||
}
|
||||
else if (field.required) {
|
||||
def += ' NOT NULL';
|
||||
}
|
||||
if (field.default) {
|
||||
def += `DEFAULT ${field.default}`;
|
||||
}
|
||||
let def = [
|
||||
field.fieldname,
|
||||
this.typeMap[field.fieldtype],
|
||||
field.fieldname === 'name' ? 'PRIMARY KEY NOT NULL' : '',
|
||||
field.required ? 'NOT NULL' : '',
|
||||
field.default ? `DEFAULT ${field.default}` : ''
|
||||
].join(' ');
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ module.exports = class Desk {
|
||||
|
||||
let body = document.querySelector('body');
|
||||
//this.navbar = new Navbar();
|
||||
frappe.ui.empty(body);
|
||||
this.container = frappe.ui.add('div', '', body);
|
||||
this.containerRow = frappe.ui.add('div', 'row no-gutters', this.container)
|
||||
this.makeColumns(columns);
|
||||
@ -100,7 +101,6 @@ module.exports = class Desk {
|
||||
this.menu.setActive();
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
toggleCenter(show) {
|
||||
@ -173,5 +173,4 @@ module.exports = class Desk {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -6,7 +6,7 @@ const Desk = require('./desk');
|
||||
const Observable = require('frappejs/utils/observable');
|
||||
|
||||
module.exports = {
|
||||
async start({server, columns = 2}) {
|
||||
async start({server, columns = 2, makeDesk = 1}) {
|
||||
window.frappe = frappe;
|
||||
frappe.init();
|
||||
frappe.registerLibs(common);
|
||||
@ -24,6 +24,12 @@ module.exports = {
|
||||
|
||||
await frappe.getSingle('SystemSettings');
|
||||
|
||||
if(makeDesk) {
|
||||
this.makeDesk(columns);
|
||||
}
|
||||
},
|
||||
|
||||
async makeDesk(columns) {
|
||||
frappe.desk = new Desk(columns);
|
||||
await frappe.login();
|
||||
},
|
||||
|
@ -4,6 +4,7 @@
|
||||
@import "node_modules/flatpickr/dist/themes/airbnb";
|
||||
@import "node_modules/codemirror/lib/codemirror";
|
||||
@import "node_modules/frappe-datatable/dist/frappe-datatable";
|
||||
// @import "node_modules/octicons/build/build.css";
|
||||
|
||||
$spacer-1: 0.25rem;
|
||||
$spacer-2: 0.5rem;
|
||||
@ -252,3 +253,157 @@ mark {
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
margin: $spacer-1;
|
||||
}
|
||||
|
||||
.vertical-margin {
|
||||
margin: $spacer-3 0px;
|
||||
}
|
||||
|
||||
.tree {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.tree li {
|
||||
list-style: none;
|
||||
margin: 2px 0px;
|
||||
}
|
||||
|
||||
ul.tree-children {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.tree-link {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.tree-link .node-parent {
|
||||
color: $gray-600;
|
||||
font-size: 14px;
|
||||
width: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tree-link .node-leaf {
|
||||
color: $gray-400;
|
||||
}
|
||||
|
||||
.tree-link .node-parent, .tree-link .node-leaf {
|
||||
margin-right: 5px;
|
||||
margin-left: 2px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.tree-link.active {
|
||||
svg {
|
||||
color: $blue;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $gray-600;
|
||||
}
|
||||
}
|
||||
|
||||
.tree-hover {
|
||||
background-color: $gray-200;
|
||||
min-height: 20px;
|
||||
border: 1px solid $gray-600;
|
||||
}
|
||||
|
||||
.tree-node-toolbar {
|
||||
display: inline-block;
|
||||
padding: 0px 5px;
|
||||
margin-left: 15px;
|
||||
margin-bottom: -4px;
|
||||
margin-top: -8px;
|
||||
}
|
||||
|
||||
// @media (max-width: @screen-xs) {
|
||||
// ul.tree-children {
|
||||
// padding-left: 10px;
|
||||
// }
|
||||
// }
|
||||
|
||||
// decoration
|
||||
// .tree, .tree-node {
|
||||
.tree.with-skeleton, .tree.with-skeleton .tree-node {
|
||||
position: relative;
|
||||
|
||||
&.opened::before, &:last-child::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
left: 7px;
|
||||
height: calc(100% - 23px);
|
||||
width: 1px;
|
||||
background: $gray-400;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
&:last-child::after {
|
||||
top: 11px;
|
||||
left: -13px;
|
||||
height: calc(100% - 15px);
|
||||
width: 3px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
&.opened > .tree-children > .tree-node > .tree-link::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 18px;
|
||||
height: 1px;
|
||||
top: 10px;
|
||||
left: -12px;
|
||||
z-index: -1;
|
||||
background: $gray-400;
|
||||
}
|
||||
}
|
||||
|
||||
.tree.with-skeleton.opened::before {
|
||||
left: 22px;
|
||||
top: 33px;
|
||||
height: calc(100% - 67px);
|
||||
}
|
||||
|
||||
.tree-link.active ~ .balance-area {
|
||||
color: $gray-600 !important;
|
||||
}
|
||||
|
||||
// just for accounting
|
||||
|
||||
.setup-container {
|
||||
margin: 40px auto;
|
||||
padding: 20px 0px;
|
||||
width: 450px;
|
||||
|
||||
border: 1px solid $gray-300;
|
||||
border-radius: 4px;
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-body {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.form-body.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.setup-link-area {
|
||||
margin: $spacer-1 $spacer-4;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,48 @@ const frappe = require('frappejs');
|
||||
const Dropdown = require('./dropdown');
|
||||
|
||||
module.exports = {
|
||||
create(tag, obj) {
|
||||
if(!obj) {
|
||||
let div = document.createElement('div');
|
||||
div.innerHTML = tag.trim();
|
||||
return div.firstChild;
|
||||
}
|
||||
let element = document.createElement(tag);
|
||||
|
||||
let $ = (expr, con) => {
|
||||
return typeof expr === "string"
|
||||
? (con || document).querySelector(expr)
|
||||
: expr || null;
|
||||
}
|
||||
|
||||
for (var i in obj) {
|
||||
let val = obj[i];
|
||||
|
||||
if (i === "inside") {
|
||||
$(val).appendChild(element);
|
||||
}
|
||||
else if (i === "around") {
|
||||
let ref = $(val);
|
||||
ref.parentNode.insertBefore(element, ref);
|
||||
element.appendChild(ref);
|
||||
|
||||
} else if (i === "styles") {
|
||||
if(typeof val === "object") {
|
||||
Object.keys(val).map(prop => {
|
||||
element.style[prop] = val[prop];
|
||||
});
|
||||
}
|
||||
} else if (i in element ) {
|
||||
element[i] = val;
|
||||
}
|
||||
else {
|
||||
element.setAttribute(i, val);
|
||||
}
|
||||
}
|
||||
|
||||
return element;
|
||||
},
|
||||
|
||||
add(tag, className, parent, textContent) {
|
||||
let element = document.createElement(tag);
|
||||
if (className) {
|
||||
@ -36,7 +78,7 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
remove_class(element, className) {
|
||||
removeClass(element, className) {
|
||||
if (element.classList) {
|
||||
element.classList.remove(className);
|
||||
} else {
|
||||
|
171
client/ui/tree.js
Normal file
171
client/ui/tree.js
Normal file
@ -0,0 +1,171 @@
|
||||
const frappe = require('frappejs');
|
||||
const octicons = require('octicons');
|
||||
const utils = require('frappejs/client/ui/utils');
|
||||
|
||||
class Tree {
|
||||
constructor({parent, label, iconSet, withSkeleton, method}) {
|
||||
Object.assign(this, arguments[0]);
|
||||
this.nodes = {};
|
||||
if(!iconSet) {
|
||||
this.iconSet = {
|
||||
open: octicons["triangle-down"].toSVG({ "width": 10, "class": "node-parent"}),
|
||||
closed: octicons["triangle-right"].toSVG({ "width": 5, "class": "node-parent"}),
|
||||
leaf: octicons["primitive-dot"].toSVG({ "width": 7, "class": "node-leaf"})
|
||||
};
|
||||
}
|
||||
this.make();
|
||||
}
|
||||
|
||||
make() {
|
||||
this.tree = frappe.ui.create('div', {
|
||||
inside: this.parent,
|
||||
className: 'tree ' + (this.withSkeleton ? 'with-skeleton' : '')
|
||||
});
|
||||
|
||||
this.rootNode = this.makeNode(this.label, this.label, true, null, this.tree);
|
||||
this.expandNode(this.rootNode);
|
||||
}
|
||||
|
||||
refresh() {
|
||||
// this.selectedNode.parentNode &&
|
||||
// this.loadChildren(this.selectedNode.parentNode, true);
|
||||
}
|
||||
|
||||
loadChildren(node, deep=false) {
|
||||
if(!deep) {
|
||||
this.renderNodeChildren(node, this.method(node.value));
|
||||
} else {
|
||||
this.renderChildrenDeep(node, this.getAllNodes(node.value));
|
||||
}
|
||||
}
|
||||
|
||||
renderChildrenDeep(dataList) {
|
||||
dataList.map(d => { this.renderNodeChildren(this.nodes[d.parent], d.data); });
|
||||
}
|
||||
|
||||
renderNodeChildren(node, dataSet=[]) {
|
||||
frappe.ui.empty(node.childrenList);
|
||||
|
||||
dataSet.forEach(data => {
|
||||
let parentNode = this.nodes[node.value];
|
||||
let childNode = this.makeNode(data.label || data.value, data.value,
|
||||
data.expandable, parentNode);
|
||||
childNode.treeLink.dataset.nodeData = data;
|
||||
});
|
||||
node.expanded = false;
|
||||
|
||||
// As children loaded
|
||||
node.loaded = true;
|
||||
this.onNodeClick(node, false);
|
||||
}
|
||||
|
||||
getAllNodes() { }
|
||||
|
||||
makeNode(label, value, expandable, parentNode, parentEl) {
|
||||
let node = {
|
||||
parent: parent,
|
||||
label: label,
|
||||
value: value,
|
||||
loaded: 0,
|
||||
expanded: 0,
|
||||
expandable: expandable,
|
||||
};
|
||||
|
||||
if(parentNode){
|
||||
node.parentNode = parentNode;
|
||||
node.parent = parentNode.childrenList;
|
||||
node.isRoot = 0;
|
||||
} else {
|
||||
node.isRoot = 1;
|
||||
node.parent = parentEl;
|
||||
}
|
||||
|
||||
this.nodes[value] = node;
|
||||
this.buildNodeElement(node);
|
||||
this.onRender && this.onRender(node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
buildNodeElement(node) {
|
||||
node.parentLi = frappe.ui.create('li', {
|
||||
inside: node.parent,
|
||||
className: 'tree-node'
|
||||
});
|
||||
|
||||
let iconHtml = '';
|
||||
if(this.iconSet) {
|
||||
iconHtml = node.expandable ? this.iconSet.closed : this.iconSet.leaf;
|
||||
}
|
||||
let labelEl = `<a class="tree-label"> ${node.label}</a>`;
|
||||
|
||||
node.treeLink = frappe.ui.create('span', {
|
||||
inside: node.parentLi,
|
||||
className: 'tree-link',
|
||||
'data-label': node.label,
|
||||
innerHTML: iconHtml + labelEl
|
||||
});
|
||||
node.treeLink.dataset.node = node;
|
||||
node.treeLink.addEventListener('click', () => {
|
||||
this.onNodeClick(node);
|
||||
});
|
||||
|
||||
node.childrenList = frappe.ui.create('ul', {
|
||||
inside: node.parentLi,
|
||||
className: 'tree-children hide'
|
||||
});
|
||||
|
||||
// if(this.toolbar) {
|
||||
// node.toolbar = this.getToolbar(node).insertAfter(node.treeLink);
|
||||
// }
|
||||
}
|
||||
|
||||
onNodeClick(node, click = true) {
|
||||
this.setSelectedNode(node);
|
||||
if(click) {
|
||||
this.onClick && this.onClick(node);
|
||||
}
|
||||
this.expandNode(node);
|
||||
// select link
|
||||
utils.activate(this.tree, node.treeLink, 'tree-link', 'active');
|
||||
if(node.toolbar) this.showToolbar(node);
|
||||
}
|
||||
|
||||
expandNode(node) {
|
||||
if(node.expandable) {
|
||||
this.toggleNode(node);
|
||||
}
|
||||
|
||||
node.expanded = !node.expanded;
|
||||
// node.parent.classList.toggle('opened', node.expanded);
|
||||
node.parent.classList.add('opened');
|
||||
node.parentLi.classList.add('opened');
|
||||
}
|
||||
|
||||
toggleNode(node) {
|
||||
if(!node.loaded) this.loadChildren(node);
|
||||
|
||||
// expand children
|
||||
if(node.childrenList) {
|
||||
if(node.childrenList.innerHTML.length) {
|
||||
node.childrenList.classList.toggle('hide', !node.expanded);
|
||||
}
|
||||
|
||||
// open close icon
|
||||
if(this.iconSet) {
|
||||
const oldIcon = node.treeLink.querySelector('svg');
|
||||
const newIconKey = !node.expanded ? 'closed' : 'open';
|
||||
const newIcon = frappe.ui.create(this.iconSet[newIconKey]);
|
||||
node.treeLink.replaceChild(newIcon, oldIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getSelectedNode() { return this.selectedNode; }
|
||||
|
||||
setSelectedNode(node) { this.selectedNode = node; }
|
||||
|
||||
showToolbar() { }
|
||||
}
|
||||
|
||||
module.exports = Tree;
|
@ -24,5 +24,33 @@ module.exports = {
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
addLink(label, parent, action, unhide = true) {
|
||||
const link = frappe.ui.add('button', 'btn btn-sm btn-outline-secondary', parent, label);
|
||||
link.addEventListener('click', action);
|
||||
if (unhide) {
|
||||
parent.classList.remove('hide');
|
||||
}
|
||||
return link;
|
||||
},
|
||||
|
||||
// https://css-tricks.com/snippets/javascript/loop-queryselectorall-matches/
|
||||
forEachNode(nodeList, callback, scope) {
|
||||
if(!nodeList) return;
|
||||
for (var i = 0; i < nodeList.length; i++) {
|
||||
callback.call(scope, nodeList[i], i);
|
||||
}
|
||||
},
|
||||
|
||||
activate($parent, $child, commonClass, activeClass='active', index = -1) {
|
||||
let $children = $parent.querySelectorAll(`.${commonClass}.${activeClass}`);
|
||||
|
||||
this.forEachNode($children, (node, i) => {
|
||||
if(index >= 0 && i <= index) return;
|
||||
node.classList.remove(activeClass);
|
||||
})
|
||||
|
||||
$child.classList.add(activeClass);
|
||||
}
|
||||
}
|
@ -1,20 +1,17 @@
|
||||
const frappe = require('frappejs');
|
||||
const controls = require('./controls');
|
||||
const FormLayout = require('./formLayout');
|
||||
const Observable = require('frappejs/utils/observable');
|
||||
const keyboard = require('frappejs/client/ui/keyboard');
|
||||
const utils = require('frappejs/client/ui/utils');
|
||||
|
||||
module.exports = class BaseForm extends Observable {
|
||||
constructor({doctype, parent, submit_label='Submit', container, meta, inline=false}) {
|
||||
super();
|
||||
Object.assign(this, arguments[0]);
|
||||
this.controls = {};
|
||||
this.controlList = [];
|
||||
this.sections = [];
|
||||
this.links = [];
|
||||
|
||||
if (!this.meta) {
|
||||
this.meta = frappe.getMeta(this.doctype);
|
||||
}
|
||||
this.meta = frappe.getMeta(this.doctype);
|
||||
|
||||
if (this.setup) {
|
||||
this.setup();
|
||||
@ -52,7 +49,13 @@ module.exports = class BaseForm extends Observable {
|
||||
|
||||
this.form.onValidate = true;
|
||||
|
||||
this.makeLayout();
|
||||
this.formLayout = new FormLayout({
|
||||
fields: this.meta.fields,
|
||||
layout: this.meta.layout
|
||||
});
|
||||
|
||||
this.form.appendChild(this.formLayout.form);
|
||||
|
||||
this.bindKeyboard();
|
||||
}
|
||||
|
||||
@ -64,47 +67,6 @@ module.exports = class BaseForm extends Observable {
|
||||
}
|
||||
}
|
||||
|
||||
makeLayout() {
|
||||
if (this.meta.layout) {
|
||||
for (let section of this.meta.layout) {
|
||||
this.makeSection(section);
|
||||
}
|
||||
} else {
|
||||
this.makeControls(this.meta.fields);
|
||||
}
|
||||
}
|
||||
|
||||
makeSection(section) {
|
||||
const sectionElement = frappe.ui.add('div', 'form-section', this.form);
|
||||
if (section.columns) {
|
||||
sectionElement.classList.add('row');
|
||||
for (let column of section.columns) {
|
||||
let columnElement = frappe.ui.add('div', 'col', sectionElement);
|
||||
this.makeControls(this.getFieldsFromLayoutElement(column.fields), columnElement);
|
||||
}
|
||||
} else {
|
||||
this.makeControls(this.getFieldsFromLayoutElement(section.fields), sectionElement);
|
||||
}
|
||||
this.sections.push(sectionElement);
|
||||
}
|
||||
|
||||
getFieldsFromLayoutElement(fields) {
|
||||
return this.meta.fields.filter(d => fields.includes(d.fieldname));
|
||||
}
|
||||
|
||||
makeControls(fields, parent) {
|
||||
for(let field of fields) {
|
||||
if (!field.hidden && controls.getControlClass(field.fieldtype)) {
|
||||
if (this.inline) {
|
||||
field.inline = true;
|
||||
}
|
||||
let control = controls.makeControl({field: field, form: this, parent: parent});
|
||||
this.controlList.push(control);
|
||||
this.controls[field.fieldname] = control;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
makeToolbar() {
|
||||
if (this.actions.includes('save')) {
|
||||
this.makeSaveButton();
|
||||
@ -247,7 +209,7 @@ module.exports = class BaseForm extends Observable {
|
||||
this.container.clearLinks();
|
||||
for(let link of links) {
|
||||
// make the link
|
||||
this.container.addLink(link.label, () => {
|
||||
utils.addLink(link.label, this.container.linksElement, () => {
|
||||
let options = link.action(this);
|
||||
|
||||
if (options) {
|
||||
@ -271,7 +233,7 @@ module.exports = class BaseForm extends Observable {
|
||||
this.doc.off(this.docListener);
|
||||
}
|
||||
this.doc = doc;
|
||||
for (let control of this.controlList) {
|
||||
for (let control of this.formLayout.controlList) {
|
||||
control.bind(this.doc);
|
||||
}
|
||||
|
||||
@ -285,7 +247,7 @@ module.exports = class BaseForm extends Observable {
|
||||
this.docListener = (params) => {
|
||||
if (params.fieldname) {
|
||||
// only single value changed
|
||||
let control = this.controls[params.fieldname];
|
||||
let control = this.formLayout.controls[params.fieldname];
|
||||
if (control && control.getInputValue() !== control.format(params.fieldname)) {
|
||||
control.refresh();
|
||||
}
|
||||
@ -304,7 +266,7 @@ module.exports = class BaseForm extends Observable {
|
||||
checkValidity() {
|
||||
let validity = this.form.checkValidity();
|
||||
if (validity) {
|
||||
for (let control of this.controlList) {
|
||||
for (let control of this.formLayout.controlList) {
|
||||
// check validity in table
|
||||
if (control.fieldtype==='Table') {
|
||||
validity = control.checkValidity();
|
||||
@ -318,9 +280,7 @@ module.exports = class BaseForm extends Observable {
|
||||
}
|
||||
|
||||
refresh() {
|
||||
for(let control of this.controlList) {
|
||||
control.refresh();
|
||||
}
|
||||
this.formLayout.refresh();
|
||||
this.trigger('refresh', this);
|
||||
this.setLinks();
|
||||
}
|
||||
|
89
client/view/formLayout.js
Normal file
89
client/view/formLayout.js
Normal file
@ -0,0 +1,89 @@
|
||||
const controls = require('./controls');
|
||||
const Observable = require('frappejs/utils/observable');
|
||||
|
||||
module.exports = class FormLayout extends Observable {
|
||||
constructor({fields, layout, events = []}) {
|
||||
super();
|
||||
Object.assign(this, arguments[0]);
|
||||
this.controls = {};
|
||||
this.controlList = [];
|
||||
this.sections = [];
|
||||
this.links = [];
|
||||
|
||||
this.doc = {
|
||||
get(fieldname) {
|
||||
return this[fieldname]
|
||||
},
|
||||
|
||||
set(fieldname, value) {
|
||||
this[fieldname] = value;
|
||||
}
|
||||
};
|
||||
|
||||
this.form = document.createElement('div');
|
||||
this.form.classList.add('form-body');
|
||||
|
||||
this.makeLayout();
|
||||
this.bindEvents(this.doc);
|
||||
}
|
||||
|
||||
makeLayout() {
|
||||
if (this.layout) {
|
||||
for (let section of this.layout) {
|
||||
this.makeSection(section);
|
||||
}
|
||||
} else {
|
||||
this.makeControls(this.fields);
|
||||
}
|
||||
}
|
||||
|
||||
makeSection(section) {
|
||||
const sectionElement = frappe.ui.add('div', 'form-section', this.form);
|
||||
if (section.columns) {
|
||||
sectionElement.classList.add('row');
|
||||
for (let column of section.columns) {
|
||||
let columnElement = frappe.ui.add('div', 'col', sectionElement);
|
||||
this.makeControls(this.getFieldsFromLayoutElement(column.fields), columnElement);
|
||||
}
|
||||
} else {
|
||||
this.makeControls(this.getFieldsFromLayoutElement(section.fields), sectionElement);
|
||||
}
|
||||
this.sections.push(sectionElement);
|
||||
}
|
||||
|
||||
getFieldsFromLayoutElement(fields) {
|
||||
return this.fields.filter(d => fields.includes(d.fieldname));
|
||||
}
|
||||
|
||||
makeControls(fields, parent) {
|
||||
for(let field of fields) {
|
||||
if (!field.hidden && controls.getControlClass(field.fieldtype)) {
|
||||
let control = controls.makeControl({field: field, form: this, parent: parent});
|
||||
this.controlList.push(control);
|
||||
this.controls[field.fieldname] = control;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async bindEvents(doc) {
|
||||
this.doc = doc;
|
||||
this.controlList.forEach(control => {
|
||||
control.bind(this.doc);
|
||||
});
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.controlList.forEach(control => {
|
||||
control.refresh();
|
||||
});
|
||||
}
|
||||
|
||||
bindFormEvents() {
|
||||
if (this.events) {
|
||||
for (let key in this.events) {
|
||||
this.on(key, this.events[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -37,15 +37,6 @@ module.exports = class Page extends Observable {
|
||||
${message}</span>`;
|
||||
}
|
||||
|
||||
addLink(label, action, unhide = true) {
|
||||
const link = frappe.ui.add('button', 'btn btn-sm btn-outline-secondary', this.linksElement, label);
|
||||
link.addEventListener('click', action);
|
||||
if (unhide) {
|
||||
this.linksElement.classList.remove('hide');
|
||||
}
|
||||
return link;
|
||||
}
|
||||
|
||||
clearLinks() {
|
||||
frappe.ui.empty(this.linksElement);
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ module.exports = class BaseDocument extends Observable {
|
||||
this.owner = frappe.session.user;
|
||||
this.creation = now;
|
||||
}
|
||||
this.modifieldBy = frappe.session.user;
|
||||
this.modifiedBy = frappe.session.user;
|
||||
this.modified = now;
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ module.exports = {
|
||||
fieldname: 'owner', fieldtype: 'Data', required: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'modifieldBy', fieldtype: 'Data', required: 1
|
||||
fieldname: 'modifiedBy', fieldtype: 'Data', required: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'creation', fieldtype: 'Datetime', required: 1
|
||||
|
10127
package-lock.json
generated
10127
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
@ -9,31 +9,27 @@
|
||||
"start": "nodemon app.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"autoprefixer": "^7.2.4",
|
||||
"awesomplete": "^1.1.2",
|
||||
"body-parser": "^1.18.2",
|
||||
"bootstrap": "^4.0.0",
|
||||
"clusterize.js": "^0.18.0",
|
||||
"codemirror": "^5.35.0",
|
||||
"commander": "^2.13.0",
|
||||
"eslint": "^4.9.0",
|
||||
"express": "^4.16.2",
|
||||
"flatpickr": "^4.3.2",
|
||||
"frappe-datatable": "link:../datatable",
|
||||
"frappe-datatable": "^0.0.3",
|
||||
"jquery": "^3.3.1",
|
||||
"mocha": "^4.1.0",
|
||||
"moment": "^2.20.1",
|
||||
"mysql": "^2.15.0",
|
||||
"node-fetch": "^1.7.3",
|
||||
"nunjucks": "^3.1.0",
|
||||
"popper.js": "^1.12.9",
|
||||
"showdown": "^1.8.6",
|
||||
"socket.io": "^2.0.4",
|
||||
"sortablejs": "^1.7.0",
|
||||
"sqlite3": "^3.1.13",
|
||||
"walk": "^2.3.9",
|
||||
"autoprefixer": "^7.2.4",
|
||||
"eslint": "^4.9.0",
|
||||
"mocha": "^4.1.0",
|
||||
"node-sass": "^4.7.2",
|
||||
"nodemon": "^1.14.7",
|
||||
"nunjucks": "^3.1.0",
|
||||
"octicons": "^7.2.0",
|
||||
"popper.js": "^1.12.9",
|
||||
"precss": "^2.0.0",
|
||||
"rollup": "^0.55.1",
|
||||
"rollup-plugin-commonjs": "^8.3.0",
|
||||
@ -41,7 +37,12 @@
|
||||
"rollup-plugin-node-resolve": "^3.0.2",
|
||||
"rollup-plugin-postcss": "^1.2.7",
|
||||
"rollup-plugin-replace": "^2.0.0",
|
||||
"rollup-plugin-sass": "^0.5.3"
|
||||
"rollup-plugin-sass": "^0.5.3",
|
||||
"showdown": "^1.8.6",
|
||||
"socket.io": "^2.0.4",
|
||||
"sortablejs": "^1.7.0",
|
||||
"sqlite3": "^3.1.13",
|
||||
"walk": "^2.3.9"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -56,6 +57,5 @@
|
||||
"url": "https://github.com/frappe/frappejs/issues"
|
||||
},
|
||||
"homepage": "https://github.com/frappe/frappejs#readme",
|
||||
"devDependencies": {
|
||||
}
|
||||
"devDependencies": {}
|
||||
}
|
||||
|
18
yarn.lock
18
yarn.lock
@ -1317,9 +1317,13 @@ forwarded@~0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
|
||||
|
||||
"frappe-datatable@link:../datatable":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
frappe-datatable@^0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/frappe-datatable/-/frappe-datatable-0.0.3.tgz#55d3fd7bafdf2a7380efab2ae2aaaa956624fca0"
|
||||
dependencies:
|
||||
clusterize.js "^0.18.0"
|
||||
lodash "^4.17.5"
|
||||
sortablejs "^1.7.0"
|
||||
|
||||
fresh@0.5.2:
|
||||
version "0.5.2"
|
||||
@ -2471,7 +2475,7 @@ oauth-sign@~0.8.1, oauth-sign@~0.8.2:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
|
||||
|
||||
object-assign@^4.0.1, object-assign@^4.1.0:
|
||||
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
|
||||
@ -2486,6 +2490,12 @@ object.omit@^2.0.0:
|
||||
for-own "^0.1.4"
|
||||
is-extendable "^0.1.1"
|
||||
|
||||
octicons@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/octicons/-/octicons-7.2.0.tgz#a721635f73c774d7ffda56a83a29dbde03fc4b53"
|
||||
dependencies:
|
||||
object-assign "^4.1.1"
|
||||
|
||||
on-finished@~2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
|
||||
|
Loading…
Reference in New Issue
Block a user