2
0
mirror of https://github.com/frappe/books.git synced 2024-11-10 07:40:55 +00:00

updated docs

This commit is contained in:
Rushabh Mehta 2018-02-22 13:06:28 +05:30
parent 18544d0d28
commit 5c3a52186e
20 changed files with 418 additions and 24 deletions

View File

@ -5,7 +5,7 @@ const frappe = require('frappejs');
module.exports = class FormPage extends Page {
constructor(doctype) {
let meta = frappe.getMeta(doctype)
super({title: `Edit ${meta.name}`});
super({title: `Edit ${meta.name}`, hasRoute: true});
this.meta = meta;
this.doctype = doctype;

View File

@ -7,7 +7,7 @@ nunjucks.configure({ autoescape: false });
module.exports = class PrintPage extends Page {
constructor(doctype) {
let meta = frappe.getMeta(doctype);
super({title: `View ${meta.name}`});
super({title: `${meta.name}`, hasRoute: true});
this.meta = meta;
this.doctype = doctype;
@ -35,6 +35,7 @@ module.exports = class PrintPage extends Page {
try {
this.body.innerHTML = `<div class="print-page">${nunjucks.renderString(this.printFormat.template, context)}</div>`;
this.setTitle(doc.name);
} catch (e) {
this.renderError('Template Error', e);
throw e;

View File

@ -87,7 +87,7 @@ class BaseControl {
}
setDisabled() {
if (this.readonly || this.disabled) {
if (this.disabled) {
this.input.disabled = true;
}
}

View File

@ -106,12 +106,12 @@ module.exports = class BaseForm extends Observable {
setTitle() {
const doctypeLabel = this.doc.meta.label || this.doc.meta.name;
if (this.doc.meta.isSingle || !this.doc.meta.showTitle) {
if (this.doc.meta.isSingle || this.doc.meta.naming == 'random') {
this.container.setTitle(doctypeLabel);
} else if (this.doc._notInserted) {
this.container.setTitle(frappe._('New {0}', doctypeLabel));
} else {
this.container.setTitle(`${doctypeLabel} ${this.doc.name}`);
this.container.setTitle(this.doc.name);
}
}

View File

@ -3,7 +3,7 @@ const Observable = require('frappejs/utils/observable');
const Dropdown = require('frappejs/client/ui/dropdown');
module.exports = class Page extends Observable {
constructor({title, parent, hasRoute=true}) {
constructor({title, parent, hasRoute=true} = {}) {
super();
Object.assign(this, arguments[0]);
if (!this.parent) {
@ -20,7 +20,7 @@ module.exports = class Page extends Observable {
make() {
this.wrapper = frappe.ui.add('div', 'page hide', this.parent);
this.wrapper.innerHTML = `<div class="page-head clearfix hide">
<span class="page-title"></span>
<span class="page-title font-weight-bold"></span>
</div>
<div class="page-body"></div>`
this.head = this.wrapper.querySelector('.page-head');

View File

@ -7,9 +7,13 @@ Frappe.js is a meta-data driven framework that enables rapid application develop
- [Making a new App](app.md)
- Models and Documents
- [Declaring Models](models/index.md)
- [Fields](models/fields.md)
- [Controllers](models/controllers.md)
- [Formula](models/fields.md)
- [Metadata](models/metadata.md)
- [Managing Documents](models/document.md)
- [Single Documents](models/singles.md)
- [Parent Child](models/parent-child.md)
- [Server](server/index.md)
- [REST API](server/rest.md)
- [Client](client/index.md)
@ -21,6 +25,11 @@ Frappe.js is a meta-data driven framework that enables rapid application develop
- [UI](client/ui/index.md)
- [Dropdown](client/ui/dropdown.md)
- [Desk](client/desk.md)
- Utilities
- [Observable](utilities/observable.md)
- [Print Format](utilities/print-format.md)
- [Number Series](utilities/number-series.md)
- [System Settings](utilities/system-settings.md)
- [Backends](server/backends.md)
- [Errors](errors.md)
- [Testing](testing.md)

View File

@ -4,6 +4,8 @@ In Frappe.js you can extend the metadata class as well as the document class for
You can write event handlers in controllers, by declaring a `.js` file in the `models/doctype/` folder along with the model file.
You must also mind the controller to the model file by the `documentClass` property.
## Naming
1. The name of the controller class must be the slugged name of the DocType (example `todo`)
@ -22,9 +24,6 @@ const frappe = require('frappejs');
// extend the document and add event handlers
class todo extends frappe.document.Document {
setup() {
this.add_handler('validate');
}
validate() {
if (!this.status) {
this.status = 'Open';
@ -40,16 +39,9 @@ The `meta` class contains actions that are done on a group of objects and a docu
```js
// extend the meta class
class todo_meta extends frappe.meta.Meta {
setupMeta() {
Object.assign(this, require('./todo.json'));
this.name = 'ToDo';
this.list_options.fields = ['name', 'subject', 'status', 'description'];
}
getRowHTML(data) {
return `<a href="#edit/todo/${data.name}">${data.subject}</a>`;
}
}
```

77
docs/models/fields.md Normal file
View File

@ -0,0 +1,77 @@
# Fields
Fields are properties a the document instance that are defined in its DocType.
## Field Types
### Data
Small, single line text (140 chars)
### Text
Long multi-line text
### Int
Integer
### Float
Number
### Currency
Number with currency
### Code
Code string (like Text but monospaced)
### Date
Date (formatted by [SystemSetings.dateFormat](../utilities/system-settings.md))
### Select
Dropdown with fixed options. Options must be set in the `options` property
```
{
fieldtype: "Select",
fieldname: "status",
label: "Status",
options: [
"Open",
"Closed",
"Pending"
]
}
```
### Link
Reference to another document set by `target`
```
{
fieldtype: "Link",
fieldname: "customer",
label: "Customer",
target: "Customer"
}
```
### Table
Property with child documents, the type of children is defined by `childtype` property
```
{
fieldtype: "Table",
fieldname: "items",
label: "Items",
target: "InvoiceItem"
}
```

65
docs/models/formula.md Normal file
View File

@ -0,0 +1,65 @@
# Formula
Formulas are dynamic document properties that can be set on the fields
Forumlas are defined as javascript functions and are called whenever any property of the document is updated using the `set` method, or just before inserting or updating the document.
### Example
```js
module.exports = {
name: "FormulaExample"
fields: [
{
fieldtype: "Float",
fieldname: "a"
},
{
fieldtype: "Float",
fieldname: "b"
}
{
fieldtype: "Float",
fieldname: "c",
formula: doc => doc.a + doc.b
}
]
}
```
## Formula on child tables
In child tables, both the parent and the child records are passed
### Example
```js
{
fieldname: "amount",
fieldtype: "Float",
formula: (doc, row) => row.qty * row.rate
}
```
## Sequence
All child tables are executed first and all fields are executed in the sequence as defined in the DocType
## Fetching Values
You can use the `getFrom` function to fetch values from another document
Example:
```
{
"fieldname": "rate",
"label": "Rate",
"fieldtype": "Currency",
formula: (row, doc) => row.rate || doc.getFrom('Item', row.item, 'rate')
}
```
## Async
Forumlas are evaluated as promises, so you can either directly pass a value or a `Promise`

View File

@ -1,14 +1,25 @@
# Declaring Models
Models are declared by adding a `.json` model file in the `models/doctype` folder of the module/app.
Models are declared by adding a `.js` model file in the `models/doctype` folder of the module/app.
Note: A model is called `DocType` in Frappe.js
### Fields
Every model must have a set of fields (these become database columns). All fields must have
- `fieldname`: Column name in database / property name
- `fieldtype`: Data type ([see details](fields.md))
- `label`: Display label
- `required`: Is mandatory
- `hidden`: Is hidden
- `disabled`: Is disabled
### Example
```json
{
"autoname": "hash",
```js
module.exports = {
"naming": "random",
"name": "ToDo",
"doctype": "DocType",
"issingle": 0,

View File

@ -0,0 +1,40 @@
# Parent Child Relationship
All documents can have child documents, identified by the `Table` field.
Though child documents have their own DocType and database table, but are not to handled or viewed on their own. FrappeJS will automatically load child documents along with the parent when you use the `frappe.getDoc` method.
### Example
A sample parent-child records looks like this:
```
{
doctype: "Invoice",
customer: "Harry Potter",
items: [
{
item: "Wand",
qty: 1,
rate: 300,
amount: 300
},{
item: "Invisibility Cloak",
qty: 1,
rate: 3000,
amount: 3000
}
]
}
```
## Child Properties
Child documents have special properties that define their relationship to their parent
- `parent`: name of the parent
- `parenttype`: DocType of the parent
- `parentfield`: Field in the parent that links this child to it
- `idx`: Sequence (row)
These properties are maintained in the table automatically by FrappeJS

21
docs/models/singles.md Normal file
View File

@ -0,0 +1,21 @@
# Single Documents
Single doctypes have only one instance. They are useful for using DocTypes as views or for settings.
To make a Single DocType, set the `isSingle` property as true.
Single documents are best viewed in a modal since they do not have a corresponding list view.
Values of single documents are stored in the table `SingleValue`
## API
### frappe.getSingle
Load a single document
```js
let systemSettings = frappe.getSingle('SystemSettings');
```
Since Single documents are also documents, you can update them with the `update()` method.

View File

@ -24,7 +24,7 @@ Connection paramter required for the sqlite backend is the path of the file
```js
sqllite = require('frappejs/frappe/backends/sqlite');
frappe.db = await new sqlite.Database({db_path: db_path})
frappe.db = await new sqlite.Database({dbPath: dbPath})
```
### SQL Queries

View File

@ -0,0 +1,25 @@
# Number Series
A number series is used to maintain a series for numbering documents (like invoices)
Properties:
- `name`: Prefix of the series example `INV-`
- `current`: Its current (or starting) value. This will be auto updated everytime the series is updated.
### API
You can get the next number in the series by using the utiltiy function
```js
const model = require("frappejs/model")
let nextValue = model.getSeriesNext("INV-");
```
### Setting naming series in a document
To setup a number series for a DocType:
- It must have its own "Settings" [single document](../models/singles.md. For example (InvoiceSettings for Invoice).
- The settings document must be set via the `settings` property in the DocType
- The settings document must have a `numberSeries` property with value of the number series

View File

@ -0,0 +1,29 @@
# Observable Base Class
The `Observable` base class makes and subclass trigger events and accept event listeners.
### Example
```js
class Test extends Observable {
doSomething() {
// work
this.trigger('work-done', {some: params})
}
}
let test = new Test();
test.on('work-done', (params) => yay());
```
### With Sockets
You can also bind sockets (SocketIO) to an `Observable` and all events will also be emitted or received via the socket. See the API below for binding sockets.
### Methods
- `on(event, listener)`: Listen to an event
- `trigger(event)`: trigger an event
- `once(event, listener)`: trigger an event once
- `bindSocketServer(socket)`: Emit triggers on this socket
- `bindSocketClient(socket)`: Listen for events on this socket

View File

@ -0,0 +1,102 @@
# Print Format
A PrintFormat represents an HTML template that is used to create a printer-friendly version of the DocType
## Creating a Print Format
To make a printer friendly version, you must create a "PrintFormat" for the doctype
Example:
```js
module.exports = {
doctype: "PrintFormat",
name: "Standard Invoice Format",
for: "Invoice",
template: require('./invoice.html')
}
```
This must be referenced in the `print.printFormat` property of the DocType.
```js
"print": {
"printFormat": "Standard Invoice Format",
},
```
## Templating
The templating system used by frappe is [nunjucks](https://mozilla.github.io/nunjucks/) and is very similar to Jinja2 system from Python
### Example
Example of a print format for an Invoice
```html
<h1>{{ doc.name }}</h1>
<div class="row py-4">
<div class="col-6">
<div><b>{{ frappe._("Customer") }}</b></div>
<div>{{ doc.customer }}</div>
</div>
<div class="col-6">
<div><b>{{ frappe._("Date") }}</b></div>
<div>{{ frappe.format(doc.date, 'Date') }}</div>
</div>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th></th>
<th>{{ frappe._("Item") }}</th>
<th class='text-right'>{{ frappe._("Qty") }}</th>
<th class='text-right'>{{ frappe._("Rate") }}</th>
<th class='text-right'>{{ frappe._("Amount") }}</th>
</tr>
</thead>
<tbody>
{% for row in doc.items %}
<tr>
<td class='text-right'>{{ row.idx + 1 }}</td>
<td>{{ row.item }}<br>{{ frappe.format(row.description, 'Text') }}</td>
<td class='text-right'>{{ row.quantity }}</td>
<td class='text-right'>{{ frappe.format(row.rate, 'Currency') }}</td>
<td class='text-right'>{{ frappe.format(row.amount, 'Currency') }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class='row'>
<div class='col-6'></div>
<div class='col-6'>
<div class='row'>
<div class='col-6'>
{{ frappe._("Total") }}
</div>
<div class='col-6 text-right'>
{{ frappe.format(doc.netTotal, 'Currency')}}
</div>
</div>
{% for tax in doc.taxes %}
<div class='row'>
<div class='col-6'>
{{ tax.account }} ({{ tax.rate }}%)
</div>
<div class='col-6 text-right'>
{{ frappe.format(tax.amount, 'Currency')}}
</div>
</div>
{% endfor %}
<div class='row py-3'>
<div class='col-6'>
<h5>{{ frappe._("Grand Total") }}</h5>
</div>
<div class='col-6 text-right'>
<h5>{{ frappe.format(doc.grandTotal, 'Currency')}}</h5>
</div>
</div>
</div>
</div>
</div>
```

View File

@ -0,0 +1,11 @@
# Single Value
The SingleValue table is where all [Single documents](../model/singles.md) are stored.
A `SingleValue` record is created for each property of the doctype
Properties:
- `parent`: name of single document
- `fieldname`: name of the field (property)
- `value`: value of the field

View File

@ -0,0 +1,11 @@
# System Settings
SystemSettings is a [Single document](../models/singles.md) that has system defaults like
- `dateFormat`: default date format
You can get system settings as
```js
frappe.getSingle("SystemSettings")
```

View File

@ -8,7 +8,7 @@ module.exports = {
"fields": [
{
"fieldname": "name",
"label": "Name",
"label": "Prefix",
"fieldtype": "Data",
"required": 1
},

View File

@ -1,5 +1,5 @@
module.exports = {
"autoname": "random",
"naming": "random",
"name": "ToDo",
"doctype": "DocType",
"isSingle": 0,