@@ -13,7 +13,7 @@ import os, sys, importlib, inspect, json | |||
from .exceptions import * | |||
from .utils.jinja import get_jenv, get_template, render_template | |||
__version__ = '8.0.4' | |||
__version__ = '8.0.5' | |||
__title__ = "Frappe Framework" | |||
local = Local() | |||
@@ -3,17 +3,6 @@ from frappe import _ | |||
def get_data(): | |||
return [ | |||
{ | |||
"module_name": 'Core', | |||
"type": 'list', | |||
"label": _('Email Inbox'), | |||
"_label": _('Email Inbox'), | |||
"_id": 'Email Inbox', | |||
"_doctype": 'Communication', | |||
"icon": 'fa fa-envelope-o', | |||
"color": '#589494', | |||
"link": 'List/Communication/Inbox' | |||
}, | |||
{ | |||
"module_name": "Desk", | |||
"label": _("Tools"), | |||
@@ -54,9 +43,21 @@ def get_data(): | |||
"type": "module", | |||
"hidden": 1 | |||
}, | |||
{ | |||
"module_name": 'Email Inbox', | |||
"type": 'list', | |||
"label": 'Email Inbox', | |||
"_label": _('Email Inbox'), | |||
"_id": 'Email Inbox', | |||
"_doctype": 'Communication', | |||
"icon": 'fa fa-envelope-o', | |||
"color": '#589494', | |||
"link": 'List/Communication/Inbox' | |||
}, | |||
{ | |||
"module_name": "Core", | |||
"label": _("Developer"), | |||
"label": "Developer", | |||
"_label": _("Developer"), | |||
"color": "#589494", | |||
"icon": "octicon octicon-circuit-board", | |||
"type": "module", | |||
@@ -2,7 +2,8 @@ frappe.listview_settings['Communication'] = { | |||
add_fields: [ | |||
"sent_or_received","recipients", "subject", | |||
"communication_medium", "communication_type", | |||
"sender", "seen", "reference_doctype", "reference_name" | |||
"sender", "seen", "reference_doctype", "reference_name", | |||
"has_attachment" | |||
], | |||
filters: [["status", "=", "Open"]], | |||
@@ -70,7 +70,10 @@ def send_feedback_request(reference_doctype, reference_name, trigger="Manual", d | |||
def get_feedback_request_details(reference_doctype, reference_name, trigger="Manual", request=None): | |||
feedback_url = "" | |||
if not trigger and not request and not frappe.db.get_value("Feedback Trigger", { "document_type": reference_doctype }): | |||
if not frappe.db.get_value(reference_doctype, reference_name): | |||
# reference document is either deleted or renamed | |||
return | |||
elif not trigger and not request and not frappe.db.get_value("Feedback Trigger", { "document_type": reference_doctype }): | |||
return | |||
elif not trigger and request: | |||
trigger = frappe.db.get_value("Feedback Request", request, "feedback_trigger") | |||
@@ -81,8 +84,8 @@ def get_feedback_request_details(reference_doctype, reference_name, trigger="Man | |||
return | |||
feedback_trigger = frappe.get_doc("Feedback Trigger", trigger) | |||
doc = frappe.get_doc(reference_doctype, reference_name) | |||
doc = frappe.get_doc(reference_doctype, reference_name) | |||
context = get_context(doc) | |||
recipients = doc.get(feedback_trigger.email_fieldname, None) | |||
@@ -28,7 +28,8 @@ frappe.pages['modules'].on_page_load = function(wrapper) { | |||
// render sidebar | |||
page.sidebar.html(frappe.render_template('modules_sidebar', | |||
{modules: frappe.get_desktop_icons(true)})); | |||
{modules: frappe.get_desktop_icons(true).sort( | |||
function(a, b){ return (a._label > b._label) ? 1 : -1 })})); | |||
// help click | |||
page.main.on("click", '.module-section-link[data-type="help"]', function(event) { | |||
@@ -247,6 +247,9 @@ class EmailAccount(Document): | |||
email_sync_rule = self.build_email_sync_rule() | |||
email_server = self.get_incoming_server(in_receive=True, email_sync_rule=email_sync_rule) | |||
if not email_server: | |||
return | |||
emails = email_server.get_messages() | |||
incoming_mails = emails.get("latest_messages") | |||
@@ -595,6 +598,9 @@ class EmailAccount(Document): | |||
uid_list = { flag.get("uid", None): flag.get("action", "Read") for flag in flags } | |||
if flags and uid_list: | |||
email_server = self.get_incoming_server() | |||
if not email_server: | |||
return | |||
email_server.update_flag(uid_list=uid_list) | |||
# mark communication as read | |||
@@ -152,12 +152,17 @@ def update_child_docs(old, new, meta): | |||
def update_link_field_values(link_fields, old, new, doctype): | |||
for field in link_fields: | |||
if field['issingle']: | |||
single_doc = frappe.get_doc(field['parent']) | |||
if single_doc.get(field['fieldname'])==old: | |||
single_doc.set(field['fieldname'], new) | |||
# update single docs using ORM rather then query | |||
# as single docs also sometimes sets defaults! | |||
single_doc.save(ignore_permissions=True) | |||
try: | |||
single_doc = frappe.get_doc(field['parent']) | |||
if single_doc.get(field['fieldname'])==old: | |||
single_doc.set(field['fieldname'], new) | |||
# update single docs using ORM rather then query | |||
# as single docs also sometimes sets defaults! | |||
single_doc.save(ignore_permissions=True) | |||
except ImportError: | |||
# fails in patches where the doctype has been renamed | |||
# or no longer exists | |||
pass | |||
else: | |||
# because the table hasn't been renamed yet! | |||
parent = field['parent'] if field['parent']!=new else old | |||
@@ -174,3 +174,4 @@ frappe.patches.v8_0.deprecate_integration_broker | |||
frappe.patches.v8_0.setup_email_inbox #2017-03-29 | |||
frappe.patches.v8_0.newsletter_childtable_migrate | |||
execute:frappe.db.sql("delete from `tabDesktop Icon` where module_name='Communication'") | |||
execute:frappe.db.sql("update `tabDesktop Icon` set type='list' where _doctype='Communication'") |
@@ -251,7 +251,6 @@ | |||
"public/js/frappe/views/treeview.js", | |||
"public/js/frappe/views/image/image_view_item_row.html", | |||
"public/js/frappe/views/image/image_view_item_main_head.html", | |||
"public/js/frappe/views/image/photoswipe_dom.html", | |||
"public/js/frappe/views/inbox/inbox_no_result.html", | |||
@@ -152,14 +152,6 @@ | |||
} | |||
.filterable { | |||
cursor: pointer; | |||
display: inline-block; | |||
text-overflow: ellipsis; | |||
} | |||
.col-sm-2:not(.list-row-right) .filterable, | |||
.col-sm-3:not(.list-row-right) .filterable { | |||
max-width: 145px; | |||
overflow: hidden; | |||
width: 100%; | |||
} | |||
.doclist-row .label { | |||
margin-right: 8px; | |||
@@ -392,3 +384,73 @@ | |||
.inbox-value { | |||
padding-top: 2px; | |||
} | |||
.list-items { | |||
width: 100%; | |||
} | |||
.list-item-container { | |||
border-bottom: 1px solid #d1d8dd; | |||
} | |||
.list-item-container:last-child { | |||
border-bottom: none; | |||
} | |||
.list-item { | |||
display: flex; | |||
align-items: center; | |||
cursor: pointer; | |||
height: 40px; | |||
padding-left: 15px; | |||
font-size: 12px; | |||
} | |||
.list-item:hover { | |||
background-color: #F7FAFC; | |||
} | |||
@media (max-width: 767px) { | |||
.list-item { | |||
height: 50px; | |||
padding-left: 10px; | |||
font-size: 14px; | |||
font-weight: normal; | |||
} | |||
} | |||
.list-item--head { | |||
background-color: #F7FAFC; | |||
border-bottom: 1px solid #d1d8dd; | |||
cursor: auto; | |||
} | |||
.list-item input[type=checkbox] { | |||
margin: 0; | |||
margin-right: 5px; | |||
} | |||
.list-item .liked-by, | |||
.list-item .liked-by-filter-button { | |||
display: inline-block; | |||
width: 20px; | |||
margin-right: 10px; | |||
} | |||
.list-item__content { | |||
flex: 1; | |||
margin-right: 15px; | |||
display: flex; | |||
align-items: center; | |||
} | |||
.list-item__content--flex-2 { | |||
flex: 2; | |||
} | |||
.list-item__content--activity { | |||
justify-content: flex-end; | |||
margin-right: 5px; | |||
} | |||
.list-item__content--activity .list-row-modified, | |||
.list-item__content--activity .avatar-small { | |||
margin-right: 10px; | |||
} | |||
.list-item__content--indicator span::before { | |||
height: 12px; | |||
width: 12px; | |||
} | |||
.list-item__content--id { | |||
justify-content: flex-end; | |||
} | |||
.frappe-timestamp { | |||
white-space: nowrap; | |||
} |
@@ -444,6 +444,10 @@ frappe.get_module = function(m, default_module) { | |||
frappe.get_desktop_icons = function(show_hidden, show_global) { | |||
// filter valid icons | |||
// hidden == hidden from desktop | |||
// blocked == no view from modules either | |||
var out = []; | |||
var add_to_out = function(module) { | |||
@@ -1,8 +1,8 @@ | |||
{% if (_checkbox) { %} | |||
<input class="list-select-all" type="checkbox" | |||
<input class="list-select-all hidden-xs" type="checkbox" | |||
title="{%= __("Select All") %}"> | |||
{% } %} | |||
<span style="display: inline-block; width: 34px; vertical-align: middle;"> | |||
<span class="liked-by-filter-button"> | |||
<i class="fa-fw octicon octicon-heart text-extra-muted not-liked like-action list-liked-by-me" | |||
title="{%= __("Likes") %}"></i> | |||
</span> |
@@ -1,17 +1,15 @@ | |||
<div class="hidden-xs"> | |||
<span class="list-row-modified text-muted"> | |||
{%= comment_when(data.modified, true) %} | |||
</span> | |||
{% if (data._assign_list.length) { %} | |||
<span class="filterable" | |||
data-filter="_assign,like,%{%= data._assign_list[data._assign_list.length - 1] %}%"> | |||
{%= frappe.avatar(data._assign_list[data._assign_list.length - 1]) %}</span> | |||
{% } else { %} | |||
<span class="avatar avatar-small avatar-empty"></span> | |||
{% } %} | |||
<span class="list-comment-count small | |||
{% if(!data._comment_count) { %} text-extra-muted {% } else { %} text-muted {% } %}"> | |||
<i class="octicon octicon-comment-discussion"></i> | |||
{%= (data._comment_count > 99 ? "99+" : data._comment_count) || 0 %} | |||
</span> | |||
</div> | |||
<span class="list-row-modified text-muted"> | |||
{%= comment_when(data.modified, true) %} | |||
</span> | |||
{% if (data._assign_list.length) { %} | |||
<span class="filterable" | |||
data-filter="_assign,like,%{%= data._assign_list[data._assign_list.length - 1] %}%"> | |||
{%= frappe.avatar(data._assign_list[data._assign_list.length - 1]) %}</span> | |||
{% } else { %} | |||
<span class="avatar avatar-small avatar-empty"></span> | |||
{% } %} | |||
<span class="list-comment-count small | |||
{% if(!data._comment_count) { %} text-extra-muted {% } else { %} text-muted {% } %}"> | |||
<i class="octicon octicon-comment-discussion"></i> | |||
{%= (data._comment_count > 99 ? "99+" : data._comment_count) || 0 %} | |||
</span> |
@@ -1,49 +1,40 @@ | |||
<div class="row"> | |||
{% var total_cols=0; for (var i=0, l=columns.length; i < l; i++ ) { | |||
var col = columns[i], value=data[col.fieldname]; total_cols += parseInt(col.colspan); %} | |||
{% if (total_cols <= 12) { %} | |||
<div class="col-sm-{%= col.colspan %} list-col ellipsis | |||
{% if(col.type==="Subject") { | |||
if (right_column) { %} | |||
col-xs-9 | |||
{% } else { %} | |||
col-xs-12 | |||
{% } %} | |||
{% } else if(right_column && col.fieldname===right_column) { %} | |||
col-xs-3 | |||
{% } else { %} | |||
hidden-xs | |||
{% } %} | |||
{% if(col.df && ["Int", "Float", "Currency", "Percent"].indexOf(col.df.fieldtype)!==-1) { %}text-right{% } %}" | |||
{% if(col.type!=="Indicator" && col.title) { %}title="{%= col.title + ": " + value %}"{% } %}> | |||
{% if(col.type!=="Indicator") { %}<span class="list-value">{% } %} | |||
{% if (col.type==="Subject") { %} | |||
{%= subject %} | |||
{% } else if (col.type==="Indicator") { %} | |||
{%= indicator %} | |||
{% } else if (col.render) { %} | |||
{%= col.render(data) %} | |||
{% } else if (col.fieldtype==="Image") { %} | |||
{% if(data[col.df.options]) { %} | |||
<img src="{%= data[col.df.options] %}" style="max-height: 30px; max-width: 100%;"> | |||
{% } else { %} | |||
<div class="missing-image small"><span class="octicon octicon-circle-slash"></span></div> | |||
{% } %} | |||
{% } else if(col.fieldtype==="Select") { %} | |||
<span class="filterable indicator {%= frappe.utils.guess_colour(value) %}" | |||
data-filter="{%= col.fieldname %},=,{%= value %}">{%= __(value) %}</span> | |||
{% } else if(col.fieldtype==="Link") { %} | |||
<a class="filterable h6 text-muted grey" | |||
data-filter="{%= col.fieldname %},=,{%= value %}">{%= value %}</a> | |||
{% } else { %} | |||
{% if(formatters && formatters[col.fieldname]) { %} | |||
{{ formatters[col.fieldname](value, col.df, data) }} | |||
{% } else { %} | |||
{{ frappe.format(value, col.df, null, data) }} | |||
{% } %} | |||
{% } %} | |||
{% if(col.type!=="Indicator") { %}</span>{% } %} | |||
</div> | |||
<div class="list-item__content ellipsis | |||
{% if(col.type==="Subject") { %} | |||
list-item__content--flex-2 | |||
{% } else { %} | |||
hidden-xs | |||
{% } %} | |||
{% if(col.df && ["Int", "Float", "Currency", "Percent"].indexOf(col.df.fieldtype)!==-1) { %}text-right{% } %}" | |||
{% if(col.type!=="Indicator" && col.title) { %} | |||
title="{%= col.title + ": " + value %}" | |||
{% } %} | |||
> | |||
{% if (col.type==="Subject") { %} | |||
{%= subject %} | |||
{% } else if (col.type==="Indicator") { %} | |||
{%= indicator %} | |||
{% } else if (col.render) { %} | |||
{%= col.render(data) %} | |||
{% } else if (col.fieldtype==="Image") { %} | |||
{% if(data[col.df.options]) { %} | |||
<img src="{%= data[col.df.options] %}" style="max-height: 30px; max-width: 100%;"> | |||
{% } else { %} | |||
<div class="missing-image small"><span class="octicon octicon-circle-slash"></span></div> | |||
{% } %} | |||
{% } else if(col.fieldtype==="Select") { %} | |||
<span class="filterable indicator {%= frappe.utils.guess_colour(value) %} ellipsis" | |||
data-filter="{%= col.fieldname %},=,{%= value %}">{%= __(value) %}</span> | |||
{% } else if(col.fieldtype==="Link") { %} | |||
<a class="filterable text-muted grey ellipsis" | |||
data-filter="{%= col.fieldname %},=,{%= value %}">{%= value %}</a> | |||
{% } else { %} | |||
<a class="filterable text-muted ellipsis" | |||
data-filter="{%= col.fieldname %},=,{%= value %}"> | |||
{% if(formatters && formatters[col.fieldname]) { %} | |||
{{ formatters[col.fieldname](value, col.df, data) }} | |||
{% } else { %} | |||
{{ frappe.format(value, col.df, null, data) }} | |||
{% } %} | |||
</a> | |||
{% } %} | |||
</div> | |||
</div> |
@@ -1,29 +1,15 @@ | |||
<div class="row"> | |||
{% var total_cols=0; for (var i=0, l=columns.length; i < l; i++ ) { | |||
var col = columns[i]; total_cols += parseInt(col.colspan); %} | |||
{% if (total_cols <= 12) { %} | |||
<div class="col-sm-{%= col.colspan %} list-col ellipsis h6 text-muted | |||
{% if(col.type==="Subject") { | |||
if (right_column) { %} | |||
col-xs-9 | |||
{% } else { %} | |||
col-xs-12 | |||
{% } %} | |||
{% } else if(right_column && col.fieldname===right_column) { %} | |||
col-xs-3 | |||
{% } else { %} | |||
hidden-xs | |||
{% } %} | |||
{% if(col.df && ["Int", "Float", "Currency", "Percent"].indexOf(col.df.fieldtype)!==-1) { %}text-right{% } %}"> | |||
<div class="list-item__content ellipsis text-muted | |||
{% if(col.type==="Subject") { %} | |||
list-item__content--flex-2 | |||
{% } else { %} | |||
hidden-xs | |||
{% } %} | |||
{% if(col.df && ["Int", "Float", "Currency", "Percent"].indexOf(col.df.fieldtype)!==-1) { %}text-right{% } %}" | |||
> | |||
<span class="list-value"> | |||
{% if (col.type==="Subject") { %} | |||
{%= frappe.render_template("header_select_all_like_filter", { _checkbox: _checkbox }) %} | |||
{% } %} | |||
<span class="list-col-title">{{ __(col.title) || __(col.label) || "" }}</span> | |||
</span> | |||
{% if (col.type==="Subject") { %} | |||
{%= frappe.render_template("header_select_all_like_filter", { _checkbox: _checkbox }) %} | |||
{% } %} | |||
<span class="list-col-title ellipsis">{{ __(col.title) || __(col.label) || "" }}</span> | |||
</div> | |||
{% } %} | |||
{% } %} | |||
</div> | |||
</div> |
@@ -1,31 +1,24 @@ | |||
<div class="row doclist-row {% if (data._checkbox) { %} has-checkbox {% } %}"> | |||
<div class="col-xs-10 | |||
{% if (meta.title_field && !settings.hide_name_column) { %} | |||
col-sm-8 | |||
{% } else { %} | |||
col-sm-10 | |||
{% } %} list-row-left"> | |||
<!-- title + columns --> | |||
{%= main %} | |||
</div> | |||
<div class="list-item"> | |||
{%= main %} | |||
<!-- id --> | |||
{% if (meta.title_field && !settings.hide_name_column) { | |||
var is_different = data.name !== data[meta.title_field]; | |||
%} | |||
<div class="list-col col-sm-2 hidden-xs text-right ellipsis list-row-id"> | |||
{% if (is_different) { %} | |||
<a class="text-muted list-value" href="#Form/{%= data._doctype_encoded %}/{%= data._name_encoded %}"> | |||
var is_different = data.name !== data[meta.title_field]; | |||
%} | |||
<div class="list-item__content list-item__content--id text-right hidden-xs hidden-sm"> | |||
{% if (is_different) { %} | |||
<a class="text-muted" href="#Form/{%= data._doctype_encoded %}/{%= data._name_encoded %}"> | |||
{%= data.name %}</a> | |||
{% } %} | |||
{% } %} | |||
</div> | |||
{% } %} | |||
<!-- comment --> | |||
<div class="list-col col-sm-2 col-xs-2 | |||
text-right list-row-right" style="padding-left:0px"> | |||
<div class="visible-xs list-row-indicator">{%= indicator_dot %}</div> | |||
<!-- comments count and assigned to section --> | |||
{%= frappe.render_template("item_assigned_to_comment_count", { data: data }) %} | |||
<div class="list-item__content list-item__content--activity hidden-xs"> | |||
<!-- comments count and assigned to section --> | |||
{%= frappe.render_template("item_assigned_to_comment_count", { data: data }) %} | |||
</div> | |||
<div class="list-item__content list-item__content--indicator visible-xs text-right"> | |||
{%= indicator_dot %} | |||
</div> | |||
</div> |
@@ -1,22 +1,11 @@ | |||
<div class="list-row list-row-head" data-list-renderer="{{list.name}}"> | |||
<div class="row doclist-row"> | |||
<div class="col-xs-10 | |||
{% if (list.meta.title_field && !list.settings.hide_name_column) { %} | |||
col-sm-8 | |||
{% } else { %} | |||
col-sm-10 | |||
{% } %} list-row-left"> | |||
<!-- title + columns --> | |||
{%= main %} | |||
</div> | |||
<div class="list-item list-item--head" data-list-renderer="{{list.name}}"> | |||
<!-- title + columns --> | |||
{%= main %} | |||
<!-- id --> | |||
{% if (list.meta.title_field && !list.settings.hide_name_column) { %} | |||
<div class="list-col col-sm-2 hidden-xs text-right"> | |||
</div> | |||
{% } %} | |||
<!-- comment --> | |||
<div class="list-col col-sm-2 hidden-xs text-right list-row-right"></div> | |||
</div> | |||
<!-- id --> | |||
{% if(list.meta.title_field && !list.settings.hide_name_column) { %} | |||
<div class="list-item__content hidden-xs hidden-sm"></div> | |||
{% } %} | |||
<!-- comment --> | |||
<div class="list-item__content list-item__content--activity hidden-xs text-right list-row-right"></div> | |||
</div> |
@@ -1,5 +1,5 @@ | |||
{% if (_checkbox) { %} | |||
<input class="list-row-checkbox" type="checkbox" data-name="{{name}}"> | |||
<input class="list-row-checkbox hidden-xs" type="checkbox" data-name="{{name}}"> | |||
{% } %} | |||
<span class="liked-by" data-liked-by=\'{{ JSON.stringify(_liked_by) }}\'> | |||
<i class="octicon octicon-heart | |||
@@ -221,6 +221,12 @@ frappe.views.ListRenderer = Class.extend({ | |||
return col; | |||
}); | |||
} | |||
// Remove duplicates | |||
this.columns = this.columns.uniqBy(col => col.title); | |||
// Limit number of columns to 4 | |||
this.columns = this.columns.slice(0, 4); | |||
}, | |||
add_column: function (df) { | |||
// field width | |||
@@ -284,7 +290,7 @@ frappe.views.ListRenderer = Class.extend({ | |||
me.list_view.refresh(true); | |||
} | |||
}); | |||
this.wrapper.on('click', '.list-row-left', function (e) { | |||
this.wrapper.on('click', '.list-item', function (e) { | |||
// don't open in case of checkbox, like, filterable | |||
if ($(e.target).hasClass('filterable') | |||
|| $(e.target).hasClass('octicon-heart') | |||
@@ -300,11 +306,18 @@ frappe.views.ListRenderer = Class.extend({ | |||
render_view: function (values) { | |||
var me = this; | |||
values.map(function (value) { | |||
var row = $('<div class="list-row">') | |||
.data("data", me.meta) | |||
.appendTo(me.wrapper).get(0); | |||
me.render_item(row, value); | |||
var $list_items = $(` | |||
<div class="list-items"> | |||
</div> | |||
`); | |||
me.wrapper.append($list_items); | |||
values.map(value => { | |||
const $item = $(this.get_item_html(value)); | |||
const $item_container = $('<div class="list-item-container">').append($item); | |||
$list_items.append($item_container); | |||
this.render_tags($item_container, value); | |||
}); | |||
this.setup_filterable(); | |||
@@ -325,14 +338,16 @@ frappe.views.ListRenderer = Class.extend({ | |||
// returns html for a data item, | |||
// usually based on a template | |||
get_item_html: function (data) { | |||
var main = frappe.render_template('list_item_main', { | |||
data: data, | |||
columns: this.columns, | |||
formatters: this.settings.formatters, | |||
subject: this.get_subject_html(data, true), | |||
indicator: this.get_indicator_html(data), | |||
right_column: this.settings.right_column | |||
}); | |||
var main = this.columns.map(column => | |||
frappe.render_template('list_item_main', { | |||
data: data, | |||
col: column, | |||
value: data[column.fieldname], | |||
formatters: this.settings.formatters, | |||
subject: this.get_subject_html(data, true), | |||
indicator: this.get_indicator_html(data), | |||
}) | |||
).join(""); | |||
return frappe.render_template('list_item_row', { | |||
data: data, | |||
@@ -340,17 +355,17 @@ frappe.views.ListRenderer = Class.extend({ | |||
settings: this.settings, | |||
meta: this.meta, | |||
indicator_dot: this.get_indicator_dot(data), | |||
right_column: this.settings.right_column | |||
}) | |||
}, | |||
get_header_html: function () { | |||
var main = frappe.render_template('list_item_main_head', { | |||
columns: this.columns, | |||
right_column: this.settings.right_column, | |||
_checkbox: ((frappe.model.can_delete(this.doctype) || this.settings.selectable) | |||
&& !this.no_delete) | |||
}); | |||
var main = this.columns.map(column => | |||
frappe.render_template('list_item_main_head', { | |||
col: column, | |||
_checkbox: ((frappe.model.can_delete(this.doctype) || this.settings.selectable) | |||
&& !this.no_delete) | |||
}) | |||
).join(""); | |||
return frappe.render_template('list_item_row_head', { main: main, list: this }); | |||
}, | |||
@@ -429,7 +444,7 @@ frappe.views.ListRenderer = Class.extend({ | |||
data._submittable = frappe.model.is_submittable(this.doctype); | |||
var title_field = frappe.get_meta(this.doctype).title_field || 'name'; | |||
data._title = strip_html(data[title_field]) || data.name; | |||
data._title = strip_html(data[title_field] || data.name); | |||
data._full_title = data._title; | |||
if (data._title.length > 35) { | |||
@@ -122,8 +122,10 @@ frappe.views.ListSidebar = Class.extend({ | |||
var $dropdown = this.page.sidebar.find('.kanban-dropdown'); | |||
var divider = false; | |||
var boards = frappe.get_meta(this.doctype).__kanban_boards; | |||
var meta = frappe.get_meta(this.doctype); | |||
var boards = meta && meta.__kanban_boards; | |||
if (!boards) return; | |||
boards.forEach(function(board) { | |||
var route = ["List", board.reference_doctype, "Kanban", board.name].join('/'); | |||
if(!divider) { | |||
@@ -250,9 +250,9 @@ frappe.views.ListView = frappe.ui.BaseList.extend({ | |||
}, | |||
init_headers: function () { | |||
this.page.main.find('.list-headers > .list-row-head').hide(); | |||
this.page.main.find('.list-headers > .list-item--head').hide(); | |||
this.list_header = this.page.main.find('.list-headers > ' | |||
+ '.list-row-head[data-list-renderer="' | |||
+ '.list-item--head[data-list-renderer="' | |||
+ this.list_renderer.name +'"]'); | |||
if(this.list_header.length > 0) { | |||
@@ -760,9 +760,9 @@ frappe.views.ListView = frappe.ui.BaseList.extend({ | |||
// multi-select using shift key | |||
var $this = $(this); | |||
if (event.shiftKey && $this.prop('checked')) { | |||
var $end_row = $this.parents('.list-row'); | |||
var $start_row = $end_row.prevAll('.list-row') | |||
.find('.list-row-checkbox:checked').last().parents('.list-row'); | |||
var $end_row = $this.parents('.list-item-container'); | |||
var $start_row = $end_row.prevAll('.list-item-container') | |||
.find('.list-row-checkbox:checked').last().parents('.list-item-container'); | |||
if ($start_row) { | |||
$start_row.nextUntil($end_row).find('.list-row-checkbox').prop('checked', true); | |||
} | |||
@@ -107,7 +107,7 @@ frappe.views.GanttView = frappe.views.ListRenderer.extend({ | |||
var $dropdown = $(dropdown) | |||
$dropdown.find(".dropdown-menu") | |||
.append(dropdown_list); | |||
me.list_view.$page.find(`.list-row-head[data-list-renderer='Gantt'] .list-row-right`).css("margin-top", 0).html($dropdown) | |||
me.list_view.$page.find(`[data-list-renderer='Gantt'] .list-row-right`).css("margin-right", "15px").html($dropdown) | |||
$dropdown.on("click", ".option", function() { | |||
var mode = $(this).data('value'); | |||
me.gantt.change_view_mode(mode); | |||
@@ -47,9 +47,8 @@ frappe.views.ImageView = frappe.views.ListRenderer.extend({ | |||
return null; | |||
}, | |||
get_header_html: function () { | |||
var main = frappe.render_template('image_view_item_main_head', { | |||
columns: this.columns, | |||
right_column: this.settings.right_column, | |||
var main = frappe.render_template('list_item_main_head', { | |||
col: { type: "Subject" }, | |||
_checkbox: ((frappe.model.can_delete(this.doctype) || this.settings.selectable) | |||
&& !this.no_delete) | |||
}); | |||
@@ -1,7 +0,0 @@ | |||
<div class="row"> | |||
<div class="col-xs-12"> | |||
<div class="list-value"> | |||
{%= frappe.render_template("header_select_all_like_filter", { _checkbox: _checkbox }) %} | |||
</div> | |||
</div> | |||
</div> |
@@ -341,7 +341,9 @@ frappe.provide("frappe.views"); | |||
function setup_restore_columns() { | |||
var cur_list = store.getState().cur_list; | |||
var columns = store.getState().columns; | |||
var list_row_right = cur_list.$page.find(`.list-row-head[data-list-renderer='Kanban'] .list-row-right`); | |||
var list_row_right = | |||
cur_list.$page.find(`[data-list-renderer='Kanban'] .list-row-right`) | |||
.css('margin-right', '15px'); | |||
list_row_right.empty(); | |||
var archived_columns = columns.filter(function (col) { | |||
@@ -364,7 +366,7 @@ frappe.provide("frappe.views"); | |||
"<ul class='dropdown-menu'>" + options + "</ul>" + | |||
"</div>") | |||
list_row_right.css("margin-top", 0).html($dropdown); | |||
list_row_right.html($dropdown); | |||
$dropdown.find(".dropdown-menu").on("click", "button.restore-column", function (e) { | |||
var column_title = $(this).data().column; | |||
@@ -189,15 +189,6 @@ | |||
.filterable { | |||
cursor: pointer; | |||
display: inline-block; | |||
text-overflow: ellipsis; | |||
} | |||
.col-sm-2:not(.list-row-right) .filterable, | |||
.col-sm-3:not(.list-row-right) .filterable { | |||
max-width: 145px; | |||
overflow: hidden; | |||
width: 100%; | |||
} | |||
@@ -240,7 +231,6 @@ | |||
} | |||
.like-action.octicon-heart { | |||
// color: #ffdb4c; | |||
color: @heart-color; | |||
} | |||
@@ -477,4 +467,92 @@ | |||
.inbox-value { | |||
padding-top: 2px; | |||
} | |||
// list view | |||
.list-items { | |||
width: 100%; | |||
} | |||
.list-item-container { | |||
border-bottom: 1px solid @border-color; | |||
&:last-child { | |||
border-bottom: none; | |||
} | |||
} | |||
.list-item { | |||
display: flex; | |||
align-items: center; | |||
cursor: pointer; | |||
height: 40px; | |||
padding-left: 15px; | |||
font-size: @text-medium; | |||
&:hover { | |||
background-color: @panel-bg; | |||
} | |||
@media (max-width: @screen-xs) { | |||
height: 50px; | |||
padding-left: 10px; | |||
font-size: @text-regular; | |||
font-weight: normal; | |||
} | |||
&--head { | |||
background-color: @panel-bg; | |||
border-bottom: 1px solid @border-color; | |||
cursor: auto; | |||
} | |||
input[type=checkbox] { | |||
margin: 0; | |||
margin-right: 5px; | |||
} | |||
.liked-by, .liked-by-filter-button { | |||
display: inline-block; | |||
width: 20px; | |||
margin-right: 10px; | |||
} | |||
} | |||
.list-item__content { | |||
flex: 1; | |||
margin-right: 15px; | |||
display: flex; | |||
align-items: center; | |||
&--flex-2 { | |||
flex: 2; | |||
} | |||
&--activity { | |||
justify-content: flex-end; | |||
margin-right: 5px; | |||
.list-row-modified, .avatar-small { | |||
margin-right: 10px; | |||
} | |||
} | |||
&--indicator span::before { | |||
height: 12px; | |||
width: 12px; | |||
} | |||
&--id { | |||
justify-content: flex-end; | |||
} | |||
} | |||
.frappe-timestamp { | |||
white-space: nowrap; | |||
} |
@@ -2,46 +2,53 @@ | |||
{% block title %}{{ _("Feedback") }}{% endblock %} | |||
{% block page_content %} | |||
<div class="feedback"> | |||
<p class='lead' id="feedback-msg"></p> | |||
<div> | |||
{{ _("Your rating: ") }} | |||
<i class='fa fa-fw fa-star-o star-icon' data-idx=1></i> | |||
<i class='fa fa-fw fa-star-o star-icon' data-idx=2></i> | |||
<i class='fa fa-fw fa-star-o star-icon' data-idx=3></i> | |||
<i class='fa fa-fw fa-star-o star-icon' data-idx=4></i> | |||
<i class='fa fa-fw fa-star-o star-icon' data-idx=5></i> | |||
</div> | |||
<div style='max-width: 500px;'> | |||
<p>{{ _("Full Name") }}</p> | |||
<input class="form-control fullname" type="text" placeholder="Your Full Name"> | |||
<p>{{ _("Detailed feedback") }}</p> | |||
<textarea class='form-control feedback-text' style='min-height: 300px;'></textarea> | |||
</div> | |||
<p><button class='btn btn-primary btn-sm btn-submit'>{{ _("Submit") }}</button></p> | |||
{% if comment_list -%} | |||
<div class="comments"> | |||
<br><br> | |||
<h3>{{ _("Communication") }}</h3> | |||
{% include 'templates/includes/comments/comments.html' %} | |||
</div> | |||
{% endif %} | |||
</div> | |||
<div class="feedback-result" style="display: none"> | |||
{% macro feedback_result(is_valid_request, subject, message='') %} | |||
<div class="feedback-result" style="{{ 'display: none' if is_valid_request else '' }}"> | |||
<div class='page-card'> | |||
<div class='page-card-head'> | |||
<span class='indicator darkgrey'>{{_("Thank You !!")}}</span> | |||
<span class='indicator darkgrey'>{{ _(subject) }}</span> | |||
</div> | |||
<p id="feedback-result"></p> | |||
<p id="feedback-result">{{ _(message) }}</p> | |||
<div><a href='/' class='btn btn-primary btn-sm'>{{ _("Home") }}</a></div> | |||
</div> | |||
</div> | |||
{% endmacro %} | |||
{% block page_content %} | |||
{% if is_valid_request %} | |||
<div class="feedback"> | |||
<p class='lead' id="feedback-msg"></p> | |||
<div> | |||
{{ _("Your rating: ") }} | |||
<i class='fa fa-fw fa-star-o star-icon' data-idx=1></i> | |||
<i class='fa fa-fw fa-star-o star-icon' data-idx=2></i> | |||
<i class='fa fa-fw fa-star-o star-icon' data-idx=3></i> | |||
<i class='fa fa-fw fa-star-o star-icon' data-idx=4></i> | |||
<i class='fa fa-fw fa-star-o star-icon' data-idx=5></i> | |||
</div> | |||
<div style='max-width: 500px;'> | |||
<p>{{ _("Full Name") }}</p> | |||
<input class="form-control fullname" type="text" placeholder="Your Full Name"> | |||
<p>{{ _("Detailed feedback") }}</p> | |||
<textarea class='form-control feedback-text' style='min-height: 300px;'></textarea> | |||
</div> | |||
<p><button class='btn btn-primary btn-sm btn-submit'>{{ _("Submit") }}</button></p> | |||
{% if comment_list -%} | |||
<div class="comments"> | |||
<br><br> | |||
<h3>{{ _("Communication") }}</h3> | |||
{% include 'templates/includes/comments/comments.html' %} | |||
</div> | |||
{% endif %} | |||
</div> | |||
{{ feedback_result(is_valid_request, "Thank You") }} | |||
{% else %} | |||
{{ feedback_result(is_valid_request, "Invalid Input", error_message) }} | |||
{% endif %} | |||
<script> | |||
window.feedback = { | |||
@@ -7,8 +7,13 @@ def get_context(context): | |||
reference_doctype = frappe.form_dict.get("reference_doctype") | |||
reference_name = frappe.form_dict.get("reference_name") | |||
if not all([reference_name, reference_doctype]): | |||
return {} | |||
if not all([reference_name, reference_doctype]) or \ | |||
not frappe.db.get_value(reference_doctype, reference_name): | |||
return { | |||
"is_valid_request": False, | |||
"error_message": "Invalid reference doctype and reference name" | |||
} | |||
communications = frappe.get_all("Communication", filters={ | |||
"reference_doctype": reference_doctype, | |||
@@ -20,14 +25,17 @@ def get_context(context): | |||
"reference_doctype": reference_doctype, | |||
"reference_name": reference_name, | |||
"comment_list": communications, | |||
"is_communication": True | |||
"is_communication": True, | |||
"is_valid_request": True | |||
} | |||
@frappe.whitelist(allow_guest=True) | |||
def accept(key, sender, reference_doctype, reference_name, feedback, rating, fullname): | |||
""" save the feedback in communication """ | |||
if not reference_doctype and not reference_name: | |||
frappe.throw("Invalid Reference Doctype, Reference Name") | |||
if not reference_doctype and not reference_name or \ | |||
not frappe.db.get_value(reference_doctype, reference_name): | |||
frappe.throw("Invalid reference doctype and reference name") | |||
if not rating or not feedback: | |||
frappe.throw("Please give both Rating and Detailed Feedback") | |||