[user-progress] slide action cards
This commit is contained in:
parent
df55d9b9b9
commit
2a0901af02
6 changed files with 254 additions and 55 deletions
|
|
@ -88,9 +88,7 @@
|
|||
"public/js/frappe/form/controls/read_only.js",
|
||||
"public/js/frappe/form/controls/button.js",
|
||||
"public/js/frappe/form/controls/html.js",
|
||||
"public/js/frappe/form/controls/heading.js",
|
||||
"public/js/frappe/form/user_progress_dialog.js",
|
||||
"public/js/frappe/form/user_progress_slide.html"
|
||||
"public/js/frappe/form/controls/heading.js"
|
||||
],
|
||||
"css/desk.min.css": [
|
||||
"public/js/lib/datepicker/datepicker.min.css",
|
||||
|
|
|
|||
|
|
@ -1126,3 +1126,42 @@ input[type="checkbox"]:checked:before {
|
|||
color: #fff;
|
||||
border-color: #b1bdca;
|
||||
}
|
||||
.cards-container .card-container {
|
||||
background-color: #fff;
|
||||
margin: 10px 7px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 3px;
|
||||
display: flex;
|
||||
}
|
||||
.cards-container .card-container.done {
|
||||
background-color: #fafbfc;
|
||||
}
|
||||
.cards-container .card-container.done .title {
|
||||
color: #8D99A6;
|
||||
}
|
||||
.cards-container .card-container.single_action {
|
||||
cursor: pointer;
|
||||
}
|
||||
.cards-container .title {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.cards-container .content {
|
||||
font-size: 12px;
|
||||
}
|
||||
.cards-container img {
|
||||
width: 195px;
|
||||
}
|
||||
.cards-container img.clip {
|
||||
margin: -15px 0px;
|
||||
clip-path: inset(15px 0px 15px 0px);
|
||||
}
|
||||
.cards-container .content-container {
|
||||
padding: 10px;
|
||||
width: 516px;
|
||||
}
|
||||
.cards-container .actions {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.cards-container .actions button:not(:first-child) {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ frappe.help.show_video = function(youtube_id, title) {
|
|||
var dialog = frappe.msgprint('<iframe width="'+size[0]+'" height="'+size[1]+'" \
|
||||
src="https://www.youtube.com/embed/'+ youtube_id +'" \
|
||||
frameborder="0" allowfullscreen></iframe>' + (frappe.help_feedback_link || ""),
|
||||
title || __("Help"));
|
||||
title || __("Help"));
|
||||
|
||||
dialog.$wrapper.find(".modal-content").addClass("video-modal");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ frappe.ui.Slide = class Slide {
|
|||
this.$form = this.$body.find(".form");
|
||||
this.$primary_btn = this.slides_footer.find('.btn-primary').addClass('primary');
|
||||
|
||||
if(this.help) this.$content.append($(`<p class="help">${this.help}</p>`));
|
||||
if(this.help) this.$content.append($(`<p class="slide-help">${this.help}</p>`));
|
||||
if(this.image_src) this.$content.append(
|
||||
$(`<img src="${this.image_src}" style="margin: 20px;">`));
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,119 @@
|
|||
frappe.provide("frappe.setup");
|
||||
frappe.provide("frappe.ui");
|
||||
|
||||
frappe.ui.ActionCard = class {
|
||||
constructor({
|
||||
data = null
|
||||
}) {
|
||||
this.data = data;
|
||||
this.make();
|
||||
this.setup();
|
||||
}
|
||||
|
||||
make() {
|
||||
this.container = $(`<div class="card-container">
|
||||
<div class="img-container">
|
||||
<img src="" class="clip">
|
||||
<div class="image-overlay hide"></div>
|
||||
</div>
|
||||
<div class="content-container">
|
||||
<h5 class="title"></h5>
|
||||
<div class="content"></div>
|
||||
<div class="action-area">
|
||||
<div class="actions"></div>
|
||||
<div class="help-links"></div>
|
||||
</div>
|
||||
<i class="check pull-right fa fa-fw fa-check-circle text-success"
|
||||
style="font-size: 24px;"></i>
|
||||
</div>
|
||||
</div>`);
|
||||
this.property_components = [
|
||||
{ card_property: 'content', component_name: '$content', class_name: 'content' },
|
||||
{ card_property: 'image', component_name: '$img_container', class_name: 'img-container'},
|
||||
{ card_property: 'done', component_name: '$check', class_name: 'check' },
|
||||
{ card_property: 'actions', component_name: '$actions', class_name: 'actions' },
|
||||
{ card_property: 'help_links', component_name: '$help_links', class_name: 'help-links' },
|
||||
];
|
||||
}
|
||||
|
||||
setup() {
|
||||
this.property_components.map(d => {
|
||||
this[d.component_name] = this.container.find('.' + d.class_name);
|
||||
});
|
||||
|
||||
if(this.data.video_id) {
|
||||
this.data.image = `http://img.youtube.com/vi/${this.data.video_id}/1.jpg`;
|
||||
this.$img_container.find('.image-overlay').removeClass('hide');
|
||||
}
|
||||
|
||||
this.refresh();
|
||||
if(this.data.video_id) {
|
||||
this.bind_single_action(() => {
|
||||
frappe.help.show_video(this.data.video_id, this.title);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
refresh() {
|
||||
// render according to props
|
||||
this.property_components.map(d => {
|
||||
if(!this.data[d.card_property]) {
|
||||
this[d.component_name].hide();
|
||||
}
|
||||
});
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
this.container.find('.title').html(this.data.title);
|
||||
if(this.data.image) {
|
||||
this.$img_container.find('img').attr({"src": this.data.image});
|
||||
}
|
||||
if(this.data.content) {
|
||||
this.$content.html(this.data.content);
|
||||
}
|
||||
if(this.data.done) {
|
||||
this.container.addClass("done");
|
||||
}
|
||||
if(this.data.actions) {
|
||||
this.data.actions.map(action => {
|
||||
let $btn = $(`<button class="btn btn-default btn-sm">${action.label}</button>`);
|
||||
this.$actions.append($btn);
|
||||
if(action.route) {
|
||||
$btn.on('click', () => {
|
||||
frappe.set_route(action.route);
|
||||
});
|
||||
} if(action.new_doc) {
|
||||
$btn.on('click', () => {
|
||||
frappe.new_doc(action.new_doc);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if(this.data.help_links) {
|
||||
this.data.help_links.map(link => {
|
||||
let $link = $(`<a target="_blank" href="${link.url}">${link.label}</a>`);
|
||||
this.$help_links.append($link);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bind_single_action(onclick) {
|
||||
if(this.data.video_id) {
|
||||
// on entire card click
|
||||
this.container.on('mouseenter', () => {
|
||||
this.container.addClass('single_action');
|
||||
}).on('mouseleave', () => {
|
||||
this.container.removeClass('single_action');
|
||||
}).on('click', onclick);
|
||||
}
|
||||
}
|
||||
|
||||
mark_as_done() {}
|
||||
|
||||
}
|
||||
|
||||
frappe.setup.UserProgressSlide = class UserProgressSlide extends frappe.ui.Slide {
|
||||
constructor(slide = null) {
|
||||
super(slide);
|
||||
|
|
@ -15,61 +128,27 @@ frappe.setup.UserProgressSlide = class UserProgressSlide extends frappe.ui.Slide
|
|||
|
||||
setup_done_state() {
|
||||
this.$body.find(".form-wrapper").hide();
|
||||
|
||||
this.make_done_state();
|
||||
this.bind_done_state();
|
||||
this.$body.find(".slide-help").hide();
|
||||
this.make_action_cards();
|
||||
}
|
||||
|
||||
make_done_state() {
|
||||
make_action_cards() {
|
||||
this.$done_state = $(`<div class="done-content">
|
||||
<div class="state text-center">
|
||||
<p><i class="octicon octicon-check text-success" style="font-size: 30px;"></i></p>
|
||||
<p style="font-size: 16px;">${__("Completed!")}</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="doctype-actions text-center hide">
|
||||
<a class="list-btn btn btn-default btn-sm"></a>
|
||||
<a class="sec-list-btn btn btn-default btn-sm hide"></a>
|
||||
<a class="import-btn btn btn-default btn-sm"></a>
|
||||
</div>
|
||||
<div class="doc-actions text-center hide">
|
||||
<a class="doc-btn btn btn-default btn-sm">${__("Check it out")}</a>
|
||||
</div>
|
||||
<div class="next-steps-links">
|
||||
<h6 class="title">${__("Going Further")}</h6>
|
||||
<a>${__("help link")}</a>
|
||||
</div>
|
||||
<div class="actions cards-container">
|
||||
|
||||
</div>
|
||||
</div>`).appendTo(this.$body);
|
||||
|
||||
this.$actions = this.$done_state.find('.actions');
|
||||
this.action_cards.map(this.add_card.bind(this));
|
||||
}
|
||||
|
||||
bind_done_state() {
|
||||
if(this.doctype) {
|
||||
this.$body.find('.doctype-actions').removeClass("hide");
|
||||
this.$list = this.$body.find('.list-btn')
|
||||
.html("Go to " + this.name)
|
||||
.on('click', () => {
|
||||
frappe.set_route("List", this.doctype);
|
||||
});
|
||||
if(this.sec_doctype) {
|
||||
this.$sec_list = this.$body.find('.sec-list-btn')
|
||||
.removeClass("hide")
|
||||
.html("Go to " + this.sec_doctype + "s")
|
||||
.on('click', () => {
|
||||
frappe.set_route("List", this.sec_doctype);
|
||||
});
|
||||
}
|
||||
this.$import = this.$body.find('.import-btn')
|
||||
.html("Import " + this.name)
|
||||
.on('click', () => {
|
||||
frappe.set_route("data-import-tool");
|
||||
});
|
||||
} else if (this.route) {
|
||||
this.$body.find('.doc-actions').removeClass("hide");
|
||||
this.$doc = this.$body.find('.doc-btn').on('click', () => {
|
||||
frappe.set_route(this.route);
|
||||
});
|
||||
}
|
||||
add_card(data) {
|
||||
let card = new frappe.ui.ActionCard({
|
||||
data: data
|
||||
});
|
||||
|
||||
card.container.appendTo(this.$actions);
|
||||
}
|
||||
|
||||
before_show() {
|
||||
|
|
@ -97,6 +176,10 @@ frappe.setup.UserProgressSlide = class UserProgressSlide extends frappe.ui.Slide
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
mark_as_done() {
|
||||
// most hard
|
||||
}
|
||||
};
|
||||
|
||||
frappe.setup.UserProgressDialog = class UserProgressDialog {
|
||||
|
|
@ -104,6 +187,11 @@ frappe.setup.UserProgressDialog = class UserProgressDialog {
|
|||
slides = []
|
||||
}) {
|
||||
this.slides = slides;
|
||||
// Add a progress bar
|
||||
// show the last visited slide
|
||||
// Add a mark as done button
|
||||
// this.progress_state_dict = this.slides.map();
|
||||
|
||||
this.setup();
|
||||
}
|
||||
|
||||
|
|
@ -130,6 +218,18 @@ frappe.setup.UserProgressDialog = class UserProgressDialog {
|
|||
this.make_dismiss_button();
|
||||
}
|
||||
|
||||
listen_for_updates() {
|
||||
// on every notif 30 sec event
|
||||
this.update_progress_state();
|
||||
}
|
||||
|
||||
update_progress_state() {
|
||||
// update states of slides and cards and refresh them
|
||||
// Update the progress bar in both the toolbar and the dialog
|
||||
|
||||
// remove on_update from original slides container
|
||||
}
|
||||
|
||||
make_dismiss_button() {
|
||||
this.dialog.set_primary_action(__('Dismiss'), () => {
|
||||
$('.user-progress').addClass('hide');
|
||||
|
|
@ -140,11 +240,11 @@ frappe.setup.UserProgressDialog = class UserProgressDialog {
|
|||
this.$dismiss_button.addClass('hide');
|
||||
|
||||
$(document).on("user-initial-setup-complete", () => {
|
||||
this.show_dismiss_button();
|
||||
this.add_finish_slide_and_make_dismissable();
|
||||
});
|
||||
}
|
||||
|
||||
show_dismiss_button() {
|
||||
add_finish_slide_and_make_dismissable() {
|
||||
this.$dismiss_button.removeClass('hide');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1074,3 +1074,65 @@ input[type="checkbox"] {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Action Cards
|
||||
.cards-container {
|
||||
.card-container {
|
||||
background-color: #fff;
|
||||
margin: 10px 7px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 3px;
|
||||
display: flex;
|
||||
|
||||
&.done {
|
||||
background-color: #fafbfc;
|
||||
|
||||
.title {
|
||||
color: #8D99A6;
|
||||
}
|
||||
}
|
||||
|
||||
&.single_action {
|
||||
cursor: pointer;
|
||||
|
||||
// .title {
|
||||
// color: blue;
|
||||
// }
|
||||
|
||||
// emphasize image overlay
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 12px;
|
||||
}
|
||||
// .img-container {
|
||||
|
||||
// }
|
||||
|
||||
img {
|
||||
width: 195px;
|
||||
|
||||
&.clip {
|
||||
margin: -15px 0px;
|
||||
clip-path: inset(15px 0px 15px 0px);
|
||||
}
|
||||
}
|
||||
|
||||
.content-container {
|
||||
padding: 10px;
|
||||
width: 516px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-top: 15px;
|
||||
|
||||
button:not(:first-child) {
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue