From 1ef2c8de17cfe3b178e8da019720f635cc175106 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 23 Mar 2015 11:24:49 +0530 Subject: [PATCH] [star] notify starrers and star in form --- .../doctype/communication/communication.py | 5 +++++ frappe/model/document.py | 9 ++++++++- frappe/public/css/common.css | 10 ++++++++++ frappe/public/css/desk.css | 10 ++++++++++ frappe/public/css/website.css | 20 +++++++++---------- frappe/public/js/frappe/form/toolbar.js | 12 +++++++++++ .../js/frappe/list/list_item_subject.html | 2 +- frappe/public/js/frappe/ui/page.js | 2 +- frappe/public/js/frappe/ui/star.js | 12 ++++++++++- frappe/public/less/common.less | 12 +++++++++++ frappe/public/less/website.less | 12 ----------- 11 files changed, 80 insertions(+), 26 deletions(-) diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index f5d758d4de..2d92035be4 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -110,6 +110,7 @@ class Communication(Document): recipients += self.get_commentors() recipients += [s.strip() for s in self.recipients.split(",")] recipients += self.get_assignees() + recipients += self.get_starrers() recipients = filter(lambda e: e and e!="Administrator", list(set(recipients))) # remove unsubscribed recipients @@ -118,6 +119,10 @@ class Communication(Document): return recipients + def get_starrers(self): + """Return list of users who have starred this document.""" + return self.get_parent_doc().get_starred_by() + def get_earlier_participants(self): return frappe.db.sql(""" select distinct sender diff --git a/frappe/model/document.py b/frappe/model/document.py index 7778b48eb4..cc09fca6c6 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -8,7 +8,7 @@ from frappe.utils import flt, cint, cstr, now, get_datetime_str from frappe.model.base_document import BaseDocument, get_controller from frappe.model.naming import set_new_name from werkzeug.exceptions import NotFound, Forbidden -import hashlib +import hashlib, json # once_only validation # methods @@ -662,3 +662,10 @@ class Document(BaseDocument): def get_signature(self): """Returns signature (hash) for private URL.""" return hashlib.sha224(get_datetime_str(self.creation)).hexdigest() + + def get_starred_by(self): + starred_by = getattr(self, "_starred_by", None) + if starred_by: + return json.dumps(starred_by) + else: + return [] diff --git a/frappe/public/css/common.css b/frappe/public/css/common.css index f90c804451..d277a1cd23 100644 --- a/frappe/public/css/common.css +++ b/frappe/public/css/common.css @@ -197,3 +197,13 @@ a.badge-hover:active .badge { #freeze.in { opacity: 0.5; } +a.no-decoration { + text-decoration: none; + color: inherit; +} +a.no-decoration:hover, +a.no-decoration:focus, +a.no-decoration:active { + text-decoration: none; + color: inherit; +} diff --git a/frappe/public/css/desk.css b/frappe/public/css/desk.css index 3d8c1faad1..76c72eeb03 100644 --- a/frappe/public/css/desk.css +++ b/frappe/public/css/desk.css @@ -197,6 +197,16 @@ a.badge-hover:active .badge { #freeze.in { opacity: 0.5; } +a.no-decoration { + text-decoration: none; + color: inherit; +} +a.no-decoration:hover, +a.no-decoration:focus, +a.no-decoration:active { + text-decoration: none; + color: inherit; +} .nav-pills a, .nav-pills a:hover { border-bottom: none; diff --git a/frappe/public/css/website.css b/frappe/public/css/website.css index 13a241893d..209f3d924f 100644 --- a/frappe/public/css/website.css +++ b/frappe/public/css/website.css @@ -197,6 +197,16 @@ a.badge-hover:active .badge { #freeze.in { opacity: 0.5; } +a.no-decoration { + text-decoration: none; + color: inherit; +} +a.no-decoration:hover, +a.no-decoration:focus, +a.no-decoration:active { + text-decoration: none; + color: inherit; +} html { min-height: 100%; } @@ -594,16 +604,6 @@ textarea { .post-content img { margin: 10px 0px; } -a.no-decoration { - text-decoration: none; - color: inherit; -} -a.no-decoration:hover, -a.no-decoration:focus, -a.no-decoration:active { - text-decoration: none; - color: inherit; -} a.active { pointer-events: none; cursor: default; diff --git a/frappe/public/js/frappe/form/toolbar.js b/frappe/public/js/frappe/form/toolbar.js index 63862d1d94..59cd055bb4 100644 --- a/frappe/public/js/frappe/form/toolbar.js +++ b/frappe/public/js/frappe/form/toolbar.js @@ -14,6 +14,7 @@ frappe.ui.form.Toolbar = Class.extend({ this.page.clear_user_actions(); this.show_title_as_dirty(); this.set_primary_action(); + this.refresh_star(); if(this.frm.meta.hide_toolbar) { this.page.hide_menu(); @@ -21,9 +22,11 @@ frappe.ui.form.Toolbar = Class.extend({ if(this.frm.doc.__islocal) { this.page.hide_menu(); this.print_icon && this.print_icon.addClass("hide"); + this.star_icon.addClass("hide"); } else { this.page.show_menu(); this.print_icon && this.print_icon.removeClass("hide"); + this.star_icon.removeClass("hide"); } } }, @@ -56,6 +59,10 @@ frappe.ui.form.Toolbar = Class.extend({ this.page.clear_indicator(); } }, + refresh_star: function() { + this.star_icon.toggleClass("text-extra-muted not-starred", !frappe.ui.is_starred(this.frm.doc)) + .attr("data-doctype", this.frm.doctype).attr("data-name", this.frm.doc.name); + }, make_menu: function() { var me = this; var p = this.frm.perm[0]; @@ -69,6 +76,11 @@ frappe.ui.form.Toolbar = Class.extend({ me.frm.print_doc();}); } + // star + this.star_icon = this.page.add_action_icon("icon-star", function() { + frappe.ui.toggle_star(me.star_icon, me.frm.doctype, me.frm.doc.name); + }).removeClass("text-muted").find(".icon-star").addClass("star-action"); + // email if(frappe.model.can_email(null, me.frm)) { this.page.add_menu_item(__("Email"), function() { diff --git a/frappe/public/js/frappe/list/list_item_subject.html b/frappe/public/js/frappe/list/list_item_subject.html index f063d6a430..9477b32f42 100644 --- a/frappe/public/js/frappe/list/list_item_subject.html +++ b/frappe/public/js/frappe/list/list_item_subject.html @@ -3,7 +3,7 @@ {% } %} + icon-fixed-width star-action" data-name="{%= _name %}" data-doctype="{%= doctype %}"> {%= _title %} diff --git a/frappe/public/js/frappe/ui/page.js b/frappe/public/js/frappe/ui/page.js index 43d5e68d89..a58cd975bf 100644 --- a/frappe/public/js/frappe/ui/page.js +++ b/frappe/public/js/frappe/ui/page.js @@ -93,7 +93,7 @@ frappe.ui.Page = Class.extend({ }, add_action_icon: function(icon, click) { - return $('') + return $('') .appendTo(this.icon_group.removeClass("hide")) .click(click); }, diff --git a/frappe/public/js/frappe/ui/star.js b/frappe/public/js/frappe/ui/star.js index b8bad1041b..01a06b6a4a 100644 --- a/frappe/public/js/frappe/ui/star.js +++ b/frappe/public/js/frappe/ui/star.js @@ -1,6 +1,15 @@ // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // MIT License. See license.txt +frappe.ui.is_starred = function(doc) { + var starred = doc._starred_by; + if(starred) { + starred = JSON.parse(starred); + return starred.indexOf(user)===-1 ? false : true; + } + return false; +} + frappe.ui.toggle_star = function($btn, doctype, name) { var add = $btn.hasClass("not-starred") ? "Yes" : "No"; frappe.call({ @@ -14,7 +23,8 @@ frappe.ui.toggle_star = function($btn, doctype, name) { callback: function(r) { if(!r.exc) { // update in all local-buttons - var action_buttons = $(".star-action[data-name='"+ name.replace(/"/g, '\"') +"']"); + var action_buttons = $('.star-action[data-name="'+ name.replace(/"/g, '\"') + +'"][data-doctype="'+ doctype.replace(/"/g, '\"')+'"]'); if(add==="Yes") { action_buttons.removeClass("not-starred").removeClass("text-extra-muted"); diff --git a/frappe/public/less/common.less b/frappe/public/less/common.less index 7208fb3518..f199f9d328 100644 --- a/frappe/public/less/common.less +++ b/frappe/public/less/common.less @@ -209,3 +209,15 @@ a.badge-hover& { #freeze.in { opacity: 0.5; } + +a.no-decoration& { + text-decoration: none; + color: inherit; + + &:hover, + &:focus, + &:active { + text-decoration: none; + color: inherit; + } +} diff --git a/frappe/public/less/website.less b/frappe/public/less/website.less index 620268327b..2549a7dd7e 100644 --- a/frappe/public/less/website.less +++ b/frappe/public/less/website.less @@ -301,18 +301,6 @@ textarea { margin: 10px 0px; } -a.no-decoration& { - text-decoration: none; - color: inherit; - - &:hover, - &:focus, - &:active { - text-decoration: none; - color: inherit; - } -} - a.active { pointer-events: none; cursor: default;