mirror of
https://github.com/frappe/books.git
synced 2024-11-08 14:50:56 +00:00
💥 frappejs
This commit is contained in:
parent
df9fc91123
commit
328a9de7d4
2
app.js
2
app.js
@ -1,4 +1,4 @@
|
||||
const server = require('frappe-core/server');
|
||||
const server = require('frappejs/server');
|
||||
|
||||
server.start({
|
||||
backend: 'sqllite',
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = class RESTClient {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const sqlite3 = require('sqlite3').verbose();
|
||||
|
||||
class sqliteDatabase {
|
||||
|
@ -1,9 +1,9 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const Search = require('./search');
|
||||
const Router = require('frappe-core/common/router');
|
||||
const Page = require('frappe-core/client/view/page');
|
||||
const List = require('frappe-core/client/view/list');
|
||||
const Form = require('frappe-core/client/view/form');
|
||||
const Router = require('frappejs/common/router');
|
||||
const Page = require('frappejs/client/view/page');
|
||||
const List = require('frappejs/client/view/list');
|
||||
const Form = require('frappejs/client/view/form');
|
||||
|
||||
module.exports = class Desk {
|
||||
constructor() {
|
||||
|
10
client/desk/navbar.js
Normal file
10
client/desk/navbar.js
Normal file
@ -0,0 +1,10 @@
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = class Navbar {
|
||||
constructor({brand_label = 'App'} = {}) {
|
||||
Object.assign(this, arguments[0]);
|
||||
this.navbar = frappe.ui.add('div', 'navbar', frappe.header);
|
||||
this.brand = frappe.ui.add('div', 'navbar-brand', this.navbar);
|
||||
this.brand.textContent = this.brand_label || 'App';
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = class Search {
|
||||
constructor(parent) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
const common = require('frappe-core/common');
|
||||
const RESTClient = require('frappe-core/backends/rest_client');
|
||||
const frappe = require('frappe-core');
|
||||
const common = require('frappejs/common');
|
||||
const RESTClient = require('frappejs/backends/rest_client');
|
||||
const frappe = require('frappejs');
|
||||
frappe.ui = require('./ui');
|
||||
const Desk = require('./desk');
|
||||
|
||||
|
61
client/style/index.scss
Normal file
61
client/style/index.scss
Normal file
@ -0,0 +1,61 @@
|
||||
@import "node_modules/bootstrap/scss/bootstrap";
|
||||
|
||||
// html {
|
||||
// font-size: 14px;
|
||||
// }
|
||||
|
||||
.desk {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.nav {
|
||||
display: none;
|
||||
border-bottom: 1px solid $border-color;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.two-column {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 4fr;
|
||||
grid-auto-rows: minmax(100%, auto);
|
||||
}
|
||||
|
||||
.main, .sidebar {
|
||||
padding: 2rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
border-right: 1px solid $border-color;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.page-error {
|
||||
text-align: center;
|
||||
padding: 200px 0px;
|
||||
}
|
||||
|
||||
.form-body {
|
||||
.form-toolbar {
|
||||
height: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.alert {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu-right {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
.list-search {
|
||||
max-width: 400px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
class Dropdown {
|
||||
constructor({parent, label, btn_class = 'btn-secondary', items = []}) {
|
||||
@ -64,11 +64,13 @@ class Dropdown {
|
||||
}
|
||||
|
||||
add_item(label, action) {
|
||||
let item = frappe.ui.add('a', 'dropdown-item', this.dropdown_menu);
|
||||
let item = frappe.ui.add('button', 'dropdown-item', this.dropdown_menu);
|
||||
item.textContent = label;
|
||||
item.setAttribute('type', 'button');
|
||||
if (typeof action === 'string') {
|
||||
item.src = action;
|
||||
item.addEventListener('click', () => {
|
||||
item.addEventListener('click', async () => {
|
||||
await frappe.router.set_route(action);
|
||||
this.toggle();
|
||||
});
|
||||
} else {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const Dropdown = require('./dropdown');
|
||||
|
||||
module.exports = {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
class BaseControl {
|
||||
constructor(docfield, parent) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const controls = require('./controls');
|
||||
|
||||
module.exports = class Form {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = class List {
|
||||
constructor({doctype, parent, fields}) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = class Page {
|
||||
constructor(title) {
|
||||
@ -17,7 +17,7 @@ module.exports = class Page {
|
||||
this.trigger('hide');
|
||||
}
|
||||
|
||||
show(params) {
|
||||
async show(params) {
|
||||
if (frappe.router.current_page) {
|
||||
frappe.router.current_page.hide();
|
||||
}
|
||||
@ -31,7 +31,7 @@ module.exports = class Page {
|
||||
frappe.router.current_page = this;
|
||||
document.title = this.title;
|
||||
|
||||
this.trigger('show', params);
|
||||
await this.trigger('show', params);
|
||||
}
|
||||
|
||||
render_error(status_code, message) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = class Router {
|
||||
constructor() {
|
||||
@ -16,6 +16,7 @@ module.exports = class Router {
|
||||
if (page.param_keys) {
|
||||
// make expression
|
||||
// '/todo/:name/:place'.replace(/\/:([a-z1-9]+)/g, "\/([a-z0-9]+)");
|
||||
page.depth = route.split('/').length;
|
||||
page.expression = route.replace(/\/:([a-z1-9]+)/g, "\/([a-z0-9]+)");
|
||||
this.dynamic_routes.push(page);
|
||||
this.sort_dynamic_routes();
|
||||
@ -26,14 +27,18 @@ module.exports = class Router {
|
||||
}
|
||||
|
||||
sort_dynamic_routes() {
|
||||
// routes with fewer parameters first
|
||||
// routes with more parts first
|
||||
this.dynamic_routes = this.dynamic_routes.sort((a, b) => {
|
||||
if (a.param_keys.length > b.param_keys.length) {
|
||||
if (a.depth < b.depth) {
|
||||
return 1;
|
||||
} else if (a.param_keys.length < b.param_keys.length) {
|
||||
} else if (a.depth > b.depth) {
|
||||
return -1;
|
||||
} else {
|
||||
return a.route.length > b.route.length ? 1 : -1;
|
||||
if (a.param_keys.length !== b.param_keys.length) {
|
||||
return a.param_keys.length > b.param_keys.length ? 1 : -1;
|
||||
} else {
|
||||
return a.route.length > b.route.length ? 1 : -1;
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
1
docs/app.md
Normal file
1
docs/app.md
Normal file
@ -0,0 +1 @@
|
||||
# Creating a new App
|
@ -9,8 +9,8 @@ Note: A single Form object can handle multiple documents.
|
||||
### Example
|
||||
|
||||
```js
|
||||
const Page = require('frappe-core/frappe/client/view/page').Page;
|
||||
const Form = require('frappe-core/frappe/client/view/form').Form;
|
||||
const Page = require('frappejs/frappe/client/view/page');
|
||||
const Form = require('frappejs/frappe/client/view/form');
|
||||
|
||||
edit_page = new Page('Edit To Do');
|
||||
|
||||
|
@ -23,13 +23,13 @@ You can setup your client by setting up the server and then importing your contr
|
||||
### Example
|
||||
|
||||
```js
|
||||
const client = require('frappe-core/frappe/client');
|
||||
const client = require('frappejs/frappe/client');
|
||||
|
||||
client.start({
|
||||
server: 'localhost:8000',
|
||||
container: document.querySelector('.container'),
|
||||
}).then(() => {
|
||||
const todo = require('frappe-core/frappe/models/doctype/todo/todo.js');
|
||||
const todo = require('frappejs/frappe/models/doctype/todo/todo.js');
|
||||
frappe.init_controller('todo', todo);
|
||||
|
||||
// ....
|
||||
|
@ -5,14 +5,14 @@ A list object handles object listing and paging, for a standard model.
|
||||
### Example
|
||||
|
||||
```js
|
||||
const Page = require('frappe-core/frappe/client/view/page').Page;
|
||||
const ListView = require('frappe-core/frappe/client/view/list').ListView;
|
||||
const Page = require('frappejs/frappe/client/view/page');
|
||||
const List = require('frappejs/frappe/client/view/list');
|
||||
|
||||
// create a new page
|
||||
let todo_list = new Page('ToDo List');
|
||||
|
||||
// init a new list
|
||||
todo_list.list = new ListView({
|
||||
todo_list.list = new List({
|
||||
doctype: 'ToDo',
|
||||
parent: this.todo_list.body
|
||||
});
|
||||
|
@ -5,7 +5,7 @@ A page is a basic container that fills up the `main` area of the Frappe.js SPA.
|
||||
### Example
|
||||
|
||||
```js
|
||||
const Page = require('frappe-core/frappe/client/view/page').Page;
|
||||
const Page = require('frappejs/frappe/client/view/page').Page;
|
||||
|
||||
let todo_list = new Page('ToDo List');
|
||||
|
||||
|
@ -11,7 +11,7 @@ Dynamic routes can be added by declaring each parameter as `:param` in the route
|
||||
### Example
|
||||
|
||||
```js
|
||||
const Page = require('frappe-core/frappe/client/view/page').Page;
|
||||
const Page = require('frappejs/frappe/client/view/page').Page;
|
||||
|
||||
let todo_list = new Page('ToDo List');
|
||||
|
||||
|
@ -17,7 +17,7 @@ Methods
|
||||
### Create
|
||||
|
||||
```js
|
||||
const Dropdown = require('frappe-core/frappe/client/ui/dropdown');
|
||||
const Dropdown = require('frappejs/frappe/client/ui/dropdown');
|
||||
|
||||
let dropdown = new Dropdown({label:'Actions', parent:this.toolbar});
|
||||
```
|
||||
|
@ -4,6 +4,7 @@ Frappe.js is a meta-data driven framework that enables rapid application develop
|
||||
|
||||
## Contents
|
||||
|
||||
- [Making a new App](app.md)
|
||||
- Models and Documents
|
||||
- [Declaring Models](models/index.md)
|
||||
- [Controllers](models/controllers.md)
|
||||
@ -19,5 +20,7 @@ Frappe.js is a meta-data driven framework that enables rapid application develop
|
||||
- [Controls](client/controls.md)
|
||||
- [UI](client/ui/index.md)
|
||||
- [Dropdown](client/ui/dropdown.md)
|
||||
- [Desk](client/desk.md)
|
||||
- [Backends](backends.md)
|
||||
- [Errors](errors.md)
|
||||
- [Testing](testing.md)
|
@ -18,7 +18,7 @@ You can bind events to the controller that will be called when an action is comp
|
||||
The document controller represents a single record and is subclassed from the `frappe.document.Document` class
|
||||
|
||||
```js
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
// extend the document and add event handlers
|
||||
class todo extends frappe.document.Document {
|
||||
|
@ -22,7 +22,7 @@ The backend will implement the following `async` methods
|
||||
Connection paramter required for the sqlite backend is the path of the file
|
||||
|
||||
```js
|
||||
sqllite = require('frappe-core/frappe/backends/sqlite');
|
||||
sqllite = require('frappejs/frappe/backends/sqlite');
|
||||
|
||||
frappe.db = await new sqlite.Database({db_path: db_path})
|
||||
```
|
||||
@ -42,7 +42,7 @@ For the client, the backend is the REST API that executes calls with web-request
|
||||
Before using, you must initialize the `frappe.fetch` property with `window.fetch` or `node-fetch`
|
||||
|
||||
```js
|
||||
const Database = require('frappe-core/frappe/backends/rest_client').Database;
|
||||
const Database = require('frappejs/frappe/backends/rest_client').Database;
|
||||
|
||||
frappe.fetch = window.fetch.bind();
|
||||
frappe.db = await new Database({server: server});
|
||||
|
@ -5,7 +5,7 @@ The framework comes bundles with an `express.js` web server with pre-built backe
|
||||
### Example
|
||||
|
||||
```js
|
||||
const server = require('frappe-core/frappe/server');
|
||||
const server = require('frappejs/frappe/server');
|
||||
|
||||
server.start({
|
||||
backend: 'sqllite',
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
class Document {
|
||||
constructor(data) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
const Document = require('./document').Document;
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
class Meta extends Document {
|
||||
constructor(data) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
const process = require('process');
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
class Models {
|
||||
constructor() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
class todo_meta extends frappe.meta.Meta {
|
||||
setup_meta() {
|
||||
|
14
package.json
14
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "frappe-core",
|
||||
"name": "frappejs",
|
||||
"version": "1.0.0",
|
||||
"description": "Frappe Core",
|
||||
"description": "Frappe.js",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "mocha tests",
|
||||
@ -9,15 +9,15 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"body-parser": "^1.18.2",
|
||||
"bootstrap": "4.0.0-beta.3",
|
||||
"express": "^4.16.2",
|
||||
"node-fetch": "^1.7.3",
|
||||
"sqlite3": "^3.1.13",
|
||||
"walk": "^2.3.9",
|
||||
"webpack-dev-server": "^2.9.7"
|
||||
"walk": "^2.3.9"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/frappe/frappe-js.git"
|
||||
"url": "git+https://github.com/frappe/frappejs.git"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017
|
||||
@ -25,9 +25,9 @@
|
||||
"author": "Frappe",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/frappe/frappe-js/issues"
|
||||
"url": "https://github.com/frappe/frappejs/issues"
|
||||
},
|
||||
"homepage": "https://github.com/frappe/frappe-js#readme",
|
||||
"homepage": "https://github.com/frappe/frappejs#readme",
|
||||
"devDependencies": {
|
||||
"css-loader": "^0.28.7",
|
||||
"eslint": "^4.9.0",
|
||||
|
@ -1,12 +1,12 @@
|
||||
const backends = {};
|
||||
backends.sqlite = require('frappe-core/backends/sqlite');
|
||||
backends.sqlite = require('frappejs/backends/sqlite');
|
||||
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const rest_api = require('./rest_api')
|
||||
const models = require('frappe-core/server/models');
|
||||
const common = require('frappe-core/common');
|
||||
const models = require('frappejs/server/models');
|
||||
const common = require('frappejs/common');
|
||||
const bodyParser = require('body-parser');
|
||||
|
||||
module.exports = {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const walk = require('walk');
|
||||
const path = require('path');
|
||||
|
||||
@ -27,7 +27,7 @@ module.exports = {
|
||||
frappe.config.apps = [];
|
||||
}
|
||||
|
||||
frappe.config.apps.unshift('frappe-core');
|
||||
frappe.config.apps.unshift('frappejs');
|
||||
|
||||
// walk and sync
|
||||
for (let app_name of frappe.config.apps) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = {
|
||||
setup(app) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
class Session {
|
||||
constructor(user, user_key) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const server = require('frappe-core/server');
|
||||
const server = require('frappejs/server');
|
||||
|
||||
module.exports = {
|
||||
async init_sqlite() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
const assert = require('assert');
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const helpers = require('./helpers');
|
||||
|
||||
describe('Controller', () => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
const assert = require('assert');
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const helpers = require('./helpers');
|
||||
|
||||
describe('Database', () => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
const assert = require('assert');
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const helpers = require('./helpers');
|
||||
|
||||
describe('Document', () => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
const assert = require('assert');
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const helpers = require('./helpers');
|
||||
|
||||
describe('Meta', () => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
const assert = require('assert');
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const helpers = require('./helpers');
|
||||
|
||||
describe('Models', () => {
|
||||
|
@ -1,10 +1,10 @@
|
||||
const assert = require('assert');
|
||||
const frappe = require('frappe-core');
|
||||
const frappe = require('frappejs');
|
||||
const fetch = require('node-fetch');
|
||||
const helpers = require('./helpers');
|
||||
const { spawn } = require('child_process');
|
||||
const process = require('process');
|
||||
const RESTClient = require('frappe-core/backends/rest_client')
|
||||
const RESTClient = require('frappejs/backends/rest_client')
|
||||
|
||||
// create a copy of frappe
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
const Router = require('frappe-core/common/router');
|
||||
const Router = require('frappejs/common/router');
|
||||
const assert = require('assert');
|
||||
|
||||
describe('Router', () => {
|
||||
@ -15,13 +15,15 @@ describe('Router', () => {
|
||||
|
||||
it('router should sort dynamic routes', () => {
|
||||
let router = new Router();
|
||||
router.add('/edit/todo/mytest', 'static');
|
||||
router.add('/edit/:doctype', 'catch');
|
||||
router.add('/edit/:doctype/:name', 'all');
|
||||
router.add('/edit/todo/:name', 'todo');
|
||||
router.add('/edit/todo/mytest', 'static');
|
||||
|
||||
assert.equal(router.match('/edit/todo/test').handler, 'todo');
|
||||
assert.equal(router.match('/edit/user/test').handler, 'all');
|
||||
assert.equal(router.match('/edit/todo/mytest').handler, 'static');
|
||||
assert.equal(router.match('/edit/user').handler, 'catch');
|
||||
});
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
const server = require('frappe-core/server');
|
||||
const server = require('frappejs/server');
|
||||
|
||||
if (require.main === module) {
|
||||
server.start({backend: 'sqlite', connection_params: {db_path: 'test.db'}});
|
||||
|
@ -339,6 +339,10 @@ boom@5.x.x:
|
||||
dependencies:
|
||||
hoek "4.x.x"
|
||||
|
||||
bootstrap@4.0.0-beta.3:
|
||||
version "4.0.0-beta.3"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.0.0-beta.3.tgz#60f0660bc3d121176514b361f6f83201c7ff8874"
|
||||
|
||||
boxen@^1.2.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
|
||||
|
Loading…
Reference in New Issue
Block a user