2
0
mirror of https://github.com/frappe/books.git synced 2024-12-23 11:29:03 +00:00

multi column layout

This commit is contained in:
Rushabh Mehta 2018-02-14 22:14:50 +05:30
parent 1f5e3d8fcb
commit a10f75b195
8 changed files with 111 additions and 25 deletions

View File

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

View File

@ -5,21 +5,19 @@ const Page = require('frappejs/client/view/page');
const FormPage = require('frappejs/client/desk/formpage'); const FormPage = require('frappejs/client/desk/formpage');
const ListPage = require('frappejs/client/desk/listpage'); const ListPage = require('frappejs/client/desk/listpage');
const Navbar = require('./navbar'); const Navbar = require('./navbar');
const DeskMenu = require('./menu');
const FormModal = require('frappejs/client/desk/formmodal'); const FormModal = require('frappejs/client/desk/formmodal');
module.exports = class Desk { module.exports = class Desk {
constructor() { constructor(columns=2) {
frappe.router = new Router(); frappe.router = new Router();
frappe.router.listen(); frappe.router.listen();
let body = document.querySelector('body'); let body = document.querySelector('body');
this.navbar = new Navbar(); this.navbar = new Navbar();
this.container = frappe.ui.add('div', 'container-fluid', body); this.container = frappe.ui.add('div', 'container-fluid', body);
this.containerRow = frappe.ui.add('div', 'row', this.container) this.containerRow = frappe.ui.add('div', 'row', this.container)
this.sidebar = frappe.ui.add('div', 'col-md-2 sidebar d-none d-md-block', this.containerRow); this.makeColumns(columns);
this.sidebarList = frappe.ui.add('div', 'list-group list-group-flush', this.sidebar);
this.body = frappe.ui.add('div', 'col-md-10 main', this.containerRow);
this.pages = { this.pages = {
lists: {}, lists: {},
@ -33,10 +31,38 @@ module.exports = class Desk {
// this.search = new Search(this.nav); // this.search = new Search(this.nav);
} }
makeColumns(columns) {
this.menu = null; this.center = null;
this.columnCount = columns;
if (columns === 3) {
this.makeMenu();
this.center = frappe.ui.add('div', 'col-md-4 desk-center', this.containerRow);
this.body = frappe.ui.add('div', 'col-md-6 desk-body', this.containerRow);
} else if (columns === 2) {
this.makeMenu();
this.body = frappe.ui.add('div', 'col-md-10 desk-body', this.containerRow);
} else if (columns === 1) {
this.makeMenuPage();
this.body = frappe.ui.add('div', 'col-md-12 desk-body', this.containerRow);
} else {
throw 'columns can be 1, 2 or 3'
}
}
makeMenu() {
this.menuColumn = frappe.ui.add('div', 'col-md-2 desk-menu', this.containerRow);
this.menu = new DeskMenu(this.menuColumn);
}
makeMenuPage() {
// make menu page for 1 column layout
this.menuPage = null;
}
initRoutes() { initRoutes() {
frappe.router.add('not-found', async (params) => { frappe.router.add('not-found', async (params) => {
if (!this.notFoundPage) { if (!this.notFoundPage) {
this.notFoundPage = new Page('Not Found'); this.notFoundPage = new Page({title: 'Not Found'});
} }
await this.notFoundPage.show(); await this.notFoundPage.show();
this.notFoundPage.renderError('Not Found', params ? params.route : ''); this.notFoundPage.renderError('Not Found', params ? params.route : '');
@ -59,8 +85,8 @@ module.exports = class Desk {
}); });
frappe.router.on('change', () => { frappe.router.on('change', () => {
if (this.routeItems[window.location.hash]) { if (this.menu) {
this.setActive(this.routeItems[window.location.hash]); this.menu.setActive();
} }
}) })

View File

@ -5,12 +5,22 @@ const view = require('frappejs/client/view');
module.exports = class ListPage extends Page { module.exports = class ListPage extends Page {
constructor(doctype) { constructor(doctype) {
let meta = frappe.getMeta(doctype); let meta = frappe.getMeta(doctype);
super(frappe._("List: {0}", meta.name));
// if center column is present, list does not have its route
const hasRoute = frappe.desk.center ? false : true;
super({
title: frappe._("List: {0}", meta.name),
parent: hasRoute ? frappe.desk.body : frappe.desk.center,
hasRoute: hasRoute
});
this.list = new (view.getList_class(doctype))({ this.list = new (view.getList_class(doctype))({
doctype: doctype, doctype: doctype,
parent: this.body, parent: this.body,
page: this page: this
}); });
this.on('show', async () => { this.on('show', async () => {
await this.list.run(); await this.list.run();
}); });

40
client/desk/menu.js Normal file
View File

@ -0,0 +1,40 @@
const frappe = require('frappejs');
module.exports = class DeskMenu {
constructor(parent) {
this.parent = parent;
this.routeItems = {};
this.make();
}
make() {
this.listGroup = frappe.ui.add('div', 'list-group list-group-flush', this.parent);
}
addItem(label, action) {
let item = frappe.ui.add('a', 'list-group-item list-group-item-action', this.listGroup);
item.textContent = label;
if (typeof action === 'string') {
item.href = action;
this.routeItems[action] = item;
} else {
item.addEventListener('click', () => {
action();
this.setActive(item);
});
}
}
setActive() {
if (this.routeItems[window.location.hash]) {
let item = this.routeItems[window.location.hash];
let className = 'list-group-item-secondary';
let activeItem = this.listGroup.querySelector('.' + className);
if (activeItem) {
activeItem.classList.remove(className);
}
item.classList.add(className);
}
}
}

View File

@ -5,7 +5,7 @@ frappe.ui = require('./ui');
const Desk = require('./desk'); const Desk = require('./desk');
module.exports = { module.exports = {
async start({server}) { async start({server, columns = 2}) {
window.frappe = frappe; window.frappe = frappe;
frappe.init(); frappe.init();
common.init_libs(frappe); common.init_libs(frappe);
@ -15,7 +15,7 @@ module.exports = {
frappe.flags.cache_docs = true; frappe.flags.cache_docs = true;
frappe.desk = new Desk(); frappe.desk = new Desk(columns);
await frappe.login(); await frappe.login();
} }
}; };

View File

@ -14,13 +14,16 @@ html {
font-size: 12px; font-size: 12px;
} }
.main { .desk-body {
margin-left: -1px;
border-left: 1px solid $gray-300; border-left: 1px solid $gray-300;
min-height: calc(100vh - 50px); min-height: calc(100vh - 50px);
} }
.sidebar { .desk-center {
border-left: 1px solid $gray-300;
}
.desk-menu {
margin-right: -1px; margin-right: -1px;
.list-group-item { .list-group-item {
@ -76,7 +79,7 @@ html {
margin-right: -15px; margin-right: -15px;
.list-row { .list-row {
padding: $spacer-2; padding: $spacer-2 15px;
border-bottom: 1px solid $gray-200; border-bottom: 1px solid $gray-200;
.checkbox { .checkbox {
margin-right: $spacer-2; margin-right: $spacer-2;

View File

@ -74,7 +74,7 @@ module.exports = class BaseList {
makeToolbar() { makeToolbar() {
this.makeSearch(); this.makeSearch();
this.btnNew = this.page.addButton(frappe._('New'), 'btn-primary', async () => { this.btnNew = this.page.addButton(frappe._('New'), 'btn-outline-primary', async () => {
await frappe.router.setRoute('new', frappe.slug(this.doctype)); await frappe.router.setRoute('new', frappe.slug(this.doctype));
}) })
this.btnDelete = this.page.addButton(frappe._('Delete'), 'btn-outline-secondary hide', async () => { this.btnDelete = this.page.addButton(frappe._('Delete'), 'btn-outline-secondary hide', async () => {
@ -92,7 +92,7 @@ module.exports = class BaseList {
this.toolbar = frappe.ui.add('div', 'list-toolbar', this.parent); this.toolbar = frappe.ui.add('div', 'list-toolbar', this.parent);
this.toolbar.innerHTML = ` this.toolbar.innerHTML = `
<div class="row"> <div class="row">
<div class="col-md-6 col-9"> <div class="col-12" style="max-width: 300px">
<div class="input-group list-search mb-2"> <div class="input-group list-search mb-2">
<input class="form-control" type="text" placeholder="Search..."> <input class="form-control" type="text" placeholder="Search...">
<div class="input-group-append"> <div class="input-group-append">

View File

@ -3,15 +3,18 @@ const Observable = require('frappejs/utils/observable');
const Dropdown = require('frappejs/client/ui/dropdown'); const Dropdown = require('frappejs/client/ui/dropdown');
module.exports = class Page extends Observable { module.exports = class Page extends Observable {
constructor(title) { constructor({title, parent, hasRoute=true}) {
super(); super();
this.title = title; Object.assign(this, arguments[0]);
if (!this.parent) {
this.parent = frappe.desk.body;
}
this.make(); this.make();
this.dropdowns = {}; this.dropdowns = {};
} }
make() { make() {
this.wrapper = frappe.ui.add('div', 'page hide', frappe.desk.body); this.wrapper = frappe.ui.add('div', 'page hide', this.parent);
this.wrapper.innerHTML = `<div class="page-head hide"></div> this.wrapper.innerHTML = `<div class="page-head hide"></div>
<div class="page-body"></div>` <div class="page-body"></div>`
this.head = this.wrapper.querySelector('.page-head'); this.head = this.wrapper.querySelector('.page-head');
@ -39,9 +42,10 @@ module.exports = class Page extends Observable {
} }
async show(params) { async show(params) {
if (frappe.router.current_page) { if (this.parent.activePage) {
frappe.router.current_page.hide(); this.parent.activePage.hide();
} }
this.wrapper.classList.remove('hide'); this.wrapper.classList.remove('hide');
this.body.classList.remove('hide'); this.body.classList.remove('hide');
@ -49,8 +53,11 @@ module.exports = class Page extends Observable {
this.page_error.classList.add('hide'); this.page_error.classList.add('hide');
} }
frappe.router.current_page = this; this.parent.activePage = this;
if (this.hasRoute) {
document.title = this.title; document.title = this.title;
}
await this.trigger('show', params); await this.trigger('show', params);
} }