diff --git a/frappe/core/doctype/doctype/test_doctype.py b/frappe/core/doctype/doctype/test_doctype.py
index 678e52451a..6a0794c7a1 100644
--- a/frappe/core/doctype/doctype/test_doctype.py
+++ b/frappe/core/doctype/doctype/test_doctype.py
@@ -8,13 +8,14 @@ import unittest
# test_records = frappe.get_test_records('DocType')
+
class TestDocType(unittest.TestCase):
- def new_doctype(self, name):
+ def new_doctype(self, name, unique=0):
return frappe.get_doc({
"doctype": "DocType",
"module": "Core",
"custom": 1,
- "fields": [{"label": "Some Field", "fieldname": "some_fieldname", "fieldtype": "Data"}],
+ "fields": [{"label": "Some Field", "fieldname": "some_fieldname", "fieldtype": "Data", "unique": unique}],
"permissions": [{"role": "System Manager", "read": 1}],
"name": name
})
@@ -28,4 +29,28 @@ class TestDocType(unittest.TestCase):
frappe.delete_doc("DocType", name)
doc = self.new_doctype(name).insert()
- doc.delete()
\ No newline at end of file
+ doc.delete()
+
+ def test_doctype_unique_constraint_dropped(self):
+ if frappe.db.exists("DocType", "With_Unique"):
+ frappe.delete_doc("DocType", "With_Unique")
+
+ dt = self.new_doctype("With_Unique", unique=1)
+ dt.insert()
+
+ doc1 = frappe.new_doc("With_Unique")
+ doc2 = frappe.new_doc("With_Unique")
+ doc1.some_fieldname = "Something"
+ doc1.name = "one"
+ doc2.some_fieldname = "Something"
+ doc2.name = "two"
+
+ doc1.insert()
+ self.assertRaises(frappe.UniqueValidationError, doc2.insert)
+
+ dt.fields[0].unique = 0
+ dt.save()
+
+ doc2.insert()
+ doc1.delete()
+ doc2.delete()
diff --git a/frappe/core/web_form/edit_profile/edit_profile.json b/frappe/core/web_form/edit_profile/edit_profile.json
index ecf1e5ba70..30e8437986 100644
--- a/frappe/core/web_form/edit_profile/edit_profile.json
+++ b/frappe/core/web_form/edit_profile/edit_profile.json
@@ -1,17 +1,24 @@
{
+ "accept_payment": 0,
"allow_comments": 0,
"allow_delete": 0,
"allow_edit": 1,
+ "allow_incomplete": 0,
"allow_multiple": 0,
+ "allow_print": 0,
+ "amount": 0.0,
+ "amount_based_on_field": 0,
"breadcrumbs": "[{\"title\": _(\"My Account\"), \"route\": \"me\"}]",
"creation": "2016-09-19 05:16:59.242754",
"doc_type": "User",
"docstatus": 0,
"doctype": "Web Form",
"idx": 0,
+ "introduction_text": "",
"is_standard": 1,
"login_required": 1,
- "modified": "2016-09-24 04:31:41.920694",
+ "max_attachment_size": 0,
+ "modified": "2017-07-24 12:14:04.039284",
"modified_by": "Administrator",
"module": "Core",
"name": "edit-profile",
@@ -29,6 +36,8 @@
"fieldtype": "Data",
"hidden": 0,
"label": "First Name",
+ "max_length": 0,
+ "max_value": 0,
"read_only": 0,
"reqd": 1
},
@@ -37,6 +46,8 @@
"fieldtype": "Data",
"hidden": 0,
"label": "Middle Name (Optional)",
+ "max_length": 0,
+ "max_value": 0,
"read_only": 0,
"reqd": 0
},
@@ -45,6 +56,8 @@
"fieldtype": "Data",
"hidden": 0,
"label": "Last Name",
+ "max_length": 0,
+ "max_value": 0,
"read_only": 0,
"reqd": 0
},
@@ -54,6 +67,8 @@
"fieldtype": "Attach",
"hidden": 0,
"label": "User Image",
+ "max_length": 0,
+ "max_value": 0,
"read_only": 0,
"reqd": 0
},
@@ -61,6 +76,8 @@
"fieldtype": "Section Break",
"hidden": 0,
"label": "More Information",
+ "max_length": 0,
+ "max_value": 0,
"read_only": 0,
"reqd": 0
},
@@ -69,6 +86,18 @@
"fieldtype": "Data",
"hidden": 0,
"label": "Phone",
+ "max_length": 0,
+ "max_value": 0,
+ "read_only": 0,
+ "reqd": 0
+ },
+ {
+ "fieldname": "mobile_no",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "label": "Mobile Number",
+ "max_length": 0,
+ "max_value": 0,
"read_only": 0,
"reqd": 0
},
@@ -78,6 +107,8 @@
"fieldtype": "Link",
"hidden": 0,
"label": "Language",
+ "max_length": 0,
+ "max_value": 0,
"options": "Language",
"read_only": 0,
"reqd": 0
diff --git a/frappe/desk/page/setup_wizard/setup_wizard.css b/frappe/desk/page/setup_wizard/setup_wizard.css
index b17b3676bc..5313a6b4bc 100644
--- a/frappe/desk/page/setup_wizard/setup_wizard.css
+++ b/frappe/desk/page/setup_wizard/setup_wizard.css
@@ -2,25 +2,6 @@
margin-top: 30px;
}
-.setup-wizard-brand {
- margin: 30px;
- text-align: center;
- display: flex;
- justify-content: center;
- align-items: center
-}
-
-.setup-wizard-brand .brand-icon {
- width: 36px;
- height: 36px;
-}
-
-.setup-wizard-brand .brand-name {
- font-size: 20px;
- margin-left: 8px;
- color: #36414C;
-}
-
.setup-wizard-slide {
padding-left: 0px;
padding-right: 0px;
@@ -59,14 +40,6 @@
font-weight: 500;
}
-.setup-wizard-slide .has-error .control-label {
- color: #ffa00a;
-}
-
-.setup-wizard-slide .has-error .form-control{
- border-color: #ffa00a;
-}
-
.setup-wizard-slide .form-control.bold {
background-color: #fff;
}
@@ -113,8 +86,7 @@
.setup-wizard-slide .frappe-control[data-fieldtype="Attach Image"] {
width: 140px;
height: 180px; /*depends on presence of heading*/
- text-align: center;
- margin-left: calc((100% - 140px)/2);
+ margin-top: 20px;
}
.setup-wizard-slide .frappe-control[data-fieldtype="Attach Image"] .form-group,
diff --git a/frappe/desk/page/setup_wizard/setup_wizard.js b/frappe/desk/page/setup_wizard/setup_wizard.js
index c5aab1c178..f76787e0e3 100644
--- a/frappe/desk/page/setup_wizard/setup_wizard.js
+++ b/frappe/desk/page/setup_wizard/setup_wizard.js
@@ -78,7 +78,6 @@ frappe.setup.Wizard = Class.extend({
', {html:html}))
},
show_working: function() {
- $('header').find('.setup-wizard-brand').hide();
this.hide_current_slide();
frappe.set_route(this.page_name);
this.current_slide = {"$wrapper": this.get_message(this.working_html()).appendTo(this.parent)};
@@ -506,7 +505,7 @@ var frappe_slides = [
icon: "fa fa-user",
fields: [
{ "fieldtype":"Attach Image", "fieldname":"attach_user_image",
- label: __("Attach Your Picture"), is_private: 0},
+ label: __("Attach Your Picture"), is_private: 0, align: 'center'},
{ "fieldname": "full_name", "label": __("Full Name"), "fieldtype": "Data",
reqd:1},
{ "fieldname": "email", "label": __("Email Address") + ' (' + __("Will be your login ID") + ')',
@@ -721,12 +720,4 @@ var utils = {
frappe.setup.on("before_load", function() {
// load slides
frappe_slides.map(frappe.setup.add_slide);
-
- // set header image
- let $icon = $('header .setup-wizard-brand');
- if($icon.length === 0) {
- $('header').append(`
-

`);
- }
});
diff --git a/frappe/desk/tags.py b/frappe/desk/tags.py
index b02e814280..5b8103a54e 100644
--- a/frappe/desk/tags.py
+++ b/frappe/desk/tags.py
@@ -47,6 +47,13 @@ def remove_tag(tag, dt, dn):
"removes tag from the record"
DocTags(dt).remove(dn, tag)
+@frappe.whitelist()
+def get_tagged_docs(doctype, tag):
+ frappe.has_permission(doctype, throw=True)
+
+ return frappe.db.sql("""SELECT name
+ FROM `tab{0}`
+ WHERE _user_tags LIKE '%{1}%'""".format(doctype, tag))
@frappe.whitelist()
def get_tags(doctype, txt, cat_tags):
diff --git a/frappe/email/doctype/email_group/email_group.py b/frappe/email/doctype/email_group/email_group.py
index d74570d0aa..ed4ab32fed 100755
--- a/frappe/email/doctype/email_group/email_group.py
+++ b/frappe/email/doctype/email_group/email_group.py
@@ -69,15 +69,15 @@ def add_subscribers(name, email_list):
count = 0
for email in email_list:
email = email.strip()
- valid = validate_email_add(email, False)
+ parsed_email = validate_email_add(email, False)
- if valid:
+ if parsed_email:
if not frappe.db.get_value("Email Group Member",
- {"email_group": name, "email": email}):
+ {"email_group": name, "email": parsed_email}):
frappe.get_doc({
"doctype": "Email Group Member",
"email_group": name,
- "email": email
+ "email": parsed_email
}).insert(ignore_permissions = frappe.flags.ignore_permissions)
count += 1
diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py
index ed81d663d8..8d37745073 100644
--- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py
+++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py
@@ -86,7 +86,7 @@ def backup_to_dropbox():
access_token = generate_oauth2_access_token_from_oauth1_token(dropbox_settings)
if not access_token.get('oauth2_token'):
- return
+ return 'Failed backup upload', 'No Access Token exists! Please generate the access token for Dropbox.'
dropbox_settings['access_token'] = access_token['oauth2_token']
set_dropbox_access_token(access_token['oauth2_token'])
diff --git a/frappe/integrations/doctype/oauth_client/test_records.json b/frappe/integrations/doctype/oauth_client/test_records.json
new file mode 100644
index 0000000000..904d959625
--- /dev/null
+++ b/frappe/integrations/doctype/oauth_client/test_records.json
@@ -0,0 +1,16 @@
+[
+ {
+ "app_name": "_Test OAuth Client",
+ "client_id": "test_client_id",
+ "client_secret": "test_client_secret",
+ "default_redirect_uri": "http://localhost",
+ "docstatus": 0,
+ "doctype": "OAuth Client",
+ "grant_type": "Authorization Code",
+ "name": "test_client_id",
+ "redirect_uris": "http://localhost",
+ "response_type": "Code",
+ "scopes": "all openid",
+ "skip_authorization": 0
+ }
+]
diff --git a/frappe/model/db_schema.py b/frappe/model/db_schema.py
index a99a783e1f..01725e12a6 100644
--- a/frappe/model/db_schema.py
+++ b/frappe/model/db_schema.py
@@ -314,7 +314,7 @@ class DbTable:
# if index key exists
if frappe.db.sql("""show index from `{0}`
where key_name=%s
- and Non_unique=%s""".format(self.name), (col.fieldname, 0 if col.unique else 1)):
+ and Non_unique=%s""".format(self.name), (col.fieldname, col.unique)):
query.append("drop index `{}`".format(col.fieldname))
for col in self.set_default:
diff --git a/frappe/patches.txt b/frappe/patches.txt
index 564c73c002..8adf636701 100644
--- a/frappe/patches.txt
+++ b/frappe/patches.txt
@@ -187,4 +187,5 @@ frappe.patches.v8_0.update_gender_and_salutation
execute:frappe.db.sql('update tabReport set module="Desk" where name="ToDo"')
frappe.patches.v8_1.enable_allow_error_traceback_in_system_settings
frappe.patches.v8_1.update_format_options_in_auto_email_report
-frappe.patches.v8_1.delete_custom_docperm_if_doctype_not_exists
\ No newline at end of file
+frappe.patches.v8_1.delete_custom_docperm_if_doctype_not_exists
+frappe.patches.v8_5.delete_email_group_member_with_invalid_emails
diff --git a/frappe/patches/v8_5/__init__.py b/frappe/patches/v8_5/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/patches/v8_5/delete_email_group_member_with_invalid_emails.py b/frappe/patches/v8_5/delete_email_group_member_with_invalid_emails.py
new file mode 100644
index 0000000000..e74f1be4ff
--- /dev/null
+++ b/frappe/patches/v8_5/delete_email_group_member_with_invalid_emails.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.utils import validate_email_add
+
+def execute():
+ ''' update/delete the email group member with the wrong email '''
+
+ email_group_members = frappe.get_all("Email Group Member", fields=["name", "email"])
+ for member in email_group_members:
+ validated_email = validate_email_add(member.email)
+ if (validated_email==member.email):
+ pass
+ else:
+ try:
+ frappe.db.set_value("Email Group Member", member.name, "email", validated_email)
+ except Exception:
+ frappe.delete_doc(doctype="Email Group Member", name=member.name, force=1, ignore_permissions=True)
\ No newline at end of file
diff --git a/frappe/public/css/form.css b/frappe/public/css/form.css
index 844c2dc761..0d21271862 100644
--- a/frappe/public/css/form.css
+++ b/frappe/public/css/form.css
@@ -287,6 +287,8 @@ h6.uppercase,
border-radius: 3px;
margin-left: -7px;
position: relative;
+ max-width: calc(100% - 50px);
+ padding-right: 0px;
overflow: visible;
}
.timeline-item.user-content .avatar-medium {
@@ -294,6 +296,11 @@ h6.uppercase,
height: 45px;
width: 45px;
}
+.timeline-item.user-content .action-btns {
+ position: absolute;
+ right: 0;
+ padding: 5px 15px 2px 5px;
+}
.timeline-item.user-content .comment-header {
background-color: #fafbfc;
padding: 10px 15px 10px 13px;
@@ -301,12 +308,19 @@ h6.uppercase,
color: #8D99A6;
border-bottom: 1px solid #EBEFF2;
}
+.timeline-item.user-content .comment-header.links-active {
+ padding-right: 60px;
+}
+.timeline-item.user-content .comment-header .commented-on-small {
+ display: none;
+}
.timeline-item.user-content .comment-header .octicon-heart {
color: #ff5858;
cursor: pointer;
}
.timeline-item.user-content .reply {
padding: 15px;
+ overflow: auto;
}
.timeline-item.user-content .reply > div > p:first-child {
margin-top: 0px;
@@ -317,11 +331,13 @@ h6.uppercase,
.timeline-item.user-content .reply hr {
margin: 10px 0px;
}
-.timeline-item.user-content .close-btn-container {
- padding: 4px 10px 2px 5px;
+.timeline-item.user-content .close-btn-container .close {
+ color: inherit;
+ opacity: 1;
+ padding: 0 0 0 10px;
}
.timeline-item.user-content .edit-btn-container {
- padding: 4px 5px;
+ padding: 0;
}
.timeline-item.user-content .edit-btn-container .edit {
color: inherit;
@@ -515,6 +531,14 @@ h6.uppercase,
padding: 0px;
margin: 0px;
}
+.flex-justify-center {
+ display: flex;
+ justify-content: center;
+}
+.flex-justify-end {
+ display: flex;
+ justify-content: flex-end;
+}
.hide-control {
display: none !important;
}
diff --git a/frappe/public/css/mobile.css b/frappe/public/css/mobile.css
index 9e0bbe3597..ebcc52084f 100644
--- a/frappe/public/css/mobile.css
+++ b/frappe/public/css/mobile.css
@@ -192,6 +192,9 @@ body {
}
}
@media (max-width: 767px) {
+ .toggle-sidebar {
+ margin-right: 0;
+ }
body[data-route^="Form"] .page-title .title-text {
font-size: 16px;
width: calc(100% - 30px);
@@ -331,4 +334,64 @@ body {
body[data-route^="Form"] .page-head .sub-heading {
right: 90px;
}
+ .timeline::before {
+ content: none;
+ }
+ .timeline .timeline-new-email {
+ margin: 20px 0;
+ padding-left: 15px;
+ }
+ .timeline .timeline-new-email::before {
+ content: none;
+ }
+ .timeline .timeline-item.user-content {
+ margin: 20px 15px;
+ }
+ .timeline .timeline-item.user-content .media-body {
+ margin-left: 0;
+ max-width: 100%;
+ overflow: hidden;
+ }
+ .timeline .timeline-item.user-content .media-body:before {
+ content: none;
+ }
+ .timeline .timeline-item.user-content .action-btns {
+ padding: 5px 10px 2px 5px;
+ }
+ .timeline .timeline-item.user-content .comment-header {
+ padding: 7px 10px;
+ }
+ .timeline .timeline-item.user-content .comment-header .links-active {
+ padding-right: 10px;
+ }
+ .timeline .timeline-item.user-content .avatar-medium {
+ margin-right: 10px;
+ }
+ .timeline .timeline-item.user-content .reply {
+ padding: 10px;
+ }
+ .timeline .timeline-item.user-content .commented-on-small {
+ display: inline-block;
+ }
+ .timeline .timeline-item.user-content .commented-on-small {
+ display: inline-block;
+ }
+ .timeline .timeline-item.notification-content {
+ padding-left: 15px;
+ margin: 20px 0;
+ }
+ .timeline .timeline-item.notification-content::before {
+ content: none;
+ }
+ .timeline .timeline-item.notification-content .small {
+ padding-left: 0;
+ }
+ .timeline .timeline-item .delivery-status-indicator {
+ float: left;
+ margin: 0 5px 0 0;
+ }
+ .timeline .asset-details {
+ line-height: 24px;
+ /*Height of avtar image -36px to align text center vertically*/
+ }
}
diff --git a/frappe/public/js/frappe/form/control.js b/frappe/public/js/frappe/form/control.js
index aacdda239c..54bb4e0595 100755
--- a/frappe/public/js/frappe/form/control.js
+++ b/frappe/public/js/frappe/form/control.js
@@ -318,7 +318,7 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({
} else {
$(me.input_area).toggle(false);
if (me.disp_area) {
- me.set_disp_area();
+ me.set_disp_area(me.value);
$(me.disp_area).toggle(true);
}
}
@@ -332,8 +332,7 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({
}
},
- set_disp_area: function() {
- let value = this.get_input_value();
+ set_disp_area: function(value) {
if(in_list(["Currency", "Int", "Float"], this.df.fieldtype)
&& (this.value === 0 || value === 0)) {
// to set the 0 value in readonly for currency, int, float field
@@ -449,7 +448,7 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({
this.last_value = this.value;
this.value = value;
this.set_formatted_input(value);
- this.set_disp_area();
+ this.set_disp_area(value);
this.set_mandatory && this.set_mandatory(value);
},
set_formatted_input: function(value) {
@@ -752,29 +751,38 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({
if(!$.fn.datepicker.language[lang]) {
lang = 'en';
}
+ this.today_text = __("Today");
this.datepicker_options = {
language: lang,
autoClose: true,
- todayButton: new Date(),
+ todayButton: frappe.datetime.now_date(true),
dateFormat: (frappe.boot.sysdefaults.date_format || 'yyyy-mm-dd'),
- onSelect: function(dateStr) {
- me.$input.trigger('change');
+ startDate: frappe.datetime.now_date(true),
+ onSelect: () => {
+ this.$input.trigger('change');
},
- onShow: function() {
- $('.datepicker--button:visible').text(__('Today'));
-
- if(!me.frm) return;
- var window_height = $(window).height();
- var window_scroll_top = $(window).scrollTop();
- var el_offset_top = me.$input.offset().top + 280;
- var position = 'top left';
- if(window_height + window_scroll_top >= el_offset_top) {
- position = 'bottom left';
- }
- me.datepicker.update('position', position);
+ onShow: () => {
+ this.datepicker.$datepicker
+ .find('.datepicker--button:visible')
+ .text(me.today_text);
+
+ this.update_datepicker_position();
}
};
},
+ update_datepicker_position: function() {
+ if(!this.frm) return;
+ // show datepicker above or below the input
+ // based on scroll position
+ var window_height = $(window).height();
+ var window_scroll_top = $(window).scrollTop();
+ var el_offset_top = this.$input.offset().top + 280;
+ var position = 'top left';
+ if(window_height + window_scroll_top >= el_offset_top) {
+ position = 'bottom left';
+ }
+ this.datepicker.update('position', position);
+ },
set_datepicker: function() {
this.$input.datepicker(this.datepicker_options);
this.datepicker = this.$input.data('datepicker');
@@ -814,6 +822,30 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({
}
});
+frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({
+ set_date_options: function() {
+ this._super();
+ this.today_text = __("Now");
+ $.extend(this.datepicker_options, {
+ timepicker: true,
+ timeFormat: "hh:ii:ss",
+ todayButton: frappe.datetime.now_datetime(true)
+ });
+ },
+ set_description: function() {
+ const { description } = this.df;
+ const { time_zone } = frappe.sys_defaults;
+ if (!frappe.datetime.is_timezone_same()) {
+ if (!description) {
+ this.df.description = time_zone;
+ } else if (!description.includes(time_zone)) {
+ this.df.description += '
' + time_zone;
+ }
+ }
+ this._super();
+ }
+});
+
frappe.ui.form.ControlTime = frappe.ui.form.ControlData.extend({
make_input: function() {
var me = this;
@@ -823,13 +855,14 @@ frappe.ui.form.ControlTime = frappe.ui.form.ControlData.extend({
timepicker: true,
onlyTimepicker: true,
timeFormat: "hh:ii:ss",
+ startDate: frappe.datetime.now_time(true),
onSelect: function() {
me.$input.trigger('change');
},
onShow: function() {
$('.datepicker--button:visible').text(__('Now'));
},
- todayButton: new Date()
+ todayButton: frappe.datetime.now_time(true)
});
this.datepicker = this.$input.data('datepicker');
this.refresh();
@@ -840,33 +873,21 @@ frappe.ui.form.ControlTime = frappe.ui.form.ControlData.extend({
&& ((this.last_value && this.last_value !== this.value)
|| (!this.datepicker.selectedDates.length))) {
- this.datepicker.selectDate(moment(value, 'hh:mm:ss')._d);
+ var date_obj = frappe.datetime.moment_to_date_obj(moment(value, 'hh:mm:ss'));
+ this.datepicker.selectDate(date_obj);
}
},
-});
-
-frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({
- set_date_options: function() {
- this._super();
- this.datepicker_options.timepicker = true;
- this.datepicker_options.timeFormat = "hh:ii:ss";
- this.datepicker_options.onShow = function() {
- $('.datepicker--button:visible').text(__('Now'));
- };
- },
- parse: function(value) {
- if(value) {
- // parse and convert
- value = frappe.datetime.convert_to_system_tz(frappe.datetime.user_to_str(value));
- }
- return value;
- },
- format_for_input: function(value) {
- if(value) {
- // convert and format
- value = frappe.datetime.str_to_user(frappe.datetime.convert_to_user_tz(value));
+ set_description: function() {
+ const { description } = this.df;
+ const { time_zone } = frappe.sys_defaults;
+ if (!frappe.datetime.is_timezone_same()) {
+ if (!description) {
+ this.df.description = time_zone;
+ } else if (!description.includes(time_zone)) {
+ this.df.description += '
' + time_zone;
+ }
}
- return value || "";
+ this._super();
}
});
@@ -903,11 +924,12 @@ frappe.ui.form.ControlDateRange = frappe.ui.form.ControlData.extend({
this.value = value;
}
if (this.value) {
- this.$input && this.$input.val(this.format_for_input(this.value[0], this.value[1]));
+ let formatted = this.format_for_input(this.value[0], this.value[1]);
+ this.$input && this.$input.val(formatted);
} else {
this.$input && this.$input.val("");
}
- this.set_disp_area();
+ this.set_disp_area(value || '');
this.set_mandatory && this.set_mandatory(value);
},
parse: function(value) {
@@ -984,7 +1006,7 @@ frappe.ui.form.ControlCheck = frappe.ui.form.ControlData.extend({
}
this.last_value = value;
this.set_mandatory(value);
- this.set_disp_area();
+ this.set_disp_area(value);
}
});
@@ -1219,6 +1241,16 @@ frappe.ui.form.ControlAttachImage = frappe.ui.form.ControlAttach.extend({
make: function() {
var me = this;
this._super();
+
+ this.container = $('').insertAfter($(this.wrapper));
+ $(this.wrapper).detach();
+ this.container.attr('data-fieldtype', this.df.fieldtype).append(this.wrapper);
+ if(this.df.align === 'center') {
+ this.container.addClass("flex-justify-center");
+ } else if (this.df.align === 'right') {
+ this.container.addClass("flex-justify-end");
+ }
+
this.img_wrapper = $('
')
.appendTo(this.wrapper);
diff --git a/frappe/public/js/frappe/form/footer/timeline.js b/frappe/public/js/frappe/form/footer/timeline.js
index f4bcad2c98..3aba3290b4 100644
--- a/frappe/public/js/frappe/form/footer/timeline.js
+++ b/frappe/public/js/frappe/form/footer/timeline.js
@@ -248,14 +248,14 @@ frappe.ui.form.Timeline = Class.extend({
c["edit"] = "";
if(c.communication_type=="Comment" && (c.comment_type || "Comment") === "Comment") {
if(frappe.model.can_delete("Communication")) {
- c["delete"] = '
';
+ c["delete"] = '
';
}
if(frappe.user.name == c.sender || (frappe.user.name == 'Administrator')) {
- c["edit"] = '
';
+ c["edit"] = '
';
}
}
-
+ c.comment_on_small = comment_when(c.creation, true);
c.comment_on = comment_when(c.creation);
if(!c.fullname) {
c.fullname = c.sender_full_name || frappe.user.full_name(c.sender);
@@ -360,7 +360,8 @@ frappe.ui.form.Timeline = Class.extend({
"Unshared": "octicon octicon-circle-slash",
"Like": "octicon octicon-heart",
"Edit": "octicon octicon-pencil",
- "Relinked": "octicon octicon-check"
+ "Relinked": "octicon octicon-check",
+ "Reply": "octicon octicon-mail-reply"
}[c.comment_type || c.communication_medium]
c.color = {
@@ -378,7 +379,8 @@ frappe.ui.form.Timeline = Class.extend({
"Label": "#2c3e50",
"Attachment": "#7f8c8d",
"Attachment Removed": "#eee",
- "Relinked": "#16a085"
+ "Relinked": "#16a085",
+ "Reply": "#8d99a6"
}[c.comment_type || c.communication_medium];
c.icon_fg = {
diff --git a/frappe/public/js/frappe/form/footer/timeline_item.html b/frappe/public/js/frappe/form/footer/timeline_item.html
index c35ffa26d6..215dd06fc2 100755
--- a/frappe/public/js/frappe/form/footer/timeline_item.html
+++ b/frappe/public/js/frappe/form/footer/timeline_item.html
@@ -1,6 +1,6 @@
{% if (data.user_content) { %}
-
+
{% if(data.user_info.image) { %}
{% } else { %}
@@ -10,88 +10,108 @@
{% } %}
-
+
-
-
- {%= data.delete %}
-
-
-
-
- {%= data.edit %}
-
+
+ {% if(data.delete) { %}
+
+
+ {%= data.delete %}
+
+
+ {% } %}
+ {% if(data.edit) { %}
+
+
+ {%= data.edit %}
+
+
+ {% } %}
{% if(data.communication_type==="Communication"
|| data.communication_type==="Feedback"
|| (data.communication_type==="Comment"
&& data.comment_type==="Comment")) { %}
-
@@ -143,7 +163,7 @@ {% if(data.link_doctype && data.link_name) { %} {% } %} - + – {%= data.comment_on %}