feat: Wiki based desk page
This commit is contained in:
parent
b4d57b0174
commit
902676ffb3
23 changed files with 9832 additions and 7323 deletions
0
frappe/desk/doctype/internal_wiki_page/__init__.py
Normal file
0
frappe/desk/doctype/internal_wiki_page/__init__.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) 2021, Frappe Technologies and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Internal Wiki Page', {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
});
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
"actions": [],
|
||||
"autoname": "field:title",
|
||||
"creation": "2021-05-02 14:44:26.490935",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"title",
|
||||
"icon",
|
||||
"parent_page",
|
||||
"column_break_4",
|
||||
"sequence_id",
|
||||
"private",
|
||||
"section_break_7",
|
||||
"content"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Title",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "icon",
|
||||
"fieldtype": "Data",
|
||||
"label": "Icon"
|
||||
},
|
||||
{
|
||||
"fieldname": "parent_page",
|
||||
"fieldtype": "Data",
|
||||
"label": "Parent Page"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "sequence_id",
|
||||
"fieldtype": "Int",
|
||||
"in_list_view": 1,
|
||||
"label": "Sequence Id"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "private",
|
||||
"fieldtype": "Check",
|
||||
"label": "Private"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_7",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "content",
|
||||
"fieldtype": "Long Text",
|
||||
"label": "Content"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2021-05-02 16:06:35.033197",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Internal Wiki Page",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
45
frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py
Normal file
45
frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2021, Frappe Technologies and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
class InternalWikiPage(Document):
|
||||
|
||||
def before_insert(self):
|
||||
if frappe.db.count('Internal Wiki Page') == 0:
|
||||
self.sequence_id = 1
|
||||
else:
|
||||
self.sequence_id = frappe.get_last_doc('Internal Wiki Page').sequence_id + 1
|
||||
|
||||
@frappe.whitelist()
|
||||
def save_wiki_page(title, parent, blocks, save=True):
|
||||
if save:
|
||||
if not frappe.db.exists("Workspace", title):
|
||||
wspace = frappe.new_doc('Workspace')
|
||||
wspace.label = title
|
||||
wspace.insert()
|
||||
|
||||
doc = frappe.new_doc('Internal Wiki Page')
|
||||
doc.title = title
|
||||
doc.parent_page = parent
|
||||
doc.content = blocks
|
||||
doc.insert()
|
||||
else:
|
||||
doc = frappe.get_doc('Internal Wiki Page', title)
|
||||
doc.content = blocks
|
||||
doc.save()
|
||||
|
||||
return doc.title
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_page_content(page):
|
||||
return frappe.db.get_value("Internal Wiki Page", page, "content")
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_pages():
|
||||
return frappe.db.get_list('Internal Wiki Page', fields=['name', 'icon', 'private', 'parent_page', 'sequence_id'],
|
||||
order_by="sequence_id asc")
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2021, Frappe Technologies and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestInternalWikiPage(unittest.TestCase):
|
||||
pass
|
||||
0
frappe/desk/page/wiki/__init__.py
Normal file
0
frappe/desk/page/wiki/__init__.py
Normal file
15
frappe/desk/page/wiki/wiki.js
Normal file
15
frappe/desk/page/wiki/wiki.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
frappe.provide('frappe.views')
|
||||
|
||||
frappe.pages['wiki'].on_page_load = function(wrapper) {
|
||||
frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
name: "Wiki",
|
||||
single_column: false,
|
||||
});
|
||||
|
||||
frappe.wiki = new frappe.views.Wiki(wrapper);
|
||||
|
||||
$(wrapper).bind('show', function () {
|
||||
frappe.wiki.show();
|
||||
});
|
||||
}
|
||||
19
frappe/desk/page/wiki/wiki.json
Normal file
19
frappe/desk/page/wiki/wiki.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"content": null,
|
||||
"creation": "2021-05-02 14:50:05.327302",
|
||||
"docstatus": 0,
|
||||
"doctype": "Page",
|
||||
"idx": 0,
|
||||
"modified": "2021-05-02 14:50:05.327302",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "wiki",
|
||||
"owner": "Administrator",
|
||||
"page_name": "wiki",
|
||||
"roles": [],
|
||||
"script": null,
|
||||
"standard": "Yes",
|
||||
"style": null,
|
||||
"system_page": 0,
|
||||
"title": "Wiki"
|
||||
}
|
||||
|
|
@ -178,6 +178,7 @@
|
|||
"public/js/frappe/views/breadcrumbs.js",
|
||||
"public/js/frappe/views/factory.js",
|
||||
"public/js/frappe/views/pageview.js",
|
||||
"public/js/frappe/views/wiki.js",
|
||||
|
||||
"public/js/frappe/ui/toolbar/awesome_bar.js",
|
||||
"public/js/frappe/ui/toolbar/energy_points_notifications.js",
|
||||
|
|
@ -196,6 +197,8 @@
|
|||
|
||||
"public/js/frappe/widgets/widget_group.js",
|
||||
|
||||
"public/js/frappe/wiki_blocks/blocks.js",
|
||||
|
||||
"public/js/frappe/ui/sort_selector.html",
|
||||
"public/js/frappe/ui/sort_selector.js",
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ frappe.router = {
|
|||
|
||||
convert_to_standard_route(route) {
|
||||
// /app/settings = ["Workspaces", "Settings"]
|
||||
// /app/wiki/accounting = ["wiki", "Accounting"]
|
||||
// /app/user = ["List", "User"]
|
||||
// /app/user/view/report = ["List", "User", "Report"]
|
||||
// /app/user/view/tree = ["Tree", "User"]
|
||||
|
|
@ -129,6 +130,9 @@ frappe.router = {
|
|||
if (frappe.workspaces[route[0]]) {
|
||||
// workspace
|
||||
route = ['Workspaces', frappe.workspaces[route[0]].name];
|
||||
} else if (frappe.wiki_pages && frappe.wiki_pages[route[1]]) {
|
||||
// wiki-pages
|
||||
route = ['wiki', frappe.wiki_pages[route[1]].name];
|
||||
} else if (this.routes[route[0]]) {
|
||||
// route
|
||||
route = this.set_doctype_route(route);
|
||||
|
|
|
|||
426
frappe/public/js/frappe/views/wiki.js
Normal file
426
frappe/public/js/frappe/views/wiki.js
Normal file
|
|
@ -0,0 +1,426 @@
|
|||
import EditorJS from '@editorjs/editorjs';
|
||||
import Header from '@editorjs/header';
|
||||
import Checklist from '@editorjs/checklist';
|
||||
import List from '@editorjs/list';
|
||||
import Undo from 'editorjs-undo';
|
||||
|
||||
frappe.views.Wiki = class Wiki {
|
||||
constructor(wrapper) {
|
||||
this.wrapper = $(wrapper);
|
||||
this.page = wrapper.page;
|
||||
this.pages = {};
|
||||
this.sections = {};
|
||||
this.sidebar_items = {};
|
||||
this.sorted_sidebar_items = {}
|
||||
this.tools = {}
|
||||
this.isReadOnly = true;
|
||||
this.prepare_container();
|
||||
this.setup_wiki_pages();
|
||||
}
|
||||
|
||||
prepare_container() {
|
||||
let list_sidebar = $(`
|
||||
<div class="list-sidebar overlay-sidebar hidden-xs hidden-sm">
|
||||
<div class="desk-sidebar list-unstyled sidebar-menu"></div>
|
||||
</div>
|
||||
`).appendTo(this.wrapper.find(".layout-side-section"));
|
||||
this.sidebar = list_sidebar.find(".desk-sidebar");
|
||||
this.body = this.wrapper.find(".layout-main-section");
|
||||
// this.body.addClass("frappe-card");
|
||||
}
|
||||
|
||||
setup_wiki_pages() {
|
||||
this.get_pages().then(() => {
|
||||
if(this.all_pages) {
|
||||
frappe.wiki_pages = {};
|
||||
let root_pages = this.all_pages.filter(page => page.parent_page == '' || page.parent_page == null)
|
||||
for (let page of this.all_pages || []) {
|
||||
frappe.wiki_pages[frappe.router.slug(page.name)] = page;
|
||||
}
|
||||
frappe.router.route();
|
||||
this.make_sidebar(root_pages);
|
||||
this.make_sidebar_sortable();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
make_sidebar_sortable() {
|
||||
let me = this;
|
||||
this.sidebar_sortable = Sortable.create(this.page.sidebar.find(".standard-sidebar-section").get(0), {
|
||||
handle: ".standard-sidebar-item-container",
|
||||
draggable: ".standard-sidebar-item-container",
|
||||
animation: 150,
|
||||
onEnd: function (evt){
|
||||
// let sb_items = me.all_pages.filter(page => page.parent_page == '' || page.parent_page == null)
|
||||
// let startBlock = sb_items[evt.oldIndex];
|
||||
// let endBlock = sb_items[evt.newIndex];
|
||||
// startBlock.sequence_id = parseInt(me.sidebar.find('.standard-sidebar-item-container')[evt.oldIndex].getAttribute('item-sequence'));
|
||||
// let oldName = me.sidebar.find('.standard-sidebar-item-container')[evt.oldIndex].getAttribute('item-name');
|
||||
// endBlock.sequence_id = parseInt(me.sidebar.find('.standard-sidebar-item-container')[evt.newIndex].getAttribute('item-sequence'));
|
||||
// let newName = me.sidebar.find('.standard-sidebar-item-container')[evt.newIndex].getAttribute('item-name');
|
||||
// frappe.db.set_value('Internal Wiki Page', newName, {["sequence_id"]: startBlock.sequence_id})
|
||||
// frappe.db.set_value('Internal Wiki Page', oldName, {["sequence_id"]: endBlock.sequence_id})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get_pages() {
|
||||
return frappe.xcall("frappe.desk.doctype.internal_wiki_page.internal_wiki_page.get_pages").then(data => {
|
||||
this.all_pages = data;
|
||||
});
|
||||
}
|
||||
|
||||
make_sidebar(items) {
|
||||
if (this.sidebar.find('.standard-sidebar-section')[0]) {
|
||||
this.sidebar.find('.standard-sidebar-section')[0].remove()
|
||||
}
|
||||
let sidebar_section = $(`<div class="standard-sidebar-section"></div>`);
|
||||
|
||||
const get_sidebar_item = function (item) {
|
||||
return $(`
|
||||
<div class="standard-sidebar-item-container" item-name="${item.name}" item-sequence="${item.sequence_id}">
|
||||
<div class="desk-sidebar-item standard-sidebar-item ${item.selected ? "selected" : ""}">
|
||||
<a
|
||||
href="/app/wiki/${frappe.router.slug(item.name)}"
|
||||
class="item-anchor"
|
||||
>
|
||||
<span>${frappe.utils.icon(item.icon || "folder-normal", "md")}</span>
|
||||
<span class="sidebar-item-label">${item.label || item.name}<span>
|
||||
</a>
|
||||
<span class="drop-icon hidden">${frappe.utils.icon("small-down", "sm")}</span>
|
||||
</div>
|
||||
<div class="sidebar-child-item hidden"></div>
|
||||
</div>
|
||||
`);
|
||||
};
|
||||
|
||||
const make_sidebar_category_item = item => {
|
||||
if (item.name == this.get_page_to_show()) {
|
||||
item.selected = true;
|
||||
this.current_page_name = item.name;
|
||||
}
|
||||
|
||||
const get_child_item = function (item) {
|
||||
return $(`
|
||||
<div class="sidebar-child-item-container">
|
||||
<a
|
||||
href="/app/wiki/${frappe.router.slug(item.name)}"
|
||||
class="desk-sidebar-item standard-sidebar-item ${item.selected ? "selected" : ""}"
|
||||
>
|
||||
<span>${frappe.utils.icon(item.icon || "folder-normal", "md")}</span>
|
||||
<span class="sidebar-item-label">${item.label || item.name}<span>
|
||||
</a>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
const make_sidebar_child_item = item => {
|
||||
let $child_item = get_child_item(item);
|
||||
$child_item.appendTo(child_item_section)
|
||||
this.sidebar_items[item.name] = $child_item;
|
||||
}
|
||||
|
||||
let $item = get_sidebar_item(item);
|
||||
let drop_icon = $item.find('.drop-icon').get(0);
|
||||
let child_item_section = $item.find('.sidebar-child-item').get(0);
|
||||
if(this.all_pages.some(e => e.parent_page == item.name)) {
|
||||
drop_icon.classList.remove('hidden');
|
||||
drop_icon.addEventListener('click', () => {
|
||||
child_item_section.classList.toggle("hidden");
|
||||
});
|
||||
}
|
||||
|
||||
let child_items = this.all_pages.filter(page => page.parent_page == item.name)
|
||||
child_items.forEach(item => make_sidebar_child_item(item));
|
||||
|
||||
$item.appendTo(sidebar_section);
|
||||
this.sidebar_items[item.name] = $item;
|
||||
};
|
||||
|
||||
items.forEach(item => make_sidebar_category_item(item));
|
||||
|
||||
sidebar_section.appendTo(this.sidebar);
|
||||
}
|
||||
|
||||
show() {
|
||||
if (!this.all_pages) {
|
||||
// pages not yet loaded, call again after a bit
|
||||
setTimeout(() => {
|
||||
this.show();
|
||||
}, 500);
|
||||
return;
|
||||
}
|
||||
let page = this.get_page_to_show();
|
||||
this.page.set_title(`${__(page)}`);
|
||||
this.show_page(page);
|
||||
this.get_content(page).then(() => {
|
||||
this.get_data(page).then(() => {
|
||||
if(this.content){
|
||||
this.tools = {
|
||||
header: {
|
||||
class: Header,
|
||||
inlineToolbar: true
|
||||
},
|
||||
paragraph: {
|
||||
class: frappe.wiki_block.blocks['paragraph'],
|
||||
inlineToolbar: true
|
||||
},
|
||||
checklist: {
|
||||
class: Checklist,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
list: {
|
||||
class: List,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
chart: {
|
||||
class: frappe.wiki_block.blocks['chart'],
|
||||
config: {
|
||||
page_data: this.page_data || []
|
||||
}
|
||||
},
|
||||
card: {
|
||||
class: frappe.wiki_block.blocks['card'],
|
||||
config: {
|
||||
page_data: this.page_data || []
|
||||
}
|
||||
},
|
||||
shortcut: {
|
||||
class: frappe.wiki_block.blocks['shortcut'],
|
||||
config: {
|
||||
page_data: this.page_data || []
|
||||
}
|
||||
},
|
||||
blank: frappe.wiki_block.blocks['blank'],
|
||||
spacingTune: frappe.wiki_block.tunes['spacing_tune'],
|
||||
}
|
||||
if(this.editor) {
|
||||
this.editor.isReady.then(() => {
|
||||
this.editor.configuration.tools.chart.config.page_data = this.page_data;
|
||||
this.editor.configuration.tools.shortcut.config.page_data = this.page_data;
|
||||
this.editor.configuration.tools.card.config.page_data = this.page_data;
|
||||
this.editor.render({
|
||||
blocks: JSON.parse(this.content) || []
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.initialize_editorjs(JSON.parse(this.content));
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
get_content(page) {
|
||||
return frappe.xcall("frappe.desk.doctype.internal_wiki_page.internal_wiki_page.get_page_content", {
|
||||
page: page
|
||||
}).then(data => {
|
||||
this.content = data;
|
||||
});
|
||||
}
|
||||
|
||||
get_data(page) {
|
||||
return frappe.xcall("frappe.desk.desktop.get_desktop_page", {
|
||||
page: page
|
||||
}).then(data => {
|
||||
this.page_data = data;
|
||||
});
|
||||
}
|
||||
|
||||
get_page_to_show() {
|
||||
let default_page;
|
||||
|
||||
if (localStorage.current_wiki_page) {
|
||||
default_page = localStorage.current_wiki_page;
|
||||
} else if (this.all_pages) {
|
||||
default_page = this.all_pages[0].name;
|
||||
} else {
|
||||
default_page = "Home";
|
||||
}
|
||||
|
||||
let page = frappe.get_route()[1] || default_page;
|
||||
return page;
|
||||
}
|
||||
|
||||
show_page(page) {
|
||||
if (this.current_page_name && this.pages[this.current_page_name]) {
|
||||
this.pages[this.current_page_name].hide();
|
||||
}
|
||||
|
||||
if (this.sidebar_items && this.sidebar_items[this.current_page_name]) {
|
||||
this.sidebar_items[this.current_page_name][0].firstElementChild.classList.remove("selected");
|
||||
this.sidebar_items[page][0].firstElementChild.classList.add("selected");
|
||||
}
|
||||
this.current_page_name = page;
|
||||
localStorage.current_wiki_page = page;
|
||||
|
||||
this.current_page = this.pages[page];
|
||||
|
||||
if (!this.body.find('#editorjs')[0]) {
|
||||
this.$page = $(`
|
||||
<div id="editorjs" class="wiki-page page-main-content"></div>
|
||||
`).appendTo(this.body);
|
||||
}
|
||||
|
||||
this.setup_actions();
|
||||
}
|
||||
|
||||
setup_actions() {
|
||||
this.page.clear_inner_toolbar();
|
||||
|
||||
this.page.set_secondary_action(
|
||||
__("Customize"),
|
||||
() => {
|
||||
this.isReadOnly = false;
|
||||
this.editor.readOnly.toggle();
|
||||
this.editor.isReady
|
||||
.then(() => {
|
||||
let me = this;
|
||||
this.undo = new Undo({ editor: this.editor });
|
||||
this.undo.initialize({blocks: JSON.parse(this.content)});
|
||||
this.setup_customization_buttons();
|
||||
this.page_sortable = Sortable.create(this.page.main.find(".codex-editor__redactor").get(0), {
|
||||
handle: ".ce-block",
|
||||
animation: 150,
|
||||
onEnd: function (evt){
|
||||
me.editor.blocks.move(evt.newIndex, evt.oldIndex);
|
||||
},
|
||||
setData: function (dataTransfer, dragEl) {
|
||||
//Do Nothing
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
this.page.add_inner_button(__('Create Page'), () => {
|
||||
this.initialize_new_page();
|
||||
});
|
||||
}
|
||||
|
||||
setup_customization_buttons() {
|
||||
this.page.clear_primary_action();
|
||||
this.page.clear_secondary_action();
|
||||
this.page.clear_inner_toolbar();
|
||||
|
||||
this.page.set_primary_action(
|
||||
__("Save Customizations"),
|
||||
() => {
|
||||
this.page.clear_primary_action();
|
||||
this.page.clear_secondary_action();
|
||||
this.save_page();
|
||||
this.editor.readOnly.toggle();
|
||||
this.isReadOnly = true;
|
||||
this.page_sortable.option("disabled", true);
|
||||
},
|
||||
null,
|
||||
__("Saving")
|
||||
);
|
||||
|
||||
this.page.set_secondary_action(
|
||||
__("Discard"),
|
||||
() => {
|
||||
this.page.clear_primary_action();
|
||||
this.page.clear_secondary_action();
|
||||
this.editor.readOnly.toggle();
|
||||
this.isReadOnly = true;
|
||||
this.page_sortable.option("disabled", true);
|
||||
this.reload();
|
||||
frappe.show_alert({ message: __("Customizations Discarded"), indicator: "info" });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
initialize_new_page() {
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Set Title'),
|
||||
fields: [
|
||||
{ label: __('Title'), fieldtype: 'Data', fieldname: 'title'},
|
||||
{ label: __('Parent'), fieldtype: 'Select', fieldname: 'parent', options: this.all_pages.map(pages => pages.name)}
|
||||
],
|
||||
primary_action_label: __('Create'),
|
||||
primary_action: (values) => {
|
||||
d.hide();
|
||||
this.setup_customization_buttons();
|
||||
this.title = values.title;
|
||||
this.parent = values.parent;
|
||||
// const index = this.all_pages.findIndex(e => e.selected == true )
|
||||
// this.all_pages[index].selected = false;
|
||||
// let item = {name: this.title, selected: true}
|
||||
// this.make_sidebar([...this.all_pages, item], 'new')
|
||||
this.editor.render({
|
||||
blocks: [
|
||||
{
|
||||
type: "header",
|
||||
data: {
|
||||
text: this.title,
|
||||
level: 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}).then(() => {
|
||||
if(this.editor.configuration.readOnly) {
|
||||
this.isReadOnly = false;
|
||||
this.editor.readOnly.toggle();
|
||||
}
|
||||
this.dirty = false;
|
||||
})
|
||||
}
|
||||
});
|
||||
d.show();
|
||||
}
|
||||
|
||||
initialize_editorjs(blocks) {
|
||||
this.dirty = false;
|
||||
const data = {
|
||||
blocks: blocks || []
|
||||
}
|
||||
this.editor = new EditorJS({
|
||||
tools: this.tools,
|
||||
autofocus: false,
|
||||
data,
|
||||
tunes: ['spacingTune'],
|
||||
onChange: () => {
|
||||
this.dirty = true;
|
||||
},
|
||||
readOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
save_page() {
|
||||
frappe.dom.freeze();
|
||||
let save = true;
|
||||
if (!this.title && this.current_page_name) {
|
||||
this.title = this.current_page_name;
|
||||
save = '';
|
||||
}
|
||||
let me = this;
|
||||
this.editor.save().then((outputData) => {
|
||||
frappe.call({
|
||||
method: "frappe.desk.doctype.internal_wiki_page.internal_wiki_page.save_wiki_page",
|
||||
args: {
|
||||
title: me.title,
|
||||
parent: me.parent || '',
|
||||
blocks: JSON.stringify(outputData.blocks),
|
||||
save: save
|
||||
},
|
||||
callback: function(res) {
|
||||
frappe.dom.unfreeze();
|
||||
if (res.message) {
|
||||
frappe.show_alert({ message: __("Page Saved Successfully"), indicator: "green" });
|
||||
me.title = '';
|
||||
me.parent = '';
|
||||
me.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
}).catch((error) => {
|
||||
console.log('Saving failed: ', error);
|
||||
});
|
||||
}
|
||||
|
||||
reload() {
|
||||
this.setup_wiki_pages();
|
||||
this.dirty = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -186,4 +186,47 @@ export default class WidgetGroup {
|
|||
}
|
||||
}
|
||||
|
||||
export class SingleWidgetGroup {
|
||||
constructor(opts) {
|
||||
Object.assign(this, opts);
|
||||
this.widgets_list = [];
|
||||
this.widgets_dict = {};
|
||||
this.widget_order = [];
|
||||
this.make();
|
||||
}
|
||||
|
||||
make() {
|
||||
this.add_widget(this.widgets);
|
||||
}
|
||||
|
||||
add_widget(widget) {
|
||||
let widget_object = frappe.widget.make_widget({
|
||||
...widget,
|
||||
widget_type: this.type,
|
||||
container: this.container,
|
||||
height: this.height || null,
|
||||
options: {
|
||||
...this.options,
|
||||
on_delete: (name) => this.on_delete(name),
|
||||
},
|
||||
});
|
||||
|
||||
this.widgets_list.push(widget_object);
|
||||
this.widgets_dict[widget.name] = widget_object;
|
||||
|
||||
return widget_object;
|
||||
}
|
||||
|
||||
customize() {
|
||||
// if (!this.hidden) this.widget_area.show();
|
||||
this.widgets_list.forEach((wid) => {
|
||||
wid.customize(this.options);
|
||||
});
|
||||
|
||||
// this.options.allow_create && this.setup_new_widget();
|
||||
// this.options.allow_sorting && this.setup_sortable();
|
||||
}
|
||||
}
|
||||
|
||||
frappe.widget.WidgetGroup = WidgetGroup;
|
||||
frappe.widget.SingleWidgetGroup = SingleWidgetGroup;
|
||||
|
|
|
|||
111
frappe/public/js/frappe/wiki_blocks/blank.js
Normal file
111
frappe/public/js/frappe/wiki_blocks/blank.js
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
export default class Blank {
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: 'Blank',
|
||||
icon: '<svg width="18" height="18" viewBox="0 0 400 400"><path d="M377.87 24.126C361.786 8.042 342.417 0 319.769 0H82.227C59.579 0 40.211 8.042 24.125 24.126 8.044 40.212.002 59.576.002 82.228v237.543c0 22.647 8.042 42.014 24.123 58.101 16.086 16.085 35.454 24.127 58.102 24.127h237.542c22.648 0 42.011-8.042 58.102-24.127 16.085-16.087 24.126-35.453 24.126-58.101V82.228c-.004-22.648-8.046-42.016-24.127-58.102zm-12.422 295.645c0 12.559-4.47 23.314-13.415 32.264-8.945 8.945-19.698 13.411-32.265 13.411H82.227c-12.563 0-23.317-4.466-32.264-13.411-8.945-8.949-13.418-19.705-13.418-32.264V82.228c0-12.562 4.473-23.316 13.418-32.264 8.947-8.946 19.701-13.418 32.264-13.418h237.542c12.566 0 23.319 4.473 32.265 13.418 8.945 8.947 13.415 19.701 13.415 32.264v237.543h-.001z"/></svg>'
|
||||
};
|
||||
}
|
||||
|
||||
static get isReadOnlySupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
constructor({data, api, config, readOnly}){
|
||||
this.data = data;
|
||||
this.api = api;
|
||||
this.config = config;
|
||||
this.readOnly = readOnly;
|
||||
this.col = this.data.col ? this.data.col : "12",
|
||||
this.pt = this.data.pt ? this.data.pt : "0",
|
||||
this.pr = this.data.pr ? this.data.pr : "0",
|
||||
this.pb = this.data.pb ? this.data.pb : "0",
|
||||
this.pl = this.data.pl ? this.data.pl : "0"
|
||||
}
|
||||
|
||||
render() {
|
||||
this.wrapper = document.createElement('div');
|
||||
if (!this.readOnly) {
|
||||
this.wrapper.innerText = 'Blank';
|
||||
this.wrapper.classList.add('widget', 'new-widget');
|
||||
this.wrapper.style.minHeight = 50 + 'px';
|
||||
}
|
||||
return this.wrapper;
|
||||
}
|
||||
|
||||
save(blockContent) {
|
||||
return {
|
||||
col: this._getCol(),
|
||||
pt: this._getPadding("t"),
|
||||
pr: this._getPadding("r"),
|
||||
pb: this._getPadding("b"),
|
||||
pl: this._getPadding("l")
|
||||
}
|
||||
}
|
||||
|
||||
rendered() {
|
||||
var e = this.wrapper.parentNode.parentNode;
|
||||
e.classList.add("col-" + this.col)
|
||||
e.classList.add("pt-" + this.pt)
|
||||
e.classList.add("pr-" + this.pr)
|
||||
e.classList.add("pb-" + this.pb)
|
||||
e.classList.add("pl-" + this.pl)
|
||||
}
|
||||
|
||||
_getCol() {
|
||||
var e = 12,
|
||||
t = "col-12",
|
||||
n = this.wrapper.parentNode.parentNode,
|
||||
r = new RegExp(/\bcol-.+?\b/, "g");
|
||||
if (n.className.match(r)) {
|
||||
n.classList.forEach(function (e) {
|
||||
e.match(r) && (t = e);
|
||||
});
|
||||
var a = t.split("-");
|
||||
e = parseInt(a[1]);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
_getPadding() {
|
||||
var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l",
|
||||
t = 0,
|
||||
n = "p" + e + "-0",
|
||||
r = this.wrapper.parentNode.parentNode,
|
||||
a = new RegExp(/\pl-.+?\b/, "g"),
|
||||
i = new RegExp(/\pr-.+?\b/, "g"),
|
||||
o = new RegExp(/\pt-.+?\b/, "g"),
|
||||
c = new RegExp(/\pb-.+?\b/, "g");
|
||||
if ("l" == e) {
|
||||
if (r.className.match(a)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(a) && (n = e);
|
||||
});
|
||||
var s = n.split("-");
|
||||
t = parseInt(s[1]);
|
||||
}
|
||||
} else if ("r" == e) {
|
||||
if (r.className.match(i)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(i) && (n = e);
|
||||
});
|
||||
var l = n.split("-");
|
||||
t = parseInt(l[1]);
|
||||
}
|
||||
} else if ("t" == e) {
|
||||
if (r.className.match(o)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(o) && (n = e);
|
||||
});
|
||||
var u = n.split("-");
|
||||
t = parseInt(u[1]);
|
||||
}
|
||||
} else if ("b" == e && r.className.match(c)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(c) && (n = e);
|
||||
});
|
||||
var p = n.split("-");
|
||||
t = parseInt(p[1]);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
23
frappe/public/js/frappe/wiki_blocks/blocks.js
Normal file
23
frappe/public/js/frappe/wiki_blocks/blocks.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// import blocks
|
||||
import Paragraph from "../wiki_blocks/paragraph";
|
||||
import Card from "../wiki_blocks/card";
|
||||
import Chart from "../wiki_blocks/chart";
|
||||
import Shortcut from "../wiki_blocks/shortcut";
|
||||
import Blank from "../wiki_blocks/blank";
|
||||
|
||||
// import tunes
|
||||
import SpacingTune from "../wiki_blocks/spacing_tune";
|
||||
|
||||
frappe.provide("frappe.wiki_block");
|
||||
|
||||
frappe.wiki_block.blocks = {
|
||||
paragraph: Paragraph,
|
||||
card: Card,
|
||||
chart: Chart,
|
||||
shortcut: Shortcut,
|
||||
blank: Blank,
|
||||
};
|
||||
|
||||
frappe.wiki_block.tunes = {
|
||||
spacing_tune : SpacingTune
|
||||
}
|
||||
155
frappe/public/js/frappe/wiki_blocks/card.js
Normal file
155
frappe/public/js/frappe/wiki_blocks/card.js
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
export default class Card {
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: 'Card',
|
||||
icon: '<svg height="24" width="24" viewBox="0 0 24 24"><path d="M7 15h3a1 1 0 000-2H7a1 1 0 000 2zM19 5H5a3 3 0 00-3 3v9a3 3 0 003 3h14a3 3 0 003-3V8a3 3 0 00-3-3zm1 12a1 1 0 01-1 1H5a1 1 0 01-1-1v-6h16zm0-8H4V8a1 1 0 011-1h14a1 1 0 011 1z"/></svg>'
|
||||
};
|
||||
}
|
||||
|
||||
static get isReadOnlySupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
constructor({data, api, config, readOnly, block}){
|
||||
this.data = data;
|
||||
this.api = api;
|
||||
this.config = config;
|
||||
this.readOnly = readOnly;
|
||||
this.sections = {};
|
||||
this.col = this.data.col ? this.data.col : "12",
|
||||
this.pt = this.data.pt ? this.data.pt : "0",
|
||||
this.pr = this.data.pr ? this.data.pr : "0",
|
||||
this.pb = this.data.pb ? this.data.pb : "0",
|
||||
this.pl = this.data.pl ? this.data.pl : "0"
|
||||
}
|
||||
|
||||
render() {
|
||||
let me = this;
|
||||
this.wrapper = document.createElement('div');
|
||||
this._make_fieldgroup(this.wrapper, [{
|
||||
fieldtype: "Select",
|
||||
label: "Card Name",
|
||||
fieldname: "card_name",
|
||||
options: this.config.page_data.cards.items.map(({ label }) => label),
|
||||
change: function() {
|
||||
if (this.value) {
|
||||
me._make_cards(this.value)
|
||||
}
|
||||
}
|
||||
}]);
|
||||
if (this.data && this.data.card_name) {
|
||||
this._make_cards(this.data.card_name)
|
||||
}
|
||||
return this.wrapper;
|
||||
}
|
||||
|
||||
save(blockContent) {
|
||||
return {
|
||||
card_name: blockContent.getAttribute('card_name'),
|
||||
col: this._getCol(),
|
||||
pt: this._getPadding("t"),
|
||||
pr: this._getPadding("r"),
|
||||
pb: this._getPadding("b"),
|
||||
pl: this._getPadding("l")
|
||||
}
|
||||
}
|
||||
|
||||
rendered() {
|
||||
var e = this.wrapper.parentNode.parentNode;
|
||||
e.classList.add("col-" + this.col)
|
||||
e.classList.add("pt-" + this.pt)
|
||||
e.classList.add("pr-" + this.pr)
|
||||
e.classList.add("pb-" + this.pb)
|
||||
e.classList.add("pl-" + this.pl)
|
||||
}
|
||||
|
||||
_getCol() {
|
||||
var e = 12,
|
||||
t = "col-12",
|
||||
n = this.wrapper.parentNode.parentNode,
|
||||
r = new RegExp(/\bcol-.+?\b/, "g");
|
||||
if (n.className.match(r)) {
|
||||
n.classList.forEach(function (e) {
|
||||
e.match(r) && (t = e);
|
||||
});
|
||||
var a = t.split("-");
|
||||
e = parseInt(a[1]);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
_getPadding() {
|
||||
var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l",
|
||||
t = 0,
|
||||
n = "p" + e + "-0",
|
||||
r = this.wrapper.parentNode.parentNode,
|
||||
a = new RegExp(/\pl-.+?\b/, "g"),
|
||||
i = new RegExp(/\pr-.+?\b/, "g"),
|
||||
o = new RegExp(/\pt-.+?\b/, "g"),
|
||||
c = new RegExp(/\pb-.+?\b/, "g");
|
||||
if ("l" == e) {
|
||||
if (r.className.match(a)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(a) && (n = e);
|
||||
});
|
||||
var s = n.split("-");
|
||||
t = parseInt(s[1]);
|
||||
}
|
||||
} else if ("r" == e) {
|
||||
if (r.className.match(i)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(i) && (n = e);
|
||||
});
|
||||
var l = n.split("-");
|
||||
t = parseInt(l[1]);
|
||||
}
|
||||
} else if ("t" == e) {
|
||||
if (r.className.match(o)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(o) && (n = e);
|
||||
});
|
||||
var u = n.split("-");
|
||||
t = parseInt(u[1]);
|
||||
}
|
||||
} else if ("b" == e && r.className.match(c)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(c) && (n = e);
|
||||
});
|
||||
var p = n.split("-");
|
||||
t = parseInt(p[1]);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
_make_fieldgroup(parent, ddf_list) {
|
||||
this.card_field = new frappe.ui.FieldGroup({
|
||||
"fields": ddf_list,
|
||||
"parent": parent
|
||||
});
|
||||
this.card_field.make();
|
||||
}
|
||||
|
||||
_make_cards(card_name) {
|
||||
let card = this.config.page_data.cards.items.find(obj => {
|
||||
return obj.label == card_name
|
||||
});
|
||||
this.wrapper.innerHTML = '';
|
||||
this.sections = {};
|
||||
let cards = new frappe.widget.SingleWidgetGroup({
|
||||
container: this.wrapper,
|
||||
type: "links",
|
||||
columns: 3,
|
||||
options: {
|
||||
allow_sorting: this.allow_customization,
|
||||
allow_create: false,
|
||||
allow_delete: false,
|
||||
allow_hiding: this.allow_customization,
|
||||
allow_edit: false,
|
||||
},
|
||||
widgets: card
|
||||
});
|
||||
|
||||
this.sections["cards"] = cards;
|
||||
this.wrapper.setAttribute("card_name", card_name);
|
||||
}
|
||||
}
|
||||
156
frappe/public/js/frappe/wiki_blocks/chart.js
Normal file
156
frappe/public/js/frappe/wiki_blocks/chart.js
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
export default class Chart {
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: 'Chart',
|
||||
icon: '<svg height="18" width="18" viewBox="0 0 512 512"><path d="M117.547 234.667H10.88c-5.888 0-10.667 4.779-10.667 10.667v256C.213 507.221 4.992 512 10.88 512h106.667c5.888 0 10.667-4.779 10.667-10.667v-256a10.657 10.657 0 00-10.667-10.666zM309.12 0H202.453c-5.888 0-10.667 4.779-10.667 10.667v490.667c0 5.888 4.779 10.667 10.667 10.667H309.12c5.888 0 10.667-4.779 10.667-10.667V10.667C319.787 4.779 315.008 0 309.12 0zM501.12 106.667H394.453c-5.888 0-10.667 4.779-10.667 10.667v384c0 5.888 4.779 10.667 10.667 10.667H501.12c5.888 0 10.667-4.779 10.667-10.667v-384c0-5.889-4.779-10.667-10.667-10.667z"/></svg>'
|
||||
};
|
||||
}
|
||||
|
||||
static get isReadOnlySupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
constructor({data, api, config, readOnly}){
|
||||
this.data = data;
|
||||
this.api = api;
|
||||
this.config = config;
|
||||
this.readOnly = readOnly;
|
||||
this.sections = {};
|
||||
this.col = this.data.col ? this.data.col : "12",
|
||||
this.pt = this.data.pt ? this.data.pt : "0",
|
||||
this.pr = this.data.pr ? this.data.pr : "0",
|
||||
this.pb = this.data.pb ? this.data.pb : "0",
|
||||
this.pl = this.data.pl ? this.data.pl : "0"
|
||||
}
|
||||
|
||||
render() {
|
||||
let me = this;
|
||||
this.wrapper = document.createElement('div');
|
||||
this._make_fieldgroup(this.wrapper, [{
|
||||
fieldtype: "Select",
|
||||
label: "Chart Name",
|
||||
fieldname: "chart_name",
|
||||
options: this.config.page_data.charts.items.map(({ chart_name }) => chart_name),
|
||||
change: function() {
|
||||
if (this.value) {
|
||||
me._make_charts(this.value)
|
||||
}
|
||||
}
|
||||
}]);
|
||||
if (this.data && this.data.chart_name) {
|
||||
this._make_charts(this.data.chart_name)
|
||||
}
|
||||
return this.wrapper;
|
||||
}
|
||||
|
||||
save(blockContent) {
|
||||
return {
|
||||
chart_name: blockContent.getAttribute('chart_name'),
|
||||
col: this._getCol(),
|
||||
pt: this._getPadding("t"),
|
||||
pr: this._getPadding("r"),
|
||||
pb: this._getPadding("b"),
|
||||
pl: this._getPadding("l")
|
||||
}
|
||||
}
|
||||
|
||||
rendered() {
|
||||
var e = this.wrapper.parentNode.parentNode;
|
||||
e.classList.add("col-" + this.col)
|
||||
e.classList.add("pt-" + this.pt)
|
||||
e.classList.add("pr-" + this.pr)
|
||||
e.classList.add("pb-" + this.pb)
|
||||
e.classList.add("pl-" + this.pl)
|
||||
}
|
||||
|
||||
_getCol() {
|
||||
var e = 12,
|
||||
t = "col-12",
|
||||
n = this.wrapper.parentNode.parentNode,
|
||||
r = new RegExp(/\bcol-.+?\b/, "g");
|
||||
if (n.className.match(r)) {
|
||||
n.classList.forEach(function (e) {
|
||||
e.match(r) && (t = e);
|
||||
});
|
||||
var a = t.split("-");
|
||||
e = parseInt(a[1]);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
_getPadding() {
|
||||
var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l",
|
||||
t = 0,
|
||||
n = "p" + e + "-0",
|
||||
r = this.wrapper.parentNode.parentNode,
|
||||
a = new RegExp(/\pl-.+?\b/, "g"),
|
||||
i = new RegExp(/\pr-.+?\b/, "g"),
|
||||
o = new RegExp(/\pt-.+?\b/, "g"),
|
||||
c = new RegExp(/\pb-.+?\b/, "g");
|
||||
if ("l" == e) {
|
||||
if (r.className.match(a)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(a) && (n = e);
|
||||
});
|
||||
var s = n.split("-");
|
||||
t = parseInt(s[1]);
|
||||
}
|
||||
} else if ("r" == e) {
|
||||
if (r.className.match(i)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(i) && (n = e);
|
||||
});
|
||||
var l = n.split("-");
|
||||
t = parseInt(l[1]);
|
||||
}
|
||||
} else if ("t" == e) {
|
||||
if (r.className.match(o)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(o) && (n = e);
|
||||
});
|
||||
var u = n.split("-");
|
||||
t = parseInt(u[1]);
|
||||
}
|
||||
} else if ("b" == e && r.className.match(c)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(c) && (n = e);
|
||||
});
|
||||
var p = n.split("-");
|
||||
t = parseInt(p[1]);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
_make_fieldgroup(parent, ddf_list) {
|
||||
this.chart_field = new frappe.ui.FieldGroup({
|
||||
"fields": ddf_list,
|
||||
"parent": parent
|
||||
});
|
||||
this.chart_field.make();
|
||||
}
|
||||
|
||||
_make_charts(chart_name) {
|
||||
let chart = this.config.page_data.charts.items.find(obj => {
|
||||
return obj.chart_name == chart_name
|
||||
});
|
||||
this.wrapper.innerHTML = '';
|
||||
this.sections = {};
|
||||
this.sections["charts"] = new frappe.widget.SingleWidgetGroup({
|
||||
container: this.wrapper,
|
||||
type: "chart",
|
||||
columns: 1,
|
||||
class_name: "widget-charts",
|
||||
// hidden: Boolean(this.onboarding_widget),
|
||||
options: {
|
||||
allow_sorting: this.allow_customization,
|
||||
allow_create: this.allow_customization,
|
||||
allow_delete: this.allow_customization,
|
||||
allow_hiding: false,
|
||||
allow_edit: true,
|
||||
max_widget_count: 2,
|
||||
},
|
||||
widgets: chart
|
||||
});
|
||||
this.wrapper.setAttribute("chart_name", chart_name)
|
||||
}
|
||||
}
|
||||
210
frappe/public/js/frappe/wiki_blocks/paragraph.js
Normal file
210
frappe/public/js/frappe/wiki_blocks/paragraph.js
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
export default class Paragraph {
|
||||
|
||||
static get DEFAULT_PLACEHOLDER() {
|
||||
return '';
|
||||
}
|
||||
|
||||
constructor({data, config, api, readOnly}) {
|
||||
this.api = api;
|
||||
this.readOnly = readOnly;
|
||||
|
||||
this._CSS = {
|
||||
block: this.api.styles.block,
|
||||
wrapper: 'ce-paragraph'
|
||||
};
|
||||
|
||||
if (!this.readOnly) {
|
||||
this.onKeyUp = this.onKeyUp.bind(this);
|
||||
}
|
||||
|
||||
this._placeholder = config.placeholder ? config.placeholder : Paragraph.DEFAULT_PLACEHOLDER;
|
||||
this._data = {};
|
||||
this._element = this.drawView();
|
||||
this._preserveBlank = config.preserveBlank !== undefined ? config.preserveBlank : false;
|
||||
|
||||
this.data = data;
|
||||
this.col = this.data.col ? this.data.col : "12",
|
||||
this.pt = this.data.pt ? this.data.pt : "0",
|
||||
this.pr = this.data.pr ? this.data.pr : "0",
|
||||
this.pb = this.data.pb ? this.data.pb : "0",
|
||||
this.pl = this.data.pl ? this.data.pl : "0"
|
||||
}
|
||||
|
||||
onKeyUp(e) {
|
||||
if (e.code !== 'Backspace' && e.code !== 'Delete') {
|
||||
return;
|
||||
}
|
||||
|
||||
const {textContent} = this._element;
|
||||
|
||||
if (textContent === '') {
|
||||
this._element.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
drawView() {
|
||||
let div = document.createElement('DIV');
|
||||
|
||||
div.classList.add(this._CSS.wrapper, this._CSS.block, 'widget');
|
||||
div.contentEditable = false;
|
||||
div.dataset.placeholder = this.api.i18n.t(this._placeholder);
|
||||
|
||||
if (!this.readOnly) {
|
||||
div.contentEditable = true;
|
||||
div.addEventListener('keyup', this.onKeyUp);
|
||||
}
|
||||
return div;
|
||||
}
|
||||
|
||||
render() {
|
||||
return this._element;
|
||||
}
|
||||
|
||||
merge(data) {
|
||||
let newData = {
|
||||
text : this.data.text + data.text
|
||||
};
|
||||
|
||||
this.data = newData;
|
||||
}
|
||||
|
||||
validate(savedData) {
|
||||
if (savedData.text.trim() === '' && !this._preserveBlank) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
save(toolsContent) {
|
||||
return {
|
||||
text: toolsContent.innerHTML,
|
||||
col: this._getCol(),
|
||||
pt: this._getPadding("t"),
|
||||
pr: this._getPadding("r"),
|
||||
pb: this._getPadding("b"),
|
||||
pl: this._getPadding("l")
|
||||
};
|
||||
}
|
||||
|
||||
rendered() {
|
||||
var e = this._element.parentNode.parentNode;
|
||||
e.classList.add("col-" + this.col)
|
||||
e.classList.add("pt-" + this.pt)
|
||||
e.classList.add("pr-" + this.pr)
|
||||
e.classList.add("pb-" + this.pb)
|
||||
e.classList.add("pl-" + this.pl)
|
||||
}
|
||||
|
||||
_getCol() {
|
||||
var e = 12,
|
||||
t = "col-12",
|
||||
n = this._element.parentNode.parentNode,
|
||||
r = new RegExp(/\bcol-.+?\b/, "g");
|
||||
if (n.className.match(r)) {
|
||||
n.classList.forEach(function (e) {
|
||||
e.match(r) && (t = e);
|
||||
});
|
||||
var a = t.split("-");
|
||||
e = parseInt(a[1]);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
_getPadding() {
|
||||
var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l",
|
||||
t = 0,
|
||||
n = "p" + e + "-0",
|
||||
r = this._element.parentNode.parentNode,
|
||||
a = new RegExp(/\pl-.+?\b/, "g"),
|
||||
i = new RegExp(/\pr-.+?\b/, "g"),
|
||||
o = new RegExp(/\pt-.+?\b/, "g"),
|
||||
c = new RegExp(/\pb-.+?\b/, "g");
|
||||
if ("l" == e) {
|
||||
if (r.className.match(a)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(a) && (n = e);
|
||||
});
|
||||
var s = n.split("-");
|
||||
t = parseInt(s[1]);
|
||||
}
|
||||
} else if ("r" == e) {
|
||||
if (r.className.match(i)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(i) && (n = e);
|
||||
});
|
||||
var l = n.split("-");
|
||||
t = parseInt(l[1]);
|
||||
}
|
||||
} else if ("t" == e) {
|
||||
if (r.className.match(o)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(o) && (n = e);
|
||||
});
|
||||
var u = n.split("-");
|
||||
t = parseInt(u[1]);
|
||||
}
|
||||
} else if ("b" == e && r.className.match(c)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(c) && (n = e);
|
||||
});
|
||||
var p = n.split("-");
|
||||
t = parseInt(p[1]);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
onPaste(event) {
|
||||
const data = {
|
||||
text: event.detail.data.innerHTML
|
||||
};
|
||||
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
static get conversionConfig() {
|
||||
return {
|
||||
export: 'text', // to convert Paragraph to other block, use 'text' property of saved data
|
||||
import: 'text' // to covert other block's exported string to Paragraph, fill 'text' property of tool data
|
||||
};
|
||||
}
|
||||
|
||||
static get sanitize() {
|
||||
return {
|
||||
text: {
|
||||
br: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static get isReadOnlySupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get data() {
|
||||
let text = this._element.innerHTML;
|
||||
|
||||
this._data.text = text;
|
||||
|
||||
return this._data;
|
||||
}
|
||||
|
||||
set data(data) {
|
||||
this._data = data || {};
|
||||
|
||||
this._element.innerHTML = this._data.text || '';
|
||||
}
|
||||
|
||||
static get pasteConfig() {
|
||||
return {
|
||||
tags: [ 'P' ]
|
||||
};
|
||||
}
|
||||
|
||||
static get toolbox() {
|
||||
return {
|
||||
icon: '<svg viewBox="0.2 -0.3 9 11.4" width="12" height="14"><path d="M0 2.77V.92A1 1 0 01.2.28C.35.1.56 0 .83 0h7.66c.28.01.48.1.63.28.14.17.21.38.21.64v1.85c0 .26-.08.48-.23.66-.15.17-.37.26-.66.26-.28 0-.5-.09-.64-.26a1 1 0 01-.21-.66V1.69H5.6v7.58h.5c.25 0 .45.08.6.23.17.16.25.35.25.6s-.08.45-.24.6a.87.87 0 01-.62.22H3.21a.87.87 0 01-.61-.22.78.78 0 01-.24-.6c0-.25.08-.44.24-.6a.85.85 0 01.61-.23h.5V1.7H1.73v1.08c0 .26-.08.48-.23.66-.15.17-.37.26-.66.26-.28 0-.5-.09-.64-.26A1 1 0 010 2.77z"/></svg>',
|
||||
title: 'Text'
|
||||
};
|
||||
}
|
||||
}
|
||||
153
frappe/public/js/frappe/wiki_blocks/shortcut.js
Normal file
153
frappe/public/js/frappe/wiki_blocks/shortcut.js
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
export default class Shortcut {
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: 'Shortcut',
|
||||
icon: '<svg height="18" width="18" viewBox="0 0 122.88 115.71"><path d="M116.56 3.69l-3.84 53.76-17.69-15c-19.5 8.72-29.96 23.99-30.51 43.77-17.95-26.98-7.46-50.4 12.46-65.97L64.96 3l51.6.69zM28.3 0h14.56v19.67H32.67c-4.17 0-7.96 1.71-10.72 4.47-2.75 2.75-4.46 6.55-4.46 10.72l-.03 46c.03 4.16 1.75 7.95 4.5 10.71 2.76 2.76 6.56 4.48 10.71 4.48h58.02c4.15 0 7.95-1.72 10.71-4.48 2.76-2.76 4.48-6.55 4.48-10.71V73.9h17.01v11.33c0 7.77-3.2 17.04-8.32 22.16-5.12 5.12-12.21 8.32-19.98 8.32H28.3c-7.77 0-14.86-3.2-19.98-8.32C3.19 102.26 0 95.18 0 87.41l.03-59.1c-.03-7.79 3.16-14.88 8.28-20C13.43 3.19 20.51 0 28.3 0z" fill-rule="evenodd" clip-rule="evenodd"/></svg>'
|
||||
};
|
||||
}
|
||||
|
||||
static get isReadOnlySupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
constructor({data, api, config, readOnly}){
|
||||
this.data = data;
|
||||
this.api = api;
|
||||
this.config = config;
|
||||
this.readOnly = readOnly;
|
||||
this.sections = {};
|
||||
this.col = this.data.col ? this.data.col : "12",
|
||||
this.pt = this.data.pt ? this.data.pt : "0",
|
||||
this.pr = this.data.pr ? this.data.pr : "0",
|
||||
this.pb = this.data.pb ? this.data.pb : "0",
|
||||
this.pl = this.data.pl ? this.data.pl : "0"
|
||||
}
|
||||
|
||||
render() {
|
||||
let me = this;
|
||||
this.wrapper = document.createElement('div');
|
||||
this._make_fieldgroup(this.wrapper, [{
|
||||
fieldtype: "Select",
|
||||
label: "Shortcut Name",
|
||||
fieldname: "shortcut_name",
|
||||
options: this.config.page_data.shortcuts.items.map(({ label }) => label),
|
||||
change: function() {
|
||||
if (this.value) {
|
||||
me._make_shortcuts(this.value);
|
||||
}
|
||||
}
|
||||
}]);
|
||||
if (this.data && this.data.shortcut_name) {
|
||||
this._make_shortcuts(this.data.shortcut_name)
|
||||
}
|
||||
return this.wrapper;
|
||||
}
|
||||
|
||||
save(blockContent) {
|
||||
return {
|
||||
shortcut_name: blockContent.getAttribute('shortcut_name'),
|
||||
col: this._getCol(),
|
||||
pt: this._getPadding("t"),
|
||||
pr: this._getPadding("r"),
|
||||
pb: this._getPadding("b"),
|
||||
pl: this._getPadding("l")
|
||||
}
|
||||
}
|
||||
|
||||
rendered() {
|
||||
var e = this.wrapper.parentNode.parentNode;
|
||||
e.classList.add("col-" + this.col)
|
||||
e.classList.add("pt-" + this.pt)
|
||||
e.classList.add("pr-" + this.pr)
|
||||
e.classList.add("pb-" + this.pb)
|
||||
e.classList.add("pl-" + this.pl)
|
||||
}
|
||||
|
||||
_getCol() {
|
||||
var e = 12,
|
||||
t = "col-12",
|
||||
n = this.wrapper.parentNode.parentNode,
|
||||
r = new RegExp(/\bcol-.+?\b/, "g");
|
||||
if (n.className.match(r)) {
|
||||
n.classList.forEach(function (e) {
|
||||
e.match(r) && (t = e);
|
||||
});
|
||||
var a = t.split("-");
|
||||
e = parseInt(a[1]);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
_getPadding() {
|
||||
var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l",
|
||||
t = 0,
|
||||
n = "p" + e + "-0",
|
||||
r = this.wrapper.parentNode.parentNode,
|
||||
a = new RegExp(/\pl-.+?\b/, "g"),
|
||||
i = new RegExp(/\pr-.+?\b/, "g"),
|
||||
o = new RegExp(/\pt-.+?\b/, "g"),
|
||||
c = new RegExp(/\pb-.+?\b/, "g");
|
||||
if ("l" == e) {
|
||||
if (r.className.match(a)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(a) && (n = e);
|
||||
});
|
||||
var s = n.split("-");
|
||||
t = parseInt(s[1]);
|
||||
}
|
||||
} else if ("r" == e) {
|
||||
if (r.className.match(i)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(i) && (n = e);
|
||||
});
|
||||
var l = n.split("-");
|
||||
t = parseInt(l[1]);
|
||||
}
|
||||
} else if ("t" == e) {
|
||||
if (r.className.match(o)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(o) && (n = e);
|
||||
});
|
||||
var u = n.split("-");
|
||||
t = parseInt(u[1]);
|
||||
}
|
||||
} else if ("b" == e && r.className.match(c)) {
|
||||
r.classList.forEach(function (e) {
|
||||
e.match(c) && (n = e);
|
||||
});
|
||||
var p = n.split("-");
|
||||
t = parseInt(p[1]);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
_make_fieldgroup(parent, ddf_list) {
|
||||
this.shortcut_field = new frappe.ui.FieldGroup({
|
||||
"fields": ddf_list,
|
||||
"parent": parent
|
||||
});
|
||||
this.shortcut_field.make();
|
||||
}
|
||||
|
||||
_make_shortcuts(shortcut_name) {
|
||||
let shortcut = this.config.page_data.shortcuts.items.find(obj => {
|
||||
return obj.label == shortcut_name
|
||||
});
|
||||
this.wrapper.innerHTML = '';
|
||||
this.sections = {};
|
||||
this.sections["shortcuts"] = new frappe.widget.SingleWidgetGroup({
|
||||
container: this.wrapper,
|
||||
type: "shortcut",
|
||||
columns: 3,
|
||||
options: {
|
||||
allow_sorting: this.allow_customization,
|
||||
allow_create: this.allow_customization,
|
||||
allow_delete: this.allow_customization,
|
||||
allow_hiding: false,
|
||||
allow_edit: true,
|
||||
},
|
||||
widgets: shortcut
|
||||
});
|
||||
this.wrapper.setAttribute("shortcut_name", shortcut_name);
|
||||
}
|
||||
}
|
||||
554
frappe/public/js/frappe/wiki_blocks/spacing_tune.js
Normal file
554
frappe/public/js/frappe/wiki_blocks/spacing_tune.js
Normal file
|
|
@ -0,0 +1,554 @@
|
|||
export default class SpacingTune {
|
||||
static get isTune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
constructor({api, settings}) {
|
||||
this.api = api;
|
||||
this.settings = settings;
|
||||
this.CSS = {
|
||||
button: 'ce-settings__button',
|
||||
wrapper: 'ce-tune-layout',
|
||||
sidebar: 'cdx-settings-sidebar',
|
||||
animation: 'wobble',
|
||||
};
|
||||
this.data = { colWidth: 12, pl: 0, pr: 0, pt: 0, pb: 0 };
|
||||
this.wrapper = undefined;
|
||||
this.sidebar = undefined;
|
||||
}
|
||||
|
||||
render() {
|
||||
let me = this;
|
||||
let layoutWrapper = document.createElement('div');
|
||||
layoutWrapper.classList.add(this.CSS.wrapper);
|
||||
let decreaseWidthButton = document.createElement('div');
|
||||
decreaseWidthButton.classList.add(this.CSS.button);
|
||||
let increaseWidthButton = document.createElement('div');
|
||||
increaseWidthButton.classList.add(this.CSS.button);
|
||||
let paddingButton = document.createElement('div');
|
||||
paddingButton.classList.add(this.CSS.button);
|
||||
|
||||
layoutWrapper.appendChild(paddingButton);
|
||||
layoutWrapper.appendChild(decreaseWidthButton);
|
||||
layoutWrapper.appendChild(increaseWidthButton);
|
||||
|
||||
// paddingButton.appendChild($.svg('padding', 15, 15));
|
||||
paddingButton.innerHTML = `<svg version="1.1" height="12" x="0px" y="0px" viewBox="-674 379 17 12" style="enable-background:new -674 379 17 12;" xml:space="preserve"><rect x="-666.1" y="379.9" width="1.7" height="10.3"/><polygon points="-657,384.2 -659.9,384.2 -658.8,383.1 -660,381.9 -663.1,385 -660,388.1 -658.8,386.9 -659.9,385.8 -657,385.8 "/><rect x="-671.9" y="379.9" width="4.1" height="1.7"/><rect x="-674" y="384.2" width="6.1" height="1.7"/><rect x="-671.9" y="388.4" width="4.1" height="1.7"/></svg>`;
|
||||
this.api.listeners.on(
|
||||
paddingButton,
|
||||
'click',
|
||||
(event) => me.showPadding(event, paddingButton),
|
||||
false
|
||||
);
|
||||
|
||||
// decreaseWidthButton.appendChild($.svg('decrease-width', 15, 15));
|
||||
decreaseWidthButton.innerHTML = `<svg version="1.1" height="10" x="0px" y="0px" viewBox="-674 380 17 10" style="enable-background:new -674 380 17 10;" xml:space="preserve"><path d="M-674,383.9h3.6l-1.7-1.7c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.1-0.4,1.6,0l3.2,3.2c0.6,0.2,0.8,0.8,0.6,1.4 c-0.1,0.1-0.1,0.3-0.2,0.4l-3.8,3.8c-0.4,0.4-1.1,0.4-1.5,0c-0.4-0.4-0.4-1.1,0-1.5l1.8-1.8h-3.6V383.9z"/><path d="M-657,386.1h-3.6l1.7,1.7c0.4,0.4,0.4,1.2,0,1.6c-0.4,0.4-1.1,0.4-1.6,0l-3.2-3.2c-0.6-0.2-0.8-0.8-0.6-1.4 c0.1-0.1,0.1-0.3,0.2-0.4l3.8-3.8c0.4-0.4,1.1-0.4,1.5,0c0.4,0.4,0.4,1.1,0,1.5l-1.8,1.8h3.6V386.1z"/></svg>`;
|
||||
this.api.listeners.on(
|
||||
decreaseWidthButton,
|
||||
'click',
|
||||
(event) => me.decreaseWidth(event, decreaseWidthButton),
|
||||
false
|
||||
);
|
||||
|
||||
// increaseWidthButton.appendChild();
|
||||
increaseWidthButton.innerHTML = `<svg width="17" height="10" viewBox="0 0 17 10"><path d="M13.568 5.925H4.056l1.703 1.703a1.125 1.125 0 0 1-1.59 1.591L.962 6.014A1.069 1.069 0 0 1 .588 4.26L4.38.469a1.069 1.069 0 0 1 1.512 1.511L4.084 3.787h9.606l-1.85-1.85a1.069 1.069 0 1 1 1.512-1.51l3.792 3.791a1.069 1.069 0 0 1-.475 1.788L13.514 9.16a1.125 1.125 0 0 1-1.59-1.591l1.644-1.644z"/></svg>`;
|
||||
this.api.listeners.on(
|
||||
increaseWidthButton,
|
||||
'click',
|
||||
(event) => me.increaseWidth(event, increaseWidthButton),
|
||||
false
|
||||
);
|
||||
|
||||
this.wrapper = layoutWrapper;
|
||||
return layoutWrapper;
|
||||
}
|
||||
|
||||
decreaseWidth(event, button) {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
||||
if (currentBlockIndex < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
||||
if (!currentBlock){
|
||||
return;
|
||||
}
|
||||
|
||||
let currentBlockElement = currentBlock.holder;
|
||||
|
||||
// let block = this.api.blocks.getBlock(currentBlockElement);
|
||||
let className = 'col-12';
|
||||
let colClass = new RegExp(/\bcol-.+?\b/, 'g');
|
||||
if (currentBlockElement.className.match(colClass)) {
|
||||
currentBlockElement.classList.forEach( cn => {
|
||||
if(cn.match(colClass)){
|
||||
className = cn;
|
||||
}
|
||||
});
|
||||
let parts = className.split('-');
|
||||
let width = parseInt(parts[1]);
|
||||
if(width >= 2){
|
||||
currentBlockElement.classList.remove('col-'+width);
|
||||
width = width - 1;
|
||||
currentBlockElement.classList.add('col-'+width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
increaseWidth(event, button) {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
||||
if (currentBlockIndex < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
||||
if (!currentBlock){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlockElement = currentBlock.holder;
|
||||
|
||||
// let block = this.api.blocks.getBlock(currentBlockElement);
|
||||
let className = 'col-12';
|
||||
const colClass = new RegExp(/\bcol-.+?\b/, 'g');
|
||||
if (currentBlockElement.className.match(colClass)) {
|
||||
currentBlockElement.classList.forEach( cn => {
|
||||
if(cn.match(colClass)){
|
||||
className = cn;
|
||||
}
|
||||
});
|
||||
let parts = className.split('-');
|
||||
let width = parseInt(parts[1]);
|
||||
if(width <= 11){
|
||||
currentBlockElement.classList.remove('col-'+width);
|
||||
width = width + 1;
|
||||
currentBlockElement.classList.add('col-'+width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showPadding(event, button) {
|
||||
let me = this;
|
||||
if(button.classList.contains('cdx-settings-button--active')){
|
||||
this.sidebar.remove();
|
||||
button.classList.remove('cdx-settings-button--active');
|
||||
} else {
|
||||
button.classList.add('cdx-settings-button--active');
|
||||
|
||||
let sidebarWrapper = document.createElement('div');
|
||||
sidebarWrapper.classList.add(this.CSS.sidebar);
|
||||
|
||||
let paddingLeftCaption = document.createElement('button');
|
||||
paddingLeftCaption.classList.add(this.CSS.button, 'disabled');
|
||||
// paddingLeftCaption.appendChild($.svg('arrow-left', 10, 10));
|
||||
paddingLeftCaption.innerHTML = `<svg version="1.1" height="10" x="0px" y="0px" viewBox="-674 380 17 10" style="enable-background:new -674 380 17 10;" xml:space="preserve"><polygon points="-659,384.1 -667.8,384.1 -665.8,381.9 -667,380.7 -671,384.9 -667.1,388.9 -665.8,387.7 -667.8,385.7 -659,385.7 "/></svg>`;
|
||||
|
||||
let paddingRightCaption = document.createElement('button');
|
||||
paddingRightCaption.classList.add(this.CSS.button, 'disabled');
|
||||
// paddingRightCaption.appendChild($.svg('arrow-right', 10, 10));
|
||||
paddingRightCaption.innerHTML = `<svg version="1.1" height="10" x="0px" y="0px" viewBox="-674 380 17 10" style="enable-background:new -674 380 17 10;" xml:space="preserve"><polygon points="-671,385.7 -662.2,385.7 -664.2,387.7 -662.9,388.9 -659,384.9 -663,380.7 -664.2,381.9 -662.2,384.1 -671,384.1 "/></svg>`;
|
||||
|
||||
let paddingTopCaption = document.createElement('button');
|
||||
paddingTopCaption.classList.add(this.CSS.button, 'disabled');
|
||||
// paddingTopCaption.appendChild($.svg('arrow-up', 10, 10));
|
||||
paddingTopCaption.innerHTML = `<svg version="1.1" height="13" x="0px" y="0px" viewBox="-674 378.5 17 13" style="enable-background:new -674 378.5 17 13;" xml:space="preserve"><polygon points="-664.6,391 -664.6,382.2 -662.6,384.2 -661.4,382.9 -665.4,379 -669.6,383 -668.4,384.2 -666.2,382.2 -666.2,391 "/></svg>`;
|
||||
|
||||
let paddingBottomCaption = document.createElement('button');
|
||||
paddingBottomCaption.classList.add(this.CSS.button, 'disabled');
|
||||
// paddingBottomCaption.appendChild($.svg('arrow-down', 10, 10));
|
||||
paddingBottomCaption.innerHTML = `<svg version="1.1" height="13" x="0px" y="0px" viewBox="-674 378.5 17 13" style="enable-background:new -674 378.5 17 13;" xml:space="preserve"><polygon points="-666.2,379 -666.2,387.8 -668.4,385.8 -669.6,387 -665.4,391 -661.4,387.1 -662.6,385.8 -664.6,387.8 -664.6,379 "/></svg>`;
|
||||
|
||||
let increasePaddingLeft = document.createElement('button');
|
||||
increasePaddingLeft.classList.add(this.CSS.button);
|
||||
|
||||
let decreasePaddingLeft = document.createElement('button');
|
||||
decreasePaddingLeft.classList.add(this.CSS.button);
|
||||
|
||||
let increasePaddingRight = document.createElement('button');
|
||||
increasePaddingRight.classList.add(this.CSS.button);
|
||||
|
||||
let decreasePaddingRight = document.createElement('button');
|
||||
decreasePaddingRight.classList.add(this.CSS.button);
|
||||
|
||||
let increasePaddingTop = document.createElement('button');
|
||||
increasePaddingTop.classList.add(this.CSS.button);
|
||||
|
||||
let decreasePaddingTop = document.createElement('button');
|
||||
decreasePaddingTop.classList.add(this.CSS.button);
|
||||
|
||||
let increasePaddingBottom = document.createElement('button');
|
||||
increasePaddingBottom.classList.add(this.CSS.button);
|
||||
|
||||
let decreasePaddingBottom = document.createElement('button');
|
||||
decreasePaddingBottom.classList.add(this.CSS.button);
|
||||
|
||||
this.sidebar = sidebarWrapper;
|
||||
|
||||
// Left Padding
|
||||
sidebarWrapper.appendChild(paddingLeftCaption);
|
||||
|
||||
// increasePaddingLeft.appendChild($.svg('plus', 15, 15));
|
||||
increasePaddingLeft.innerHTML = `<svg version="1.1" height="10" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-664.7,388.5 -664.7,381.5 -666.3,381.5 -666.3,388.5 "/><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
|
||||
|
||||
this.api.listeners.on(
|
||||
increasePaddingLeft,
|
||||
'click',
|
||||
(event) => me.increasePaddingLeft(event, increasePaddingLeft),
|
||||
false
|
||||
);
|
||||
sidebarWrapper.appendChild(increasePaddingLeft);
|
||||
|
||||
// decreasePaddingLeft.appendChild($.svg('minus', 15, 15));
|
||||
decreasePaddingLeft.innerHTML = `<svg version="1.1" height="10" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
|
||||
|
||||
this.api.listeners.on(
|
||||
decreasePaddingLeft,
|
||||
'click',
|
||||
(event) => me.decreasePaddingLeft(event, decreasePaddingLeft),
|
||||
false
|
||||
);
|
||||
sidebarWrapper.appendChild(decreasePaddingLeft);
|
||||
|
||||
// Right Padding
|
||||
sidebarWrapper.appendChild(paddingRightCaption);
|
||||
// increasePaddingRight.appendChild($.svg('plus', 15, 15));
|
||||
increasePaddingRight.innerHTML = `<svg version="1.1" height="10" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-664.7,388.5 -664.7,381.5 -666.3,381.5 -666.3,388.5 "/><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
|
||||
|
||||
this.api.listeners.on(
|
||||
increasePaddingRight,
|
||||
'click',
|
||||
(event) => me.increasePaddingRight(event, increasePaddingRight),
|
||||
false
|
||||
);
|
||||
sidebarWrapper.appendChild(increasePaddingRight);
|
||||
|
||||
// decreasePaddingRight.appendChild($.svg('minus', 15, 15));
|
||||
decreasePaddingRight.innerHTML = `<svg version="1.1" height="10" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
|
||||
|
||||
this.api.listeners.on(
|
||||
decreasePaddingRight,
|
||||
'click',
|
||||
(event) => me.decreasePaddingRight(event, decreasePaddingRight),
|
||||
false
|
||||
);
|
||||
sidebarWrapper.appendChild(decreasePaddingRight);
|
||||
|
||||
// Top Padding
|
||||
sidebarWrapper.appendChild(paddingTopCaption);
|
||||
// increasePaddingTop.appendChild($.svg('plus', 15, 15));
|
||||
increasePaddingTop.innerHTML = `<svg version="1.1" height="10" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-664.7,388.5 -664.7,381.5 -666.3,381.5 -666.3,388.5 "/><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
|
||||
|
||||
this.api.listeners.on(
|
||||
increasePaddingTop,
|
||||
'click',
|
||||
(event) => me.increasePaddingTop(event, increasePaddingTop),
|
||||
false
|
||||
);
|
||||
sidebarWrapper.appendChild(increasePaddingTop);
|
||||
|
||||
// decreasePaddingTop.appendChild($.svg('minus', 15, 15));
|
||||
decreasePaddingTop.innerHTML = `<svg version="1.1" height="10" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
|
||||
|
||||
this.api.listeners.on(
|
||||
decreasePaddingTop,
|
||||
'click',
|
||||
(event) => me.decreasePaddingTop(event, decreasePaddingTop),
|
||||
false
|
||||
);
|
||||
sidebarWrapper.appendChild(decreasePaddingTop);
|
||||
|
||||
// Bottom Padding
|
||||
sidebarWrapper.appendChild(paddingBottomCaption);
|
||||
// increasePaddingBottom.appendChild($.svg('plus', 15, 15));
|
||||
increasePaddingBottom.innerHTML = `<svg version="1.1" height="10" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-664.7,388.5 -664.7,381.5 -666.3,381.5 -666.3,388.5 "/><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
|
||||
|
||||
this.api.listeners.on(
|
||||
increasePaddingBottom,
|
||||
'click',
|
||||
(event) => me.increasePaddingBottom(event, increasePaddingBottom),
|
||||
false
|
||||
);
|
||||
sidebarWrapper.appendChild(increasePaddingBottom);
|
||||
|
||||
// decreasePaddingBottom.appendChild($.svg('minus', 15, 15));
|
||||
decreasePaddingBottom.innerHTML = `<svg version="1.1" height="10" x="0px" y="0px" viewBox="-674 381.5 17 7" style="enable-background:new -674 381.5 17 7;" xml:space="preserve"><polygon points="-669,385.8 -662,385.8 -662,384.2 -669,384.2 "/></svg>`;
|
||||
|
||||
this.api.listeners.on(
|
||||
decreasePaddingBottom,
|
||||
'click',
|
||||
(event) => me.decreasePaddingBottom(event, decreasePaddingBottom),
|
||||
false
|
||||
);
|
||||
sidebarWrapper.appendChild(decreasePaddingBottom);
|
||||
|
||||
this.wrapper.appendChild(sidebarWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
increasePaddingLeft(event, button) {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
||||
if(currentBlockIndex < 0){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
||||
if (!currentBlock){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlockElement = currentBlock.holder;
|
||||
|
||||
// let block = this.api.blocks.getBlock(currentBlockElement);
|
||||
let className = 'pl-0';
|
||||
const paddingClass = new RegExp(/\pl-.+?\b/, 'g');
|
||||
if (currentBlockElement.className.match(paddingClass)) {
|
||||
currentBlockElement.classList.forEach( cn => {
|
||||
if(cn.match(paddingClass)){
|
||||
className = cn;
|
||||
}
|
||||
});
|
||||
let parts = className.split('-');
|
||||
let padding = parseInt(parts[1]);
|
||||
if(padding <= 4){
|
||||
currentBlockElement.classList.remove('pl-'+padding);
|
||||
padding = padding + 1;
|
||||
currentBlockElement.classList.add('pl-'+padding);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
decreasePaddingLeft(event, button) {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
||||
if(currentBlockIndex < 0){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
||||
if (!currentBlock){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlockElement = currentBlock.holder;
|
||||
|
||||
// let block = this.api.blocks.getBlock(currentBlockElement);
|
||||
let className = 'pl-0';
|
||||
const paddingClass = new RegExp(/\pl-.+?\b/, 'g');
|
||||
if (currentBlockElement.className.match(paddingClass)) {
|
||||
currentBlockElement.classList.forEach( cn => {
|
||||
if(cn.match(paddingClass)){
|
||||
className = cn;
|
||||
}
|
||||
});
|
||||
let parts = className.split('-');
|
||||
let padding = parseInt(parts[1]);
|
||||
if(padding >= 1){
|
||||
currentBlockElement.classList.remove('pl-'+padding);
|
||||
padding = padding - 1;
|
||||
currentBlockElement.classList.add('pl-'+padding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
increasePaddingRight(event, button) {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
||||
if(currentBlockIndex < 0){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
||||
if (!currentBlock){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlockElement = currentBlock.holder;
|
||||
|
||||
// let block = this.api.blocks.getBlock(currentBlockElement);
|
||||
let className = 'pr-0';
|
||||
const paddingClass = new RegExp(/\pr-.+?\b/, 'g');
|
||||
if (currentBlockElement.className.match(paddingClass)) {
|
||||
currentBlockElement.classList.forEach( cn => {
|
||||
if(cn.match(paddingClass)){
|
||||
className = cn;
|
||||
}
|
||||
});
|
||||
let parts = className.split('-');
|
||||
let padding = parseInt(parts[1]);
|
||||
if(padding <= 4){
|
||||
currentBlockElement.classList.remove('pr-'+padding);
|
||||
padding = padding + 1;
|
||||
currentBlockElement.classList.add('pr-'+padding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decreasePaddingRight(event, button) {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
||||
if(currentBlockIndex < 0){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
||||
if (!currentBlock){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlockElement = currentBlock.holder;
|
||||
|
||||
// let block = this.api.blocks.getBlock(currentBlockElement);
|
||||
let className = 'pr-0';
|
||||
const paddingClass = new RegExp(/\pr-.+?\b/, 'g');
|
||||
if (currentBlockElement.className.match(paddingClass)) {
|
||||
currentBlockElement.classList.forEach( cn => {
|
||||
if(cn.match(paddingClass)){
|
||||
className = cn;
|
||||
}
|
||||
});
|
||||
let parts = className.split('-');
|
||||
let padding = parseInt(parts[1]);
|
||||
if(padding >= 1){
|
||||
currentBlockElement.classList.remove('pr-'+padding);
|
||||
padding = padding - 1;
|
||||
currentBlockElement.classList.add('pr-'+padding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
increasePaddingTop(event, button) {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
||||
if(currentBlockIndex < 0){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
||||
if (!currentBlock){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlockElement = currentBlock.holder;
|
||||
|
||||
// let block = this.api.blocks.getBlock(currentBlockElement);
|
||||
let className = 'pt-0';
|
||||
const paddingClass = new RegExp(/\pt-.+?\b/, 'g');
|
||||
if (currentBlockElement.className.match(paddingClass)) {
|
||||
currentBlockElement.classList.forEach( cn => {
|
||||
if(cn.match(paddingClass)){
|
||||
className = cn;
|
||||
}
|
||||
});
|
||||
let parts = className.split('-');
|
||||
let padding = parseInt(parts[1]);
|
||||
if(padding <= 4){
|
||||
currentBlockElement.classList.remove('pt-'+padding);
|
||||
padding = padding + 1;
|
||||
currentBlockElement.classList.add('pt-'+padding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decreasePaddingTop(event, button) {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
||||
if(currentBlockIndex < 0){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
||||
if (!currentBlock){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlockElement = currentBlock.holder;
|
||||
|
||||
// let block = this.api.blocks.getBlock(currentBlockElement);
|
||||
let className = 'pt-0';
|
||||
const paddingClass = new RegExp(/\pt-.+?\b/, 'g');
|
||||
if (currentBlockElement.className.match(paddingClass)) {
|
||||
currentBlockElement.classList.forEach( cn => {
|
||||
if(cn.match(paddingClass)){
|
||||
className = cn;
|
||||
}
|
||||
});
|
||||
let parts = className.split('-');
|
||||
let padding = parseInt(parts[1]);
|
||||
if(padding >= 1){
|
||||
currentBlockElement.classList.remove('pt-'+padding);
|
||||
padding = padding - 1;
|
||||
currentBlockElement.classList.add('pt-'+padding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
increasePaddingBottom(event, button) {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
||||
if(currentBlockIndex < 0){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
||||
if (!currentBlock){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlockElement = currentBlock.holder;
|
||||
|
||||
// let block = this.api.blocks.getBlock(currentBlockElement);
|
||||
let className = 'pb-0';
|
||||
const paddingClass = new RegExp(/\pb-.+?\b/, 'g');
|
||||
if (currentBlockElement.className.match(paddingClass)) {
|
||||
currentBlockElement.classList.forEach( cn => {
|
||||
if(cn.match(paddingClass)){
|
||||
className = cn;
|
||||
}
|
||||
});
|
||||
let parts = className.split('-');
|
||||
let padding = parseInt(parts[1]);
|
||||
if(padding <= 4){
|
||||
currentBlockElement.classList.remove('pb-'+padding);
|
||||
padding = padding + 1;
|
||||
currentBlockElement.classList.add('pb-'+padding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decreasePaddingBottom(event, button) {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
||||
if(currentBlockIndex < 0){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
||||
if (!currentBlock){
|
||||
return;
|
||||
}
|
||||
|
||||
const currentBlockElement = currentBlock.holder;
|
||||
|
||||
// let block = this.api.blocks.getBlock(currentBlockElement);
|
||||
let className = 'pb-0';
|
||||
const paddingClass = new RegExp(/\pb-.+?\b/, 'g');
|
||||
if (currentBlockElement.className.match(paddingClass)) {
|
||||
currentBlockElement.classList.forEach( cn => {
|
||||
if(cn.match(paddingClass)){
|
||||
className = cn;
|
||||
}
|
||||
});
|
||||
let parts = className.split('-');
|
||||
let padding = parseInt(parts[1]);
|
||||
if(padding >= 1){
|
||||
currentBlockElement.classList.remove('pb-'+padding);
|
||||
padding = padding - 1;
|
||||
currentBlockElement.classList.add('pb-'+padding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
@import "notification";
|
||||
@import "global_search";
|
||||
@import "desktop";
|
||||
@import "wiki";
|
||||
@import "../common/awesomeplete";
|
||||
@import "sidebar";
|
||||
@import "filters";
|
||||
|
|
|
|||
154
frappe/public/scss/desk/wiki.scss
Normal file
154
frappe/public/scss/desk/wiki.scss
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
[data-page-route="wiki"] {
|
||||
@media (min-width: map-get($grid-breakpoints, "lg")) {
|
||||
.layout-main {
|
||||
height: calc(100vh - var(--navbar-height) - var(--page-head-height) - 5px);
|
||||
.layout-side-section, .layout-main-section-wrapper {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.desk-sidebar {
|
||||
margin-bottom: var(--margin-2xl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ce-header {
|
||||
padding: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.codex-editor {
|
||||
min-height: 630px;
|
||||
|
||||
svg {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.ce-toolbar {
|
||||
svg {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.icon {
|
||||
stroke: none;
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
.ce-inline-tool, .ce-inline-toolbar__dropdown {
|
||||
.icon {
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1199px) {
|
||||
.ce-toolbar__content {
|
||||
max-width: 930px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 995px) {
|
||||
.ce-toolbar__content {
|
||||
max-width: 760px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1199px) {
|
||||
.ce-block.col-4 {
|
||||
flex: 0 0 50%;
|
||||
max-width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 750px) {
|
||||
.ce-block.col-4 {
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
@media (max-width: 750px) {
|
||||
.ce-block.col-6 {
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
div[card_name] {
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.codex-editor__redactor{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
margin: 0px -7px;
|
||||
}
|
||||
.ce-block{
|
||||
width: 100%;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
.cdx-settings-input{
|
||||
border: 1px solid rgba(201,201,204,.48);
|
||||
-webkit-box-shadow: inset 0 1px 2px 0 rgba(35,44,72,.06);
|
||||
box-shadow: inset 0 1px 2px 0 rgba(35,44,72,.06);
|
||||
border-radius: 3px;padding: 3px 8px;outline: none;
|
||||
width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.cdx-small{
|
||||
font-size: .6rem
|
||||
}
|
||||
.ce-block__content {
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
padding: 7px;
|
||||
|
||||
&> div {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.cdx-settings-button.disabled{
|
||||
pointer-events: none;
|
||||
opacity: .5
|
||||
}
|
||||
.cdx-settings-sidebar{
|
||||
position: absolute;
|
||||
right: 100%;
|
||||
top:0;
|
||||
background: #fff;
|
||||
width: 108px;
|
||||
height: 145px;
|
||||
box-shadow: 0 3px 15px -3px rgba(13,20,33,.13);
|
||||
border-radius: 0 4px 4px 0;z-index: 0;
|
||||
}
|
||||
|
||||
|
||||
[data-page-route="wiki"] {
|
||||
|
||||
.standard-sidebar-item {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.sidebar-child-item-container {
|
||||
margin-left: 10px;
|
||||
|
||||
.standard-sidebar-item {
|
||||
justify-content: start;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-item-label {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.item-anchor {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,6 +18,8 @@
|
|||
},
|
||||
"homepage": "https://frappeframework.com",
|
||||
"dependencies": {
|
||||
"@editorjs/editorjs": "^2.20.0",
|
||||
"@editorjs/header": "^2.6.1",
|
||||
"ace-builds": "^1.4.8",
|
||||
"air-datepicker": "github:frappe/air-datepicker",
|
||||
"autoprefixer": "^9.8.6",
|
||||
|
|
@ -54,8 +56,11 @@
|
|||
"vue-router": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@editorjs/checklist": "^1.3.0",
|
||||
"@editorjs/list": "^1.6.2",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"chalk": "^2.3.2",
|
||||
"editorjs-undo": "^0.1.5",
|
||||
"graphlib": "^2.1.8",
|
||||
"less": "^3.11.1",
|
||||
"rollup": "^1.2.2",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue