Merge branch 'develop'
This commit is contained in:
commit
eb6bd89ce0
28 changed files with 402 additions and 258 deletions
|
|
@ -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
|
||||
{% } %}
|
||||
</div>
|
||||
{% 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>
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue