Anoop 2 роки тому
джерело
коміт
8b55af2df9
46 змінених файлів з 189 додано та 4527 видалено
  1. +2
    -2
      README.md
  2. +21
    -21
      datavalue_theme_14/api.py
  3. +1
    -1
      datavalue_theme_14/config/desktop.py
  4. +2
    -2
      datavalue_theme_14/datavalue_theme_14/doctype/slideshow_photos/slideshow_photos.py
  5. +1
    -1
      datavalue_theme_14/datavalue_theme_14/doctype/theme_settings/test_theme_settings.py
  6. +2
    -2
      datavalue_theme_14/datavalue_theme_14/doctype/theme_settings/theme_settings.js
  7. +2
    -2
      datavalue_theme_14/datavalue_theme_14/doctype/theme_settings/theme_settings.json
  8. +2
    -2
      datavalue_theme_14/datavalue_theme_14/doctype/theme_settings/theme_settings.py
  9. +6
    -6
      datavalue_theme_14/hooks.py
  10. +1
    -1
      datavalue_theme_14/public/css/datavalue_theme.css
  11. +1
    -1
      datavalue_theme_14/public/css/datavalue_theme.css.map
  12. +1
    -1
      datavalue_theme_14/public/css/login.css
  13. +0
    -12
      datavalue_theme_14/public/icons/social/frappe.svg
  14. +1
    -1
      datavalue_theme_14/public/icons/timeless/icons.svg
  15. +2
    -2
      datavalue_theme_14/public/icons/timeless/symbol-defs.svg
  16. BIN
      ).png
  17. BIN
      datavalue_theme_14/public/images/erpnext-hero-compressed.png
  18. +3
    -3
      datavalue_theme_14/public/js/customizations/file/file.js
  19. +9
    -9
      datavalue_theme_14/public/js/datavalue_theme.bundle.js
  20. +9
    -9
      datavalue_theme_14/public/js/datavalue_theme.js
  21. +0
    -656
      datavalue_theme_14/public/js/frappe/desk.js
  22. +0
    -102
      datavalue_theme_14/public/js/frappe/form/controls/icon.js
  23. +0
    -89
      datavalue_theme_14/public/js/frappe/form/icon_picker/icon_picker.js
  24. +0
    -795
      datavalue_theme_14/public/js/frappe/form/icon_picker/icons_list.js
  25. +0
    -443
      datavalue_theme_14/public/js/frappe/ui/notifications/notifications.js
  26. +0
    -84
      datavalue_theme_14/public/js/frappe/ui/page.html
  27. +0
    -911
      datavalue_theme_14/public/js/frappe/ui/page.js
  28. +0
    -145
      datavalue_theme_14/public/js/frappe/ui/toolbar/navbar.html
  29. +0
    -52
      datavalue_theme_14/public/js/frappe/ui/toolbar/theme-setting.js
  30. +0
    -293
      datavalue_theme_14/public/js/frappe/ui/toolbar/toolbar.js
  31. +0
    -202
      datavalue_theme_14/public/js/frappe/views/breadcrumbs.js
  32. +0
    -129
      datavalue_theme_14/public/js/frappe/views/container.js
  33. +21
    -21
      datavalue_theme_14/public/js/vue/components/Menu.vue
  34. +1
    -1
      datavalue_theme_14/public/js/vue/theme-settings.js
  35. +1
    -1
      datavalue_theme_14/public/scss/datavalue_theme.bundle.scss
  36. +1
    -1
      datavalue_theme_14/public/scss/datavalue_theme.scss
  37. +1
    -1
      datavalue_theme_14/public/scss/partials/_body.scss
  38. +0
    -425
      datavalue_theme_14/public/scss/partials/_frappe.scss
  39. +6
    -6
      datavalue_theme_14/public/scss/partials/_rtl.scss
  40. +15
    -15
      datavalue_theme_14/templates/includes/login/login.js
  41. +5
    -5
      datavalue_theme_14/www/app.html
  42. +27
    -27
      datavalue_theme_14/www/app.py
  43. +3
    -3
      datavalue_theme_14/www/login.html
  44. +40
    -40
      datavalue_theme_14/www/login.py
  45. +1
    -1
      requirements.txt
  46. +1
    -1
      setup.py

+ 2
- 2
README.md Переглянути файл

@@ -1,7 +1,7 @@
## Datavalue Theme 14

Data Value Frappe 14 Theme
Data Value Xhiveframework 14 Theme

#### License

MIT
MIT

+ 21
- 21
datavalue_theme_14/api.py Переглянути файл

@@ -1,18 +1,18 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.cache_manager import clear_user_cache
import xhiveframework
from xhiveframework import _
from xhiveframework.cache_manager import clear_user_cache


@frappe.whitelist()
@xhiveframework.whitelist()
def get_module_name_from_doctype(doc_name, current_module=""):
# frappe.msgprint("======"+str(doc_name))
# xhiveframework.msgprint("======"+str(doc_name))
condition = ""
if doc_name:
if current_module:
condition = "and w.`name` = {current_module} ".format(current_module=current_module)

list_od_dicts = frappe.db.sql("""
list_od_dicts = xhiveframework.db.sql("""
select *
from (
select w.`name` `module`,
@@ -28,7 +28,7 @@ def get_module_name_from_doctype(doc_name, current_module=""):
if list_od_dicts:
return [{"module": list_od_dicts[0]["module"]}]
else:
list_od_dicts = frappe.db.sql("""
list_od_dicts = xhiveframework.db.sql("""
select *
from (
select w.`name` `module`,
@@ -44,33 +44,33 @@ def get_module_name_from_doctype(doc_name, current_module=""):
return [{"module": list_od_dicts[0]["module"]}]


@frappe.whitelist()
@xhiveframework.whitelist()
def change_language(language):
frappe.db.set_value("User", frappe.session.user, "language", language)
xhiveframework.db.set_value("User", xhiveframework.session.user, "language", language)
clear()
return True


@frappe.whitelist()
@xhiveframework.whitelist()
def get_current_language():
return frappe.db.get_value("User", frappe.session.user, "language")
return xhiveframework.db.get_value("User", xhiveframework.session.user, "language")


@frappe.whitelist()
@xhiveframework.whitelist()
def get_company_logo():
logo_path = ""
current_company = frappe.defaults.get_user_default("company")
current_company = xhiveframework.defaults.get_user_default("company")
if current_company:
logo_path = frappe.db.get_value("Company", current_company, "company_logo")
logo_path = xhiveframework.db.get_value("Company", current_company, "company_logo")

return logo_path


@frappe.whitelist(allow_guest=True)
@xhiveframework.whitelist(allow_guest=True)
def get_theme_settings():
slideshow_photos = []
settings_list = {}
settings = frappe.db.sql("""
settings = xhiveframework.db.sql("""
SELECT * FROM tabSingles WHERE doctype = 'Theme Settings';
""", as_dict=True, debug=False)

@@ -78,7 +78,7 @@ def get_theme_settings():
settings_list[setting['field']] = setting['value']

if (("background_type" in settings_list) and settings_list['background_type'] == 'Slideshow'):
slideshow_photos = frappe.db.sql("""
slideshow_photos = xhiveframework.db.sql("""
SELECT `photo` FROM `tabSlideshow Photos` WHERE `parent` = 'Theme Settings';
""", as_dict=True, debug=False)

@@ -99,7 +99,7 @@ def get_theme_settings():
}

def clear():
frappe.local.session_obj.update(force=True)
frappe.local.db.commit()
clear_user_cache(frappe.session.user)
frappe.response['message'] = _("Cache Cleared")
xhiveframework.local.session_obj.update(force=True)
xhiveframework.local.db.commit()
clear_user_cache(xhiveframework.session.user)
xhiveframework.response['message'] = _("Cache Cleared")

+ 1
- 1
datavalue_theme_14/config/desktop.py Переглянути файл

@@ -1,4 +1,4 @@
from frappe import _
from xhiveframework import _

def get_data():
return [


+ 2
- 2
datavalue_theme_14/datavalue_theme_14/doctype/slideshow_photos/slideshow_photos.py Переглянути файл

@@ -1,8 +1,8 @@
# Copyright (c) 2021, Abdo Hamoud and contributors
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document
# import xhiveframework
from xhiveframework.model.document import Document

class SlideshowPhotos(Document):
pass

+ 1
- 1
datavalue_theme_14/datavalue_theme_14/doctype/theme_settings/test_theme_settings.py Переглянути файл

@@ -1,7 +1,7 @@
# Copyright (c) 2021, Abdo Hamoud and Contributors
# See license.txt

# import frappe
# import xhiveframework
import unittest

class TestThemeSettings(unittest.TestCase):


+ 2
- 2
datavalue_theme_14/datavalue_theme_14/doctype/theme_settings/theme_settings.js Переглянути файл

@@ -1,11 +1,11 @@
// Copyright (c) 2021, Abdo Hamoud and contributors
// For license information, please see license.txt

frappe.ui.form.on('Theme Settings', {
xhiveframework.ui.form.on('Theme Settings', {
refresh: function (frm) {
$('[data-fieldname="font_family"] select').chosen({width: '50%'})
},
after_save: function (frm) {
setTimeout(() => frappe.ui.toolbar.clear_cache(), 500);
setTimeout(() => xhiveframework.ui.toolbar.clear_cache(), 500);
}
});

+ 2
- 2
datavalue_theme_14/datavalue_theme_14/doctype/theme_settings/theme_settings.json Переглянути файл

@@ -1,7 +1,7 @@
{
"actions": [
{
"action": "frappe.sessions.clear",
"action": "xhiveframework.sessions.clear",
"action_type": "Server Action",
"label": "Clear Cache"
}
@@ -178,4 +178,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

+ 2
- 2
datavalue_theme_14/datavalue_theme_14/doctype/theme_settings/theme_settings.py Переглянути файл

@@ -1,8 +1,8 @@
# Copyright (c) 2021, Abdo Hamoud and contributors
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document
# import xhiveframework
from xhiveframework.model.document import Document

class ThemeSettings(Document):
pass

+ 6
- 6
datavalue_theme_14/hooks.py Переглянути файл

@@ -3,7 +3,7 @@ from . import __version__ as app_version
app_name = "datavalue_theme_14"
app_title = "Datavalue Theme 14"
app_publisher = "Abdo Hamoud"
app_description = "Data Value Frappe 14 Theme"
app_description = "Data Value Xhiveframework 14 Theme"
app_email = "abdo.host@gmail.com"
app_license = "MIT"

@@ -108,7 +108,7 @@ web_include_js = [

# Desk Notifications
# ------------------
# See frappe.core.notifications.get_notification_config
# See xhiveframework.core.notifications.get_notification_config

# notification_config = "datavalue_theme_14.notifications.get_notification_config"

@@ -117,11 +117,11 @@ web_include_js = [
# Permissions evaluated in scripted ways

# permission_query_conditions = {
# "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions",
# "Event": "xhiveframework.desk.doctype.event.event.get_permission_query_conditions",
# }
#
# has_permission = {
# "Event": "frappe.desk.doctype.event.event.has_permission",
# "Event": "xhiveframework.desk.doctype.event.event.has_permission",
# }

# DocType Class
@@ -174,12 +174,12 @@ web_include_js = [
# ------------------------------
#
# override_whitelisted_methods = {
# "frappe.desk.doctype.event.event.get_events": "datavalue_theme_14.event.get_events"
# "xhiveframework.desk.doctype.event.event.get_events": "datavalue_theme_14.event.get_events"
# }
#
# each overriding function accepts a `data` argument;
# generated from the base implementation of the doctype dashboard,
# along with any modifications made in other Frappe apps
# along with any modifications made in other Xhiveframework apps
# override_doctype_dashboards = {
# "Task": "datavalue_theme_14.task.get_dashboard_data"
# }


+ 1
- 1
datavalue_theme_14/public/css/datavalue_theme.css
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 1
- 1
datavalue_theme_14/public/css/datavalue_theme.css.map
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 1
- 1
datavalue_theme_14/public/css/login.css
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 0
- 12
datavalue_theme_14/public/icons/social/frappe.svg Переглянути файл

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 61.2 (89653) - https://sketch.com -->
<title>Artboard</title>
<desc>Created with Sketch.</desc>
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="frappe" transform="translate(3.000000, 1.000000)" fill="#0089FF" fill-rule="nonzero">
<polygon id="Path" points="9.360932 0 0 0 0 2.46232 9.360932 2.46232"></polygon>
<polygon id="Path" points="0 6.281996 0 14 2.98788 14 2.98788 8.74846 8.740172 8.74846 8.740172 6.281996"></polygon>
</g>
</g>
</svg>

+ 1
- 1
datavalue_theme_14/public/icons/timeless/icons.svg Переглянути файл

@@ -1,4 +1,4 @@
<svg id="frappe-symbols" aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" class="d-block" xmlns="http://www.w3.org/2000/svg">
<svg id="xhiveframework-symbols" aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" class="d-block" xmlns="http://www.w3.org/2000/svg">
<symbol viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" id="icon-up-line">
<path d="M13 10.5L8 5.5L3 10.5" stroke="var(--icon-stroke)" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>


+ 2
- 2
datavalue_theme_14/public/icons/timeless/symbol-defs.svg Переглянути файл

@@ -1,4 +1,4 @@
<svg id="frappe-symbols" aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" class="d-block" xmlns="http://www.w3.org/2000/svg">
<svg id="xhiveframework-symbols" aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" class="d-block" xmlns="http://www.w3.org/2000/svg">
<symbol viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" id="icon-resting">
<path d="M7.606 3.799L8 4.302l.394-.503.106-.14c.048-.065.08-.108.129-.159a3.284 3.284 0 0 1 4.72 0c.424.434.655 1.245.65 2.278-.006 1.578-.685 2.931-1.728 4.159-1.05 1.234-2.439 2.308-3.814 3.328a.763.763 0 0 1-.914 0c-1.375-1.02-2.764-2.094-3.814-3.328C2.686 8.709 2.007 7.357 2 5.778c-.004-1.033.227-1.844.651-2.278a3.284 3.284 0 0 1 4.72 0c.05.05.081.094.129.158.028.038.061.083.106.14z"
stroke="var(--icon-stroke)"></path>
@@ -567,7 +567,7 @@
<path d="M6.45466 8.81824L4.47873 10.7942C3.85205 11.4211 3.5 12.2713 3.5 13.1577C3.5 14.0442 3.85205 14.8943 4.47873 15.5213V15.5213C5.10568 16.148 5.95584 16.5 6.84229 16.5C7.72874 16.5 8.5789 16.148 9.20584 15.5213L11.1818 13.5453" stroke="var(--icon-stroke)" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol viewBox="0 0 24 24" fill="none" id="icon-scan" xmlns="http://www.w3.org/2000/svg">
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"
stroke="var(--icon-stroke)" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
</symbol>
<symbol viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" id="icon-dashboard">


BIN
datavalue_theme_14/public/images/erpnext-hero-compressed → ).png Переглянути файл


BIN
datavalue_theme_14/public/images/erpnext-hero-compressed.png Переглянути файл

Перед Після
Ширина: 965  |  Висота: 666  |  Розмір: 121 KiB

+ 3
- 3
datavalue_theme_14/public/js/customizations/file/file.js Переглянути файл

@@ -1,4 +1,4 @@
frappe.ui.form.on("File", {
xhiveframework.ui.form.on("File", {
onload: function (frm) {

},
@@ -6,7 +6,7 @@ frappe.ui.form.on("File", {
let wrapper = frm.get_field("preview_html").$wrapper;
let selected_doc = frm.selected_doc;
let file_ext = (selected_doc.file_name) ? selected_doc.file_name.split('.').pop() : '';
let is_viewable = (file_ext && file_ext.toLowerCase() == 'pdf') ? true : frappe.utils.is_image_file(frm.doc.file_url);
let is_viewable = (file_ext && file_ext.toLowerCase() == 'pdf') ? true : xhiveframework.utils.is_image_file(frm.doc.file_url);
frm.toggle_display("preview", is_viewable);
frm.toggle_display("preview_html", is_viewable);
console.log(frm)
@@ -21,7 +21,7 @@ frappe.ui.form.on("File", {
<embed style="background:#323639;" width="100%" height="1190" src="${frm.doc.file_url}" type="application/pdf">
</object>
</div>`);
} else if (frappe.utils.is_image_file(frm.doc.file_url)) {
} else if (xhiveframework.utils.is_image_file(frm.doc.file_url)) {
wrapper.html(`<div class="img_preview">
<img class="img-responsive" src="${frm.doc.file_url}">
</div>`);


+ 9
- 9
datavalue_theme_14/public/js/datavalue_theme.bundle.js Переглянути файл

@@ -1,10 +1,10 @@
import "./frappe/ui/page.html";
import "./frappe/ui/page.js";
import "./frappe/views/container.js";
import "./frappe/views/breadcrumbs.js";
import "./frappe/ui/toolbar/toolbar.js";
import "./frappe/ui/toolbar/navbar.html";
import "./frappe/ui/notifications/notifications.js";
import "./frappe/form/controls/icon.js";
import "./xhiveframework/ui/page.html";
import "./xhiveframework/ui/page.js";
import "./xhiveframework/views/container.js";
import "./xhiveframework/views/breadcrumbs.js";
import "./xhiveframework/ui/toolbar/toolbar.js";
import "./xhiveframework/ui/toolbar/navbar.html";
import "./xhiveframework/ui/notifications/notifications.js";
import "./xhiveframework/form/controls/icon.js";
import "./vue/side-menu.js";
import "./frappe/ui/toolbar/theme-setting.js";
import "./xhiveframework/ui/toolbar/theme-setting.js";

+ 9
- 9
datavalue_theme_14/public/js/datavalue_theme.js Переглянути файл

@@ -63,7 +63,7 @@
// files icon
$(this).on('click', '.dv-navbar .files-icon', function (event) {
event.preventDefault();
frappe.set_route("List", "File");
xhiveframework.set_route("List", "File");
});
// files icon
$(this).on('click', '.dv-navbar .full-screen-icon', function (event) {
@@ -85,14 +85,14 @@
let language = $this.data('lang');
let selected_flag = $this.find(".dv-lang-flag").attr("class");
$("#header-navbar-change-lang .dropdown-lang-link").html(`<span class="${selected_flag}"></span> ${language}`);
frappe.call({
xhiveframework.call({
method: "datavalue_theme_14.api.change_language",
args: {
language: language.toLowerCase()
},
callback: function (r) {
localStorage.setItem("active_lang", language);
frappe.ui.toolbar.clear_cache();
xhiveframework.ui.toolbar.clear_cache();
}
});
});
@@ -170,7 +170,7 @@

$(document).on("app-loaded", function () {

if (frappe.is_app_loaded)
if (xhiveframework.is_app_loaded)
return;

let AppLogoVM = new Vue({
@@ -184,7 +184,7 @@
methods: {
get_company_logo: function () {
const $this = this;
frappe.call({
xhiveframework.call({
type: 'POST',
method: 'datavalue_theme_14.api.get_company_logo',
args: {},
@@ -204,7 +204,7 @@
await this.get_company_logo();
},
created: function () {
this.user = frappe.get_cookies();
this.user = xhiveframework.get_cookies();
}
});

@@ -216,8 +216,8 @@
user_type: ''
},
created: function () {
this.user = frappe.get_cookies();
frappe.db.get_value('User', this.user.user_id, 'user_type', (response) => {
this.user = xhiveframework.get_cookies();
xhiveframework.db.get_value('User', this.user.user_id, 'user_type', (response) => {
if (this.user.user_id == 'Administrator') {
this.user_type = __('Administrator');
} else {
@@ -247,7 +247,7 @@
methods: {
get_current_language: function () {
const $this = this;
frappe.call({
xhiveframework.call({
method: "datavalue_theme_14.api.get_current_language",
args: {},
callback: function (response) {


+ 0
- 656
datavalue_theme_14/public/js/frappe/desk.js Переглянути файл

@@ -1,656 +0,0 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
/* eslint-disable no-console */

// __('Modules') __('Domains') __('Places') __('Administration') # for translation, don't remove

frappe.start_app = function () {
if (!frappe.Application) return;
frappe.assets.check();
frappe.provide("frappe.app");
frappe.provide("frappe.desk");
frappe.app = new frappe.Application();
};

$(document).ready(function () {
if (!frappe.utils.supportsES6) {
frappe.msgprint({
indicator: "red",
title: __("Browser not supported"),
message: __(
"Some of the features might not work in your browser. Please update your browser to the latest version."
),
});
}
frappe.start_app();
});

frappe.Application = class Application {
constructor() {
this.startup();
}

startup() {
frappe.socketio.init();
frappe.model.init();

if (frappe.boot.status === "failed") {
frappe.msgprint({
message: frappe.boot.error,
title: __("Session Start Failed"),
indicator: "red",
});
throw "boot failed";
}

this.setup_frappe_vue();
this.load_bootinfo();
this.load_user_permissions();
this.make_nav_bar();
this.set_favicon();
this.setup_analytics();
this.set_fullwidth_if_enabled();
this.add_browser_class();
this.setup_energy_point_listeners();
this.setup_copy_doc_listener();
this.set_rtl();

frappe.ui.keys.setup();

frappe.ui.keys.add_shortcut({
shortcut: "shift+ctrl+g",
description: __("Switch Theme"),
action: () => {
if (frappe.theme_switcher && frappe.theme_switcher.dialog.is_visible) {
frappe.theme_switcher.hide();
} else {
frappe.theme_switcher = new frappe.ui.ThemeSwitcher();
frappe.theme_switcher.show();
}
},
});

frappe.ui.add_system_theme_switch_listener();
const root = document.documentElement;

// const observer = new MutationObserver(() => {
// frappe.ui.set_theme();
// });
// observer.observe(root, {
// attributes: true,
// attributeFilter: ["data-theme-mode"],
// });

frappe.ui.set_theme();

// page container
this.make_page_container();
this.set_route();

// trigger app startup
$(document).trigger("startup");

$(document).trigger("app_ready");

if (frappe.boot.messages) {
frappe.msgprint(frappe.boot.messages);
}

if (frappe.user_roles.includes("System Manager")) {
// delayed following requests to make boot faster
setTimeout(() => {
this.show_change_log();
this.show_update_available();
}, 1000);
}

if (!frappe.boot.developer_mode) {
let console_security_message = __(
"Using this console may allow attackers to impersonate you and steal your information. Do not enter or paste code that you do not understand."
);
console.log(`%c${console_security_message}`, "font-size: large");
}

this.show_notes();

if (frappe.ui.startup_setup_dialog && !frappe.boot.setup_complete) {
frappe.ui.startup_setup_dialog.pre_show();
frappe.ui.startup_setup_dialog.show();
}

frappe.realtime.on("version-update", function () {
var dialog = frappe.msgprint({
message: __(
"The application has been updated to a new version, please refresh this page"
),
indicator: "green",
title: __("Version Updated"),
});
dialog.set_primary_action(__("Refresh"), function () {
location.reload(true);
});
dialog.get_close_btn().toggle(false);
});

// listen to build errors
this.setup_build_events();

if (frappe.sys_defaults.email_user_password) {
var email_list = frappe.sys_defaults.email_user_password.split(",");
for (var u in email_list) {
if (email_list[u] === frappe.user.name) {
this.set_password(email_list[u]);
}
}
}

// REDESIGN-TODO: Fix preview popovers
this.link_preview = new frappe.ui.LinkPreview();

if (!frappe.boot.developer_mode) {
if (frappe.user.has_role("System Manager")) {
setInterval(function () {
frappe.call({
method: "frappe.core.doctype.log_settings.log_settings.has_unseen_error_log",
args: {
user: frappe.session.user,
},
callback: function (r) {
if (r.message.show_alert) {
frappe.show_alert({
indicator: "red",
message: r.message.message,
});
}
},
});
}, 600000); // check every 10 minutes
}
}
}

set_route() {
frappe.flags.setting_original_route = true;
if (frappe.boot && localStorage.getItem("session_last_route")) {
frappe.set_route(localStorage.getItem("session_last_route"));
localStorage.removeItem("session_last_route");
} else {
// route to home page
frappe.router.route();
}
frappe.after_ajax(() => (frappe.flags.setting_original_route = false));
frappe.router.on("change", () => {
$(".tooltip").hide();
});
}

setup_frappe_vue() {
Vue.prototype.__ = window.__;
Vue.prototype.frappe = window.frappe;
}

set_password(user) {
var me = this;
frappe.call({
method: "frappe.core.doctype.user.user.get_email_awaiting",
args: {
user: user,
},
callback: function (email_account) {
email_account = email_account["message"];
if (email_account) {
var i = 0;
if (i < email_account.length) {
me.email_password_prompt(email_account, user, i);
}
}
},
});
}

email_password_prompt(email_account, user, i) {
var me = this;
const email_id = email_account[i]["email_id"];
let d = new frappe.ui.Dialog({
title: __("Password missing in Email Account"),
fields: [
{
fieldname: "password",
fieldtype: "Password",
label: __(
"Please enter the password for: <b>{0}</b>",
[email_id],
"Email Account"
),
reqd: 1,
},
{
fieldname: "submit",
fieldtype: "Button",
label: __("Submit", null, "Submit password for Email Account"),
},
],
});
d.get_input("submit").on("click", function () {
//setup spinner
d.hide();
var s = new frappe.ui.Dialog({
title: __("Checking one moment"),
fields: [
{
fieldtype: "HTML",
fieldname: "checking",
},
],
});
s.fields_dict.checking.$wrapper.html('<i class="fa fa-spinner fa-spin fa-4x"></i>');
s.show();
frappe.call({
method: "frappe.email.doctype.email_account.email_account.set_email_password",
args: {
email_account: email_account[i]["email_account"],
password: d.get_value("password"),
},
callback: function (passed) {
s.hide();
d.hide(); //hide waiting indication
if (!passed["message"]) {
frappe.show_alert(
{message: __("Login Failed please try again"), indicator: "error"},
5
);
me.email_password_prompt(email_account, user, i);
} else {
if (i + 1 < email_account.length) {
i = i + 1;
me.email_password_prompt(email_account, user, i);
}
}
},
});
});
d.show();
}

load_bootinfo() {
if (frappe.boot) {
this.setup_workspaces();
frappe.model.sync(frappe.boot.docs);
this.check_metadata_cache_status();
this.set_globals();
this.sync_pages();
frappe.router.setup();
this.setup_moment();
if (frappe.boot.print_css) {
frappe.dom.set_style(frappe.boot.print_css, "print-style");
}
frappe.user.name = frappe.boot.user.name;
frappe.router.setup();
} else {
this.set_as_guest();
}
}

setup_workspaces() {
frappe.modules = {};
frappe.workspaces = {};
for (let page of frappe.boot.allowed_workspaces || []) {
frappe.modules[page.module] = page;
frappe.workspaces[frappe.router.slug(page.name)] = page;
}
}

load_user_permissions() {
frappe.defaults.update_user_permissions();

frappe.realtime.on(
"update_user_permissions",
frappe.utils.debounce(() => {
frappe.defaults.update_user_permissions();
}, 500)
);
}

check_metadata_cache_status() {
if (frappe.boot.metadata_version != localStorage.metadata_version) {
frappe.assets.clear_local_storage();
frappe.assets.init_local_storage();
}
}

set_globals() {
frappe.session.user = frappe.boot.user.name;
frappe.session.logged_in_user = frappe.boot.user.name;
frappe.session.user_email = frappe.boot.user.email;
frappe.session.user_fullname = frappe.user_info().fullname;

frappe.user_defaults = frappe.boot.user.defaults;
frappe.user_roles = frappe.boot.user.roles;
frappe.sys_defaults = frappe.boot.sysdefaults;

frappe.ui.py_date_format = frappe.boot.sysdefaults.date_format
.replace("dd", "%d")
.replace("mm", "%m")
.replace("yyyy", "%Y");
frappe.boot.user.last_selected_values = {};
}

sync_pages() {
// clear cached pages if timestamp is not found
if (localStorage["page_info"]) {
frappe.boot.allowed_pages = [];
var page_info = JSON.parse(localStorage["page_info"]);
$.each(frappe.boot.page_info, function (name, p) {
if (!page_info[name] || page_info[name].modified != p.modified) {
delete localStorage["_page:" + name];
}
frappe.boot.allowed_pages.push(name);
});
} else {
frappe.boot.allowed_pages = Object.keys(frappe.boot.page_info);
}
localStorage["page_info"] = JSON.stringify(frappe.boot.page_info);
}

set_as_guest() {
frappe.session.user = "Guest";
frappe.session.user_email = "";
frappe.session.user_fullname = "Guest";

frappe.user_defaults = {};
frappe.user_roles = ["Guest"];
frappe.sys_defaults = {};
}

make_page_container() {
if ($("#body").length) {
$(".splash").remove();
frappe.temp_container = $("<div id='temp-container' style='display: none;'>").appendTo(
"body"
);
frappe.container = new frappe.views.Container();
}
}

make_nav_bar() {
// toolbar
if (frappe.boot && frappe.boot.home_page !== "setup-wizard") {
frappe.frappe_toolbar = new frappe.ui.toolbar.Toolbar();
}
}

logout() {
var me = this;
me.logged_out = true;
return frappe.call({
method: "logout",
callback: function (r) {
if (r.exc) {
return;
}
me.redirect_to_login();
},
});
}

handle_session_expired() {
if (!frappe.app.session_expired_dialog) {
var dialog = new frappe.ui.Dialog({
title: __("Session Expired"),
keep_open: true,
fields: [
{
fieldtype: "Password",
fieldname: "password",
label: __("Please Enter Your Password to Continue"),
},
],
onhide: () => {
if (!dialog.logged_in) {
frappe.app.redirect_to_login();
}
},
});
dialog.set_primary_action(__("Login"), () => {
dialog.set_message(__("Authenticating..."));
frappe.call({
method: "login",
args: {
usr: frappe.session.user,
pwd: dialog.get_values().password,
},
callback: (r) => {
if (r.message === "Logged In") {
dialog.logged_in = true;

// revert backdrop
$(".modal-backdrop").css({
opacity: "",
"background-color": "#334143",
});
}
dialog.hide();
},
statusCode: () => {
dialog.hide();
},
});
});
frappe.app.session_expired_dialog = dialog;
}
if (!frappe.app.session_expired_dialog.display) {
frappe.app.session_expired_dialog.show();
// add backdrop
$(".modal-backdrop").css({
opacity: 1,
"background-color": "#4B4C9D",
});
}
}

redirect_to_login() {
window.location.href = "/";
}

set_favicon() {
var link = $('link[type="image/x-icon"]').remove().attr("href");
$('<link rel="shortcut icon" href="' + link + '" type="image/x-icon">').appendTo("head");
$('<link rel="icon" href="' + link + '" type="image/x-icon">').appendTo("head");
}

trigger_primary_action() {
// to trigger change event on active input before triggering primary action
$(document.activeElement).blur();
// wait for possible JS validations triggered after blur (it might change primary button)
setTimeout(() => {
if (window.cur_dialog && cur_dialog.display) {
// trigger primary
cur_dialog.get_primary_btn().trigger("click");
} else if (cur_frm && cur_frm.page.btn_primary.is(":visible")) {
cur_frm.page.btn_primary.trigger("click");
} else if (frappe.container.page.save_action) {
frappe.container.page.save_action();
}
}, 100);
}

show_change_log() {
var me = this;
let change_log = frappe.boot.change_log;

// frappe.boot.change_log = [{
// "change_log": [
// [<version>, <change_log in markdown>],
// [<version>, <change_log in markdown>],
// ],
// "description": "ERP made simple",
// "title": "ERPNext",
// "version": "12.2.0"
// }];

if (
!Array.isArray(change_log) ||
!change_log.length ||
window.Cypress ||
cint(frappe.boot.sysdefaults.disable_change_log_notification)
) {
return;
}

// Iterate over changelog
var change_log_dialog = frappe.msgprint({
message: frappe.render_template("change_log", {change_log: change_log}),
title: __("Updated To A New Version 🎉"),
wide: true,
});
change_log_dialog.keep_open = true;
change_log_dialog.custom_onhide = function () {
frappe.call({
method: "frappe.utils.change_log.update_last_known_versions",
});
me.show_notes();
};
}

show_update_available() {
if (frappe.boot.sysdefaults.disable_system_update_notification) return;

frappe.call({
method: "frappe.utils.change_log.show_update_popup",
});
}

setup_analytics() {
if (window.mixpanel) {
window.mixpanel.identify(frappe.session.user);
window.mixpanel.people.set({
$first_name: frappe.boot.user.first_name,
$last_name: frappe.boot.user.last_name,
$created: frappe.boot.user.creation,
$email: frappe.session.user,
});
}
}

add_browser_class() {
$("html").addClass(frappe.utils.get_browser().name.toLowerCase());
}

set_fullwidth_if_enabled() {
frappe.ui.toolbar.set_fullwidth_if_enabled();
}

set_rtl() {
if (frappe.utils.is_rtl()) {
$('body').addClass('frappe-rtl');
}
}

show_notes() {
var me = this;
if (frappe.boot.notes.length) {
frappe.boot.notes.forEach(function (note) {
if (!note.seen || note.notify_on_every_login) {
var d = frappe.msgprint({message: note.content, title: note.title});
d.keep_open = true;
d.custom_onhide = function () {
note.seen = true;

// Mark note as read if the Notify On Every Login flag is not set
if (!note.notify_on_every_login) {
frappe.call({
method: "frappe.desk.doctype.note.note.mark_as_seen",
args: {
note: note.name,
},
});
}

// next note
me.show_notes();
};
}
});
}
}

setup_build_events() {
if (frappe.boot.developer_mode) {
frappe.require("build_events.bundle.js");
}
}

setup_energy_point_listeners() {
frappe.realtime.on("energy_point_alert", (message) => {
frappe.show_alert(message);
});
}

setup_copy_doc_listener() {
$("body").on("paste", (e) => {
try {
let pasted_data = frappe.utils.get_clipboard_data(e);
let doc = JSON.parse(pasted_data);
if (doc.doctype) {
e.preventDefault();
const sleep = frappe.utils.sleep;

frappe.dom.freeze(__("Creating {0}", [doc.doctype]) + "...");
// to avoid abrupt UX
// wait for activity feedback
sleep(500).then(() => {
let res = frappe.model.with_doctype(doc.doctype, () => {
let newdoc = frappe.model.copy_doc(doc);
newdoc.__newname = doc.name;
delete doc.name;
newdoc.idx = null;
newdoc.__run_link_triggers = false;
frappe.set_route("Form", newdoc.doctype, newdoc.name);
frappe.dom.unfreeze();
});
res && res.fail(frappe.dom.unfreeze);
});
}
} catch (e) {
//
}
});
}

setup_moment() {
moment.updateLocale("en", {
week: {
dow: frappe.datetime.get_first_day_of_the_week_index(),
},
});
moment.locale("en");
moment.user_utc_offset = moment().utcOffset();
if (frappe.boot.timezone_info) {
moment.tz.add(frappe.boot.timezone_info);
}
}
};

frappe.get_module = function (m, default_module) {
var module = frappe.modules[m] || default_module;
if (!module) {
return;
}

if (module._setup) {
return module;
}

if (!module.label) {
module.label = m;
}

if (!module._label) {
module._label = __(module.label);
}

module._setup = true;

return module;
};


+ 0
- 102
datavalue_theme_14/public/js/frappe/form/controls/icon.js Переглянути файл

@@ -1,102 +0,0 @@
import Picker from "../icon_picker/icon_picker";
import dv_icons_list from "../icon_picker/icons_list";

frappe.ui.form.ControlIcon = class ControlIcon extends frappe.ui.form.ControlData {
make_input() {
this.df.placeholder = this.df.placeholder || __("Choose an icon");
super.make_input();
this.make_icon_input();
}

get_all_icons() {
frappe.symbols = [];
$("#frappe-symbols > symbol[id]").each(function () {
this.id.includes("icon-") && frappe.symbols.push(this.id.replace("icon-", ""));
});
}

make_icon_input() {
let picker_wrapper = $("<div>");
this.picker = new Picker({
parent: picker_wrapper,
icon: this.get_icon(),
icons: dv_icons_list,
});

this.$wrapper
.popover({
trigger: "manual",
offset: `${-this.$wrapper.width() / 4.5}, 5`,
boundary: "viewport",
placement: "bottom",
template: `
<div class="popover icon-picker-popover">
<div class="picker-arrow arrow"></div>
<div class="popover-body popover-content"></div>
</div>
`,
content: () => picker_wrapper,
html: true,
})
.on("show.bs.popover", () => {
setTimeout(() => {
this.picker.refresh();
}, 10);
})
.on("hidden.bs.popover", () => {
$("body").off("click.icon-popover");
$(window).off("hashchange.icon-popover");
});

this.picker.on_change = (icon) => {
this.set_value(icon);
};

if (!this.selected_icon) {
this.selected_icon = $(
`<div class="selected-icon"></div>`
);
this.selected_icon.html('<i class="fal fa-folder"></i>');
this.selected_icon.insertAfter(this.$input);
}

this.$wrapper
.find(".selected-icon")
.parent()
.on("click", (e) => {
this.$wrapper.popover("toggle");
if (!this.get_icon()) {
this.$input.val("");
}
e.stopPropagation();
$("body").on("click.icon-popover", (ev) => {
if (!$(ev.target).parents().is(".popover")) {
this.$wrapper.popover("hide");
}
});
$(document).on("hashchange.icon-popover", () => {
this.$wrapper.popover("hide");
});
});
}

refresh() {
super.refresh();
let icon = this.get_icon();
if (this.picker && this.picker.icon !== icon) {
this.picker.icon = icon;
this.picker.refresh();
}
}

set_formatted_input(value) {
super.set_formatted_input(value);
this.$input.val(value);
this.selected_icon.html(`<i class="${value || 'fal fa-folder'}"></i>`);
this.selected_icon.toggleClass("no-value", !value);
}

get_icon() {
return this.get_value() || 'fal fa-folder';
}
};

+ 0
- 89
datavalue_theme_14/public/js/frappe/form/icon_picker/icon_picker.js Переглянути файл

@@ -1,89 +0,0 @@
class Picker {
constructor(opts) {
this.parent = opts.parent;
this.width = opts.width;
this.height = opts.height;
this.set_icon(opts.icon);
this.icons = opts.icons;
this.setup_picker();
}

refresh() {
this.update_icon_selected(true);
}

setup_picker() {
this.icon_picker_wrapper = $(`
<div class="icon-picker">
<div class="search-icons">
<input type="search" placeholder="Search for icons.." class="form-control">
<span class="search-icon">${frappe.utils.icon("search", "sm")}</span>
</div>
<div class="icon-section">
<div class="icons"></div>
</div>
</div>
`);
this.parent.append(this.icon_picker_wrapper);
this.icon_wrapper = this.icon_picker_wrapper.find(".icons");
this.search_input = this.icon_picker_wrapper.find(".search-icons > input");
this.refresh();
this.setup_icons();
}

setup_icons() {
this.icons.forEach((icon) => {
let $icon = $(
`<div id="${icon.replace('fad fa-', '')}" class="icon-wrapper"><i class="${icon}"></i></div>`
);
this.icon_wrapper.append($icon);
const set_values = () => {
this.set_icon(icon);
this.update_icon_selected();
};
$icon.on("click", () => {
set_values();
});
$icon.keydown((e) => {
const key_code = e.keyCode;
if ([13, 32].includes(key_code)) {
e.preventDefault();
set_values();
}
});
});
this.search_input.keyup((e) => {
e.preventDefault();
this.filter_icons();
});

this.search_input.on("search", () => {
this.filter_icons();
});
}

filter_icons() {
let value = this.search_input.val();
console.log('filter_icons-value', value)
if (!value) {
this.icon_wrapper.find(".icon-wrapper").removeClass("hidden");
} else {
this.icon_wrapper.find(".icon-wrapper").addClass("hidden");
this.icon_wrapper.find(`.icon-wrapper[id*='${value}']`).removeClass("hidden");
}
}

update_icon_selected(silent) {
!silent && this.on_change && this.on_change(this.get_icon());
}

set_icon(icon) {
this.icon = icon || "";
}

get_icon() {
return this.icon || "";
}
}

export default Picker;

+ 0
- 795
datavalue_theme_14/public/js/frappe/form/icon_picker/icons_list.js Переглянути файл

@@ -1,795 +0,0 @@
const dv_icons_list = [
"fal fa-address-book",
"fal fa-address-card",
"fal fa-adjust",
"fal fa-alarm-clock",
"fal fa-align-center",
"fal fa-align-justify",
"fal fa-align-left",
"fal fa-align-right",
"fal fa-allergies",
"fal fa-ambulance",
"fal fa-american-sign-language-interpreting",
"fal fa-anchor",
"fal fa-angle-double-down",
"fal fa-angle-double-left",
"fal fa-angle-double-right",
"fal fa-angle-double-up",
"fal fa-angle-down",
"fal fa-angle-left",
"fal fa-angle-right",
"fal fa-angle-up",
"fal fa-archive",
"fal fa-arrow-alt-circle-down",
"fal fa-arrow-alt-circle-left",
"fal fa-arrow-alt-circle-right",
"fal fa-arrow-alt-circle-up",
"fal fa-arrow-alt-down",
"fal fa-arrow-alt-from-bottom",
"fal fa-arrow-alt-from-left",
"fal fa-arrow-alt-from-right",
"fal fa-arrow-alt-from-top",
"fal fa-arrow-alt-left",
"fal fa-arrow-alt-right",
"fal fa-arrow-alt-square-down",
"fal fa-arrow-alt-square-left",
"fal fa-arrow-alt-square-right",
"fal fa-arrow-alt-square-up",
"fal fa-arrow-alt-to-bottom",
"fal fa-arrow-alt-to-left",
"fal fa-arrow-alt-to-right",
"fal fa-arrow-alt-to-top",
"fal fa-arrow-alt-up",
"fal fa-arrow-circle-down",
"fal fa-arrow-circle-left",
"fal fa-arrow-circle-right",
"fal fa-arrow-circle-up",
"fal fa-arrow-down",
"fal fa-arrow-from-bottom",
"fal fa-arrow-from-left",
"fal fa-arrow-from-right",
"fal fa-arrow-from-top",
"fal fa-arrow-left",
"fal fa-arrow-right",
"fal fa-arrow-square-down",
"fal fa-arrow-square-left",
"fal fa-arrow-square-right",
"fal fa-arrow-square-up",
"fal fa-arrow-to-bottom",
"fal fa-arrow-to-left",
"fal fa-arrow-to-right",
"fal fa-arrow-to-top",
"fal fa-arrow-up",
"fal fa-arrows",
"fal fa-arrows-alt",
"fal fa-arrows-alt-h",
"fal fa-arrows-alt-v",
"fal fa-arrows-h",
"fal fa-arrows-v",
"fal fa-assistive-listening-systems",
"fal fa-asterisk",
"fal fa-at",
"fal fa-audio-description",
"fal fa-backward",
"fal fa-badge",
"fal fa-badge-check",
"fal fa-balance-scale",
"fal fa-ban",
"fal fa-band-aid",
"fal fa-barcode",
"fal fa-barcode-alt",
"fal fa-barcode-read",
"fal fa-barcode-scan",
"fal fa-bars",
"fal fa-baseball",
"fal fa-baseball-ball",
"fal fa-basketball-ball",
"fal fa-basketball-hoop",
"fal fa-bath",
"fal fa-battery-bolt",
"fal fa-battery-empty",
"fal fa-battery-full",
"fal fa-battery-half",
"fal fa-battery-quarter",
"fal fa-battery-slash",
"fal fa-battery-three-quarters",
"fal fa-bed",
"fal fa-beer",
"fal fa-bell",
"fal fa-bell-slash",
"fal fa-bicycle",
"fal fa-binoculars",
"fal fa-birthday-cake",
"fal fa-blanket",
"fal fa-blind",
"fal fa-bold",
"fal fa-bolt",
"fal fa-bomb",
"fal fa-book",
"fal fa-book-heart",
"fal fa-bookmark",
"fal fa-bowling-ball",
"fal fa-bowling-pins",
"fal fa-box",
"fal fa-box-alt",
"fal fa-box-check",
"fal fa-box-fragile",
"fal fa-box-full",
"fal fa-box-heart",
"fal fa-box-open",
"fal fa-box-up",
"fal fa-box-usd",
"fal fa-boxes",
"fal fa-boxes-alt",
"fal fa-boxing-glove",
"fal fa-braille",
"fal fa-briefcase",
"fal fa-briefcase-medical",
"fal fa-browser",
"fal fa-bug",
"fal fa-building",
"fal fa-bullhorn",
"fal fa-bullseye",
"fal fa-burn",
"fal fa-bus",
"fal fa-calculator",
"fal fa-calendar",
"fal fa-calendar-alt",
"fal fa-calendar-check",
"fal fa-calendar-edit",
"fal fa-calendar-exclamation",
"fal fa-calendar-minus",
"fal fa-calendar-plus",
"fal fa-calendar-times",
"fal fa-camera",
"fal fa-camera-alt",
"fal fa-camera-retro",
"fal fa-capsules",
"fal fa-car",
"fal fa-caret-circle-down",
"fal fa-caret-circle-left",
"fal fa-caret-circle-right",
"fal fa-caret-circle-up",
"fal fa-caret-down",
"fal fa-caret-left",
"fal fa-caret-right",
"fal fa-caret-square-down",
"fal fa-caret-square-left",
"fal fa-caret-square-right",
"fal fa-caret-square-up",
"fal fa-caret-up",
"fal fa-cart-arrow-down",
"fal fa-cart-plus",
"fal fa-certificate",
"fal fa-chart-area",
"fal fa-chart-bar",
"fal fa-chart-line",
"fal fa-chart-pie",
"fal fa-check",
"fal fa-check-circle",
"fal fa-check-square",
"fal fa-chess",
"fal fa-chess-bishop",
"fal fa-chess-bishop-alt",
"fal fa-chess-board",
"fal fa-chess-clock",
"fal fa-chess-clock-alt",
"fal fa-chess-king",
"fal fa-chess-king-alt",
"fal fa-chess-knight",
"fal fa-chess-knight-alt",
"fal fa-chess-pawn",
"fal fa-chess-pawn-alt",
"fal fa-chess-queen",
"fal fa-chess-queen-alt",
"fal fa-chess-rook",
"fal fa-chess-rook-alt",
"fal fa-chevron-circle-down",
"fal fa-chevron-circle-left",
"fal fa-chevron-circle-right",
"fal fa-chevron-circle-up",
"fal fa-chevron-double-down",
"fal fa-chevron-double-left",
"fal fa-chevron-double-right",
"fal fa-chevron-double-up",
"fal fa-chevron-down",
"fal fa-chevron-left",
"fal fa-chevron-right",
"fal fa-chevron-square-down",
"fal fa-chevron-square-left",
"fal fa-chevron-square-right",
"fal fa-chevron-square-up",
"fal fa-chevron-up",
"fal fa-child",
"fal fa-circle",
"fal fa-circle-notch",
"fal fa-clipboard",
"fal fa-clipboard-check",
"fal fa-clipboard-list",
"fal fa-clock",
"fal fa-clone",
"fal fa-closed-captioning",
"fal fa-cloud",
"fal fa-cloud-download",
"fal fa-cloud-download-alt",
"fal fa-cloud-upload",
"fal fa-cloud-upload-alt",
"fal fa-club",
"fal fa-code",
"fal fa-code-branch",
"fal fa-code-commit",
"fal fa-code-merge",
"fal fa-coffee",
"fal fa-cog",
"fal fa-cogs",
"fal fa-columns",
"fal fa-comment",
"fal fa-comment-alt",
"fal fa-comment-alt-check",
"fal fa-comment-alt-dots",
"fal fa-comment-alt-edit",
"fal fa-comment-alt-exclamation",
"fal fa-comment-alt-lines",
"fal fa-comment-alt-minus",
"fal fa-comment-alt-plus",
"fal fa-comment-alt-slash",
"fal fa-comment-alt-smile",
"fal fa-comment-alt-times",
"fal fa-comment-check",
"fal fa-comment-dots",
"fal fa-comment-edit",
"fal fa-comment-exclamation",
"fal fa-comment-lines",
"fal fa-comment-minus",
"fal fa-comment-plus",
"fal fa-comment-slash",
"fal fa-comment-smile",
"fal fa-comment-times",
"fal fa-comments",
"fal fa-comments-alt",
"fal fa-compass",
"fal fa-compress",
"fal fa-compress-alt",
"fal fa-compress-wide",
"fal fa-container-storage",
"fal fa-conveyor-belt",
"fal fa-conveyor-belt-alt",
"fal fa-copy",
"fal fa-copyright",
"fal fa-couch",
"fal fa-credit-card",
"fal fa-credit-card-blank",
"fal fa-credit-card-front",
"fal fa-cricket",
"fal fa-crop",
"fal fa-crosshairs",
"fal fa-cube",
"fal fa-cubes",
"fal fa-curling",
"fal fa-cut",
"fal fa-database",
"fal fa-deaf",
"fal fa-desktop",
"fal fa-desktop-alt",
"fal fa-diagnoses",
"fal fa-diamond",
"fal fa-dna",
"fal fa-dollar-sign",
"fal fa-dolly",
"fal fa-dolly-empty",
"fal fa-dolly-flatbed",
"fal fa-dolly-flatbed-alt",
"fal fa-dolly-flatbed-empty",
"fal fa-donate",
"fal fa-dot-circle",
"fal fa-dove",
"fal fa-download",
"fal fa-dumbbell",
"fal fa-edit",
"fal fa-eject",
"fal fa-ellipsis-h",
"fal fa-ellipsis-h-alt",
"fal fa-ellipsis-v",
"fal fa-ellipsis-v-alt",
"fal fa-envelope",
"fal fa-envelope-open",
"fal fa-envelope-square",
"fal fa-eraser",
"fal fa-euro-sign",
"fal fa-exchange",
"fal fa-exchange-alt",
"fal fa-exclamation",
"fal fa-exclamation-circle",
"fal fa-exclamation-square",
"fal fa-exclamation-triangle",
"fal fa-expand",
"fal fa-expand-alt",
"fal fa-expand-arrows",
"fal fa-expand-arrows-alt",
"fal fa-expand-wide",
"fal fa-external-link",
"fal fa-external-link-alt",
"fal fa-external-link-square",
"fal fa-external-link-square-alt",
"fal fa-eye",
"fal fa-eye-dropper",
"fal fa-eye-slash",
"fal fa-fast-backward",
"fal fa-fast-forward",
"fal fa-fax",
"fal fa-female",
"fal fa-field-hockey",
"fal fa-fighter-jet",
"fal fa-file",
"fal fa-file-alt",
"fal fa-file-archive",
"fal fa-file-audio",
"fal fa-file-check",
"fal fa-file-code",
"fal fa-file-edit",
"fal fa-file-excel",
"fal fa-file-exclamation",
"fal fa-file-image",
"fal fa-file-medical",
"fal fa-file-medical-alt",
"fal fa-file-minus",
"fal fa-file-pdf",
"fal fa-file-plus",
"fal fa-file-powerpoint",
"fal fa-file-times",
"fal fa-file-video",
"fal fa-file-word",
"fal fa-film",
"fal fa-film-alt",
"fal fa-filter",
"fal fa-fire",
"fal fa-fire-extinguisher",
"fal fa-first-aid",
"fal fa-flag",
"fal fa-flag-checkered",
"fal fa-flask",
"fal fa-folder",
"fal fa-folder-open",
"fal fa-font",
"fal fa-football-ball",
"fal fa-football-helmet",
"fal fa-forklift",
"fal fa-forward",
"fal fa-fragile",
"fal fa-frown",
"fal fa-futbol",
"fal fa-gamepad",
"fal fa-gavel",
"fal fa-gem",
"fal fa-genderless",
"fal fa-gift",
"fal fa-glass-martini",
"fal fa-globe",
"fal fa-golf-ball",
"fal fa-golf-club",
"fal fa-graduation-cap",
"fal fa-h-square",
"fal fa-h1",
"fal fa-h2",
"fal fa-h3",
"fal fa-hand-heart",
"fal fa-hand-holding",
"fal fa-hand-holding-box",
"fal fa-hand-holding-heart",
"fal fa-hand-holding-seedling",
"fal fa-hand-holding-usd",
"fal fa-hand-holding-water",
"fal fa-hand-lizard",
"fal fa-hand-paper",
"fal fa-hand-peace",
"fal fa-hand-point-down",
"fal fa-hand-point-left",
"fal fa-hand-point-right",
"fal fa-hand-point-up",
"fal fa-hand-pointer",
"fal fa-hand-receiving",
"fal fa-hand-rock",
"fal fa-hand-scissors",
"fal fa-hand-spock",
"fal fa-hands",
"fal fa-hands-heart",
"fal fa-hands-helping",
"fal fa-hands-usd",
"fal fa-handshake",
"fal fa-handshake-alt",
"fal fa-hashtag",
"fal fa-hdd",
"fal fa-heading",
"fal fa-headphones",
"fal fa-heart",
"fal fa-heart-circle",
"fal fa-heart-square",
"fal fa-heartbeat",
"fal fa-hexagon",
"fal fa-history",
"fal fa-hockey-puck",
"fal fa-hockey-sticks",
"fal fa-home",
"fal fa-home-heart",
"fal fa-hospital",
"fal fa-hospital-alt",
"fal fa-hospital-symbol",
"fal fa-hourglass",
"fal fa-hourglass-end",
"fal fa-hourglass-half",
"fal fa-hourglass-start",
"fal fa-i-cursor",
"fal fa-id-badge",
"fal fa-id-card",
"fal fa-id-card-alt",
"fal fa-image",
"fal fa-images",
"fal fa-inbox",
"fal fa-inbox-in",
"fal fa-inbox-out",
"fal fa-indent",
"fal fa-industry",
"fal fa-industry-alt",
"fal fa-info",
"fal fa-info-circle",
"fal fa-info-square",
"fal fa-inventory",
"fal fa-italic",
"fal fa-jack-o-lantern",
"fal fa-key",
"fal fa-keyboard",
"fal fa-lamp",
"fal fa-language",
"fal fa-laptop",
"fal fa-leaf",
"fal fa-leaf-heart",
"fal fa-lemon",
"fal fa-level-down",
"fal fa-level-down-alt",
"fal fa-level-up",
"fal fa-level-up-alt",
"fal fa-life-ring",
"fal fa-lightbulb",
"fal fa-link",
"fal fa-lira-sign",
"fal fa-list",
"fal fa-list-alt",
"fal fa-list-ol",
"fal fa-list-ul",
"fal fa-location-arrow",
"fal fa-lock",
"fal fa-lock-alt",
"fal fa-lock-open",
"fal fa-lock-open-alt",
"fal fa-long-arrow-alt-down",
"fal fa-long-arrow-alt-left",
"fal fa-long-arrow-alt-right",
"fal fa-long-arrow-alt-up",
"fal fa-long-arrow-down",
"fal fa-long-arrow-left",
"fal fa-long-arrow-right",
"fal fa-long-arrow-up",
"fal fa-loveseat",
"fal fa-low-vision",
"fal fa-luchador",
"fal fa-magic",
"fal fa-magnet",
"fal fa-male",
"fal fa-map",
"fal fa-map-marker",
"fal fa-map-marker-alt",
"fal fa-map-pin",
"fal fa-map-signs",
"fal fa-mars",
"fal fa-mars-double",
"fal fa-mars-stroke",
"fal fa-mars-stroke-h",
"fal fa-mars-stroke-v",
"fal fa-medkit",
"fal fa-meh",
"fal fa-mercury",
"fal fa-microchip",
"fal fa-microphone",
"fal fa-microphone-alt",
"fal fa-microphone-slash",
"fal fa-minus",
"fal fa-minus-circle",
"fal fa-minus-hexagon",
"fal fa-minus-octagon",
"fal fa-minus-square",
"fal fa-mobile",
"fal fa-mobile-alt",
"fal fa-mobile-android",
"fal fa-mobile-android-alt",
"fal fa-money-bill",
"fal fa-money-bill-alt",
"fal fa-moon",
"fal fa-motorcycle",
"fal fa-mouse-pointer",
"fal fa-music",
"fal fa-neuter",
"fal fa-newspaper",
"fal fa-notes-medical",
"fal fa-object-group",
"fal fa-object-ungroup",
"fal fa-octagon",
"fal fa-outdent",
"fal fa-paint-brush",
"fal fa-pallet",
"fal fa-pallet-alt",
"fal fa-paper-plane",
"fal fa-paperclip",
"fal fa-parachute-box",
"fal fa-paragraph",
"fal fa-paste",
"fal fa-pause",
"fal fa-pause-circle",
"fal fa-paw",
"fal fa-pen",
"fal fa-pen-alt",
"fal fa-pen-square",
"fal fa-pencil",
"fal fa-pencil-alt",
"fal fa-pennant",
"fal fa-people-carry",
"fal fa-percent",
"fal fa-person-carry",
"fal fa-person-dolly",
"fal fa-person-dolly-empty",
"fal fa-phone",
"fal fa-phone-plus",
"fal fa-phone-slash",
"fal fa-phone-square",
"fal fa-phone-volume",
"fal fa-piggy-bank",
"fal fa-pills",
"fal fa-plane",
"fal fa-plane-alt",
"fal fa-play",
"fal fa-layer-group",
"fal fa-play-circle",
"fal fa-plug",
"fal fa-plus",
"fal fa-plus-circle",
"fal fa-plus-hexagon",
"fal fa-plus-octagon",
"fal fa-plus-square",
"fal fa-podcast",
"fal fa-poo",
"fal fa-portrait",
"fal fa-pound-sign",
"fal fa-power-off",
"fal fa-prescription-bottle",
"fal fa-prescription-bottle-alt",
"fal fa-print",
"fal fa-procedures",
"fal fa-puzzle-piece",
"fal fa-qrcode",
"fal fa-question",
"fal fa-question-circle",
"fal fa-question-square",
"fal fa-quidditch",
"fal fa-quote-left",
"fal fa-quote-right",
"fal fa-racquet",
"fal fa-ramp-loading",
"fal fa-random",
"fal fa-rectangle-landscape",
"fal fa-rectangle-portrait",
"fal fa-rectangle-wide",
"fal fa-recycle",
"fal fa-redo",
"fal fa-redo-alt",
"fal fa-registered",
"fal fa-repeat",
"fal fa-repeat-1",
"fal fa-repeat-1-alt",
"fal fa-repeat-alt",
"fal fa-reply",
"fal fa-reply-all",
"fal fa-retweet",
"fal fa-retweet-alt",
"fal fa-ribbon",
"fal fa-road",
"fal fa-rocket",
"fal fa-route",
"fal fa-rss",
"fal fa-rss-square",
"fal fa-ruble-sign",
"fal fa-rupee-sign",
"fal fa-save",
"fal fa-scanner",
"fal fa-scanner-keyboard",
"fal fa-scanner-touchscreen",
"fal fa-scrubber",
"fal fa-search",
"fal fa-search-minus",
"fal fa-search-plus",
"fal fa-seedling",
"fal fa-server",
"fal fa-share",
"fal fa-share-all",
"fal fa-share-alt",
"fal fa-share-alt-square",
"fal fa-share-square",
"fal fa-shekel-sign",
"fal fa-shield",
"fal fa-shield-alt",
"fal fa-shield-check",
"fal fa-ship",
"fal fa-shipping-fast",
"fal fa-shipping-timed",
"fal fa-shopping-bag",
"fal fa-shopping-basket",
"fal fa-shopping-cart",
"fal fa-shower",
"fal fa-shuttlecock",
"fal fa-sign",
"fal fa-sign-in",
"fal fa-sign-in-alt",
"fal fa-sign-language",
"fal fa-sign-out",
"fal fa-sign-out-alt",
"fal fa-signal",
"fal fa-sitemap",
"fal fa-sliders-h",
"fal fa-sliders-h-square",
"fal fa-sliders-v",
"fal fa-sliders-v-square",
"fal fa-smile",
"fal fa-smile-plus",
"fal fa-smoking",
"fal fa-snowflake",
"fal fa-sort",
"fal fa-sort-alpha-down",
"fal fa-sort-alpha-up",
"fal fa-sort-amount-down",
"fal fa-sort-amount-up",
"fal fa-sort-down",
"fal fa-sort-numeric-down",
"fal fa-sort-numeric-up",
"fal fa-sort-up",
"fal fa-space-shuttle",
"fal fa-spade",
"fal fa-spinner",
"fal fa-spinner-third",
"fal fa-square",
"fal fa-square-full",
"fal fa-star",
"fal fa-star-exclamation",
"fal fa-star-half",
"fal fa-step-backward",
"fal fa-step-forward",
"fal fa-stethoscope",
"fal fa-sticky-note",
"fal fa-stop",
"fal fa-stop-circle",
"fal fa-stopwatch",
"fal fa-street-view",
"fal fa-strikethrough",
"fal fa-subscript",
"fal fa-subway",
"fal fa-suitcase",
"fal fa-sun",
"fal fa-superscript",
"fal fa-sync",
"fal fa-sync-alt",
"fal fa-syringe",
"fal fa-table",
"fal fa-table-tennis",
"fal fa-tablet",
"fal fa-tablet-alt",
"fal fa-tablet-android",
"fal fa-tablet-android-alt",
"fal fa-tablet-rugged",
"fal fa-tablets",
"fal fa-tachometer",
"fal fa-tachometer-alt",
"fal fa-tag",
"fal fa-tags",
"fal fa-tape",
"fal fa-tasks",
"fal fa-taxi",
"fal fa-tennis-ball",
"fal fa-terminal",
"fal fa-text-height",
"fal fa-text-width",
"fal fa-th",
"fal fa-th-large",
"fal fa-th-list",
"fal fa-thermometer",
"fal fa-thermometer-empty",
"fal fa-thermometer-full",
"fal fa-thermometer-half",
"fal fa-thermometer-quarter",
"fal fa-thermometer-three-quarters",
"fal fa-thumbs-down",
"fal fa-thumbs-up",
"fal fa-thumbtack",
"fal fa-ticket",
"fal fa-ticket-alt",
"fal fa-times",
"fal fa-times-circle",
"fal fa-times-hexagon",
"fal fa-times-octagon",
"fal fa-times-square",
"fal fa-tint",
"fal fa-toggle-off",
"fal fa-toggle-on",
"fal fa-trademark",
"fal fa-train",
"fal fa-transgender",
"fal fa-transgender-alt",
"fal fa-trash",
"fal fa-trash-alt",
"fal fa-tree",
"fal fa-tree-alt",
"fal fa-triangle",
"fal fa-trophy",
"fal fa-trophy-alt",
"fal fa-truck",
"fal fa-truck-container",
"fal fa-truck-couch",
"fal fa-truck-loading",
"fal fa-truck-moving",
"fal fa-truck-ramp",
"fal fa-tty",
"fal fa-tv",
"fal fa-tv-retro",
"fal fa-umbrella",
"fal fa-underline",
"fal fa-undo",
"fal fa-undo-alt",
"fal fa-universal-access",
"fal fa-university",
"fal fa-unlink",
"fal fa-unlock",
"fal fa-unlock-alt",
"fal fa-upload",
"fal fa-usd-circle",
"fal fa-usd-square",
"fal fa-user",
"fal fa-user-alt",
"fal fa-user-circle",
"fal fa-user-md",
"fal fa-user-plus",
"fal fa-user-secret",
"fal fa-user-times",
"fal fa-users",
"fal fa-utensil-fork",
"fal fa-utensil-knife",
"fal fa-utensil-spoon",
"fal fa-utensils",
"fal fa-utensils-alt",
"fal fa-venus",
"fal fa-venus-double",
"fal fa-venus-mars",
"fal fa-vial",
"fal fa-vials",
"fal fa-video",
"fal fa-video-plus",
"fal fa-video-slash",
"fal fa-volleyball-ball",
"fal fa-volume-down",
"fal fa-volume-mute",
"fal fa-volume-off",
"fal fa-volume-up",
"fal fa-warehouse",
"fal fa-warehouse-alt",
"fal fa-watch",
"fal fa-weight",
"fal fa-wheelchair",
"fal fa-whistle",
"fal fa-wifi",
"fal fa-window",
"fal fa-window-alt",
"fal fa-window-close",
"fal fa-window-maximize",
"fal fa-window-minimize",
"fal fa-window-restore",
"fal fa-wine-glass",
"fal fa-won-sign",
"fal fa-wrench",
"fal fa-x-ray"
];
export default dv_icons_list;

+ 0
- 443
datavalue_theme_14/public/js/frappe/ui/notifications/notifications.js Переглянути файл

@@ -1,443 +0,0 @@
frappe.provide('frappe.search');

frappe.ui.Notifications = class Notifications {
constructor() {
this.tabs = {};
this.notification_settings = frappe.boot.notification_settings;
this.make();
}

make() {
this.dropdown = $('.dv-navbar.datavalue-nav').find('.dv-dropdown-notifications').removeClass('hidden');
this.dropdown_list = this.dropdown.find('.notifications-list');
this.header_items = this.dropdown_list.find('.header-items').html('');
this.header_actions = this.dropdown_list.find('.header-actions').html('');
this.body = this.dropdown_list.find('.notification-list-body');
this.panel_events = this.dropdown_list.find('.panel-events');
this.panel_notifications = this.dropdown_list.find('.panel-notifications');

this.user = frappe.session.user;

this.setup_headers();
this.setup_dropdown_events();
}

setup_headers() {
// Add header actions
$(`<span class="notification-settings pull-right" data-action="go_to_settings">
${frappe.utils.icon('setting-gear')}
</span>`)
.on('click', (e) => {
e.stopImmediatePropagation();
this.dropdown.dropdown('hide');
frappe.set_route('Form', 'Notification Settings', frappe.session.user);
}).appendTo(this.header_actions)
.attr('title', __("Notification Settings"))
.tooltip({delay: {"show": 600, "hide": 100}, trigger: "hover"});

$(`<span class="mark-all-read pull-right" data-action="mark_all_as_read">
${frappe.utils.icon('mark-as-read')}
</span>`)
.on('click', (e) => this.mark_all_as_read(e))
.appendTo(this.header_actions)
.attr('title', __("Mark all as read"))
.tooltip({delay: {"show": 600, "hide": 100}, trigger: "hover"});

this.categories = [
{
label: __("Notifications"),
id: "notifications",
view: NotificationsView,
el: this.panel_notifications,
},
{
label: __("Today's Events"),
id: "todays_events",
view: EventsView,
el: this.panel_events,
}
];

let get_headers_html = (item) => {
let active = item.id == "notifications" ? 'active' : '';

let html = `<li class="notifications-category ${active}"
id="${item.id}"
data-toggle="collapse"
>${item.label}</li>`;

return html;
};

let navitem = $(`<ul class="notification-item-tabs nav nav-tabs" role="tablist"></ul>`);
this.categories = this.categories.map(item => {
item.$tab = $(get_headers_html(item));
item.$tab.on('click', (e) => {
e.stopImmediatePropagation();
this.switch_tab(item);
});
navitem.append(item.$tab);

return item;
});
navitem.appendTo(this.header_items);
this.categories.forEach(category => {
this.make_tab_view(category);
});
this.switch_tab(this.categories[0]);
}

switch_tab(item) {
// Set active tab
this.categories.forEach((item) => {
item.$tab.removeClass("active");
});

item.$tab.addClass("active");

// Hide other tabs
Object.keys(this.tabs).forEach(tab_name => this.tabs[tab_name].hide());
this.tabs[item.id].show();
}

make_tab_view(item) {
let tabView = new item.view(
item.el,
this.dropdown,
this.notification_settings
);
this.tabs[item.id] = tabView;
}

mark_all_as_read(e) {
e.stopImmediatePropagation();
this.dropdown_list.find('.unread').removeClass('unread');
frappe.call(
'frappe.desk.doctype.notification_log.notification_log.mark_all_as_read',
);
}

setup_dropdown_events() {
this.dropdown.on('hide.bs.dropdown', e => {
let hide = $(e.currentTarget).data('closable');
$(e.currentTarget).data('closable', true);
return hide;
});

this.dropdown.on('click', e => {
$(e.currentTarget).data('closable', true);
});
}
};


frappe.ui.notifications = {
get_notification_config() {
return frappe.xcall('frappe.desk.notifications.get_notification_info').then(r => {
frappe.ui.notifications.config = r;
return r;
});
},

show_open_count_list(doctype) {
if (!frappe.ui.notifications.config) {
this.get_notification_config().then(() => {
this.route_to_list_with_filters(doctype);
});
} else {
this.route_to_list_with_filters(doctype);
}
},

route_to_list_with_filters(doctype) {
let filters = frappe.ui.notifications.config['conditions'][doctype];
if (filters && $.isPlainObject(filters)) {
if (!frappe.route_options) {
frappe.route_options = {};
}
$.extend(frappe.route_options, filters);
}
frappe.set_route('List', doctype);
}
};

class BaseNotificationsView {
constructor(wrapper, parent, settings) {
// wrapper, max_length
this.wrapper = wrapper;
this.parent = parent;
this.settings = settings;
this.max_length = 20;
this.wrapper.html('');
this.container = $(`<div></div>`).appendTo(this.wrapper);
this.make();
}

show() {
this.container.show();
}

hide() {
this.container.hide();
}
}

class NotificationsView extends BaseNotificationsView {
make() {
this.notifications_icon = this.parent.find('.notifications-icon');
this.notifications_icon.attr("title", __('Notifications')).tooltip(
{delay: {"show": 600, "hide": 100}, trigger: "hover"}
);

this.setup_notification_listeners();
this.get_notifications_list(this.max_length).then(list => {
this.dropdown_items = list;
this.render_notifications_dropdown();
if (this.settings.seen == 0) {
this.toggle_notification_icon(false);
}
});

}

update_dropdown() {
this.get_notifications_list(1).then(r => {
let new_item = r[0];
this.dropdown_items.unshift(new_item);
if (this.dropdown_items.length > this.max_length) {
this.container
.find('.recent-notification')
.last()
.remove();
this.dropdown_items.pop();
}

this.insert_into_dropdown();
});
}

change_activity_status() {
if (this.container.find('.activity-status')) {
this.container.find('.activity-status').replaceWith(
`<a class="recent-item text-center text-muted"
href="/app/List/Notification Log">
<div class="full-log-btn">${__('View Full Log')}</div>
</a>`
);
}
}

mark_as_read(docname, $el) {
frappe.call(
'frappe.desk.doctype.notification_log.notification_log.mark_as_read',
{docname: docname}
).then(() => {
$el.removeClass('unread');
});
}

insert_into_dropdown() {
let new_item = this.dropdown_items[0];
let new_item_html = this.get_dropdown_item_html(new_item);
$(new_item_html).prependTo(this.container);
this.change_activity_status();
}

get_dropdown_item_html(field) {
let doc_link = this.get_item_link(field);

let read_class = field.read ? '' : 'unread';
let message = field.subject;

let title = message.match(/<b class="subject-title">(.*?)<\/b>/);
message = title ? message.replace(title[1], frappe.ellipsis(strip_html(title[1]), 100)) : message;

let timestamp = frappe.datetime.comment_when(field.creation);
let message_html = `<div class="message">
<div>${message}</div>
<div class="notification-timestamp text-muted">
${timestamp}
</div>
</div>`;

let user = field.from_user;
let user_avatar = frappe.avatar(user, 'avatar-medium user-avatar');

let item_html =
$(`<a class="recent-item notification-item ${read_class}"
href="${doc_link}"
data-name="${field.name}"
>
<div class="notification-body">
${user_avatar}
${message_html}
</div>
<div class="mark-as-read" title="${__("Mark as Read")}">
</div>
</a>`);

if (!field.read) {
let mark_btn = item_html.find(".mark-as-read");
mark_btn.tooltip({delay: {"show": 600, "hide": 100}, trigger: "hover"});
mark_btn.on('click', (e) => {
e.preventDefault();
e.stopImmediatePropagation();
this.mark_as_read(field.name, item_html);
});

item_html.on('click', () => {
this.mark_as_read(field.name, item_html);
});
}

return item_html;
}

render_notifications_dropdown() {
if (this.settings && !this.settings.enabled) {
this.container.html(`<li class="recent-item notification-item">
<span class="text-muted">
${__('Notifications Disabled')}
</span></li>`);
} else {
if (this.dropdown_items.length) {
this.container.empty();
this.dropdown_items.forEach(field => {
this.container.append(this.get_dropdown_item_html(field));
});
this.container.append(`<a class="list-footer"
href="/app/List/Notification Log">
<div class="full-log-btn">${__('See all Activity')}</div>
</a>`);
} else {
this.container.append($(`<div class="notification-null-state">
<div class="text-center">
<img src="/assets/frappe/images/ui-states/notification-empty-state.svg" alt="Generic Empty State" class="null-state">
<div class="title">${__('No New notifications')}</div>
<div class="subtitle">
${__('Looks like you haven’t received any notifications.')}
</div></div></div>`));
}
}
}

get_notifications_list(limit) {
return frappe.db.get_list('Notification Log', {
fields: ['*'],
limit: limit,
order_by: 'creation desc'
});
}

get_item_link(notification_doc) {
const link_doctype =
notification_doc.type == 'Alert' ? 'Notification Log' : notification_doc.document_type;
const link_docname =
notification_doc.type == 'Alert' ? notification_doc.name : notification_doc.document_name;
return frappe.utils.get_form_link(
link_doctype,
link_docname
);
}

toggle_notification_icon(seen) {
this.notifications_icon.find('.notifications-seen').toggle(seen);
this.notifications_icon.find('.notifications-unseen').toggle(!seen);
}

toggle_seen(flag) {
frappe.call(
'frappe.desk.doctype.notification_settings.notification_settings.set_seen_value',
{
value: cint(flag),
user: frappe.session.user
}
);
}

setup_notification_listeners() {
frappe.realtime.on('notification', () => {
this.toggle_notification_icon(false);
this.update_dropdown();
});

frappe.realtime.on('indicator_hide', () => {
this.toggle_notification_icon(true);
});

this.parent.on('show.bs.dropdown', () => {
this.toggle_seen(true);
if (this.notifications_icon.find('.notifications-unseen').is(':visible')) {
this.toggle_notification_icon(true);
frappe.call(
'frappe.desk.doctype.notification_log.notification_log.trigger_indicator_hide'
);
}
});

}
}

class EventsView extends BaseNotificationsView {
make() {
let today = frappe.datetime.get_today();
frappe.xcall('frappe.desk.doctype.event.event.get_events', {
start: today,
end: today
}).then(event_list => {
this.render_events_html(event_list);
});
}

render_events_html(event_list) {
let html = '';
if (event_list.length) {
let get_event_html = (event) => {
let time = __("All Day");
if (!event.all_day) {
let start_time = frappe.datetime.get_time(event.starts_on);
let days_diff = frappe.datetime.get_day_diff(event.ends_on, event.starts_on);
let end_time = frappe.datetime.get_time(event.ends_on);
if (days_diff > 1) {
end_time = __("Rest of the day");
}
time = `${start_time} - ${end_time}`;
}

// REDESIGN-TODO: Add Participants to get_events query
let particpants = '';
if (event.particpants) {
particpants = frappe.avatar_group(event.particpants, 3);
}

// REDESIGN-TODO: Add location to calendar field
let location = '';
if (event.location) {
location = `, ${event.location}`;
}

return `<a class="recent-item event" href="/app/event/${event.name}">
<div class="event-border" style="border-color: ${event.color}"></div>
<div class="event-item">
<div class="event-subject">${event.subject}</div>
<div class="event-time">${time}${location}</div>
${particpants}
</div>
</a>`;
};
html = event_list.map(get_event_html).join('');
} else {
html = `
<div class="notification-null-state">
<div class="text-center">
<img src="/assets/frappe/images/ui-states/event-empty-state.svg" alt="Generic Empty State" class="null-state">
<div class="title">${__('No Upcoming Events')}</div>
<div class="subtitle">
${__('There are no upcoming events for you.')}
</div></div></div>
`;
}

this.container.html(html);
}
}

+ 0
- 84
datavalue_theme_14/public/js/frappe/ui/page.html Переглянути файл

@@ -1,84 +0,0 @@
<div class="page-head flex">
<div class="container">
<div class="row flex align-center page-head-content justify-between">
<div class="col-md-4 col-sm-6 col-xs-8 page-title">
<!-- <div class="title-image hide hidden-md hidden-lg"></div> -->
<!-- title -->
<span class="sidebar-toggle-btn show-in-mobile-lg">
<svg class="icon icon-md sidebar-toggle-placeholder">
<use xlink:href="#icon-menu"></use>
</svg>
<span class="sidebar-toggle-icon">
<svg class="icon icon-md">
<use xlink:href="#icon-sidebar-collapse">
</use>
</svg>
</span>
</span>
<button type="button" class="btn-toggle-main-menu menu-shown"><i class="far fa-bars"></i></button>
<div class="flex fill-width title-area">
<div>
<div class="flex">
<h3 class="ellipsis title-text"></h3>
<span class="indicator-pill whitespace-nowrap"></span>
</div>
<div class="ellipsis sub-heading hide text-muted"></div>
</div>
<button class="btn btn-default more-button hide">
<svg class="icon icon-sm">
<use xlink:href="#icon-dot-horizontal">
</use>
</svg>
</button>
</div>
</div>
<div class="flex col page-actions justify-content-end">
<!-- buttons -->
<div class="custom-actions hide hidden-xs hidden-md"></div>
<div class="standard-actions flex">
<span class="page-icon-group hide hidden-xs hidden-sm"></span>
<div class="menu-btn-group hide">
<button type="button" class="btn btn-default icon-btn" data-toggle="dropdown" aria-expanded="false">
<span>
<span class="menu-btn-group-label">
<svg class="icon icon-sm">
<use xlink:href="#icon-dot-horizontal">
</use>
</svg>
</span>
</span>
</button>
<ul class="dropdown-menu dropdown-menu-right" role="menu"></ul>
</div>
<button class="btn btn-secondary btn-default btn-sm hide"></button>
<div class="actions-btn-group hide">
<button type="button" class="btn btn-primary btn-sm" data-toggle="dropdown" aria-expanded="false">
<span class="hidden-xs">
<span class="actions-btn-group-label">{%= __("Actions") %}</span>
<svg class="icon icon-xs">
<use xlink:href="#icon-select">
</use>
</svg>
</span>
</button>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
</ul>
</div>
<button class="btn btn-primary btn-sm hide primary-action"></button>
</div>
</div>
</div>
</div>
</div>
<div class="container page-body">
<div class="page-toolbar hide">
<div class="container">
</div>
</div>
<div class="page-wrapper">
<div class="page-content">
<div class="workflow-button-area btn-group pull-right hide"></div>
<div class="clearfix"></div>
</div>
</div>
</div>

+ 0
- 911
datavalue_theme_14/public/js/frappe/ui/page.js Переглянути файл

@@ -1,911 +0,0 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

/**
* Make a standard page layout with a toolbar and title
*
* @param {Object} opts
*
* @param {string} opts.parent [HTMLElement] Parent element
* @param {boolean} opts.single_column Whether to include sidebar
* @param {string} [opts.title] Page title
* @param {Object} [opts.make_page]
*
* @returns {frappe.ui.Page}
*/

/**
* @typedef {Object} frappe.ui.Page
*/


frappe.ui.make_app_page = function (opts) {
opts.parent.page = new frappe.ui.Page(opts);
return opts.parent.page;
}

frappe.ui.pages = {};

frappe.ui.Page = Class.extend({
init: function (opts) {
$.extend(this, opts);

this.set_document_title = true;
this.buttons = {};
this.fields_dict = {};
this.views = {};

this.make();
frappe.ui.pages[frappe.get_route_str()] = this;
},

make: function () {
this.wrapper = $(this.parent);
this.add_main_section();
this.setup_scroll_handler();
this.setup_sidebar_toggle();
},

setup_scroll_handler() {
window.addEventListener('scroll', () => {
if (document.documentElement.scrollTop >= 60) {
$('.page-head').toggleClass('drop-shadow', true);
} else {
$('.page-head').removeClass('drop-shadow');
}
});
},

get_empty_state: function (title, message, primary_action) {
let $empty_state = $(`<div class="page-card-container">
<div class="page-card">
<div class="page-card-head">
<span class="indicator blue">
${title}</span>
</div>
<p>${message}</p>
<div>
<button class="btn btn-primary btn-sm">${primary_action}</button>
</div>
</div>
</div>`);

return $empty_state;
},

load_lib: function (callback) {
frappe.require(this.required_libs, callback);
},

add_main_section: function () {
$(frappe.render_template("page", {})).appendTo(this.wrapper);
if (this.single_column) {
// nesting under col-sm-12 for consistency
this.add_view("main", `<div class="row layout-main">
<div class="col-md-12 layout-main-section-wrapper">
<div class="layout-main-section"></div>
<div class="layout-footer hide"></div>
</div>
</div>`);
} else {
this.add_view("main", `
<div class="row layout-main">
<div class="col-lg-2 layout-side-section"></div>
<div class="col layout-main-section-wrapper">
<div class="layout-main-section"></div>
<div class="layout-footer hide"></div>
</div>
</div>
`);
}

this.setup_page();
},

setup_page: function () {
let $this = this;
this.$title_area = this.wrapper.find(".title-area");

this.$sub_title_area = this.wrapper.find("h6");

if (this.title)
this.set_title(this.title);

if (this.icon)
this.get_main_icon(this.icon);

this.body = this.main = this.wrapper.find(".layout-main-section");
this.container = this.wrapper.find(".page-body");
this.sidebar = this.wrapper.find(".layout-side-section");
this.footer = this.wrapper.find(".layout-footer");
this.indicator = this.wrapper.find(".indicator-pill");

this.page_actions = this.wrapper.find(".page-actions");

this.btn_primary = this.page_actions.find(".primary-action");
this.btn_secondary = this.page_actions.find(".btn-secondary");

this.menu = this.page_actions.find(".menu-btn-group .dropdown-menu");
this.menu_btn_group = this.page_actions.find(".menu-btn-group");

this.actions = this.page_actions.find(".actions-btn-group .dropdown-menu");
this.actions_btn_group = this.page_actions.find(".actions-btn-group");

this.standard_actions = this.page_actions.find(".standard-actions");
this.custom_actions = this.page_actions.find(".custom-actions");

this.page_form = $('<div class="page-form row hide"></div>').prependTo(this.main);
this.inner_toolbar = this.custom_actions;
this.icon_group = this.page_actions.find(".page-icon-group");

if (this.make_page) {
this.make_page();
}

this.card_layout && this.main.addClass('frappe-card');

// keyboard shortcuts
let menu_btn = this.menu_btn_group.find('button');
menu_btn.attr("title", __("Menu")).tooltip({delay: {"show": 600, "hide": 100}});
frappe.ui.keys.get_shortcut_group(this.page_actions[0]).add(menu_btn, menu_btn.find('.menu-btn-group-label'));

let action_btn = this.actions_btn_group.find('button');
frappe.ui.keys.get_shortcut_group(this.page_actions[0]).add(action_btn, action_btn.find('.actions-btn-group-label'));

let route = frappe.get_route();
let sidebar_wrapper = this.wrapper.find('.layout-side-section');
this.body.append('<button type="button" class="btn-toggle-sidebar sidebar-shown"><i class="far fa-angle-right"></i></button>');
this.page_container = this.body.parents('.page-container');

// if (this.sidebar.length) {
// console.log('Hide this.sidebar', this.sidebar)
// this.sidebar.hide();
// }


if (route && route.length && route[0]) {
if (route[0] != 'Workspaces' && route[0] != 'query-report' && route[0] != 'Tree') {
if (frappe.utils.is_xs() || frappe.utils.is_sm()) {

} else {
setTimeout(() => $('.btn-toggle-sidebar', this.page_container).trigger('click'), 250);
}
$('.btn-toggle-sidebar', this.page_container).show();
} else {
$('.btn-toggle-sidebar', this.page_container).hide();
}
} else {
$('.btn-toggle-sidebar', this.page_container).hide();
}

$(this.page_container).on('click', '.btn-toggle-sidebar', function () {
if ($(this).hasClass('sidebar-shown')) {
$(this).removeClass('sidebar-shown');
} else {
$(this).addClass('sidebar-shown');
}
if (frappe.utils.is_xs() || frappe.utils.is_sm()) {
$this.setup_overlay_sidebar();
} else {
sidebar_wrapper.toggle();
}
$(document.body).trigger('toggleSidebar');
});

},

setup_sidebar_toggle() {
let sidebar_toggle = $('.page-head').find('.sidebar-toggle-btn');
let sidebar_wrapper = this.wrapper.find('.layout-side-section');
if (this.disable_sidebar_toggle || !sidebar_wrapper.length) {
sidebar_toggle.remove();
} else {
if ($(window).width() > 1024) {
sidebar_toggle.attr("title", __("Toggle Sidebar")).tooltip({
delay: {"show": 600, "hide": 100},
trigger: "hover",
});
}
sidebar_toggle.click(() => {
if (frappe.utils.is_xs() || frappe.utils.is_sm()) {
this.setup_overlay_sidebar();
} else {
sidebar_wrapper.toggle();
}
$(document.body).trigger('toggleSidebar');
this.update_sidebar_icon();
});
}
},

setup_overlay_sidebar() {
let overlay_sidebar = this.sidebar.find('.overlay-sidebar').addClass('opened');
$('<div class="close-sidebar">').hide().appendTo(this.sidebar).fadeIn();
let scroll_container = $('html').css("overflow-y", "hidden");

this.sidebar.find(".close-sidebar").on('click', (e) => close_sidebar(e));
this.sidebar.on("click", "button:not(.dropdown-toggle)", (e) => close_sidebar(e));

let close_sidebar = () => {
scroll_container.css("overflow-y", "");
this.sidebar.find("div.close-sidebar").fadeOut(() => {
overlay_sidebar.removeClass('opened').find('.dropdown-toggle').removeClass('text-muted');
});
};
},

update_sidebar_icon() {
let sidebar_toggle = $('.page-head').find('.sidebar-toggle-btn');
let sidebar_toggle_icon = sidebar_toggle.find('.sidebar-toggle-icon');
let sidebar_wrapper = this.wrapper.find('.layout-side-section');
let is_sidebar_visible = $(sidebar_wrapper).is(":visible");
sidebar_toggle_icon.html(frappe.utils.icon(is_sidebar_visible ? 'sidebar-collapse' : 'sidebar-expand', 'md'));
},

set_indicator: function (label, color) {
this.clear_indicator().removeClass("hide").html(`<span>${label}</span>`).addClass(color);
},

add_action_icon: function (icon, click, css_class = '', tooltip_label) {
const button = $(`
<button class="text-muted btn btn-default ${css_class} icon-btn">
${frappe.utils.icon(icon)}
</button>
`);

button.appendTo(this.icon_group.removeClass("hide"));
button.click(click);
button.attr("title", __(tooltip_label || frappe.unscrub(icon)))
.tooltip({delay: {"show": 600, "hide": 100}, trigger: "hover"});

return button;
},

clear_indicator: function () {
return this.indicator.removeClass().addClass("indicator-pill whitespace-nowrap hide");
},

get_icon_label: function (icon, label) {
let icon_name = icon;
let size = 'xs';
if (typeof icon === 'object') {
icon_name = icon.icon;
size = icon.size || 'xs';
}
return `${icon ? frappe.utils.icon(icon_name, size) : ''} <span class="hidden-xs"> ${__(label)} </span>`;
},

set_action: function (btn, opts) {
let me = this;
if (opts.icon) {
opts.label = this.get_icon_label(opts.icon, opts.label);
}

this.clear_action_of(btn);

btn.removeClass("hide")
.prop("disabled", false)
.html(opts.label)
.on("click", function () {
let response = opts.click.apply(this);
me.btn_disable_enable(btn, response);
});

if (opts.working_label) {
btn.attr("data-working-label", opts.working_label);
}

// alt shortcuts
let text_span = btn.find('span');
frappe.ui.keys
.get_shortcut_group(this)
.add(btn, text_span.length ? text_span : btn);
},

set_primary_action: function (label, click, icon, working_label) {
this.set_action(this.btn_primary, {
label: label,
click: click,
icon: icon,
working_label: working_label
});
return this.btn_primary;

},

set_secondary_action: function (label, click, icon, working_label) {
this.set_action(this.btn_secondary, {
label: label,
click: click,
icon: icon,
working_label: working_label
});

return this.btn_secondary;
},


clear_action_of: function (btn) {
btn.addClass("hide").unbind("click").removeAttr("data-working-label");
},

clear_primary_action: function () {
this.clear_action_of(this.btn_primary);
},

clear_secondary_action: function () {
this.clear_action_of(this.btn_secondary);
},

clear_actions: function () {
this.clear_primary_action();
this.clear_secondary_action();
},

clear_custom_actions() {
this.custom_actions.addClass("hide").empty();
},

clear_icons: function () {
this.icon_group.addClass("hide").empty();
},

//--- Menu --//

add_menu_item: function (label, click, standard, shortcut) {
return this.add_dropdown_item({
label,
click,
standard,
parent: this.menu,
shortcut
});
},

add_custom_menu_item: function (parent, label, click, standard, shortcut, icon = null) {
return this.add_dropdown_item({
label,
click,
standard,
parent: parent,
shortcut,
icon
});
},

clear_menu: function () {
this.clear_btn_group(this.menu);
},

show_menu: function () {
this.menu_btn_group.removeClass("hide");
},

hide_menu: function () {
this.menu_btn_group.addClass("hide");
},

show_icon_group: function () {
this.icon_group.removeClass("hide");
},

hide_icon_group: function () {
this.icon_group.addClass("hide");
},

//--- Actions Menu--//

show_actions_menu: function () {
this.actions_btn_group.removeClass("hide");
},

hide_actions_menu: function () {
this.actions_btn_group.addClass("hide");
},


add_action_item: function (label, click, standard) {
return this.add_dropdown_item({
label,
click,
standard,
parent: this.actions
});
},

add_actions_menu_item: function (label, click, standard) {
return this.add_dropdown_item({
label,
click,
standard,
parent: this.actions,
show_parent: false
});
},

clear_actions_menu: function () {
this.clear_btn_group(this.actions);
},


//-- Generic --//

/*
* Add label to given drop down menu. If label, is already contained in the drop
* down menu, it will be ignored.
* @param {string} label - Text for the drop down menu
* @param {function} click - function to be called when `label` is clicked
* @param {Boolean} standard
* @param {object} parent - DOM object representing the parent of the drop down item lists
* @param {string} shortcut - Keyboard shortcut associated with the element
* @param {Boolean} show_parent - Whether to show the dropdown button if dropdown item is added
*/
add_dropdown_item: function ({label, click, standard, parent, shortcut, show_parent = true, icon = null}) {
if (show_parent) {
parent.parent().removeClass("hide");
}

let $link = this.is_in_group_button_dropdown(parent, 'li > a.grey-link', label);
if ($link) return $link;

let $li;
let $icon = ``;

if (icon) {
$icon = `<span class="menu-item-icon">${frappe.utils.icon(icon)}</span>`;
}

if (shortcut) {
let shortcut_obj = this.prepare_shortcut_obj(shortcut, click, label);
$li = $(`
<li>
<a class="grey-link dropdown-item" href="#" onClick="return false;">
${$icon}
<span class="menu-item-label">${label}</span>
<kbd class="pull-right">
<span>${shortcut_obj.shortcut_label}</span>
</kbd>
</a>
</li>
`);
frappe.ui.keys.add_shortcut(shortcut_obj);
} else {
$li = $(`
<li>
<a class="grey-link dropdown-item" href="#" onClick="return false;">
${$icon}
<span class="menu-item-label">${label}</span>
</a>
</li>
`);
}

$link = $li.find("a").on("click", click);

if (standard) {
$li.appendTo(parent);
} else {
this.divider = parent.find(".dropdown-divider");
if (!this.divider.length) {
this.divider = $('<li class="dropdown-divider user-action"></li>').prependTo(parent);
}
$li.addClass("user-action").insertBefore(this.divider);
}

// alt shortcut
frappe.ui.keys
.get_shortcut_group(parent.get(0))
.add($link, $link.find('.menu-item-label'));

return $link;
},

prepare_shortcut_obj(shortcut, click, label) {
let shortcut_obj;
// convert to object, if shortcut string passed
if (typeof shortcut === 'string') {
shortcut_obj = {shortcut};
} else {
shortcut_obj = shortcut;
}
// label
if (frappe.utils.is_mac()) {
shortcut_obj.shortcut_label = shortcut_obj.shortcut.replace('Ctrl', '⌘');
} else {
shortcut_obj.shortcut_label = shortcut_obj.shortcut;
}
// actual shortcut string
shortcut_obj.shortcut = shortcut_obj.shortcut.toLowerCase();
// action is button click
if (!shortcut_obj.action) {
shortcut_obj.action = click;
}
// shortcut description can be button label
if (!shortcut_obj.description) {
shortcut_obj.description = label;
}
// page
shortcut_obj.page = this;
return shortcut_obj;
},

/*
* Check if there already exists a button with a specified label in a specified button group
* @param {object} parent - This should be the `ul` of the button group.
* @param {string} selector - CSS Selector of the button to be searched for. By default, it is `li`.
* @param {string} label - Label of the button
*/
is_in_group_button_dropdown: function (parent, selector, label) {

if (!selector) selector = 'li';

if (!label || !parent) return false;

const result = $(parent).find(`${selector}:contains('${label}')`)
.filter(function () {
let item = $(this).html();
return $(item).attr('data-label') === label;
});
return result.length > 0 && result;
},

clear_btn_group: function (parent) {
parent.empty();
parent.parent().addClass("hide");
},

add_divider: function () {
return $('<li class="dropdown-divider"></li>').appendTo(this.menu);
},

get_or_add_inner_group_button: function (label) {
var $group = this.inner_toolbar.find(`.inner-group-button[data-label="${encodeURIComponent(label)}"]`);
if (!$group.length) {
$group = $(
`<div class="inner-group-button" data-label="${encodeURIComponent(label)}">
<button type="button" class="btn btn-default ellipsis" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
${label}
${frappe.utils.icon('select', 'xs')}
</button>
<div role="menu" class="dropdown-menu"></div>
</div>`
).appendTo(this.inner_toolbar);
}
return $group;
},

get_inner_group_button: function (label) {
return this.inner_toolbar.find(`.inner-group-button[data-label="${encodeURIComponent(label)}"]`);
},

set_inner_btn_group_as_primary: function (label) {
this.get_or_add_inner_group_button(label).find("button").removeClass("btn-default").addClass("btn-primary");
},

btn_disable_enable: function (btn, response) {
if (response && response.then) {
btn.prop('disabled', true);
response.then(() => {
btn.prop('disabled', false);
})
} else if (response && response.always) {
btn.prop('disabled', true);
response.always(() => {
btn.prop('disabled', false);
});
}
},

/*
* Add button to button group. If there exists another button with the same label,
* `add_inner_button` will not add the new button to the button group even if the callback
* function is different.
*
* @param {string} label - Label of the button to be added to the group
* @param {object} action - function to be called when button is clicked
* @param {string} group - Label of the group button
*/
add_inner_button: function (label, action, group, type = "default") {
var me = this;
let _action = function () {
let btn = $(this);
let response = action();
me.btn_disable_enable(btn, response);
};
if (group) {
var $group = this.get_or_add_inner_group_button(group);
$(this.inner_toolbar).removeClass("hide");

if (!this.is_in_group_button_dropdown($group.find(".dropdown-menu"), 'a', label)) {
return $(`<a class="dropdown-item" href="#" onclick="return false;" data-label="${encodeURIComponent(label)}">${label}</a>`)
.on('click', _action)
.appendTo($group.find(".dropdown-menu"));
}

} else {
let button = this.inner_toolbar.find(`button[data-label="${encodeURIComponent(label)}"]`);
if (button.length == 0) {
button = $(`<button data-label="${encodeURIComponent(label)}" class="btn btn-${type} ellipsis">
${__(label)}
</button>`);
button.on("click", _action);
button.appendTo(this.inner_toolbar.removeClass("hide"));
}
return button;
}
},

remove_inner_button: function (label, group) {
if (typeof label === 'string') {
label = [label];
}
// translate
label = label.map(l => __(l));

if (group) {
var $group = this.get_inner_group_button(__(group));
if ($group.length) {
$group.find(`.dropdown-item[data-label="${encodeURIComponent(label)}"]`).remove();
}
if ($group.find('.dropdown-item').length === 0) $group.remove();
} else {
this.inner_toolbar.find(`button[data-label="${encodeURIComponent(label)}"]`).remove();
}
},

change_inner_button_type: function (label, group, type) {
let btn;

if (group) {
var $group = this.get_inner_group_button(__(group));
if ($group.length) {
btn = $group.find(`.dropdown-item[data-label="${encodeURIComponent(label)}"]`);
}
} else {
btn = this.inner_toolbar.find(`button[data-label="${encodeURIComponent(label)}"]`);
}

if (btn) {
btn.removeClass().addClass(`btn btn-${type} ellipsis`);
}
},

add_inner_message: function (message) {
let $message = $(`<span class='inner-page-message text-muted small'>${message}</div>`);
this.inner_toolbar.find('.inner-page-message').remove();
this.inner_toolbar.removeClass("hide").prepend($message);

return $message;
},

clear_inner_toolbar: function () {
this.inner_toolbar.empty().addClass("hide");
},

//-- Sidebar --//

add_sidebar_item: function (label, action, insert_after, prepend) {
var parent = this.sidebar.find(".sidebar-menu.standard-actions");
var li = $('<li>');
var link = $('<a>').html(label).on("click", action).appendTo(li);

if (insert_after) {
li.insertAfter(parent.find(insert_after));
} else {
if (prepend) {
li.prependTo(parent);
} else {
li.appendTo(parent);
}
}
return link;
},

//---//

clear_user_actions: function () {
this.menu.find(".user-action").remove();
},

// page::title
get_title_area: function () {
return this.$title_area;
},

set_title: function (title, icon = null, strip = true, tab_title = "") {
if (!title) title = "";
if (strip) {
title = strip_html(title);
}
this.title = title;
frappe.utils.set_title(tab_title || title);
if (icon) {
title = `${frappe.utils.icon(icon)} ${title}`;
}
let title_wrapper = this.$title_area.find(".title-text");
title_wrapper.html(title);
title_wrapper.attr('title', this.title);
},

set_title_sub: function (txt) {
// strip icon
this.$sub_title_area.html(txt).toggleClass("hide", !!!txt);
},

get_main_icon: function (icon) {
return this.$title_area.find(".title-icon")
.html('<i class="' + icon + ' fa-fw"></i> ')
.toggle(true);
},

add_help_button: function (txt) {
//
},

add_button: function (label, click, opts) {
if (!opts) opts = {};
let button = $(`<button
class="btn ${opts.btn_class || 'btn-default'} ${opts.btn_size || 'btn-sm'} ellipsis">
${opts.icon ? frappe.utils.icon(opts.icon) : ''}
${label}
</button>`);
button.appendTo(this.custom_actions);
button.on('click', click);
this.custom_actions.removeClass('hide');

return button;
},

add_custom_button_group: function (label, icon, parent) {
let dropdown_label = `<span class="hidden-xs">
<span class="custom-btn-group-label">${__(label)}</span>
${frappe.utils.icon('select', 'xs')}
</span>`;

if (icon) {
dropdown_label = `<span class="hidden-xs">
${frappe.utils.icon(icon)}
<span class="custom-btn-group-label">${__(label)}</span>
${frappe.utils.icon('select', 'xs')}
</span>
<span class="visible-xs">
${frappe.utils.icon(icon)}
</span>`;
}

let custom_btn_group = $(`
<div class="custom-btn-group">
<button type="button" class="btn btn-default btn-sm ellipsis" data-toggle="dropdown" aria-expanded="false">
${dropdown_label}
</button>
<ul class="dropdown-menu" role="menu"></ul>
</div>
`);

if (!parent) parent = this.custom_actions;
parent.removeClass('hide').append(custom_btn_group);

return custom_btn_group.find('.dropdown-menu');
},

add_dropdown_button: function (parent, label, click, icon) {
frappe.ui.toolbar.add_dropdown_button(parent, label, click, icon);
},

// page::form
add_label: function (label) {
this.show_form();
return $("<label class='col-md-1 page-only-label'>" + label + " </label>")
.appendTo(this.page_form);
},
add_select: function (label, options) {
var field = this.add_field({label: label, fieldtype: "Select"});
return field.$wrapper.find("select").empty().add_options(options);
},
add_data: function (label) {
var field = this.add_field({label: label, fieldtype: "Data"});
return field.$wrapper.find("input").attr("placeholder", label);
},
add_date: function (label, date) {
var field = this.add_field({label: label, fieldtype: "Date", "default": date});
return field.$wrapper.find("input").attr("placeholder", label);
},
add_check: function (label) {
return $("<div class='checkbox'><label><input type='checkbox'>" + label + "</label></div>")
.appendTo(this.page_form)
.find("input");
},
add_break: function () {
// add further fields in the next line
this.page_form.append('<div class="clearfix invisible-xs"></div>');
},
add_field: function (df, parent) {
this.show_form();

if (!df.placeholder) {
df.placeholder = df.label;
}

df.input_class = 'input-xs';

var f = frappe.ui.form.make_control({
df: df,
parent: parent || this.page_form,
only_input: df.fieldtype == "Check" ? false : true,
})
f.refresh();
$(f.wrapper)
.addClass('col-md-2')
.attr("title", __(df.label)).tooltip({
delay: {"show": 600, "hide": 100},
trigger: "hover"
});

// html fields in toolbar are only for display
if (df.fieldtype == 'HTML') {
return;
}

// hidden fields dont have $input
if (!f.$input) f.make_input();

f.$input.attr("placeholder", __(df.label));

if (df.fieldtype === "Check") {
$(f.wrapper).find(":first-child")
.removeClass("col-md-offset-4 col-md-8");
}

if (df.fieldtype == "Button") {
$(f.wrapper).find(".page-control-label").html("&nbsp;");
f.$input.addClass("btn-xs").css({"width": "100%", "margin-top": "-1px"});
}

if (df["default"])
f.set_input(df["default"])
this.fields_dict[df.fieldname || df.label] = f;
return f;
},
clear_fields: function () {
this.page_form.empty();
},
show_form: function () {
this.page_form.removeClass("hide");
},
hide_form: function () {
this.page_form.addClass("hide");
},
get_form_values: function () {
var values = {};
this.page_form.fields_dict.forEach(function (field, key) {
values[key] = field.get_value();
});
return values;
},
add_view: function (name, html) {
let element = html;
if (typeof (html) === "string") {
element = $(html);
}
this.views[name] = element.appendTo($(this.wrapper).find(".page-content"));
if (!this.current_view) {
this.current_view = this.views[name];
} else {
this.views[name].toggle(false);
}
return this.views[name];
},
set_view: function (name) {
if (this.current_view_name === name)
return;
this.current_view && this.current_view.toggle(false);
this.current_view = this.views[name];

this.previous_view_name = this.current_view_name;
this.current_view_name = name;

this.views[name].toggle(true);

this.wrapper.trigger('view-change');
},
});

+ 0
- 145
datavalue_theme_14/public/js/frappe/ui/toolbar/navbar.html Переглянути файл

@@ -1,145 +0,0 @@
<div class="dv-navbar-overlay"></div>
<div class="dv-navbar datavalue-nav">
<div class="container-fluid">
<div class="dv-nav-left">
<button type="button" class="btn-open-mobile-menu"><i class="far fa-bars"></i></button>
<button type="button" class="btn-open-modules"><i class="flaticon-menu"></i></button>
<div class="logo" id="datavalue-app-logo" :class="logo_class"><a href="/app"><img v-if="logo_path && logo_path.length" :src="logo_path"></a></div>
<div class="navbar-breadcrumbs">
<ul class="nav navbar-nav d-none d-sm-flex" id="navbar-breadcrumbs"></ul>
</div>
</div>
<div class="dv-nav-right">
<ul class="list-unstyled">
<li class="nav-item dropdown dropdown-user" id="header-navbar-user">
<a class="nav-link dropdown-toggle dropdown-user-link" data-toggle="dropdown">
<span class="dv-nav-avatar">
{{ avatar }}
<span class="avatar-status-online"></span>
</span>
<div class="dv-user-info">
<span class="user-name">[[user.full_name]]</span>
<span class="user-status">[[user_type]]</span>
</div>
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdown-user">
<div class="dropdown-item dropdown-item-username show-on-mobile">
[[user.full_name]]
</div>
<div class="dropdown-divider show-on-mobile"></div>
{% for item in navbar_settings.settings_dropdown %}
{% if (!item.hidden) { %}
{% if (item.route) { %}
<a class="dropdown-item" href="{{ item.route }}">
{%= __(item.item_label) %}
</a>
{% } else if (item.action && item.action!="new frappe.ui.ThemeSwitcher().show()") { %}
<a class="dropdown-item" onclick="return {{ item.action }}">
{%= __(item.item_label) %}
</a>
{% } else { %}
<div class="dropdown-divider"></div>
{% } %}
{% } %}
{% endfor %}
</div>
</li>
<li class="nav-item dropdown dv-dropdown-notifications">
<a class="nav-link notifications-icon animated-tada" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" href="#" onclick="return false;">
<span class="notifications-seen">
<i class="far fa-bell animated-icon"></i>
</span>
<span class="notifications-unseen">
<svg class="icon icon-md"><use href="#icon-notification-with-indicator"></use></svg>
</span>
</a>
<div class="dropdown-menu notifications-list dropdown-menu-right" role="menu">
<div class="notification-list-header">
<div class="header-items"></div>
<div class="header-actions"></div>
</div>
<div class="notification-list-body">
<div class="panel-notifications"></div>
<div class="panel-events"></div>
</div>
</div>
</li>
<li class="nav-item dropdown dropdown-files">
<button type="button" class="nav-link files-icon animated-tada">
<i class="far fa-folder-open animated-icon"></i>
</button>
</li>
<li class="nav-item dropdown-full-screen">
<button type="button" class="nav-link full-screen-icon animated-tada">
<i class="far fa-expand animated-icon"></i>
</button>
</li>
<li class="nav-item dropdown-full-screen">
<button type="button" class="nav-link open-theme-setting animated-tada">
<i class="far fa-palette animated-icon"></i>
</button>
</li>
<li class="nav-item dropdown-search">
<button type="button" class="nav-link open-search animated-tada">
<i class="far fa-search"></i>
</button>
</li>
<li class="nav-item dropdown dropdown-language" id="header-navbar-change-lang">
<a class="nav-link dropdown-lang-link" data-toggle="dropdown">
<span :class="lang_list[active_lang].flag" v-if="hide_language_icon!=1"></span>
[[lang_list[active_lang].label]]
<span>
<svg class="icon icon-xs"><use href="#icon-small-down"></use></svg>
</span>
</a>
<div class="dropdown-menu dropdown-menu-right">
<a class="dropdown-item" data-lang="EN">
<span class="dv-lang-flag lang-en" v-if="hide_language_icon!=1"></span> EN
</a>
<a class="dropdown-item" data-lang="AR">
<span class="dv-lang-flag lang-ar" v-if="hide_language_icon!=1"></span> AR
</a>
</div>
</li>
{% if(show_help_icon) { %}
<li class="nav-item dropdown dropdown-language">
<a class="nav-link dropdown-lang-link animated-tada" data-toggle="dropdown" href="#" onclick="return false;">
{{ __("Help") }}
<span>
<svg class="icon icon-xs"><use href="#icon-small-down"></use></svg>
</span>
</a>
<div class="dropdown-menu dropdown-menu-right" id="toolbar-help" role="menu" style="width:auto;">
<div id="help-links"></div>
<div class="dropdown-divider documentation-links"></div>
{% for item in navbar_settings.help_dropdown %}
{% if (!item.hidden) { %}
{% if (item.route) { %}
<a class="dropdown-item" href="{{ item.route }}">
{%= __(item.item_label) %}
</a>
{% } else if (item.action) { %}
<a class="dropdown-item" onclick="return {{ item.action }}">
{%= __(item.item_label) %}
</a>
{% } else { %}
<div class="dropdown-divider"></div>
{% } %}
{% } %}
{% endfor %}
</div>
</li>
{% } %}
</ul>
</div>
<form class="dv-nav-search" onsubmit="return false;">
<input id="navbar-search" type="text" class="form-control" placeholder="{%= __(" Search or type a command (Ctrl + G)") %}" aria-haspopup="true">
<span class="search-icon"><i class="fal fa-search"></i></span>
<button type="button" class="dv-nav-search-close"><i class="far fa-times"></i></button>
</form>
</div>
</div>
<header class="navbar navbar-expand sticky-top" role="navigation" style="display:none;">
<div class="container">
</div>
</header>

+ 0
- 52
datavalue_theme_14/public/js/frappe/ui/toolbar/theme-setting.js Переглянути файл

@@ -1,52 +0,0 @@
// open-theme-setting

$(document).on('click', '.theme-setting-colors-select.theme-setting-modal button', function (event) {
event.preventDefault();
$('.theme-setting-colors-select.theme-setting-modal button').removeClass('active');
$(this).addClass('active');
});
$(document).on('click', '.open-theme-setting', function (event) {
event.preventDefault();
let colors_list = ['Blue', 'Green', 'Red', 'Orange', 'Yellow', 'Pink', 'Violet']
let d = new frappe.ui.Dialog({
title: __('Theme Settings'),
fields: [
{
label: 'Dark Style',
fieldname: 'dark_style',
fieldtype: 'Check',
default: ($('html').attr('data-theme') == 'dark' && $('body').hasClass('dv-dark-style')) ? 1 : 0
},
{
label: 'Colors',
fieldname: 'colors_icons',
fieldtype: 'HTML',
options: `
<div class="theme-setting-colors-select theme-setting-modal">
<h4>${__('Theme Colors')}</h4>
<div class="dv-row dv-row-sm">
${colors_list.map(color => `<div class="dv-col"><button type="button" class="${($('body').data('theme-color') == color) ? 'active' : ''}" data-color="${color}" data-class="dv-${color}-style">${color}</button></div>`).join("")}
</div>
</div>
`
}
],
primary_action_label: __('Save Settings'),
primary_action(values) {
let active_btn = $('.theme-setting-colors-select.theme-setting-modal button.active');
let data = {
color_name: active_btn.data('color'),
color_class: active_btn.data('class'),
dark_style: values.dark_style
}
frappe.db.set_value('Theme Settings', 'Theme Settings', {
'dark_view': data.dark_style,
'theme_color': data.color_name
}, function () {
frappe.ui.toolbar.clear_cache();
setTimeout(() => d.hide(), 1000);
});
}
});
d.show();
});

+ 0
- 293
datavalue_theme_14/public/js/frappe/ui/toolbar/toolbar.js Переглянути файл

@@ -1,293 +0,0 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

frappe.provide("frappe.ui.toolbar");
frappe.provide("frappe.search");

frappe.ui.toolbar.Toolbar = class {
constructor() {
$("header").replaceWith(
frappe.render_template("navbar", {
avatar: frappe.avatar(frappe.session.user, "avatar-medium"),
navbar_settings: frappe.boot.navbar_settings,
show_help_icon: ($('body').data('show-help-icon') == 1) ? true : false,
})
);
$(".dropdown-toggle").dropdown();

this.setup_awesomebar();
this.setup_notifications();
this.setup_help();
this.make();
}

make() {
this.bind_events();
$(document).trigger("toolbar_setup");
}

bind_events() {
// clear all custom menus on page change
$(document).on("page-change", function () {
$("header .navbar .custom-menu").remove();
});

//focus search-modal on show in mobile view
$("#search-modal").on("shown.bs.modal", function () {
var search_modal = $(this);
setTimeout(function () {
search_modal.find("#modal-search").focus();
}, 300);
});
$(".navbar-toggle-full-width").click(() => {
frappe.ui.toolbar.toggle_full_width();
});
}

setup_help() {
if (!frappe.boot.desk_settings.notifications) {
// hide the help section
$(".navbar .vertical-bar").removeClass("d-sm-block");
$(".dropdown-help").removeClass("d-lg-block");
return;
}
frappe.provide("frappe.help");
frappe.help.show_results = show_results;

this.search = new frappe.search.SearchDialog();
frappe.provide("frappe.searchdialog");
frappe.searchdialog.search = this.search;

$(".dropdown-help .dropdown-toggle").on("click", function () {
$(".dropdown-help input").focus();
});

$(".dropdown-help .dropdown-menu").on("click", "input, button", function (e) {
e.stopPropagation();
});

$("#input-help").on("keydown", function (e) {
if (e.which == 13) {
$(this).val("");
}
});

$(document).on("page-change", function () {
var $help_links = $(".dropdown-help #help-links");
$help_links.html("");

var route = frappe.get_route_str();
var breadcrumbs = route.split("/");

var links = [];
for (var i = 0; i < breadcrumbs.length; i++) {
var r = route.split("/", i + 1);
var key = r.join("/");
var help_links = frappe.help.help_links[key] || [];
links = $.merge(links, help_links);
}

if (links.length === 0) {
$help_links.next().hide();
} else {
$help_links.next().show();
}

for (var i = 0; i < links.length; i++) {
var link = links[i];
var url = link.url;
$("<a>", {
href: url,
class: "dropdown-item",
text: __(link.label),
target: "_blank",
}).appendTo($help_links);
}

$(".dropdown-help .dropdown-menu").on("click", "a", show_results);
});

var $result_modal = frappe.get_modal("", "");
$result_modal.addClass("help-modal");

$(document).on("click", ".help-modal a", show_results);

function show_results(e) {
//edit links
var href = e.target.href;
if (href.indexOf("blob") > 0) {
window.open(href, "_blank");
}
var path = $(e.target).attr("data-path");
if (path) {
e.preventDefault();
}
}
}

setup_awesomebar() {
if (frappe.boot.desk_settings.search_bar) {
let awesome_bar = new frappe.search.AwesomeBar();
awesome_bar.setup("#navbar-search");

// TODO: Remove this in v14
frappe.search.utils.make_function_searchable(function () {
frappe.set_route("List", "Client Script");
}, __("Custom Script List"));
}
}

setup_notifications() {
if (frappe.boot.desk_settings.notifications && frappe.session.user !== "Guest") {
this.notifications = new frappe.ui.Notifications();
}
}
};

$.extend(frappe.ui.toolbar, {
add_dropdown_button: function (parent, label, click, icon) {
var menu = frappe.ui.toolbar.get_menu(parent);
if (menu.find("li:not(.custom-menu)").length && !menu.find(".divider").length) {
frappe.ui.toolbar.add_menu_divider(menu);
}

return $(
'<li class="custom-menu"><a><i class="fa-fw ' + icon + '"></i> ' + label + "</a></li>"
)
.insertBefore(menu.find(".divider"))
.find("a")
.click(function () {
click.apply(this);
});
},
get_menu: function (label) {
return $("#navbar-" + label.toLowerCase());
},
add_menu_divider: function (menu) {
menu = typeof menu == "string" ? frappe.ui.toolbar.get_menu(menu) : menu;

$('<li class="divider custom-menu"></li>').prependTo(menu);
},
add_icon_link(route, icon, index, class_name) {
let parent_element = $(".navbar-right").get(0);
let new_element = $(`<li class="${class_name}">
<a class="btn" href="${route}" title="${frappe.utils.to_title_case(
class_name,
true
)}" aria-haspopup="true" aria-expanded="true">
<div>
<i class="octicon ${icon}"></i>
</div>
</a>
</li>`).get(0);

parent_element.insertBefore(new_element, parent_element.children[index]);
},
toggle_full_width() {
let fullwidth = JSON.parse(localStorage.container_fullwidth || "false");
fullwidth = !fullwidth;
localStorage.container_fullwidth = fullwidth;
frappe.ui.toolbar.set_fullwidth_if_enabled();
$(document.body).trigger("toggleFullWidth");
},
set_fullwidth_if_enabled() {
let fullwidth = JSON.parse(localStorage.container_fullwidth || "false");
$(document.body).toggleClass("full-width", fullwidth);
},
show_shortcuts(e) {
e.preventDefault();
frappe.ui.keys.show_keyboard_shortcut_dialog();
return false;
},
});

frappe.ui.toolbar.clear_cache = frappe.utils.throttle(function () {
frappe.assets.clear_local_storage();
frappe.xcall("frappe.sessions.clear").then((message) => {
frappe.show_alert({
message: message,
indicator: "info",
});
location.reload(true);
});
}, 10000);

frappe.ui.toolbar.show_about = function () {
try {
frappe.ui.misc.about();
} catch (e) {
console.log(e);
}
return false;
};

frappe.ui.toolbar.route_to_user = function () {
frappe.set_route("Form", "User", frappe.session.user);
};

frappe.ui.toolbar.view_website = function () {
let website_tab = window.open();
website_tab.opener = null;
website_tab.location = "/index";
};

frappe.ui.toolbar.setup_session_defaults = function () {
let fields = [];
frappe.call({
method: "frappe.core.doctype.session_default_settings.session_default_settings.get_session_default_values",
callback: function (data) {
fields = JSON.parse(data.message);
let perms = frappe.perm.get_perm("Session Default Settings");
//add settings button only if user is a System Manager or has permission on 'Session Default Settings'
if (in_list(frappe.user_roles, "System Manager") || perms[0].read == 1) {
fields[fields.length] = {
fieldname: "settings",
fieldtype: "Button",
label: __("Settings"),
click: () => {
frappe.set_route(
"Form",
"Session Default Settings",
"Session Default Settings"
);
},
};
}
frappe.prompt(
fields,
function (values) {
//if default is not set for a particular field in prompt
fields.forEach(function (d) {
if (!values[d.fieldname]) {
values[d.fieldname] = "";
}
});
frappe.call({
method: "frappe.core.doctype.session_default_settings.session_default_settings.set_session_default_values",
args: {
default_values: values,
},
callback: function (data) {
if (data.message == "success") {
frappe.show_alert({
message: __("Session Defaults Saved"),
indicator: "green",
});
frappe.ui.toolbar.clear_cache();
} else {
frappe.show_alert({
message: __(
"An error occurred while setting Session Defaults"
),
indicator: "red",
});
}
},
});
},
__("Session Defaults"),
__("Save")
);
},
});
};

+ 0
- 202
datavalue_theme_14/public/js/frappe/views/breadcrumbs.js Переглянути файл

@@ -1,202 +0,0 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

frappe.breadcrumbs = {
all: {},

preferred: {
"File": "",
"Dashboard": "Customization",
"Dashboard Chart": "Customization",
"Dashboard Chart Source": "Customization"
},

module_map: {
'Core': 'Settings',
'Email': 'Settings',
'Custom': 'Settings',
'Workflow': 'Settings',
'Printing': 'Settings',
'Setup': 'Settings',
'Event Streaming': 'Tools',
'Automation': 'Tools',
},

set_doctype_module(doctype, module) {
localStorage["preferred_breadcrumbs:" + doctype] = module;
},

get_doctype_module(doctype) {
return localStorage["preferred_breadcrumbs:" + doctype];
},

add(module, doctype, type) {
let obj;
if (typeof module === 'object') {
obj = module;
} else {
obj = {
module: module,
doctype: doctype,
type: type
}
}

let breadcrumb = frappe.breadcrumbs.current_page();
breadcrumb = breadcrumb.split('/');
this.all[frappe.breadcrumbs.current_page()] = obj;

this.update();
},

current_page() {
return frappe.get_route_str();
},

update() {
var breadcrumbs = this.all[frappe.breadcrumbs.current_page()];

this.clear();
if (!breadcrumbs) return this.toggle(false);

if (breadcrumbs.type === 'Custom') {
this.set_custom_breadcrumbs(breadcrumbs);
} else {
// workspace
this.set_workspace_breadcrumb(breadcrumbs);

// form / print
let view = frappe.get_route()[0];
view = view ? view.toLowerCase() : null;
if (breadcrumbs.doctype && ["print", "form"].includes(view)) {
this.set_list_breadcrumb(breadcrumbs);
this.set_form_breadcrumb(breadcrumbs, view);
} else if (breadcrumbs.doctype && view === 'list') {
this.set_list_breadcrumb(breadcrumbs);
}
}

this.toggle(true);
},

set_custom_breadcrumbs(breadcrumbs) {
const html = `<li><a href="${breadcrumbs.route}">${breadcrumbs.label}</a></li>`;
this.$breadcrumbs.append(html);
},

set_workspace_breadcrumb(breadcrumbs) {
// get preferred module for breadcrumbs, based on sent via module

if (!breadcrumbs.workspace) {
this.set_workspace(breadcrumbs);
}

if (breadcrumbs.workspace) {
if (!breadcrumbs.module_info.blocked && frappe.visible_modules.includes(breadcrumbs.module_info.module)) {
$(`<li><a href="/app/${frappe.router.slug(breadcrumbs.workspace)}">${__(breadcrumbs.workspace)}</a></li>`)
.appendTo(this.$breadcrumbs);
}
}

},

set_workspace(breadcrumbs) {
// try and get module from doctype or other settings
// then get the workspace for that module

this.setup_modules();
var from_module = this.get_doctype_module(breadcrumbs.doctype);

if (from_module) {
breadcrumbs.module = from_module;
} else if (this.preferred[breadcrumbs.doctype] !== undefined) {
// get preferred module for breadcrumbs
breadcrumbs.module = this.preferred[breadcrumbs.doctype];
}

if (breadcrumbs.module) {
if (this.module_map[breadcrumbs.module]) {
breadcrumbs.module = this.module_map[breadcrumbs.module];
}

breadcrumbs.module_info = frappe.get_module(breadcrumbs.module);

// set workspace
if (breadcrumbs.module_info && frappe.boot.module_page_map[breadcrumbs.module]) {
breadcrumbs.workspace = frappe.boot.module_page_map[breadcrumbs.module];
}
}
},

set_list_breadcrumb(breadcrumbs) {
const doctype = breadcrumbs.doctype;
const doctype_meta = frappe.get_doc('DocType', doctype);
if ((doctype === "User" && !frappe.user.has_role('System Manager'))
|| (doctype_meta && doctype_meta.issingle)) {
// no user listview for non-system managers and single doctypes
} else {
let route;
const doctype_route = frappe.router.slug(frappe.router.doctype_layout || doctype);
if (frappe.boot.treeviews.indexOf(doctype) !== -1) {
let view = frappe.model.user_settings[doctype].last_view || 'Tree';
route = `${doctype_route}/view/${view}`;
} else {
route = doctype_route;
}
$(`<li><a href="/app/${route}">${__(doctype)}</a></li>`).appendTo(this.$breadcrumbs);
}
},

set_form_breadcrumb(breadcrumbs, view) {
const doctype = breadcrumbs.doctype;
const docname = frappe.get_route()[2];
let form_route = `/app/${frappe.router.slug(doctype)}/${docname}`;
$(`<li><a href="${form_route}">${this.limit_string(__(docname))}</a></li>`).appendTo(this.$breadcrumbs);
if (view === "form") {
let last_crumb = this.$breadcrumbs.find('li').last();
last_crumb.addClass('disabled');
last_crumb.css("cursor", "copy");
last_crumb.click((event) => {
event.stopImmediatePropagation();
frappe.utils.copy_to_clipboard(last_crumb.text());
});
}
},

setup_modules() {
if (!frappe.visible_modules) {
frappe.visible_modules = $.map(frappe.boot.allowed_workspaces, (m) => {
return m.module;
});
}
},

rename(doctype, old_name, new_name) {
var old_route_str = ["Form", doctype, old_name].join("/");
var new_route_str = ["Form", doctype, new_name].join("/");
this.all[new_route_str] = this.all[old_route_str];
delete frappe.breadcrumbs.all[old_route_str];
this.update();
},

clear() {
this.$breadcrumbs = $("#navbar-breadcrumbs").empty();
},

toggle(show) {
if (show) {
$("body").addClass("no-breadcrumbs");
} else {
$("body").removeClass("no-breadcrumbs");
}
},

limit_string(string, limit = 25) {
if (string && string.length >= limit) {
return string.substring(0, limit) + ' ...';
} else {
return string;
}
}

}

+ 0
- 129
datavalue_theme_14/public/js/frappe/views/container.js Переглянути файл

@@ -1,129 +0,0 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

// page container
frappe.provide("frappe.pages");
frappe.provide("frappe.views");

window.cur_page = null;
frappe.modules_list = [];
frappe.module_items_list = [];
frappe.active_module = {};
frappe.theme_settings = {};
frappe.is_app_loaded = false;
frappe.is_page_changed = false;

frappe.views.Container = class Container {
// Container contains pages inside `#container` and manages page creation, switching
constructor() {
this.container = $("#body").get(0);
this.page = null; // current page
this.pagewidth = $(this.container).width();
this.pagemargin = 50;
localStorage.container_fullwidth = true;
$('body').addClass('full-width');

var me = this;

$(document).trigger('app-loaded');
frappe.is_app_loaded = true;
document.documentElement.setAttribute("data-theme", document.documentElement.getAttribute('data-dv-theme'));
if ($('body').data('close-sub-menu') == '1') {
$('.btn-toggle-main-menu').removeClass('menu-shown');
$('body').addClass('hide-main-menu');
}

$(document).on("page-change", function () {
// set data-route in body
var route_str = frappe.get_route_str();
var route_obj = frappe.get_route();
let current_page = $('.content.page-container:visible', this);
$("body").attr("data-route", route_str);
$("body").attr("data-sidebar", me.has_sidebar() ? 1 : 0);
setTimeout(() => $('input#navbar-search').trigger('blur'), 250);
$('.dv-nav-search ul[role="listbox"]').prop('hidden', true);
$(document).trigger('show-side-menu');
});

$(document).bind("rename", function (event, dt, old_name, new_name) {
frappe.breadcrumbs.rename(dt, old_name, new_name);
});
}

add_page(label) {
var page = $('<div class="content page-container"></div>')
.attr("id", "page-" + label)
.attr("data-page-route", label)
.hide()
.appendTo(this.container)
.get(0);
page.label = label;
frappe.pages[label] = page;

return page;
}

change_to(label) {
cur_page = this;
if (label.tagName) {
// if sent the div, get the table
var page = label;
} else {
var page = frappe.pages[label];
}
if (!page) {
console.log(__("Page not found") + ": " + label);
return;
}

// hide dialog
if (window.cur_dialog && cur_dialog.display && !cur_dialog.keep_open) {
if (!cur_dialog.minimizable) {
cur_dialog.hide();
} else if (!cur_dialog.is_minimized) {
cur_dialog.toggle_minimize();
}
}

// hide current
if (this.page && this.page != page) {
$(this.page).hide();
$(this.page).trigger("hide");
}

// show new
if (!this.page || this.page != page) {
this.page = page;
// $(this.page).fadeIn(300);
$(this.page).show();
}

$(document).trigger("page-change");

this.page._route = frappe.router.get_sub_path();
$(this.page).trigger("show");
!this.page.disable_scroll_to_top && frappe.utils.scroll_to(0);
frappe.breadcrumbs.update();

return this.page;
}

has_sidebar() {
var flag = 0;
var route_str = frappe.get_route_str();
// check in frappe.ui.pages
flag = frappe.ui.pages[route_str] && !frappe.ui.pages[route_str].single_column;

// sometimes frappe.ui.pages is updated later,
// so check the dom directly
if (!flag) {
var page_route = route_str.split("/").slice(0, 2).join("/");
flag = $(`.page-container[data-page-route="${page_route}"] .layout-side-section`)
.length
? 1
: 0;
}

return flag;
}
};

+ 21
- 21
datavalue_theme_14/public/js/vue/components/Menu.vue Переглянути файл

@@ -22,7 +22,7 @@
</div>
<ul class="list-unstyled mobile-modules-menu-list" v-if="is_shown_mobile_menu && module_items_list[active_module.name] && module_items_list[active_module.name].length">
<li :class="(active_module.name==current_doctype)?'active':''">
<a v-on:click="open_dashboard(active_module.name)" :data-dashboard="active_module.name">{{ frappe._("Dashboard") }}</a>
<a v-on:click="open_dashboard(active_module.name)" :data-dashboard="active_module.name">{{ xhiveframework._("Dashboard") }}</a>
</li>
<li v-for="item in module_items_list[active_module.name]">
<a> {{ item.label }} <i class="far fa-angle-down sub-menu-arrow"></i></a>
@@ -53,7 +53,7 @@
<div><i :class="get_module_icon(module.name,module.icon)+' animated-icon'"></i></div>
<span v-if="theme_settings.show_icon_label && theme_settings.show_icon_label=='1'">{{ (module.label) ? module.label : module.name }}</span>
<!-- <i :class="get_module_icon(module.name,module.icon)+' animated-icon'"></i>-->
<!-- <span v-html="frappe.utils.icon(module.icon || 'folder-normal', 'lg')"></span>-->
<!-- <span v-html="xhiveframework.utils.icon(module.icon || 'folder-normal', 'lg')"></span>-->
</a>
</li>
</ul>
@@ -84,8 +84,8 @@ export default {
name: "Menu",
data() {
return {
route: frappe.get_route(),
is_rtl: frappe.utils.is_rtl(),
route: xhiveframework.get_route(),
is_rtl: xhiveframework.utils.is_rtl(),
theme_settings: {},
current_doctype: '',
current_page: '',
@@ -121,8 +121,8 @@ export default {
"Website": "flaticon-browser",
"Settings": "fal fa-cog",
"Utilities": 'flaticon-configuration',
"ERPNext Settings": 'flaticon-admin',
"ERPNext Integrations": 'flaticon-configuration',
"XhiveERP Settings": 'flaticon-admin',
"XhiveERP Integrations": 'flaticon-configuration',
},
modules_list: [],
module_items_list: {},
@@ -132,31 +132,31 @@ export default {
methods: {
get_modules: function (callback) {
const $this = this;
frappe.call({
xhiveframework.call({
type: 'POST',
method: 'frappe.desk.desktop.get_workspace_sidebar_items',
method: 'xhiveframework.desk.desktop.get_workspace_sidebar_items',
args: {},
callback: callback
});
},
get_module_items: function (module = '', callback) {
const $this = this;
frappe.call({
xhiveframework.call({
type: 'POST',
method: 'frappe.desk.desktop.get_desktop_page',
method: 'xhiveframework.desk.desktop.get_desktop_page',
args: {page: '{"name":"' + module + '","title":"' + module + '"}'},
callback: callback
});
},
get_module_name_from_doctype: function () {
const $this = this;
const route = frappe.get_route();
const route = xhiveframework.get_route();
$this.current_doctype = (route && route.length >= 2 && route[1]) ? route[1] : '';
if (route && route[0] && route[0] == 'dashboard-view') {
$this.current_doctype = 'Dashboard';
}
$this.is_dashboard = (route && route.length == 2 && route[1] && route[0] && route[0] == 'dashboard-view') ? true : false;
frappe.call({
xhiveframework.call({
type: 'POST',
method: 'datavalue_theme_14.api.get_module_name_from_doctype',
args: {
@@ -175,7 +175,7 @@ export default {
});
},
module_menu_list: function (current_module) {
const route = frappe.get_route();
const route = xhiveframework.get_route();
let _module = current_module;
if (route && route[0] && route[0] == 'Workspaces') {
_module = route[1];
@@ -248,7 +248,7 @@ export default {
},
after_side_menu_items: function () {
const $this = this;
const route = frappe.get_route();
const route = xhiveframework.get_route();
$this.current_doctype = (route && route.length >= 2 && route[1]) ? route[1] : '';
setTimeout(() => {
$('.side-menu .side-menu-items > ul.dropdown-list').niceScroll({
@@ -303,7 +303,7 @@ export default {
if ($this.theme_settings && Object.keys($this.theme_settings).length) {
callback();
} else {
frappe.call({
xhiveframework.call({
type: 'POST',
method: 'datavalue_theme_14.api.get_theme_settings',
args: {},
@@ -323,7 +323,7 @@ export default {
if (link.link_type == "Report" && !link.is_query_report) {
opts.doctype = link.dependencies;
}
const route = frappe.utils.generate_route(opts);
const route = xhiveframework.utils.generate_route(opts);
return route;
},
open_module: function (module, is_mobile = false) {
@@ -332,9 +332,9 @@ export default {
setTimeout(() => this.module_menu_list(module), 100);
if (is_mobile == false) {
if ($('body').data('menu-opening-type') == 'Dashboard') {
frappe.set_route('/dashboard-view/' + (module));
xhiveframework.set_route('/dashboard-view/' + (module));
} else {
frappe.set_route('/' + (module.replace(/ /g, "-")).toLowerCase());
xhiveframework.set_route('/' + (module.replace(/ /g, "-")).toLowerCase());
}
$('.btn-toggle-main-menu').addClass('menu-shown');
$('body').removeClass('hide-main-menu');
@@ -343,7 +343,7 @@ export default {
}
},
open_dashboard: function (module) {
frappe.set_route('/dashboard-view/' + (module));
xhiveframework.set_route('/dashboard-view/' + (module));
},
mobile_back_modules: function () {
const $this = this;
@@ -366,9 +366,9 @@ export default {
}
},
created() {
const route = frappe.get_route();
const route = xhiveframework.get_route();
this.current_doctype = (route && route.length >= 2 && route[1]) ? route[1] : '';
if ($('body').hasClass('frappe-rtl')) {
if ($('body').hasClass('xhiveframework-rtl')) {
this.menu_items_animate = 'slideInRight';
}
this.get_theme_settings(() => {


+ 1
- 1
datavalue_theme_14/public/js/vue/theme-settings.js Переглянути файл

@@ -5,7 +5,7 @@
if ($('#page-login').length) {
$('#page-login').each(function () {
let page = $(this);
frappe.call({
xhiveframework.call({
type: 'POST',
method: 'datavalue_theme_14.api.get_theme_settings',
args: {},


+ 1
- 1
datavalue_theme_14/public/scss/datavalue_theme.bundle.scss Переглянути файл

@@ -1,6 +1,6 @@
@import 'partials/reset';
@import 'partials/grid';
@import 'partials/frappe';
@import 'partials/xhiveframework';
@import 'partials/tooltip';
@import 'partials/chosen';
@import 'partials/forms-ui';


+ 1
- 1
datavalue_theme_14/public/scss/datavalue_theme.scss Переглянути файл

@@ -1,6 +1,6 @@
@import 'partials/reset';
@import 'partials/grid';
@import 'partials/frappe';
@import 'partials/xhiveframework';
@import 'partials/tooltip';
@import 'partials/chosen';
@import 'partials/forms-ui';


+ 1
- 1
datavalue_theme_14/public/scss/partials/_body.scss Переглянути файл

@@ -7,7 +7,7 @@ body.hide-main-menu {
margin-left: 80px;
}

&.frappe-rtl {
&.xhiveframework-rtl {
.dv-app-theme .dv-app-content {
margin-left: 0 $imp;
margin-right: 80px $imp;


+ 0
- 425
datavalue_theme_14/public/scss/partials/_frappe.scss Переглянути файл

@@ -1,425 +0,0 @@
@media (min-width: 768px) {
body.full-width .container {
width: 100% $imp;
max-width: 100% $imp;
padding: 0px 5px $imp;
}
}

.page-container {
background-color: $body_bg_color;
}

.page-head {
border-bottom: 1px solid transparent;
height: 50px;
position: relative;
top: 0px;
}

.page-head .page-head-content {
height: auto;
}

.page-head.drop-shadow {
box-shadow: none;
background-color: #fff !important;
border-bottom: 1px solid #ddd;
z-index: 150;
top: 60px;
position: sticky;
margin: 0px -20px;
padding: 10px 20px;
transition: all 0.2s ease-in-out;
}

.page-container[data-page-route="Workspaces"] {
.layout-side-section, .page-title .sidebar-toggle-btn {
display: none $imp;
}

.layout-main-section-wrapper {
width: 100% $imp;
}
}

.centered.splash {
background: #f8fafb;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
transform: inherit;
-webkit-transform: initial;
text-align: center;
vertical-align: middle;
z-index: 9999999999999999;

img {
position: absolute;
left: 50%;
top: 50%;
margin: -50px 0px 0px -50px;
}
}

@media (min-width: 992px) {
[data-page-route="Workspaces"] .layout-main {
height: auto;
}
}

@media (min-width: 992px) {
[data-page-route="Workspaces"] .layout-main .layout-side-section, [data-page-route="Workspaces"] .layout-main .layout-main-section-wrapper {
height: auto;
padding-right: 20px;
padding-left: 20px;
}
}

.list-sidebar .list-filters input {
background: #ffffff;
border: 1px solid #d0d0d0;
}

.awesomplete .input-with-feedback {
background-color: #ffffff;
border: 1px solid #bbb;
}

.btn {
box-shadow: none $imp;
transition: all 0.2s ease-in-out;
border-radius: 5px;
}

.form-control {
background: #ffffff;
border: 1px solid #bbb;
transition: all 0.2s ease-in-out;
box-shadow: inset 1px 1px 7px -4px rgba(0, 0, 0, 0.44) $imp;
border-radius: 5px;

&:hover {
border-color: #999999;
}

&:focus {
background: #ffffff $imp;
border-color: var(--primary) $imp;
box-shadow: inset 1px 1px 7px -4px rgba(0, 0, 0, 0.44), 0 4px 24px 0 rgba(34, 41, 47, 0.10) $imp;
}
}

.btn.btn-default {
border: 1px solid #d1d3d8 $imp;

&:hover {
background: rgba(235, 239, 243, 0.7) $imp;
border-color: #a2a8b1 $imp;
}
}

.page-head {
.primary-action {
.icon {
display: none $imp;
}

span.hidden-xs {
display: inline-block $imp;
}
}
}

.page-form {
border-bottom: 1px solid #efefef;
}

select.input-xs {
line-height: 14px;
padding: 0 12px;
cursor: pointer;
}

input[type="radio"], input[type="checkbox"] {
cursor: pointer;
}

button.btn.btn-default.btn-sm.btn-paging.btn-info {
background: #14a6ef $imp;
border-color: #14a6ef $imp;
color: #fff $imp;
}

.frappe-list {
padding: 0px $imp;
}

.list-row-head {
background: #f3f3f5;
border-bottom: 1px solid #e8e8e8;
cursor: default;
font-size: 16px;
font-weight: 600;
}

.report-summary .summary-value {
height: auto;
min-height: 30px;
}

.alert.desk-alert {

.dv-alert-icon {
margin: 0px;
}

&.dv-alert-success, &.dv-alert-green {
border: 1px solid var(--success);
}

&.dv-alert-info, &.dv-alert-blue {
border: 1px solid var(--info);
}

&.dv-alert-error, &.dv-alert-red {
border: 1px solid var(--danger);
}

&.dv-alert-warning, &.dv-alert-orange, &.dv-alert-yellow {
border: 1px solid var(--orange);
}
}

.alert-body {
text-align: left;
padding: 0px 15px 10px 15px;
}

.btn svg.icon.icon-sm {
position: relative;
top: -1px;
}

.layout-main {
position: relative;

.btn-toggle-sidebar {
background: #fff;
border: 0;
box-shadow: -2px 0px 5px -2px #00000030;
margin: 0px 15px 0px 0px;
height: 30px;
width: 20px;
display: none;
text-align: center;
line-height: 29px;
font-size: 16px;
padding: 0;
position: absolute;
left: 0px;
top: 0px;
z-index: 50;
color: #666666;
border-radius: 5px 0px 0px 5px;
transition: all 0.2s ease-in;

&.sidebar-shown {
> i {
display: inline-block;
transform: rotate(180deg);
}
}

&:hover {
color: #434346;
}
}
}

.sidebar-toggle-btn {
display: none $imp;
}

.btn-toggle-main-menu {
background: $my_color;
border: 0px;
margin: 0px 15px 0px 0px;
height: 30px;
width: 30px;
min-width: 30px;
display: inline-block;
text-align: center;
line-height: 30px;
font-size: 16px;
padding: 0;
color: #ffffff;
border-radius: 5px;
transition: all 0.2s ease-in;

&:hover {
background: $my_color_hover;
}
}

.page-form .filter-button.btn-primary-light {
color: #000000;
}

.filter-icon.active use {
stroke: #000000;
}

.layout-main-section-wrapper {
margin-bottom: 0;
}

.widget .widget-head .widget-label .widget-title {
font-weight: 600;
}

.widget.shortcut-widget-box {
border: 1px solid #ddd;
box-shadow: 0px 3px 10px -5px rgba(0, 0, 0, .20);
border-radius: 6px;
padding: 10px 12px;
transition: all 0.2s ease-in-out;

.widget-title {
transition: all 0.2s ease-in-out;
}

& ~ .divider {
display: none;
}

&:hover {
border-color: var(--blue-500);

.widget-title {
color: var(--blue-500) !important;
}
}
}

.widget.dashboard-widget-box, .number-widget-box {
border: 1px solid #ddd;
box-shadow: 0px 3px 10px -5px rgba(0, 0, 0, .20);
}

.widget.links-widget-box {
border: 1px solid #ddd;
box-shadow: 0px 3px 10px -5px rgba(0, 0, 0, .20);

.widget-head {
border-bottom: 1px solid #ddd;
padding: 8px 15px 10px 15px;
margin: -13px -13px -8px -13px;
}

.link-item {
font-weight: 600;
}
}

.layout-main-section .frappe-list .result, .layout-main-section .frappe-list .no-result, .layout-main-section .frappe-list .freeze, .layout-main-section .report-wrapper .result, .layout-main-section .report-wrapper .no-result, .layout-main-section .report-wrapper .freeze {
min-height: calc(100vh - 295px);
}

.theme-setting-colors-select {
margin: 0px;

> h4 {
font-weight: 600;
margin-bottom: 15px;
}

button {
background: #aaaaaa;
border: 0px;
outline: none;
width: 100%;
height: 65px;
text-align: center;
line-height: 65px;
color: #ffffff;
border-radius: 5px;
transition: all 0.2s ease-in-out;

&.active {
position: relative;
box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.45);

&:after {
content: "\f058";
font-family: "Font Awesome 5 Pro";
font-weight: 700;
font-size: 18px;
position: absolute;
line-height: 26px;
top: 0px;
right: 5px;
}
}

&[data-color="Blue"] {
background: $my_color;
}

&[data-color="Green"] {
background: $green_color_style;
}

&[data-color="Red"] {
background: $red_color_style;
}

&[data-color="Orange"] {
background: $orange_color_style;
}

&[data-color="Yellow"] {
background: $yellow_color_style;
}

&[data-color="Pink"] {
background: $pink_color_style;
}

&[data-color="Violet"] {
background: $violet_color_style;
}
}
}

.form-tabs-sticky-down {
top: calc(var(--navbar-height) + var(--page-head-height) - 25px) $imp;
}

.frappe-control[data-fieldtype=Icon] .selected-icon {
top: calc(50% + -1px);
font-size: 18px;
}

.icon-picker .icons .icon-wrapper {
font-size: 20px;
opacity: .8;
color: #444;
border: 1px solid #aaa;
border-radius: 4px;
margin: 2.4px 2px;
transition: all 0.2s ease-in-out;

&:hover {
border-color: #444444;
color: #000000;
opacity: 1;
}

> i {
display: block;
margin: 0px auto;
}
}

+ 6
- 6
datavalue_theme_14/public/scss/partials/_rtl.scss Переглянути файл

@@ -1,4 +1,4 @@
body.frappe-rtl {
body.xhiveframework-rtl {
direction: rtl;
text-align: right;
overflow-x: hidden $imp;
@@ -180,7 +180,7 @@ body.frappe-rtl {
text-align: right;
}

.frappe-control[data-fieldtype="Select"] .control-input .select-icon, .frappe-control[data-fieldtype="Select"].form-group .select-icon {
.xhiveframework-control[data-fieldtype="Select"] .control-input .select-icon, .xhiveframework-control[data-fieldtype="Select"].form-group .select-icon {
top: 6px;
right: inherit;
left: 12px;
@@ -211,7 +211,7 @@ body.frappe-rtl {
line-height: 21px;
}

.frappe-control[data-fieldtype="Select"] .control-input .placeholder, .frappe-control[data-fieldtype="Select"].form-group .placeholder {
.xhiveframework-control[data-fieldtype="Select"] .control-input .placeholder, .xhiveframework-control[data-fieldtype="Select"].form-group .placeholder {
right: 12px;
left: inherit;
}
@@ -287,7 +287,7 @@ body.frappe-rtl {
text-align: right;
}

.frappe-control {
.xhiveframework-control {
text-align: right;
}

@@ -530,7 +530,7 @@ body.frappe-rtl {
margin-right: 0;
}

.frappe-control[data-fieldtype="Select"] .control-input select, .frappe-control[data-fieldtype="Select"].form-group select {
.xhiveframework-control[data-fieldtype="Select"] .control-input select, .xhiveframework-control[data-fieldtype="Select"].form-group select {
text-align: right $imp;
}

@@ -563,7 +563,7 @@ body.frappe-rtl {
padding-right: 0px;
padding-left: 15px;
}
.layout-main-section.form-dashboard-section, .layout-main-section.form-section.card-section, .layout-main-section.frappe-card {
.layout-main-section.form-dashboard-section, .layout-main-section.form-section.card-section, .layout-main-section.xhiveframework-card {
overflow: visible;
}
}


+ 15
- 15
datavalue_theme_14/templates/includes/login/login.js Переглянути файл

@@ -17,11 +17,11 @@ login.bind_events = function () {
event.preventDefault();
var args = {};
args.cmd = "login";
args.usr = frappe.utils.xss_sanitise(($("#login_email").val() || "").trim());
args.usr = xhiveframework.utils.xss_sanitise(($("#login_email").val() || "").trim());
args.pwd = $("#login_password").val();
args.device = "desktop";
if (!args.usr || !args.pwd) {
frappe.msgprint('{{ _("Both login and password required") }}');
xhiveframework.msgprint('{{ _("Both login and password required") }}');
return false;
}
login.call(args);
@@ -31,10 +31,10 @@ login.bind_events = function () {
$(".form-signup").on("submit", function (event) {
event.preventDefault();
var args = {};
args.cmd = "frappe.core.doctype.user.user.sign_up";
args.cmd = "xhiveframework.core.doctype.user.user.sign_up";
args.email = ($("#signup_email").val() || "").trim();
args.redirect_to = frappe.utils.sanitise_redirect(frappe.utils.get_url_arg("redirect-to"));
args.full_name = frappe.utils.xss_sanitise(($("#signup_fullname").val() || "").trim());
args.redirect_to = xhiveframework.utils.sanitise_redirect(xhiveframework.utils.get_url_arg("redirect-to"));
args.full_name = xhiveframework.utils.xss_sanitise(($("#signup_fullname").val() || "").trim());
if (!args.email || !validate_email(args.email) || !args.full_name) {
login.set_status('{{ _("Valid email and name required") }}', 'red');
return false;
@@ -46,7 +46,7 @@ login.bind_events = function () {
$(".form-forgot").on("submit", function (event) {
event.preventDefault();
var args = {};
args.cmd = "frappe.core.doctype.user.user.reset_password";
args.cmd = "xhiveframework.core.doctype.user.user.reset_password";
args.user = ($("#forgot_email").val() || "").trim();
if (!args.user) {
login.set_status('{{ _("Valid Login id required.") }}', 'red');
@@ -138,7 +138,7 @@ login.signup = function () {
login.call = function (args, callback) {
login.set_status('{{ _("Verifying...") }}', 'blue');

return frappe.call({
return xhiveframework.call({
type: "POST",
args: args,
callback: callback,
@@ -196,20 +196,20 @@ login.login_handlers = (function () {
if (data.message == 'Logged In') {
login.set_status('{{ _("Success") }}', 'green');
document.body.innerHTML = `{% include "templates/includes/splash_screen.html" %}`;
window.location.href = frappe.utils.sanitise_redirect(frappe.utils.get_url_arg("redirect-to")) || data.home_page;
window.location.href = xhiveframework.utils.sanitise_redirect(xhiveframework.utils.get_url_arg("redirect-to")) || data.home_page;
} else if (data.message == 'Password Reset') {
window.location.href = frappe.utils.sanitise_redirect(data.redirect_to);
window.location.href = xhiveframework.utils.sanitise_redirect(data.redirect_to);
} else if (data.message == "No App") {
login.set_status("{{ _('Success') }}", 'green');
if (localStorage) {
var last_visited =
localStorage.getItem("last_visited")
|| frappe.utils.sanitise_redirect(frappe.utils.get_url_arg("redirect-to"));
|| xhiveframework.utils.sanitise_redirect(xhiveframework.utils.get_url_arg("redirect-to"));
localStorage.removeItem("last_visited");
}

if (data.redirect_to) {
window.location.href = frappe.utils.sanitise_redirect(data.redirect_to);
window.location.href = xhiveframework.utils.sanitise_redirect(data.redirect_to);
}

if (last_visited && last_visited != "/login") {
@@ -234,7 +234,7 @@ login.login_handlers = (function () {
login.set_status(data.message[1], 'red');
} else {
login.set_status('{{ _("Success") }}', 'green');
frappe.msgprint(data.message[1])
xhiveframework.msgprint(data.message[1])
}
//login.set_status(__(data.message), 'green');
}
@@ -261,7 +261,7 @@ login.login_handlers = (function () {
return login_handlers;
})();

frappe.ready(function () {
xhiveframework.ready(function () {

login.bind_events();

@@ -281,9 +281,9 @@ var verify_token = function (event) {
var args = {};
args.cmd = "login";
args.otp = $("#login_token").val();
args.tmp_id = frappe.get_cookie('tmp_id');
args.tmp_id = xhiveframework.get_cookie('tmp_id');
if (!args.otp) {
frappe.msgprint('{{ _("Login token required") }}');
xhiveframework.msgprint('{{ _("Login token required") }}');
return false;
}
login.call(args);


+ 5
- 5
datavalue_theme_14/www/app.html Переглянути файл

@@ -44,7 +44,7 @@
<div class="dv-content-overlay"></div>
<div class="dv-app-content" id="body"></div>
<footer></footer>
{{ frappe.render_template('templates/side-menu.html', {}) }}
{{ xhiveframework.render_template('templates/side-menu.html', {}) }}
</div>

<script type="text/javascript">
@@ -53,11 +53,11 @@
window.app = true;
window.dev_server = {{ dev_server }};

if (!window.frappe) window.frappe = {};
if (!window.xhiveframework) window.xhiveframework = {};

frappe.boot = JSON.parse({{ boot }});
frappe._messages = frappe.boot["__messages"];
frappe.csrf_token = "{{ csrf_token }}";
xhiveframework.boot = JSON.parse({{ boot }});
xhiveframework._messages = xhiveframework.boot["__messages"];
xhiveframework.csrf_token = "{{ csrf_token }}";

</script>
{% for include in include_js %}


+ 27
- 27
datavalue_theme_14/www/app.py Переглянути файл

@@ -1,4 +1,4 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2015, Xhiveframework Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE
no_cache = 1

@@ -7,42 +7,42 @@ import os
import re
import secrets

import frappe
import frappe.sessions
from frappe import _
from frappe.utils.jinja_globals import is_rtl
import xhiveframework
import xhiveframework.sessions
from xhiveframework import _
from xhiveframework.utils.jinja_globals import is_rtl

SCRIPT_TAG_PATTERN = re.compile(r"\<script[^<]*\</script\>")
CLOSING_SCRIPT_TAG_PATTERN = re.compile(r"</script\>")


def get_context(context):
if frappe.session.user == "Guest":
frappe.throw(_("Log in to access this page."), frappe.PermissionError)
if xhiveframework.session.user == "Guest":
xhiveframework.throw(_("Log in to access this page."), xhiveframework.PermissionError)
elif (
frappe.db.get_value("User", frappe.session.user, "user_type", order_by=None) == "Website User"
xhiveframework.db.get_value("User", xhiveframework.session.user, "user_type", order_by=None) == "Website User"
):
frappe.throw(_("You are not permitted to access this page."), frappe.PermissionError)
xhiveframework.throw(_("You are not permitted to access this page."), xhiveframework.PermissionError)

hooks = frappe.get_hooks()
hooks = xhiveframework.get_hooks()
try:
boot = frappe.sessions.get()
boot = xhiveframework.sessions.get()
except Exception as e:
boot = frappe._dict(status="failed", error=str(e))
print(frappe.get_traceback())
boot = xhiveframework._dict(status="failed", error=str(e))
print(xhiveframework.get_traceback())

# this needs commit
csrf_token = frappe.sessions.get_csrf_token()
csrf_token = xhiveframework.sessions.get_csrf_token()

frappe.db.commit()
xhiveframework.db.commit()

theme_settings_list = {}

theme_settings = frappe.db.sql(""" SELECT * FROM tabSingles WHERE doctype = 'Theme Settings'; """, as_dict=True)
theme_settings = xhiveframework.db.sql(""" SELECT * FROM tabSingles WHERE doctype = 'Theme Settings'; """, as_dict=True)
for theme_setting in theme_settings:
theme_settings_list[theme_setting['field']] = theme_setting['value']

boot_json = frappe.as_json(boot, indent=None, separators=(",", ":"))
boot_json = xhiveframework.as_json(boot, indent=None, separators=(",", ":"))

# remove script tags from boot
boot_json = SCRIPT_TAG_PATTERN.sub("", boot_json)
@@ -57,19 +57,19 @@ def get_context(context):
context.update(
{
"no_cache": 1,
"build_version": frappe.utils.get_build_version(),
"build_version": xhiveframework.utils.get_build_version(),
"build_version_dev": secrets.randbits(50),
"include_js": hooks["app_include_js"],
"include_css": hooks["app_include_css"],
"layout_direction": "rtl" if is_rtl() else "ltr",
"lang": frappe.local.lang,
"lang": xhiveframework.local.lang,
"sounds": hooks["sounds"],
"boot": boot if context.get("for_mobile") else boot_json,
"desk_theme": boot.get("desk_theme") or "Light",
"csrf_token": csrf_token,
"google_analytics_id": frappe.conf.get("google_analytics_id"),
"google_analytics_anonymize_ip": frappe.conf.get("google_analytics_anonymize_ip"),
"mixpanel_id": frappe.conf.get("mixpanel_id"),
"google_analytics_id": xhiveframework.conf.get("google_analytics_id"),
"google_analytics_anonymize_ip": xhiveframework.conf.get("google_analytics_anonymize_ip"),
"mixpanel_id": xhiveframework.conf.get("mixpanel_id"),
"get_theme_settings": theme_settings_list,
"dark_theme": theme
}
@@ -78,7 +78,7 @@ def get_context(context):
return context


@frappe.whitelist()
@xhiveframework.whitelist()
def get_desk_assets(build_version):
"""Get desk assets to be loaded for mobile app"""
data = get_context({"for_mobile": True})
@@ -92,8 +92,8 @@ def get_desk_assets(build_version):
if path.startswith("/assets/"):
path = path.replace("/assets/", "assets/")
try:
with open(os.path.join(frappe.local.sites_path, path)) as f:
assets[0]["data"] = assets[0]["data"] + "\n" + frappe.safe_decode(f.read(), "utf-8")
with open(os.path.join(xhiveframework.local.sites_path, path)) as f:
assets[0]["data"] = assets[0]["data"] + "\n" + xhiveframework.safe_decode(f.read(), "utf-8")
except OSError:
pass

@@ -101,8 +101,8 @@ def get_desk_assets(build_version):
if path.startswith("/assets/"):
path = path.replace("/assets/", "assets/")
try:
with open(os.path.join(frappe.local.sites_path, path)) as f:
assets[1]["data"] = assets[1]["data"] + "\n" + frappe.safe_decode(f.read(), "utf-8")
with open(os.path.join(xhiveframework.local.sites_path, path)) as f:
assets[1]["data"] = assets[1]["data"] + "\n" + xhiveframework.safe_decode(f.read(), "utf-8")
except OSError:
pass



+ 3
- 3
datavalue_theme_14/www/login.html Переглянути файл

@@ -73,7 +73,7 @@
<div class="login-content page-card">
<div class="login-content-bg">
<img class="app-logo" src="{{ logo }}">
<img class="app-login-bg" src="/assets/datavalue_theme_14/images/erpnext-hero-compressed.png">
<img class="app-login-bg" src="/assets/datavalue_theme_14/images/xhiveerp-hero-compressed.png">
<div class="text-center login-copyrights">Powered By <a href="https://www.datavaluenet.net/" target="_blank">Data Value</a></div>
</div>
<div class="login-content-form">
@@ -134,7 +134,7 @@
<div class="login-content page-card">
<div class="login-content-bg">
<img class="app-logo" src="{{ logo }}">
<img class="app-login-bg" src="/assets/datavalue_theme_14/images/erpnext-hero-compressed.png">
<img class="app-login-bg" src="/assets/datavalue_theme_14/images/xhiveerp-hero-compressed.png">
<div class="text-center login-copyrights">Powered By <a href="https://www.datavaluenet.net/" target="_blank">Data Value</a></div>
</div>
<div class="login-content-form">
@@ -187,7 +187,7 @@
<div class="login-content page-card">
<div class="login-content-bg">
<img class="app-logo" src="{{ logo }}">
<img class="app-login-bg" src="/assets/datavalue_theme_14/images/erpnext-hero-compressed.png">
<img class="app-login-bg" src="/assets/datavalue_theme_14/images/xhiveerp-hero-compressed.png">
<div class="text-center login-copyrights">Powered By <a href="https://www.datavaluenet.net/" target="_blank">Data Value</a></div>
</div>
<div class="login-content-form">


+ 40
- 40
datavalue_theme_14/www/login.py Переглянути файл

@@ -1,54 +1,54 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2015, Xhiveframework Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals
import secrets
import frappe
import frappe.utils
from frappe.utils.oauth import get_oauth2_authorize_url, get_oauth_keys, login_via_oauth2, login_via_oauth2_id_token, login_oauth_user as _login_oauth_user, redirect_post_login
import xhiveframework
import xhiveframework.utils
from xhiveframework.utils.oauth import get_oauth2_authorize_url, get_oauth_keys, login_via_oauth2, login_via_oauth2_id_token, login_oauth_user as _login_oauth_user, redirect_post_login
import json
from frappe import _
from frappe.auth import LoginManager
from frappe.integrations.doctype.ldap_settings.ldap_settings import LDAPSettings
from frappe.utils.password import get_decrypted_password
from frappe.utils.html_utils import get_icon_html
from frappe.integrations.oauth2_logins import decoder_compat
from frappe.website.utils import get_home_page
from xhiveframework import _
from xhiveframework.auth import LoginManager
from xhiveframework.integrations.doctype.ldap_settings.ldap_settings import LDAPSettings
from xhiveframework.utils.password import get_decrypted_password
from xhiveframework.utils.html_utils import get_icon_html
from xhiveframework.integrations.oauth2_logins import decoder_compat
from xhiveframework.website.utils import get_home_page

no_cache = True

def get_context(context):
redirect_to = frappe.local.request.args.get("redirect-to")
redirect_to = xhiveframework.local.request.args.get("redirect-to")

if frappe.session.user != "Guest":
if xhiveframework.session.user != "Guest":
if not redirect_to:
if frappe.session.data.user_type=="Website User":
if xhiveframework.session.data.user_type=="Website User":
redirect_to = get_home_page()
else:
redirect_to = "/app"

if redirect_to != 'login':
frappe.local.flags.redirect_location = redirect_to
raise frappe.Redirect
xhiveframework.local.flags.redirect_location = redirect_to
raise xhiveframework.Redirect

# get settings from site config
context.no_header = True
context.for_test = 'login.html'
context["title"] = "Login"
context["provider_logins"] = []
context["disable_signup"] = frappe.utils.cint(frappe.db.get_single_value("Website Settings", "disable_signup"))
context["logo"] = (frappe.db.get_single_value('Website Settings', 'app_logo') or
frappe.get_hooks("app_logo_url")[-1])
context["app_name"] = (frappe.db.get_single_value('Website Settings', 'app_name') or
frappe.get_system_settings("app_name") or _("Frappe"))
providers = [i.name for i in frappe.get_all("Social Login Key", filters={"enable_social_login":1}, order_by="name")]
context["disable_signup"] = xhiveframework.utils.cint(xhiveframework.db.get_single_value("Website Settings", "disable_signup"))
context["logo"] = (xhiveframework.db.get_single_value('Website Settings', 'app_logo') or
xhiveframework.get_hooks("app_logo_url")[-1])
context["app_name"] = (xhiveframework.db.get_single_value('Website Settings', 'app_name') or
xhiveframework.get_system_settings("app_name") or _("Xhiveframework"))
providers = [i.name for i in xhiveframework.get_all("Social Login Key", filters={"enable_social_login":1}, order_by="name")]
for provider in providers:
client_id, base_url = frappe.get_value("Social Login Key", provider, ["client_id", "base_url"])
client_id, base_url = xhiveframework.get_value("Social Login Key", provider, ["client_id", "base_url"])
client_secret = get_decrypted_password("Social Login Key", provider, "client_secret")
provider_name = frappe.get_value("Social Login Key", provider, "provider_name")
provider_name = xhiveframework.get_value("Social Login Key", provider, "provider_name")

icon = None
icon_url = frappe.get_value("Social Login Key", provider, "icon")
icon_url = xhiveframework.get_value("Social Login Key", provider, "icon")
if icon_url:
if provider_name != "Custom":
icon = "<img src='{0}' alt={1}>".format(icon_url, provider_name)
@@ -68,10 +68,10 @@ def get_context(context):

login_label = [_("Email")]

if frappe.utils.cint(frappe.get_system_settings("allow_login_using_mobile_number")):
if xhiveframework.utils.cint(xhiveframework.get_system_settings("allow_login_using_mobile_number")):
login_label.append(_("Mobile"))

if frappe.utils.cint(frappe.get_system_settings("allow_login_using_user_name")):
if xhiveframework.utils.cint(xhiveframework.get_system_settings("allow_login_using_user_name")):
login_label.append(_("Username"))

context['login_label'] = ' {0} '.format(_('or')).join(login_label)
@@ -79,34 +79,34 @@ def get_context(context):

return context

@frappe.whitelist(allow_guest=True)
@xhiveframework.whitelist(allow_guest=True)
def login_via_google(code, state):
login_via_oauth2("google", code, state, decoder=decoder_compat)

@frappe.whitelist(allow_guest=True)
@xhiveframework.whitelist(allow_guest=True)
def login_via_github(code, state):
login_via_oauth2("github", code, state)

@frappe.whitelist(allow_guest=True)
@xhiveframework.whitelist(allow_guest=True)
def login_via_facebook(code, state):
login_via_oauth2("facebook", code, state, decoder=decoder_compat)

@frappe.whitelist(allow_guest=True)
def login_via_frappe(code, state):
login_via_oauth2("frappe", code, state, decoder=decoder_compat)
@xhiveframework.whitelist(allow_guest=True)
def login_via_xhiveframework(code, state):
login_via_oauth2("xhiveframework", code, state, decoder=decoder_compat)

@frappe.whitelist(allow_guest=True)
@xhiveframework.whitelist(allow_guest=True)
def login_via_office365(code, state):
login_via_oauth2_id_token("office_365", code, state, decoder=decoder_compat)

@frappe.whitelist(allow_guest=True)
@xhiveframework.whitelist(allow_guest=True)
def login_via_token(login_token):
sid = frappe.cache().get_value("login_token:{0}".format(login_token), expires=True)
sid = xhiveframework.cache().get_value("login_token:{0}".format(login_token), expires=True)
if not sid:
frappe.respond_as_web_page(_("Invalid Request"), _("Invalid Login Token"), http_status_code=417)
xhiveframework.respond_as_web_page(_("Invalid Request"), _("Invalid Login Token"), http_status_code=417)
return

frappe.local.form_dict.sid = sid
frappe.local.login_manager = LoginManager()
xhiveframework.local.form_dict.sid = sid
xhiveframework.local.login_manager = LoginManager()

redirect_post_login(desk_user = frappe.db.get_value("User", frappe.session.user, "user_type")=="System User")
redirect_post_login(desk_user = xhiveframework.db.get_value("User", xhiveframework.session.user, "user_type")=="System User")

+ 1
- 1
requirements.txt Переглянути файл

@@ -1 +1 @@
# frappe -- https://github.com/frappe/frappe is installed via 'bench init'
# xhiveframework -- https://github.com/xhiveframework/xhiveframework is installed via 'bench init'

+ 1
- 1
setup.py Переглянути файл

@@ -9,7 +9,7 @@ from datavalue_theme_14 import __version__ as version
setup(
name="datavalue_theme_14",
version=version,
description="Data Value Frappe 14 Theme",
description="Data Value Xhiveframework 14 Theme",
author="Abdo Hamoud",
author_email="abdo.host@gmail.com",
packages=find_packages(),


Завантаження…
Відмінити
Зберегти