From c9eb03dce7de1f2cd22ae4d9a9c7707fcc0a2ef5 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 23 Mar 2020 15:42:13 +0530 Subject: [PATCH] feat: setup customize API for base widget --- .../public/js/frappe/widgets/base_widget.js | 58 +++++- .../public/js/frappe/widgets/widget_group.js | 23 ++- frappe/public/less/desktop.less | 180 ++++++++++++++++-- 3 files changed, 228 insertions(+), 33 deletions(-) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 7461f2ddc0..4064c34d01 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -10,14 +10,35 @@ export default class Widget { this.set_body(); } - customize() { + customize(options) { + this.action_area.empty(); + options.allow_delete && + this.add_custom_button( + '', + () => this.delete() + ); + options.allow_sorting && + this.add_custom_button( + '', + null, + "drag-handle" + ); + options.allow_hiding && + this.add_custom_button( + '', + () => this.hide() + ); + options.allow_edit && + this.add_custom_button( + '', + () => this.edit() + ); } make() { this.make_widget(); this.widget.appendTo(this.container); - this.setup_events(); } make_widget() { @@ -46,6 +67,33 @@ export default class Widget { this.title_field[0].innerHTML = this.label || this.name; } + add_custom_button(html, action, class_name = "") { + let button = $( + `` + ); + action && button.on("click", () => action()); + button.appendTo(this.action_area); + } + + delete() { + this.widget.addClass("zoomOutDelete"); + // wait for animation + setTimeout(() => { + this.widget.remove(); + this.on_delete && this.on_delete(this.name); + }, 300); + } + + edit() { + this.on_edit && this.on_edit(this.name); + } + + hide() { + this.body.css("opacity", 0.5); + this.title_field.css("opacity", 0.5); + this.footer.css("opacity", 0.5); + } + set_actions() { // } @@ -53,8 +101,4 @@ export default class Widget { set_body() { // } - - setup_events() { - // - } -} \ No newline at end of file +} diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index 18a9e3f88d..a34b1dc450 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -32,7 +32,6 @@ export default class WidgetGroup { refresh() { this.title && this.set_title(this.title); this.widgets && this.make_widgets(); - this.options.allow_sorting && this.setup_sortable(); } make_container() { @@ -63,7 +62,10 @@ export default class WidgetGroup { let widget_object = new widget_class({ ...widget, container: this.body, - on_delete: (name) => this.on_delete(name) + options: { + ...this.options, + on_delete: (name) => this.on_delete(name) + } }); this.widgets_list.push(widget_object); this.widgets_dict[widget.name] = widget_object; @@ -71,18 +73,16 @@ export default class WidgetGroup { } customize() { - const options = { - delete: this.options.allow_delete, - sort: this.options.allow_sorting - } - this.widgets_list.forEach(wid => { - wid.customize(options); + wid.customize(this.options); }) this.options.allow_create && new NewWidget({ - container: this.body + container: this.body, + type: this.type }) + + this.options.allow_sorting && this.setup_sortable(); } on_delete(name) { @@ -93,11 +93,10 @@ export default class WidgetGroup { const container = this.body[0]; this.sortable = new Sortable(container, { animation: 150, + handle: ".drag-handle", onEnd: () => { console.log("Sorting") - }, - // onChoose: (evt) => this.sortable_config.on_choose(evt, container), - // onStart: (evt) => this.sortable_config.on_start(evt, container) + }, // onStart: (evt) => this.sortable_config.on_start(evt, container) }); } } diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index 14d19aae88..7d7643ec3e 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -78,15 +78,23 @@ padding-right: 15px; .desk-page.allow-customization { - .customize-page { + .customize-options { text-align: right; margin-top: 7px; color: @text-muted; - cursor: pointer; z-index: 99; + + .save-customization { + cursor: pointer; + color: @text-color; + } + + .discard-customization { + cursor: pointer; + } } - .widget-group:nth-child(2) { + .widget-group:nth-child(3) { margin-top: -25px; } } @@ -104,6 +112,9 @@ .widget-group { margin-bottom: 25px; + // -webkit-animation-name: slideInUp; + // animation-name: slideInUp; + // animation-duration: 0.4s; .widget-group-head { display: flex; @@ -215,6 +226,17 @@ margin-left: 5px; } + .drag-handle { + cursor: all-scroll; + cursor: -webkit-grabbing; + + &:active { + cursor: grabbing; + cursor: -moz-grabbing; + cursor: -webkit-grabbing; + } + } + .dashboard-date-field { .clearfix, .help-box { @@ -381,23 +403,153 @@ border-radius: 10px; } -.pill-green { - background: #71b92c; - // color: #000; +@-webkit-keyframes smallBounce { + from, + 20%, + 53%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -12px, 0); + transform: translate3d(0, -12px, 0); + } + + 70% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -6px, 0); + transform: translate3d(0, -6px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -4px, 0); + transform: translate3d(0, -4px, 0); + } } -.pill-red { - background: @red; +@keyframes smallBounce { + from, + 20%, + 53%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -12px, 0); + transform: translate3d(0, -12px, 0); + } + + 70% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -6px, 0); + transform: translate3d(0, -6px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -4px, 0); + transform: translate3d(0, -4px, 0); + } } -.pill-blue { - background: @blue; +.small-bounce { + -webkit-animation-name: smallBounce; + animation-name: smallBounce; + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + animation-duration: 1s; } -.pill-yellow { - background: @yellow; +@-webkit-keyframes slideInUp { + from { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } } -.pill-orange { - background: @orange; +@keyframes slideInUp { + from { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.slide-in-up { + -webkit-animation-name: slideInUp; + animation-name: slideInUp; + animation-duration: 1s; +} + + +@-webkit-keyframes pulse { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes pulse { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.zoomOutDelete { + // -webkit-animation-name: zoomOut; + // animation-name: zoomOut; + // animation-duration: 1s; + transition: opacity 0.2s, visibility 0.2s, transform 0.2s; + transform: scale3d(0.5, 0.5, 0.5); + opacity: 0; + visibility: hidden; } \ No newline at end of file