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