Merge branch 'develop' of https://github.com/frappe/frappe into pref_global_search
This commit is contained in:
commit
f616a7c814
15 changed files with 722 additions and 891 deletions
50
cypress/integration/grid_pagination.js
Normal file
50
cypress/integration/grid_pagination.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
context('Grid Pagination', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.visit('/desk');
|
||||
});
|
||||
before(() => {
|
||||
cy.login();
|
||||
cy.visit('/desk');
|
||||
cy.window().its('frappe').then(frappe => {
|
||||
frappe.call("frappe.tests.ui_test_helpers.create_contact_phone_nos_records");
|
||||
});
|
||||
});
|
||||
it('creates pages for child table', () => {
|
||||
cy.visit('/desk#Form/Contact/Test Contact');
|
||||
cy.get('.frappe-control[data-fieldname="phone_nos"]').as('table');
|
||||
cy.get('@table').find('.current-page-number').should('contain', '1');
|
||||
cy.get('@table').find('.total-page-number').should('contain', '50');
|
||||
cy.get('@table').find('.grid-body .grid-row').should('have.length', 20);
|
||||
});
|
||||
it('goes to the next and previous page', () => {
|
||||
cy.visit('/desk#Form/Contact/Test Contact');
|
||||
cy.get('.frappe-control[data-fieldname="phone_nos"]').as('table');
|
||||
cy.get('@table').find('.next-page').click();
|
||||
cy.get('@table').find('.current-page-number').should('contain', '2');
|
||||
cy.get('@table').find('.grid-body .grid-row').first().should('have.attr', 'data-idx', '21');
|
||||
cy.get('@table').find('.prev-page').click();
|
||||
cy.get('@table').find('.current-page-number').should('contain', '1');
|
||||
cy.get('@table').find('.grid-body .grid-row').first().should('have.attr', 'data-idx', '1');
|
||||
});
|
||||
it('adds and deletes rows and changes page', ()=> {
|
||||
cy.visit('/desk#Form/Contact/Test Contact');
|
||||
cy.get('.frappe-control[data-fieldname="phone_nos"]').as('table');
|
||||
cy.get('@table').find('button.grid-add-row').click();
|
||||
cy.get('@table').find('.grid-body .row-index').should('contain', 1001);
|
||||
cy.get('@table').find('.current-page-number').should('contain', '51');
|
||||
cy.get('@table').find('.total-page-number').should('contain', '51');
|
||||
cy.get('@table').find('.grid-body .grid-row .grid-row-check').click({force: true});
|
||||
cy.get('@table').find('button.grid-remove-rows').click();
|
||||
cy.get('@table').find('.grid-body .row-index').last().should('contain', 1000);
|
||||
cy.get('@table').find('.current-page-number').should('contain', '50');
|
||||
cy.get('@table').find('.total-page-number').should('contain', '50');
|
||||
});
|
||||
it('deletes all rows', ()=> {
|
||||
cy.visit('/desk#Form/Contact/Test Contact');
|
||||
cy.get('.frappe-control[data-fieldname="phone_nos"]').as('table');
|
||||
cy.get('@table').find('.grid-heading-row .grid-row-check').click({force: true});
|
||||
cy.get('@table').find('button.grid-remove-all-rows').click();
|
||||
cy.get('@table').find('.grid-body .grid-row').should('have.length', 0);
|
||||
});
|
||||
});
|
||||
|
|
@ -36,13 +36,15 @@ def generate_and_cache_results(chart, chart_name, function, cache_key):
|
|||
|
||||
def get_from_date_from_timespan(to_date, timespan):
|
||||
days = months = years = 0
|
||||
if "Last Week" == timespan:
|
||||
if timespan == "Last Week":
|
||||
days = -7
|
||||
if "Last Month" == timespan:
|
||||
if timespan == "Last Month":
|
||||
months = -1
|
||||
elif "Last Quarter" == timespan:
|
||||
elif timespan == "Last Quarter":
|
||||
months = -3
|
||||
elif "Last Year" == timespan:
|
||||
elif timespan == "Last Year":
|
||||
years = -1
|
||||
elif timespan == "All Time":
|
||||
years = -50
|
||||
return add_to_date(to_date, years=years, months=months, days=days,
|
||||
as_datetime=True)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,15 @@
|
|||
|
||||
frappe.ui.form.on('Bulk Update', {
|
||||
refresh: function(frm) {
|
||||
frm.set_query("document_type", function() {
|
||||
return {
|
||||
filters: [
|
||||
['DocType', 'issingle', '=', 0],
|
||||
['DocType', 'name', 'not in', frappe.model.core_doctypes_list]
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
frm.page.set_primary_action(__('Update'), function() {
|
||||
if (!frm.doc.update_value) {
|
||||
frappe.throw(__('Field "value" is mandatory. Please specify value to be updated'));
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ frappe.ui.form.on('Dashboard Chart', {
|
|||
timespan: function(frm) {
|
||||
const time_interval_options = {
|
||||
"Select Date Range": ["Quarterly", "Monthly", "Weekly", "Daily"],
|
||||
"All Time": ["Yearly", "Monthly"],
|
||||
"Last Year": ["Quarterly", "Monthly", "Weekly", "Daily"],
|
||||
"Last Quarter": ["Monthly", "Weekly", "Daily"],
|
||||
"Last Month": ["Weekly", "Daily"],
|
||||
|
|
|
|||
|
|
@ -82,14 +82,14 @@
|
|||
"fieldname": "timespan",
|
||||
"fieldtype": "Select",
|
||||
"label": "Timespan",
|
||||
"options": "Last Year\nLast Quarter\nLast Month\nLast Week\nSelect Date Range"
|
||||
"options": "All Time\nLast Year\nLast Quarter\nLast Month\nLast Week\nSelect Date Range"
|
||||
},
|
||||
{
|
||||
"depends_on": "timeseries",
|
||||
"fieldname": "time_interval",
|
||||
"fieldtype": "Select",
|
||||
"label": "Time Interval",
|
||||
"options": "Quarterly\nMonthly\nWeekly\nDaily"
|
||||
"options": "Yearly\nQuarterly\nMonthly\nWeekly\nDaily"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
|
|
@ -187,7 +187,7 @@
|
|||
"label": "To Date"
|
||||
}
|
||||
],
|
||||
"modified": "2019-11-04 12:32:14.525409",
|
||||
"modified": "2019-11-18 16:20:11.529496",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Desk",
|
||||
"name": "Dashboard Chart",
|
||||
|
|
|
|||
|
|
@ -74,8 +74,7 @@ def get_chart_config(chart, filters, timespan, timegrain, from_date, to_date):
|
|||
result = convert_to_dates(data, timegrain)
|
||||
|
||||
# add missing data points for periods where there was no result
|
||||
result = add_missing_values(result, timegrain, from_date, to_date)
|
||||
|
||||
result = add_missing_values(result, timegrain, timespan, from_date, to_date)
|
||||
chart_config = {
|
||||
"labels": [formatdate(r[0].strftime('%Y-%m-%d')) for r in result],
|
||||
"datasets": [{
|
||||
|
|
@ -133,7 +132,9 @@ def get_aggregate_function(chart_type):
|
|||
"Average": "AVG",
|
||||
}[chart_type]
|
||||
|
||||
|
||||
def convert_to_dates(data, timegrain):
|
||||
""" Converts individual dates within data to the end of period """
|
||||
result = []
|
||||
for d in data:
|
||||
if timegrain == 'Daily':
|
||||
|
|
@ -141,10 +142,11 @@ def convert_to_dates(data, timegrain):
|
|||
elif timegrain == 'Weekly':
|
||||
result.append([add_to_date(add_to_date('{:d}-01-01'.format(int(d[0])), weeks = d[1] + 1), days = -1), d[2]])
|
||||
elif timegrain == 'Monthly':
|
||||
result.append([add_to_date(add_to_date('{:d}-01-01'.format(int(d[0])), months = d[1]), days = -1), d[2]])
|
||||
result.append([add_to_date(add_to_date('{:d}-01-01'.format(int(d[0])), months=d[1]), days = -1), d[2]])
|
||||
elif timegrain == 'Quarterly':
|
||||
result.append([add_to_date(add_to_date('{:d}-01-01'.format(int(d[0])), months = d[1] * 3), days = -1), d[2]])
|
||||
|
||||
result.append([add_to_date(add_to_date('{:d}-01-01'.format(int(d[0])), months=d[1] * 3), days = -1), d[2]])
|
||||
elif timegrain == 'Yearly':
|
||||
result.append([add_to_date(add_to_date('{:d}-01-01'.format(int(d[0])), months=12), days = -1), d[2]])
|
||||
result[-1][0] = getdate(result[-1][0])
|
||||
|
||||
return result
|
||||
|
|
@ -164,17 +166,17 @@ def get_unit_function(datefield, timegrain):
|
|||
|
||||
return unit_function
|
||||
|
||||
def add_missing_values(data, timegrain, from_date, to_date):
|
||||
def add_missing_values(data, timegrain, timespan, from_date, to_date):
|
||||
# add missing intervals
|
||||
result = []
|
||||
|
||||
first_expected_date = get_period_ending(from_date, timegrain)
|
||||
|
||||
# fill out data before the first data point
|
||||
first_data_point_date = data[0][0] if data else getdate(add_to_date(to_date, days=1))
|
||||
while first_data_point_date > first_expected_date:
|
||||
result.append([first_expected_date, 0.0])
|
||||
first_expected_date = get_next_expected_date(first_expected_date, timegrain)
|
||||
if timespan != 'All Time':
|
||||
first_expected_date = get_period_ending(from_date, timegrain)
|
||||
# fill out data before the first data point
|
||||
first_data_point_date = data[0][0] if data else getdate(add_to_date(to_date, days=1))
|
||||
while first_data_point_date > first_expected_date:
|
||||
result.append([first_expected_date, 0.0])
|
||||
first_expected_date = get_next_expected_date(first_expected_date, timegrain)
|
||||
|
||||
# fill data points and missing points
|
||||
for i, d in enumerate(data):
|
||||
|
|
@ -212,14 +214,16 @@ def get_next_expected_date(date, timegrain):
|
|||
|
||||
def get_period_ending(date, timegrain):
|
||||
date = getdate(date)
|
||||
if timegrain=='Daily':
|
||||
if timegrain == 'Daily':
|
||||
pass
|
||||
elif timegrain=='Weekly':
|
||||
elif timegrain == 'Weekly':
|
||||
date = get_week_ending(date)
|
||||
elif timegrain=='Monthly':
|
||||
elif timegrain == 'Monthly':
|
||||
date = get_month_ending(date)
|
||||
elif timegrain=='Quarterly':
|
||||
elif timegrain == 'Quarterly':
|
||||
date = get_quarter_ending(date)
|
||||
elif timegrain == 'Yearly':
|
||||
date = get_year_ending(date)
|
||||
|
||||
return getdate(date)
|
||||
|
||||
|
|
@ -231,7 +235,7 @@ def get_week_ending(date):
|
|||
# first day of next week
|
||||
date = add_to_date('{}-01-01'.format(date.year), weeks = week_of_the_year + 1)
|
||||
# last day of this week
|
||||
return add_to_date(date, days = -1)
|
||||
return add_to_date(date, days=-1)
|
||||
|
||||
def get_month_ending(date):
|
||||
month_of_the_year = int(date.strftime('%m'))
|
||||
|
|
@ -239,7 +243,7 @@ def get_month_ending(date):
|
|||
|
||||
date = add_to_date('{}-01-01'.format(date.year), months = month_of_the_year)
|
||||
# last day of this month
|
||||
return add_to_date(date, days = -1)
|
||||
return add_to_date(date, days=-1)
|
||||
|
||||
def get_quarter_ending(date):
|
||||
date = getdate(date)
|
||||
|
|
@ -255,8 +259,17 @@ def get_quarter_ending(date):
|
|||
|
||||
return date
|
||||
|
||||
def get_year_ending(date):
|
||||
''' returns year ending of the given date '''
|
||||
|
||||
# first day of next year (note year starts from 1)
|
||||
date = add_to_date('{}-01-01'.format(date.year), months = 12)
|
||||
# last day of this month
|
||||
return add_to_date(date, days=-1)
|
||||
|
||||
|
||||
class DashboardChart(Document):
|
||||
|
||||
def on_update(self):
|
||||
frappe.cache().delete_key('chart-data:{}'.format(self.name))
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ class TestDashboardChart(unittest.TestCase):
|
|||
self.assertEqual(get_period_ending('2019-10-01', 'Quarterly'),
|
||||
getdate('2019-12-31'))
|
||||
|
||||
self.assertEqual(get_period_ending('2019-10-01', 'Yearly'),
|
||||
getdate('2019-12-31'))
|
||||
|
||||
def test_dashboard_chart(self):
|
||||
if frappe.db.exists('Dashboard Chart', 'Test Dashboard Chart'):
|
||||
frappe.delete_doc('Dashboard Chart', 'Test Dashboard Chart')
|
||||
|
|
|
|||
|
|
@ -1,700 +1,183 @@
|
|||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2017-11-18 15:36:09.676722",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"allow_import": 1,
|
||||
"creation": "2017-11-18 15:36:09.676722",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"enable_social_login",
|
||||
"client_credentials",
|
||||
"social_login_provider",
|
||||
"client_id",
|
||||
"column_break_0",
|
||||
"provider_name",
|
||||
"client_secret",
|
||||
"sb_identity_details",
|
||||
"icon",
|
||||
"column_break_1",
|
||||
"base_url",
|
||||
"client_urls",
|
||||
"authorize_url",
|
||||
"access_token_url",
|
||||
"column_break_3",
|
||||
"redirect_url",
|
||||
"api_endpoint",
|
||||
"custom_base_url",
|
||||
"client_information",
|
||||
"api_endpoint_args",
|
||||
"auth_url_data",
|
||||
"user_id_property"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "enable_social_login",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Enable Social Login",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"default": "0",
|
||||
"fieldname": "enable_social_login",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable Social Login"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.enable_social_login",
|
||||
"columns": 0,
|
||||
"fieldname": "client_credentials",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Client Credentials",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.enable_social_login",
|
||||
"fieldname": "client_credentials",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Client Credentials"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Custom",
|
||||
"depends_on": "eval:doc.custom!=1",
|
||||
"fieldname": "social_login_provider",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Social Login Provider",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Custom\nFacebook\nFrappe\nGitHub\nGoogle\nOffice 365\nSalesforce\nfairlogin",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"unique": 0
|
||||
},
|
||||
"default": "Custom",
|
||||
"depends_on": "eval:doc.custom!=1",
|
||||
"fieldname": "social_login_provider",
|
||||
"fieldtype": "Select",
|
||||
"label": "Social Login Provider",
|
||||
"options": "Custom\nFacebook\nFrappe\nGitHub\nGoogle\nOffice 365\nSalesforce\nfairlogin",
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "client_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Client ID",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "client_id",
|
||||
"fieldtype": "Data",
|
||||
"label": "Client ID"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_0",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_0",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "provider_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Provider Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "provider_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Provider Name",
|
||||
"reqd": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "client_secret",
|
||||
"fieldtype": "Password",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Client Secret",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "client_secret",
|
||||
"fieldtype": "Password",
|
||||
"label": "Client Secret"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.custom_base_url",
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "sb_identity_details",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Identity Details",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.custom_base_url",
|
||||
"fieldname": "sb_identity_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Identity Details"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "icon",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Icon",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "icon",
|
||||
"fieldtype": "Data",
|
||||
"label": "Icon"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_1",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "base_url",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Base URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "base_url",
|
||||
"fieldtype": "Data",
|
||||
"label": "Base URL"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.social_login_provider===\"Custom\"",
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "client_urls",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Client URLs",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.social_login_provider===\"Custom\"",
|
||||
"fieldname": "client_urls",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Client URLs"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "authorize_url",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Authorize URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "authorize_url",
|
||||
"fieldtype": "Data",
|
||||
"label": "Authorize URL"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "access_token_url",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Access Token URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "access_token_url",
|
||||
"fieldtype": "Data",
|
||||
"label": "Access Token URL"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "redirect_url",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Redirect URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "redirect_url",
|
||||
"fieldtype": "Data",
|
||||
"label": "Redirect URL"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "api_endpoint",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "API Endpoint",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "api_endpoint",
|
||||
"fieldtype": "Data",
|
||||
"label": "API Endpoint"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "custom_base_url",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Custom Base URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"default": "0",
|
||||
"fieldname": "custom_base_url",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Custom Base URL"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.social_login_provider===\"Custom\"",
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "client_information",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Client Information",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.social_login_provider===\"Custom\"",
|
||||
"fieldname": "client_information",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Client Information"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "api_endpoint_args",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "API Endpoint Args",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "api_endpoint_args",
|
||||
"fieldtype": "Code",
|
||||
"label": "API Endpoint Args"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "auth_url_data",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Auth URL Data",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
"fieldname": "auth_url_data",
|
||||
"fieldtype": "Code",
|
||||
"label": "Auth URL Data"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.social_login_provider===\"Custom\"",
|
||||
"fieldname": "user_id_property",
|
||||
"fieldtype": "Data",
|
||||
"label": "User ID Property"
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-09-15 09:00:00.000000",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Integrations",
|
||||
"name": "Social Login Key",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"modified": "2019-12-03 12:35:55.115260",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Integrations",
|
||||
"name": "Social Login Key",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "provider_name",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "provider_name",
|
||||
"track_changes": 1
|
||||
}
|
||||
|
|
@ -80,8 +80,8 @@ def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reloa
|
|||
if not (for_reload or frappe.flags.in_migrate or frappe.flags.in_install or frappe.flags.in_test):
|
||||
try:
|
||||
delete_controllers(name, doc.module)
|
||||
except (FileNotFoundError, OSError):
|
||||
# in case a doctype doesnt have any controller code
|
||||
except (FileNotFoundError, OSError, KeyError):
|
||||
# in case a doctype doesnt have any controller code nor any app and module
|
||||
pass
|
||||
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -352,7 +352,11 @@ frappe.ui.form.Form = class FrappeForm {
|
|||
}
|
||||
}
|
||||
// reset visible columns, since column headings can change in different docs
|
||||
this.grids.forEach(grid_obj => grid_obj.grid.visible_columns = null);
|
||||
this.grids.forEach(grid_obj => {
|
||||
grid_obj.grid.visible_columns = null
|
||||
// reset page number to 1
|
||||
grid_obj.grid.grid_pagination.go_to_page(1);
|
||||
});
|
||||
frappe.ui.form.close_grid_form();
|
||||
this.docname = docname;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// MIT License. See license.txt
|
||||
|
||||
import GridRow from "./grid_row";
|
||||
import GridPagination from './grid_pagination';
|
||||
|
||||
frappe.ui.form.get_open_grid_form = function() {
|
||||
return $(".grid-row-open").data("grid_row");
|
||||
|
|
@ -47,8 +48,8 @@ export default class Grid {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
make() {
|
||||
var me = this;
|
||||
|
||||
let template = `<div class="form-group">
|
||||
<div class="clearfix">
|
||||
|
|
@ -63,25 +64,38 @@ export default class Grid {
|
|||
</div>
|
||||
<div class="small form-clickable-section grid-footer">
|
||||
<div class="row">
|
||||
<div class="col-sm-6 grid-buttons">
|
||||
<div class="col-sm-5 grid-buttons">
|
||||
<button type="reset"
|
||||
class="btn btn-xs btn-danger grid-remove-rows hidden"
|
||||
style="margin-right: 4px;">
|
||||
${__("Delete")}</button>
|
||||
style="margin-right: 4px;"
|
||||
data-action="delete_rows">
|
||||
${__("Delete")}
|
||||
</button>
|
||||
<button type="reset"
|
||||
class="btn btn-xs btn-danger grid-remove-all-rows hidden"
|
||||
style="margin-right: 4px;"
|
||||
data-action="delete_all_rows">
|
||||
${__("Delete All")}
|
||||
</button>
|
||||
<button type="reset"
|
||||
class="grid-add-multiple-rows btn btn-xs btn-default hidden"
|
||||
style="margin-right: 4px;">
|
||||
${__("Add Multiple")}</a>
|
||||
</button>
|
||||
<!-- hack to allow firefox include this in tabs -->
|
||||
<button type="reset" class="btn btn-xs btn-default grid-add-row">
|
||||
${__("Add Row")}</button>
|
||||
<button type="reset"
|
||||
class="btn btn-xs btn-default grid-add-row">
|
||||
${__("Add Row")}
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<div class="col-sm-4 grid-pagination">
|
||||
</div>
|
||||
<div class="col-sm-3 text-right">
|
||||
<a href="#" class="grid-download btn btn-xs btn-default hidden"
|
||||
style="margin-left: 10px;">
|
||||
style="margin-left: 4px;">
|
||||
${__("Download")}</a>
|
||||
<a href="#" class="grid-upload btn btn-xs btn-default hidden"
|
||||
style="margin-left: 10px;">
|
||||
style="margin-left: 4px;">
|
||||
${__("Upload")}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -90,20 +104,20 @@ export default class Grid {
|
|||
|
||||
this.wrapper = $(template)
|
||||
.appendTo(this.parent)
|
||||
.attr("data-fieldname", this.df.fieldname);
|
||||
.attr('data-fieldname', this.df.fieldname);
|
||||
|
||||
frappe.utils.bind_actions_with_object(this.wrapper, this);
|
||||
|
||||
this.form_grid = this.wrapper.find('.form-grid');
|
||||
|
||||
this.wrapper.find(".grid-add-row").click(function() {
|
||||
me.add_new_row(null, null, true);
|
||||
me.set_focus_on_row();
|
||||
this.setup_add_row();
|
||||
|
||||
return false;
|
||||
});
|
||||
this.setup_grid_pagination();
|
||||
|
||||
this.custom_buttons = {};
|
||||
this.grid_buttons = this.wrapper.find('.grid-buttons');
|
||||
this.remove_rows_button = this.grid_buttons.find('.grid-remove-rows')
|
||||
this.remove_rows_button = this.grid_buttons.find('.grid-remove-rows');
|
||||
this.remove_all_rows_button = this.grid_buttons.find('.grid-remove-all-rows');
|
||||
|
||||
this.setup_allow_bulk_edit();
|
||||
this.setup_check();
|
||||
|
|
@ -112,79 +126,118 @@ export default class Grid {
|
|||
}
|
||||
}
|
||||
|
||||
setup_check() {
|
||||
var me = this;
|
||||
setup_grid_pagination() {
|
||||
this.grid_pagination = new GridPagination({
|
||||
grid: this,
|
||||
wrapper: this.wrapper,
|
||||
});
|
||||
}
|
||||
|
||||
this.wrapper.on('click', '.grid-row-check', function(e) {
|
||||
var $check = $(this);
|
||||
if($check.parents('.grid-heading-row:first').length!==0) {
|
||||
setup_check() {
|
||||
|
||||
this.wrapper.on('click', '.grid-row-check', (e) => {
|
||||
var $check = $(e.currentTarget);
|
||||
if ($check.parents('.grid-heading-row:first').length !== 0) {
|
||||
// select all?
|
||||
var checked = $check.prop('checked');
|
||||
$check.parents('.form-grid:first')
|
||||
.find('.grid-row-check').prop('checked', checked);
|
||||
|
||||
// set all
|
||||
(me.grid_rows || []).forEach(function(row) { row.doc.__checked = checked ? 1 : 0; });
|
||||
let result_length = this.grid_pagination.get_result_length();
|
||||
let page_index = this.grid_pagination.page_index;
|
||||
let page_length = this.grid_pagination.page_length;
|
||||
for (var ri = (page_index-1)*page_length; ri < result_length; ri++) {
|
||||
this.grid_rows[ri].doc.__checked = checked ? 1: 0;
|
||||
}
|
||||
} else {
|
||||
var docname = $check.parents('.grid-row:first').attr('data-name');
|
||||
me.grid_rows_by_docname[docname].select($check.prop('checked'));
|
||||
this.grid_rows_by_docname[docname].select($check.prop('checked'));
|
||||
}
|
||||
me.refresh_remove_rows_button();
|
||||
this.refresh_remove_rows_button();
|
||||
});
|
||||
|
||||
this.remove_rows_button.on('click', function() {
|
||||
var dirty = false;
|
||||
|
||||
let tasks = [];
|
||||
me.get_selected_children().forEach((doc) => {
|
||||
tasks.push(() => {
|
||||
if (!me.frm) {
|
||||
me.df.data = me.get_data();
|
||||
me.df.data = me.df.data.filter((row)=> row.idx != doc.idx);
|
||||
}
|
||||
me.grid_rows_by_docname[doc.name].remove();
|
||||
dirty = true;
|
||||
});
|
||||
tasks.push(() => frappe.timeout(0.1));
|
||||
});
|
||||
|
||||
if (!me.frm) {
|
||||
tasks.push(() => {
|
||||
// reorder idx of df.data
|
||||
me.df.data.forEach((row, index) => row.idx = index + 1);
|
||||
});
|
||||
}
|
||||
|
||||
tasks.push(() => {
|
||||
if (dirty) me.refresh();
|
||||
});
|
||||
|
||||
frappe.run_serially(tasks);
|
||||
});
|
||||
}
|
||||
|
||||
delete_rows() {
|
||||
var dirty = false;
|
||||
|
||||
let tasks = [];
|
||||
let selected_children = this.get_selected_children();
|
||||
selected_children.forEach(doc => {
|
||||
tasks.push(() => {
|
||||
if (!this.frm) {
|
||||
this.df.data = this.get_data();
|
||||
this.df.data = this.df.data.filter(row => row.idx != doc.idx);
|
||||
}
|
||||
this.grid_rows_by_docname[doc.name].remove();
|
||||
dirty = true;
|
||||
});
|
||||
tasks.push(() => frappe.timeout(0.1));
|
||||
});
|
||||
|
||||
if (!this.frm) {
|
||||
tasks.push(() => {
|
||||
// reorder idx of df.data
|
||||
this.df.data.forEach((row, index) => row.idx = index + 1);
|
||||
});
|
||||
}
|
||||
|
||||
tasks.push(() => {
|
||||
if (dirty) this.refresh();
|
||||
});
|
||||
|
||||
frappe.run_serially(tasks);
|
||||
|
||||
if (selected_children.length == this.grid_pagination.page_length) {
|
||||
frappe.utils.scroll_to(this.wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
delete_all_rows() {
|
||||
this.frm.doc[this.df.fieldname] = [];
|
||||
$(this.parent).find('.rows').empty();
|
||||
this.grid_rows = [];
|
||||
this.refresh();
|
||||
frappe.utils.scroll_to(this.wrapper);
|
||||
}
|
||||
|
||||
select_row(name) {
|
||||
this.grid_rows_by_docname[name].select();
|
||||
}
|
||||
|
||||
remove_all() {
|
||||
this.grid_rows.forEach(row => {
|
||||
row.remove();
|
||||
});
|
||||
}
|
||||
|
||||
refresh_remove_rows_button() {
|
||||
this.remove_rows_button.toggleClass('hidden',
|
||||
this.wrapper.find('.grid-body .grid-row-check:checked:first').length ? false : true);
|
||||
this.remove_all_rows_button.toggleClass('hidden',
|
||||
this.wrapper.find('.grid-body .grid-row-check:checked:first').length ? false : true);
|
||||
}
|
||||
|
||||
get_selected() {
|
||||
return (this.grid_rows || []).map(function(row) { return row.doc.__checked ? row.doc.name : null; })
|
||||
.filter(function(d) { return d; });
|
||||
return (this.grid_rows || []).map(row => {
|
||||
return row.doc.__checked ? row.doc.name : null;
|
||||
}).filter(d => {
|
||||
return d;
|
||||
});
|
||||
}
|
||||
|
||||
get_selected_children() {
|
||||
return (this.grid_rows || []).map(function(row) { return row.doc.__checked ? row.doc : null; })
|
||||
.filter(function(d) { return d; });
|
||||
return (this.grid_rows || []).map(row => {
|
||||
return row.doc.__checked ? row.doc : null;
|
||||
}).filter(d => {
|
||||
return d;
|
||||
});
|
||||
}
|
||||
|
||||
make_head() {
|
||||
// labels
|
||||
if(!this.header_row) {
|
||||
if (!this.header_row) {
|
||||
this.header_row = new GridRow({
|
||||
parent: $(this.parent).find(".grid-heading-row"),
|
||||
parent_df: this.df,
|
||||
|
|
@ -194,15 +247,16 @@ export default class Grid {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
refresh(force) {
|
||||
this.data = this.get_data();
|
||||
|
||||
!this.wrapper && this.make();
|
||||
var me = this,
|
||||
$rows = $(me.parent).find(".rows"),
|
||||
data = this.get_data();
|
||||
let $rows = $(this.parent).find('.rows');
|
||||
|
||||
this.setup_fields();
|
||||
|
||||
if(this.frm) {
|
||||
if (this.frm) {
|
||||
this.display_status = frappe.perm.get_field_display_status(this.df, this.frm.doc,
|
||||
this.perm);
|
||||
} else {
|
||||
|
|
@ -213,24 +267,57 @@ export default class Grid {
|
|||
if(this.display_status === "None") return;
|
||||
|
||||
// redraw
|
||||
var _scroll_y = $(document).scrollTop();
|
||||
this.make_head();
|
||||
|
||||
if(!this.grid_rows) {
|
||||
if (!this.grid_rows) {
|
||||
this.grid_rows = [];
|
||||
}
|
||||
|
||||
this.truncate_rows(data);
|
||||
this.truncate_rows();
|
||||
this.grid_rows_by_docname = {};
|
||||
|
||||
for(var ri=0; ri < data.length; ri++) {
|
||||
var d = data[ri];
|
||||
this.grid_pagination.update_page_numbers();
|
||||
this.render_result_rows($rows, false);
|
||||
this.grid_pagination.check_page_number();
|
||||
this.wrapper.find('.grid-empty').toggleClass('hidden', Boolean(this.data.length));
|
||||
|
||||
if(d.idx===undefined) {
|
||||
// toolbar
|
||||
this.setup_toolbar();
|
||||
this.toggle_checkboxes(this.display_status !== 'Read');
|
||||
|
||||
// sortable
|
||||
if (this.frm && this.is_sortable() && !this.sortable_setup_done) {
|
||||
this.make_sortable($rows);
|
||||
this.sortable_setup_done = true;
|
||||
}
|
||||
|
||||
this.last_display_status = this.display_status;
|
||||
this.last_docname = this.frm && this.frm.docname;
|
||||
|
||||
// red if mandatory
|
||||
this.form_grid.toggleClass('error', !!(this.df.reqd && !(this.data && this.data.length)));
|
||||
|
||||
this.refresh_remove_rows_button();
|
||||
|
||||
this.wrapper.trigger('change');
|
||||
}
|
||||
|
||||
|
||||
render_result_rows($rows, append_row) {
|
||||
|
||||
let result_length = this.grid_pagination.get_result_length();
|
||||
let page_index = this.grid_pagination.page_index;
|
||||
let page_length = this.grid_pagination.page_length;
|
||||
|
||||
for (var ri = (page_index-1)*page_length; ri < result_length; ri++) {
|
||||
var d = this.data[ri];
|
||||
if (!d) {
|
||||
return;
|
||||
}
|
||||
if (d.idx===undefined) {
|
||||
d.idx = ri + 1;
|
||||
}
|
||||
|
||||
if(this.grid_rows[ri]) {
|
||||
if (this.grid_rows[ri] && !append_row) {
|
||||
var grid_row = this.grid_rows[ri];
|
||||
grid_row.doc = d;
|
||||
grid_row.refresh();
|
||||
|
|
@ -243,71 +330,49 @@ export default class Grid {
|
|||
frm: this.frm,
|
||||
grid: this
|
||||
});
|
||||
this.grid_rows.push(grid_row);
|
||||
this.grid_rows[ri] = grid_row;
|
||||
}
|
||||
|
||||
this.grid_rows_by_docname[d.name] = grid_row;
|
||||
}
|
||||
|
||||
this.wrapper.find(".grid-empty").toggleClass("hidden", Boolean(data.length));
|
||||
|
||||
// toolbar
|
||||
this.setup_toolbar();
|
||||
this.toggle_checkboxes(this.display_status !== 'Read');
|
||||
|
||||
// sortable
|
||||
if(this.frm && this.is_sortable() && !this.sortable_setup_done) {
|
||||
this.make_sortable($rows);
|
||||
this.sortable_setup_done = true;
|
||||
}
|
||||
|
||||
this.last_display_status = this.display_status;
|
||||
this.last_docname = this.frm && this.frm.docname;
|
||||
|
||||
// frappe.utils.scroll_to(_scroll_y);
|
||||
|
||||
// red if mandatory
|
||||
this.form_grid.toggleClass('error', !!(this.df.reqd && !(data && data.length)));
|
||||
|
||||
this.refresh_remove_rows_button();
|
||||
|
||||
this.wrapper.trigger('change');
|
||||
}
|
||||
|
||||
setup_toolbar() {
|
||||
if(this.is_editable()) {
|
||||
this.wrapper.find(".grid-footer").toggle(true);
|
||||
|
||||
if (this.is_editable()) {
|
||||
this.wrapper.find('.grid-footer').toggle(true);
|
||||
|
||||
// show, hide buttons to add rows
|
||||
if(this.cannot_add_rows || (this.df && this.df.cannot_add_rows)) {
|
||||
if (this.cannot_add_rows || (this.df && this.df.cannot_add_rows)) {
|
||||
// add 'hidden' to buttons
|
||||
this.wrapper.find(".grid-add-row, .grid-add-multiple-rows")
|
||||
this.wrapper.find('.grid-add-row, .grid-add-multiple-rows')
|
||||
.addClass('hidden');
|
||||
} else {
|
||||
// show buttons
|
||||
this.wrapper.find(".grid-add-row").removeClass('hidden');
|
||||
this.wrapper.find('.grid-add-row').removeClass('hidden');
|
||||
|
||||
if(this.multiple_set) {
|
||||
this.wrapper.find(".grid-add-multiple-rows").removeClass('hidden');
|
||||
if (this.multiple_set) {
|
||||
this.wrapper.find('.grid-add-multiple-rows').removeClass('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
this.wrapper.find(".grid-footer").toggle(false);
|
||||
} else if (this.grid_rows.length < this.grid_pagination.page_length ) {
|
||||
this.wrapper.find('.grid-footer').toggle(false);
|
||||
}
|
||||
|
||||
}
|
||||
truncate_rows(data) {
|
||||
if(this.grid_rows.length > data.length) {
|
||||
|
||||
truncate_rows() {
|
||||
if (this.grid_rows.length > this.data.length) {
|
||||
// remove extra rows
|
||||
for(var i=data.length; i < this.grid_rows.length; i++) {
|
||||
for (var i=this.data.length; i < this.grid_rows.length; i++) {
|
||||
var grid_row = this.grid_rows[i];
|
||||
grid_row.wrapper.remove();
|
||||
}
|
||||
this.grid_rows.splice(data.length);
|
||||
this.grid_rows.splice(this.data.length);
|
||||
}
|
||||
}
|
||||
|
||||
setup_fields() {
|
||||
var me = this;
|
||||
// reset docfield
|
||||
if (this.frm && this.frm.docname) {
|
||||
// use doc specific docfield object
|
||||
|
|
@ -320,21 +385,23 @@ export default class Grid {
|
|||
}
|
||||
}
|
||||
|
||||
if(this.doctype && this.frm) {
|
||||
if (this.doctype && this.frm) {
|
||||
this.docfields = frappe.meta.get_docfields(this.doctype, this.frm.docname);
|
||||
} else {
|
||||
// fields given in docfield
|
||||
this.docfields = this.df.fields;
|
||||
}
|
||||
|
||||
this.docfields.forEach(function(df) {
|
||||
me.fields_map[df.fieldname] = df;
|
||||
this.docfields.forEach(df => {
|
||||
this.fields_map[df.fieldname] = df;
|
||||
});
|
||||
}
|
||||
|
||||
refresh_row(docname) {
|
||||
this.grid_rows_by_docname[docname] &&
|
||||
this.grid_rows_by_docname[docname].refresh();
|
||||
}
|
||||
|
||||
make_sortable($rows) {
|
||||
new Sortable($rows.get(0), {
|
||||
group: {name: this.df.fieldname},
|
||||
|
|
@ -349,14 +416,14 @@ export default class Grid {
|
|||
}
|
||||
// prevent drag behaviour if _sortable property is "false"
|
||||
let idx = $(event.dragged).closest('.grid-row').attr('data-idx');
|
||||
let doc = this.get_data()[idx - 1];
|
||||
let doc = this.data[idx%this.grid_pagination.page_length];
|
||||
if (doc && doc._sortable === false) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
onUpdate: (event) => {
|
||||
let idx = $(event.item).closest('.grid-row').attr('data-idx');
|
||||
let doc = this.get_data()[idx - 1];
|
||||
let doc = this.data[idx%this.grid_pagination.page_length];
|
||||
this.renumber_based_on_dom();
|
||||
this.frm.script_manager.trigger(this.df.fieldname + "_move", this.df.options, doc.name);
|
||||
this.refresh();
|
||||
|
|
@ -366,13 +433,15 @@ export default class Grid {
|
|||
|
||||
$(this.frm.wrapper).trigger("grid-make-sortable", [this.frm]);
|
||||
}
|
||||
|
||||
get_data() {
|
||||
var data = this.frm ?
|
||||
this.frm.doc[this.df.fieldname] || []
|
||||
: this.df.data || this.get_modal_data();
|
||||
data.sort(function(a, b) { return a.idx - b.idx});
|
||||
// data.sort(function(a, b) { return a.idx - b.idx});
|
||||
return data;
|
||||
}
|
||||
|
||||
get_modal_data() {
|
||||
return this.df.get_data() ? this.df.get_data().filter(data => {
|
||||
if (!this.deleted_docs || !in_list(this.deleted_docs, data.name)) {
|
||||
|
|
@ -380,12 +449,12 @@ export default class Grid {
|
|||
}
|
||||
}) : [];
|
||||
}
|
||||
|
||||
set_column_disp(fieldname, show) {
|
||||
if($.isArray(fieldname)) {
|
||||
var me = this;
|
||||
for(var i=0, l=fieldname.length; i<l; i++) {
|
||||
var fname = fieldname[i];
|
||||
me.get_docfield(fname).hidden = show ? 0 : 1;
|
||||
this.get_docfield(fname).hidden = show ? 0 : 1;
|
||||
this.set_editable_grid_column_disp(fname, show);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -395,11 +464,12 @@ export default class Grid {
|
|||
|
||||
this.refresh(true);
|
||||
}
|
||||
|
||||
set_editable_grid_column_disp(fieldname, show) {
|
||||
//Hide columns for editable grids
|
||||
if (this.meta.editable_grid && this.grid_rows) {
|
||||
this.grid_rows.forEach(function(row) {
|
||||
row.columns_list.forEach(function(column) {
|
||||
this.grid_rows.forEach( row => {
|
||||
row.columns_list.forEach( column => {
|
||||
//Hide the column specified
|
||||
if (column.df.fieldname == fieldname) {
|
||||
if (show) {
|
||||
|
|
@ -433,27 +503,33 @@ export default class Grid {
|
|||
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
toggle_reqd(fieldname, reqd) {
|
||||
this.get_docfield(fieldname).reqd = reqd;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
toggle_enable(fieldname, enable) {
|
||||
this.get_docfield(fieldname).read_only = enable ? 0 : 1;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
toggle_display(fieldname, show) {
|
||||
this.get_docfield(fieldname).hidden = show ? 0 : 1;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
toggle_checkboxes(enable) {
|
||||
this.wrapper.find(".grid-row-check").prop('disabled', !enable)
|
||||
}
|
||||
|
||||
get_docfield(fieldname) {
|
||||
return frappe.meta.get_docfield(this.doctype, fieldname, this.frm ? this.frm.docname : null);
|
||||
}
|
||||
|
||||
get_row(key) {
|
||||
if(typeof key == 'number') {
|
||||
if(key < 0) {
|
||||
if (typeof key == 'number') {
|
||||
if (key < 0) {
|
||||
return this.grid_rows[this.grid_rows.length + key];
|
||||
} else {
|
||||
return this.grid_rows[key];
|
||||
|
|
@ -462,9 +538,11 @@ export default class Grid {
|
|||
return this.grid_rows_by_docname[key];
|
||||
}
|
||||
}
|
||||
|
||||
get_grid_row(key) {
|
||||
return this.get_row(key);
|
||||
}
|
||||
|
||||
get_field(fieldname) {
|
||||
// Note: workaround for get_query
|
||||
if(!this.fieldinfo[fieldname])
|
||||
|
|
@ -472,16 +550,30 @@ export default class Grid {
|
|||
}
|
||||
return this.fieldinfo[fieldname];
|
||||
}
|
||||
|
||||
set_value(fieldname, value, doc) {
|
||||
if(this.display_status!=="None" && this.grid_rows_by_docname[doc.name]) {
|
||||
this.grid_rows_by_docname[doc.name].refresh_field(fieldname, value);
|
||||
}
|
||||
}
|
||||
add_new_row(idx, callback, show, copy_doc) {
|
||||
if(this.is_editable()) {
|
||||
if(this.frm) {
|
||||
|
||||
setup_add_row() {
|
||||
this.wrapper.find(".grid-add-row").click(() => {
|
||||
this.add_new_row(null, null, true, null, true);
|
||||
this.set_focus_on_row();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
add_new_row(idx, callback, show, copy_doc, go_to_last_page=false) {
|
||||
if (this.is_editable()) {
|
||||
if (go_to_last_page) {
|
||||
this.grid_pagination.go_to_last_page_to_add_row();
|
||||
}
|
||||
if (this.frm) {
|
||||
var d = frappe.model.add_child(this.frm.doc, this.df.options, this.df.fieldname, idx);
|
||||
if(copy_doc) {
|
||||
if (copy_doc) {
|
||||
d = this.duplicate_row(d, copy_doc);
|
||||
}
|
||||
d.__unedited = true;
|
||||
|
|
@ -495,13 +587,13 @@ export default class Grid {
|
|||
this.refresh();
|
||||
}
|
||||
|
||||
if(show) {
|
||||
if(idx) {
|
||||
if (show) {
|
||||
if (idx) {
|
||||
// always open inserted rows
|
||||
this.wrapper.find("[data-idx='"+idx+"']").data("grid_row")
|
||||
.toggle_view(true, callback);
|
||||
} else {
|
||||
if(!this.allow_on_grid_editing()) {
|
||||
if (!this.allow_on_grid_editing()) {
|
||||
// open last row only if on-grid-editing is disabled
|
||||
this.wrapper.find(".grid-row:last").data("grid_row")
|
||||
.toggle_view(true, callback);
|
||||
|
|
@ -515,21 +607,18 @@ export default class Grid {
|
|||
|
||||
renumber_based_on_dom() {
|
||||
// renumber based on dom
|
||||
let me = this;
|
||||
let $rows = $(me.parent).find(".rows");
|
||||
|
||||
me.grid_rows = [];
|
||||
me.frm.doc[me.df.fieldname] = [];
|
||||
|
||||
$rows.find(".grid-row").each(function(i, item) {
|
||||
let $rows = $(this.parent).find(".rows");
|
||||
|
||||
$rows.find(".grid-row").each( (i, item) => {
|
||||
let $item = $(item);
|
||||
let d = locals[me.doctype][$item.attr('data-name')];
|
||||
d.idx = i + 1;
|
||||
let index = (this.grid_pagination.page_index-1)*this.grid_pagination.page_length+i;
|
||||
let d = locals[this.doctype][$item.attr('data-name')];
|
||||
d.idx = index + 1;
|
||||
$item.attr('data-idx', d.idx);
|
||||
|
||||
me.frm.doc[me.df.fieldname].push(d);
|
||||
me.grid_rows.push(me.grid_rows_by_docname[d.name]);
|
||||
this.frm.doc[this.df.fieldname][index] = (d);
|
||||
this.data[index] = d;
|
||||
this.grid_rows[index]=(this.grid_rows_by_docname[d.name]);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -545,12 +634,11 @@ export default class Grid {
|
|||
}
|
||||
|
||||
set_focus_on_row(idx) {
|
||||
var me = this;
|
||||
if(!idx) {
|
||||
idx = me.grid_rows.length - 1;
|
||||
idx = this.grid_rows.length - 1;
|
||||
}
|
||||
setTimeout(function() {
|
||||
me.grid_rows[idx].row
|
||||
setTimeout(() => {
|
||||
this.grid_rows[idx].row
|
||||
.find('input[type="Text"],textarea,select').filter(':visible:first').focus();
|
||||
}, 100);
|
||||
}
|
||||
|
|
@ -563,23 +651,22 @@ export default class Grid {
|
|||
|
||||
this.visible_columns = [];
|
||||
|
||||
for(var ci in fields) {
|
||||
for (var ci in fields) {
|
||||
var _df = fields[ci];
|
||||
|
||||
// get docfield if from fieldname
|
||||
df = this.fields_map[_df.fieldname];
|
||||
|
||||
if(!df.hidden
|
||||
if (!df.hidden
|
||||
&& (this.editable_fields || df.in_list_view)
|
||||
&& (this.frm && this.frm.get_perm(df.permlevel, "read") || !this.frm)
|
||||
&& !in_list(frappe.model.layout_fields, df.fieldtype)) {
|
||||
|
||||
if(df.columns) {
|
||||
if (df.columns) {
|
||||
df.colsize=df.columns;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
var colsize = 2;
|
||||
switch(df.fieldtype) {
|
||||
switch (df.fieldtype) {
|
||||
case "Text":
|
||||
case "Small Text": colsize = 3; break;
|
||||
case "Check": colsize = 1;
|
||||
|
|
@ -596,7 +683,7 @@ export default class Grid {
|
|||
}
|
||||
|
||||
total_colsize += df.colsize;
|
||||
if(total_colsize > 11)
|
||||
if (total_colsize > 11)
|
||||
return false;
|
||||
this.visible_columns.push([df, df.colsize]);
|
||||
}
|
||||
|
|
@ -604,11 +691,11 @@ export default class Grid {
|
|||
|
||||
// redistribute if total-col size is less than 12
|
||||
var passes = 0;
|
||||
while(total_colsize < 11 && passes < 12) {
|
||||
for(var i in this.visible_columns) {
|
||||
while (total_colsize < 11 && passes < 12) {
|
||||
for (var i in this.visible_columns) {
|
||||
var df = this.visible_columns[i][0];
|
||||
var colsize = this.visible_columns[i][1];
|
||||
if(colsize > 1 && colsize < 11
|
||||
if (colsize > 1 && colsize < 11
|
||||
&& !in_list(frappe.model.std_fields_list, df.fieldname)) {
|
||||
|
||||
if (passes < 3 && ["Int", "Currency", "Float", "Check", "Percent"].indexOf(df.fieldtype)!==-1) {
|
||||
|
|
@ -620,7 +707,7 @@ export default class Grid {
|
|||
total_colsize++;
|
||||
}
|
||||
|
||||
if(total_colsize > 10)
|
||||
if (total_colsize > 10)
|
||||
break;
|
||||
}
|
||||
passes++;
|
||||
|
|
@ -631,18 +718,21 @@ export default class Grid {
|
|||
is_editable() {
|
||||
return this.display_status=="Write" && !this.static_rows;
|
||||
}
|
||||
|
||||
is_sortable() {
|
||||
return this.sortable_status || this.is_editable();
|
||||
}
|
||||
|
||||
only_sortable(status) {
|
||||
if(status===undefined ? true : status) {
|
||||
if (status===undefined ? true : status) {
|
||||
this.sortable_status = true;
|
||||
this.static_rows = true;
|
||||
}
|
||||
}
|
||||
|
||||
set_multiple_add(link, qty) {
|
||||
if(this.multiple_set) return;
|
||||
var me = this;
|
||||
if (this.multiple_set) return;
|
||||
|
||||
var link_field = frappe.meta.get_docfield(this.df.options, link);
|
||||
var btn = $(this.wrapper).find(".grid-add-multiple-rows");
|
||||
|
||||
|
|
@ -650,27 +740,28 @@ export default class Grid {
|
|||
btn.removeClass('hidden');
|
||||
|
||||
// open link selector on click
|
||||
btn.on("click", function() {
|
||||
btn.on("click", () => {
|
||||
new frappe.ui.form.LinkSelector({
|
||||
doctype: link_field.options,
|
||||
fieldname: link,
|
||||
qty_fieldname: qty,
|
||||
target: me,
|
||||
target: this,
|
||||
txt: ""
|
||||
});
|
||||
this.grid_pagination.go_to_last_page_to_add_row();
|
||||
return false;
|
||||
});
|
||||
this.multiple_set = true;
|
||||
}
|
||||
|
||||
setup_allow_bulk_edit() {
|
||||
var me = this;
|
||||
if(this.frm && this.frm.get_docfield(this.df.fieldname).allow_bulk_edit) {
|
||||
if (this.frm && this.frm.get_docfield(this.df.fieldname).allow_bulk_edit) {
|
||||
// download
|
||||
me.setup_download();
|
||||
this.setup_download();
|
||||
|
||||
// upload
|
||||
frappe.flags.no_socketio = true;
|
||||
$(this.wrapper).find(".grid-upload").removeClass('hidden').on("click", function() {
|
||||
$(this.wrapper).find(".grid-upload").removeClass('hidden').on("click", () => {
|
||||
new frappe.ui.FileUploader({
|
||||
as_dataurl: true,
|
||||
allow_multiple: false,
|
||||
|
|
@ -679,29 +770,29 @@ export default class Grid {
|
|||
// row #2 contains fieldnames;
|
||||
var fieldnames = data[2];
|
||||
|
||||
me.frm.clear_table(me.df.fieldname);
|
||||
$.each(data, function(i, row) {
|
||||
if(i > 6) {
|
||||
this.frm.clear_table(this.df.fieldname);
|
||||
$.each(data, (i, row) => {
|
||||
if (i > 6) {
|
||||
var blank_row = true;
|
||||
$.each(row, function(ci, value) {
|
||||
if(value) {
|
||||
if (value) {
|
||||
blank_row = false;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if(!blank_row) {
|
||||
var d = me.frm.add_child(me.df.fieldname);
|
||||
$.each(row, function(ci, value) {
|
||||
if (!blank_row) {
|
||||
var d = this.frm.add_child(this.df.fieldname);
|
||||
$.each(row, (ci, value) => {
|
||||
var fieldname = fieldnames[ci];
|
||||
var df = frappe.meta.get_docfield(me.df.options, fieldname);
|
||||
var df = frappe.meta.get_docfield(this.df.options, fieldname);
|
||||
|
||||
// convert date formatting
|
||||
if(df.fieldtype==="Date" && value) {
|
||||
if (df.fieldtype==="Date" && value) {
|
||||
value = frappe.datetime.user_to_str(value);
|
||||
}
|
||||
|
||||
if(df.fieldtype==="Int" || df.fieldtype==="Check") {
|
||||
if (df.fieldtype==="Int" || df.fieldtype==="Check") {
|
||||
value = cint(value);
|
||||
}
|
||||
|
||||
|
|
@ -711,18 +802,18 @@ export default class Grid {
|
|||
}
|
||||
});
|
||||
|
||||
me.frm.refresh_field(me.df.fieldname);
|
||||
frappe.msgprint({message:__('Table updated'), title:__('Success'), indicator:'green'})
|
||||
this.frm.refresh_field(this.df.fieldname);
|
||||
frappe.msgprint({message: __('Table updated'), title: __('Success'), indicator: 'green'});
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setup_download() {
|
||||
var me = this;
|
||||
let title = me.df.label || frappe.model.unscrub(me.df.fieldname);
|
||||
$(this.wrapper).find(".grid-download").removeClass('hidden').on("click", function() {
|
||||
let title = this.df.label || frappe.model.unscrub(this.df.fieldname);
|
||||
$(this.wrapper).find(".grid-download").removeClass('hidden').on("click", () => {
|
||||
var data = [];
|
||||
var docfields = [];
|
||||
data.push([__("Bulk Edit {0}", [title])]);
|
||||
|
|
@ -732,9 +823,9 @@ export default class Grid {
|
|||
data.push([__("The CSV format is case sensitive")]);
|
||||
data.push([__("Do not edit headers which are preset in the template")]);
|
||||
data.push(["------"]);
|
||||
$.each(frappe.get_meta(me.df.options).fields, function(i, df) {
|
||||
$.each(frappe.get_meta(this.df.options).fields, (i, df) => {
|
||||
// don't include the read-only field in the template
|
||||
if(frappe.model.is_value_type(df.fieldtype)) {
|
||||
if (frappe.model.is_value_type(df.fieldtype)) {
|
||||
data[1].push(df.label);
|
||||
data[2].push(df.fieldname);
|
||||
let description = (df.description || "") + ' ';
|
||||
|
|
@ -747,13 +838,13 @@ export default class Grid {
|
|||
});
|
||||
|
||||
// add data
|
||||
$.each(me.frm.doc[me.df.fieldname] || [], function(i, d) {
|
||||
$.each(this.frm.doc[this.df.fieldname] || [], (i, d) => {
|
||||
var row = [];
|
||||
$.each(data[2], function(i, fieldname) {
|
||||
$.each(data[2], (i, fieldname) => {
|
||||
var value = d[fieldname];
|
||||
|
||||
// format date
|
||||
if(docfields[i].fieldtype==="Date" && value) {
|
||||
if (docfields[i].fieldtype==="Date" && value) {
|
||||
value = frappe.datetime.str_to_user(value);
|
||||
}
|
||||
|
||||
|
|
@ -766,10 +857,11 @@ export default class Grid {
|
|||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
add_custom_button(label, click) {
|
||||
// add / unhide a custom button
|
||||
var btn = this.custom_buttons[label];
|
||||
if(!btn) {
|
||||
if (!btn) {
|
||||
btn = $('<button class="btn btn-default btn-xs btn-custom">' + label + '</button>')
|
||||
.css('margin-right', '4px')
|
||||
.prependTo(this.grid_buttons)
|
||||
|
|
@ -779,6 +871,7 @@ export default class Grid {
|
|||
btn.removeClass('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
clear_custom_buttons() {
|
||||
// hide all custom buttons
|
||||
this.grid_buttons.find('.btn-custom').addClass('hidden');
|
||||
|
|
|
|||
132
frappe/public/js/frappe/form/grid_pagination.js
Normal file
132
frappe/public/js/frappe/form/grid_pagination.js
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
export default class GridPagination {
|
||||
|
||||
constructor(opts) {
|
||||
$.extend(this, opts);
|
||||
this.setup_pagination();
|
||||
}
|
||||
|
||||
setup_pagination() {
|
||||
this.page_length = 20;
|
||||
this.page_index = 1;
|
||||
this.total_pages = Math.ceil(this.grid.data.length/this.page_length);
|
||||
|
||||
this.render_pagination();
|
||||
}
|
||||
|
||||
render_pagination() {
|
||||
if (this.grid.data.length <= this.page_length) {
|
||||
this.wrapper.find('.grid-pagination').html('');
|
||||
} else {
|
||||
let $pagination_template = this.get_pagination_html();
|
||||
this.wrapper.find('.grid-pagination').html($pagination_template);
|
||||
this.prev_page_button = this.wrapper.find('.prev-page');
|
||||
this.next_page_button = this.wrapper.find('.next-page');
|
||||
this.$page_number = this.wrapper.find('.current-page-number');
|
||||
this.$total_pages = this.wrapper.find('.total-page-number');
|
||||
this.first_page_button = this.wrapper.find('.first-page');
|
||||
this.last_page_button = this.wrapper.find('.last-page');
|
||||
|
||||
this.bind_pagination_events();
|
||||
}
|
||||
}
|
||||
|
||||
bind_pagination_events() {
|
||||
this.prev_page_button.on('click', () => {
|
||||
this.render_prev_page();
|
||||
});
|
||||
|
||||
this.next_page_button.on('click', () => {
|
||||
this.render_next_page();
|
||||
});
|
||||
|
||||
this.first_page_button.on('click', () => {
|
||||
this.go_to_page(1);
|
||||
});
|
||||
|
||||
this.last_page_button.on('click', () => {
|
||||
this.go_to_page(this.total_pages);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
update_page_numbers() {
|
||||
let total_pages = Math.ceil(this.grid.data.length/this.page_length);
|
||||
if (this.total_pages !== total_pages) {
|
||||
this.total_pages = total_pages;
|
||||
this.render_pagination();
|
||||
}
|
||||
}
|
||||
|
||||
check_page_number() {
|
||||
if (this.page_index > this.total_pages && this.page_index > 1) {
|
||||
this.go_to_page(this.page_index-1);
|
||||
}
|
||||
}
|
||||
|
||||
get_pagination_html() {
|
||||
let page_text_html = `<div class="page-text">
|
||||
<span class="current-page-number page-number">${__(this.page_index)}</span>
|
||||
<span>${__('of')}</span>
|
||||
<span class="total-page-number page-number"> ${__(this.total_pages)} </span>
|
||||
</div>`;
|
||||
|
||||
return $(`<button class="btn btn-default btn-xs first-page"">
|
||||
<span class="first-page-icon">«</span>
|
||||
<span>${__('First')}</span>
|
||||
</button>
|
||||
<a class="prev-page">‹</a>
|
||||
${page_text_html}
|
||||
<a class="next-page">›</a>
|
||||
<button class="btn btn-default btn-xs last-page">
|
||||
<span>${__('Last')}</span>
|
||||
<span class="first-page-icon">»</span>
|
||||
</button>`);
|
||||
}
|
||||
|
||||
render_next_page() {
|
||||
if (this.page_index*this.page_length < this.grid.data.length) {
|
||||
this.page_index++;
|
||||
this.go_to_page();
|
||||
}
|
||||
}
|
||||
|
||||
render_prev_page() {
|
||||
if (this.page_index > 1) {
|
||||
this.page_index--;
|
||||
this.go_to_page();
|
||||
}
|
||||
}
|
||||
|
||||
go_to_page(index) {
|
||||
if (!index) {
|
||||
index = this.page_index;
|
||||
} else {
|
||||
this.page_index = index;
|
||||
}
|
||||
let $rows = $(this.grid.parent).find(".rows").empty();
|
||||
this.grid.render_result_rows($rows, true);
|
||||
if (this.$page_number) {
|
||||
this.$page_number.text(index);
|
||||
}
|
||||
|
||||
this.update_page_numbers();
|
||||
}
|
||||
|
||||
go_to_last_page_to_add_row() {
|
||||
let total_pages = this.total_pages;
|
||||
let page_length = this.page_length;
|
||||
if (this.grid.data.length == page_length*total_pages) {
|
||||
this.go_to_page(total_pages + 1);
|
||||
} else {
|
||||
this.go_to_page(total_pages);
|
||||
}
|
||||
frappe.utils.scroll_to(this.wrapper);
|
||||
}
|
||||
|
||||
get_result_length() {
|
||||
return this.grid.data.length < this.page_index*this.page_length
|
||||
? this.grid.data.length
|
||||
: this.page_index*this.page_length;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -34,13 +34,17 @@ frappe.ui.Tags = class {
|
|||
}
|
||||
|
||||
bind() {
|
||||
const me = this;
|
||||
const select_tag = function() {
|
||||
const tagValue = frappe.utils.xss_sanitise(me.$input.val());
|
||||
me.addTag(tagValue);
|
||||
me.$input.val('');
|
||||
}
|
||||
|
||||
this.$input.keypress((e) => {
|
||||
if(e.which == 13 || e.keyCode == 13) {
|
||||
const tagValue = frappe.utils.xss_sanitise(this.$input.val());
|
||||
this.addTag(tagValue);
|
||||
this.$input.val('');
|
||||
}
|
||||
if (e.which == 13 || e.keyCode == 13) select_tag();
|
||||
});
|
||||
this.$input.focusout(select_tag);
|
||||
|
||||
this.$input.on('blur', () => {
|
||||
this.deactivate();
|
||||
|
|
|
|||
|
|
@ -268,6 +268,32 @@
|
|||
border-top: 0px;
|
||||
}
|
||||
|
||||
.grid-pagination {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.page-text {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.prev-page, .next-page {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
a.prev-page {
|
||||
padding-left: 15px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.next-page {
|
||||
padding-right: 15px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.page-number {
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
.grid-footer-toolbar {
|
||||
padding: 10px 15px;
|
||||
border-top: 1px solid @border-color;
|
||||
|
|
|
|||
|
|
@ -63,3 +63,14 @@ def setup_workflow():
|
|||
create_todo_workflow()
|
||||
create_todo_records()
|
||||
frappe.clear_cache()
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_contact_phone_nos_records():
|
||||
if frappe.db.get_all('Contact', {'first_name': 'Test Contact'}):
|
||||
return
|
||||
|
||||
doc = frappe.new_doc('Contact')
|
||||
doc.first_name = 'Test Contact'
|
||||
for index in range(1000):
|
||||
doc.append('phone_nos', {'phone': '123456{}'.format(index)})
|
||||
doc.insert()
|
||||
Loading…
Add table
Reference in a new issue