[user-progress] slide action cards

This commit is contained in:
pratu16x7 2017-08-27 13:58:59 +05:30
parent df55d9b9b9
commit 2a0901af02
6 changed files with 254 additions and 55 deletions

View file

@ -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",

View file

@ -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;
}

View file

@ -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");
}

View file

@ -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;">`));

View file

@ -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');
}

View file

@ -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;
}
}
}