ソースを参照

feat(explore_page): Modules and Module Detail views

version-14
Prateeksha Singh 6年前
コミット
c01ace6048
10個のファイルの変更482行の追加282行の削除
  1. +53
    -41
      frappe/config/desktop.py
  2. +0
    -51
      frappe/config/settings.py
  3. +106
    -3
      frappe/desk/doctype/desktop_icon/desktop_icon.json
  4. +1
    -1
      frappe/desk/doctype/desktop_icon/desktop_icon.py
  5. +0
    -185
      frappe/desk/page/modules/modules.js
  6. +5
    -1
      frappe/public/build.json
  7. +136
    -0
      frappe/public/js/frappe/modules/ModuleDetail.vue
  8. +134
    -0
      frappe/public/js/frappe/modules/Modules.vue
  9. +21
    -0
      frappe/public/js/frappe/modules/modules_factory.js
  10. +26
    -0
      frappe/public/js/frappe/modules/modules_home.js

+ 53
- 41
frappe/config/desktop.py ファイルの表示

@@ -3,14 +3,6 @@ from frappe import _

def get_data():
return [
{
"module_name": "Desk",
"label": _("Tools"),
"color": "#FFF5A7",
"reverse": 1,
"icon": "octicon octicon-calendar",
"type": "module"
},
{
"module_name": "File Manager",
"color": "#AA784D",
@@ -22,18 +14,27 @@ def get_data():
"hidden": 1
},
{
"module_name": "Website",
"color": "#16a085",
"icon": "octicon octicon-globe",
"type": "module",
"hidden": 1
"module_name": 'Email Inbox',
"type": 'list',
"label": 'Email Inbox',
"_label": _('Email Inbox'),
"_id": 'Email Inbox',
"_doctype": 'Communication',
"icon": 'fa fa-envelope-o',
"color": '#589494',
"link": 'List/Communication/Inbox'
},


# Administration
{
"module_name": "Integrations",
"color": "#16a085",
"icon": "octicon octicon-globe",
"type": "module",
"hidden": 1
"module_name": 'Contacts',
"type": 'module',
"icon": "octicon octicon-book",
"color": '#ffaedb',
"category": "Administration",
"hidden": 1,
"description": "People Contacts and Address Book."
},
{
"module_name": "Setup",
@@ -41,18 +42,28 @@ def get_data():
"reverse": 1,
"icon": "octicon octicon-settings",
"type": "module",
"hidden": 1
"category": "Administration",
"hidden": 1,
"description": "Configure your ERPNext account."
},
{
"module_name": 'Email Inbox',
"type": 'list',
"label": 'Email Inbox',
"_label": _('Email Inbox'),
"_id": 'Email Inbox',
"_doctype": 'Communication',
"icon": 'fa fa-envelope-o',
"color": '#589494',
"link": 'List/Communication/Inbox'
"module_name": "Integrations",
"color": "#16a085",
"icon": "octicon octicon-globe",
"type": "module",
"category": "Administration",
"hidden": 1,
"description": "DropBox, Woocomerce, AWS, Shopify and GoCardless."
},
{
"module_name": "Desk",
"label": _("Tools"),
"color": "#FFF5A7",
"reverse": 1,
"icon": "octicon octicon-calendar",
"type": "module",
"category": "Administration",
"description": "Todos, Notes and other basic tools to help you track your work."
},
{
"module_name": "Core",
@@ -62,14 +73,20 @@ def get_data():
"icon": "octicon octicon-circuit-board",
"type": "module",
"system_manager": 1,
"hidden": 1
"category": "Administration",
"hidden": 1,
"description": "The Frappe innards of ERPNext. (Only active when developer mode is enabled)"
},

# Places
{
"module_name": 'Contacts',
"type": 'module',
"icon": "octicon octicon-book",
"color": '#FFAEDB',
"module_name": "Website",
"color": "#16a085",
"icon": "octicon octicon-globe",
"type": "module",
"category": "Places",
"hidden": 1,
"description": "Webpages and the Portal Side of Things."
},
{
"module_name": 'Social',
@@ -79,13 +96,8 @@ def get_data():
"link": 'social/home',
"color": '#FF4136',
'standard': 1,
'idx': 15
"category": "Places",
'idx': 15,
"description": "Build your profile and share posts on the feed with other users."
},
{
"module_name": 'Settings',
"color": "#bdc3c7",
"reverse": 1,
"icon": "octicon octicon-settings",
"type": "module"
}
]

+ 0
- 51
frappe/config/settings.py ファイルの表示

@@ -1,51 +0,0 @@
from frappe import _

def get_data():
return [{
"label": _("Settings"),
"icon": "fa fa-wrench",
"items": [
{
"type": "doctype",
"name": "System Settings",
"label": _("System Settings"),
"description": _("Language, Date and Time settings"),
"hide_count": True
},
{
"type": "doctype",
"name": "Domain Settings",
"label": _("Domain Settings"),
"description": _("Enable / Disable Domains"),
"hide_count": True
},
{
"type": "doctype",
"name": "Print Settings",
"label": _("Print Settings"),
"description": _("Print Style, PDF Size"),
"hide_count": True
},
{
"type": "doctype",
"name": "Website Settings",
"label": _("Website Settings"),
"description": _("Landing Page, Website Theme, Brand Setup and more"),
"hide_count": True
},
{
"type": "doctype",
"name": "S3 Backup Settings",
"label": _("S3 Backup Settings"),
"description": _("Enable / Disable Backup, Backup Frequency"),
"hide_count": True
},
{
"type": "doctype",
"name": "SMS Settings",
"label": _("SMS Settings"),
"description": _("SMS Gateway URL, Message & Receiver Parameter"),
"hide_count": True
}
]
}]

+ 106
- 3
frappe/desk/doctype/desktop_icon/desktop_icon.json ファイルの表示

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -14,6 +15,7 @@
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -40,10 +42,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -70,10 +74,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -100,10 +106,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -130,10 +138,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -159,10 +169,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -189,10 +201,76 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "description",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Description",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "category",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Category",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -219,10 +297,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -249,10 +329,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -279,10 +361,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -308,10 +392,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -339,10 +425,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -370,10 +458,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -401,10 +491,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -431,10 +523,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -460,10 +554,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -490,10 +586,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -520,10 +618,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -550,10 +650,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -580,6 +682,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
@@ -593,7 +696,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-05-08 15:41:31.121652",
"modified": "2019-01-24 04:58:58.720618",
"modified_by": "Administrator",
"module": "Desk",
"name": "Desktop Icon",
@@ -602,7 +705,6 @@
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -629,5 +731,6 @@
"sort_order": "DESC",
"title_field": "module_name",
"track_changes": 1,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

+ 1
- 1
frappe/desk/doctype/desktop_icon/desktop_icon.py ファイルの表示

@@ -31,7 +31,7 @@ def get_desktop_icons(user=None):
user_icons = frappe.cache().hget('desktop_icons', user)

if not user_icons:
fields = ['module_name', 'hidden', 'label', 'link', 'type', 'icon', 'color',
fields = ['module_name', 'hidden', 'label', 'link', 'type', 'icon', 'color', 'description', 'category',
'_doctype', '_report', 'idx', 'force_show', 'reverse', 'custom', 'standard', 'blocked']

active_domains = frappe.get_active_domains()


+ 0
- 185
frappe/desk/page/modules/modules.js ファイルの表示

@@ -1,185 +0,0 @@
frappe.pages['modules'].on_page_load = function(wrapper) {
var page = frappe.ui.make_app_page({
parent: wrapper,
title: 'Modules',
single_column: false
});

frappe.modules_page = page;
frappe.module_links = {};
page.section_data = {};

page.wrapper.find('.page-head h1').css({'padding-left': '15px'});
// page.wrapper.find('.page-content').css({'margin-top': '0px'});

// menu
page.add_menu_item(__('Set Desktop Icons'), function() {
frappe.frappe_toolbar.modules_select
.show(frappe.session.user);
});

if(frappe.user.has_role('System Manager')) {
page.add_menu_item(__('Install Apps'), function() {
frappe.set_route("applications");
});
}

page.get_page_modules = () => {
return frappe.get_desktop_icons(true)
.filter(d => d.type==='module' && !d.blocked)
.sort((a, b) => { return (a._label > b._label) ? 1 : -1; });
};

let get_module_sidebar_item = (item) => `<li class="strong module-sidebar-item">
<a class="module-link" data-name="${item.module_name}" href="#${item.link}">
<i class="fa fa-chevron-right pull-right" style="display: none;"></i>
<span>${item._label}</span>
</a>
</li>`;

let get_sidebar_html = () => {
let sidebar_items_html = page.get_page_modules()
.map(get_module_sidebar_item.bind(this)).join("");

return `<ul class="module-sidebar-nav overlay-sidebar nav nav-pills nav-stacked">
${sidebar_items_html}
<li class="divider"></li>
</ul>`;
};

// render sidebar
page.sidebar.html(get_sidebar_html());

// help click
page.main.on("click", '.module-section-link[data-type="help"]', function() {
frappe.help.show_video($(this).attr("data-youtube-id"));
return false;
});

// notifications click
page.main.on("click", '.open-notification', function() {
var doctype = $(this).attr('data-doctype');
if(doctype) {
frappe.ui.notifications.show_open_count_list(doctype);
}
});

page.activate_link = function(link) {
page.last_link = link;
page.wrapper.find('.module-sidebar-item.active, .module-link.active').removeClass('active');
$(link).addClass('active').parent().addClass("active");
show_section($(link).attr('data-name'));
};

var show_section = function(module_name) {
if (!module_name) return;
if(module_name in page.section_data) {
render_section(page.section_data[module_name]);
} else {
page.main.empty();
return frappe.call({
method: "frappe.desk.moduleview.get",
args: {
module: module_name
},
callback: function(r) {
var m = frappe.get_module(module_name);
m.data = r.message.data;
process_data(module_name, m.data);
page.section_data[module_name] = m;
render_section(m);
},
freeze: true,
});
}

};

var render_section = function(m) {
page.set_title(__(m.label));
page.main.html(frappe.render_template('modules_section', m));

// if(frappe.utils.is_xs() || frappe.utils.is_sm()) {
// // call this after a timeout, becuase a refresh will set the page to the top
// setTimeout(function() {
// $(document).scrollTop($('.module-body').offset().top - 150);
// }, 100);
// }

//setup_section_toggle();
frappe.app.update_notification_count_in_modules();
};

var process_data = function(module_name, data) {
frappe.module_links[module_name] = [];
data.forEach(function(section) {
section.items.forEach(function(item) {
item.style = '';
if(item.type==="doctype") {
item.doctype = item.name;

// map of doctypes that belong to a module
frappe.module_links[module_name].push(item.name);
}
if(!item.route) {
if(item.link) {
item.route=strip(item.link, "#");
}
else if(item.type==="doctype") {
if(frappe.model.is_single(item.doctype)) {
item.route = 'Form/' + item.doctype;
} else {
if (item.filters) {
frappe.route_options=item.filters;
}
item.route="List/" + item.doctype;
//item.style = 'font-weight: 500;';
}
// item.style = 'font-weight: bold;';
}
else if(item.type==="report" && item.is_query_report) {
item.route="query-report/" + item.name;
}
else if(item.type==="report") {
item.route="List/" + item.doctype + "/Report/" + item.name;
}
else if(item.type==="page") {
item.route=item.name;
}
}

if(item.route_options) {
item.route += "?" + $.map(item.route_options, function(value, key) {
return encodeURIComponent(key) + "=" + encodeURIComponent(value); }).join('&');
}

if(item.type==="page" || item.type==="help" || item.type==="report" ||
(item.doctype && frappe.model.can_read(item.doctype))) {
item.shown = true;
}
});
});
};
};

frappe.pages['modules'].on_page_show = function(wrapper) {
let route = frappe.get_route();
let modules = frappe.modules_page.get_page_modules().map(d => d.module_name);
$("body").attr("data-sidebar", 1);
if(route.length > 1) {
// activate section based on route
let module_name = route[1];
if(modules.includes(module_name)) {
frappe.modules_page.activate_link(
frappe.modules_page.sidebar.find('.module-link[data-name="'+ module_name +'"]'));
} else {
frappe.throw(__(`Module ${module_name} not found.`));
}
} else if(frappe.modules_page.last_link) {
// open last link
frappe.set_route('modules', frappe.modules_page.last_link.attr('data-name'));
} else {
// first time, open the first page
frappe.modules_page.activate_link(frappe.modules_page.sidebar.find('.module-link:first'));
}
};

+ 5
- 1
frappe/public/build.json ファイルの表示

@@ -248,7 +248,8 @@

"public/js/frappe/chat.js",

"public/js/frappe/social/social_factory.js"
"public/js/frappe/social/social_factory.js",
"public/js/frappe/modules/modules_factory.js"
],
"css/module.min.css": [
"public/less/module.less"
@@ -381,5 +382,8 @@
],
"js/social.min.js": [
"public/js/frappe/social/social_home.js"
],
"js/modules.min.js": [
"public/js/frappe/modules/modules_home.js"
]
}

+ 136
- 0
frappe/public/js/frappe/modules/ModuleDetail.vue ファイルの表示

@@ -0,0 +1,136 @@
<template>
<div class="sections-container">
<div v-for="section in sections"
:key="section.name"
class="border section-box"
>
<h4 class="h4"> {{ section.label }} </h4>
<p v-for="item in section.items" class="small"
:key="item.name"
:data-youtube-id="item.type==='help' ? item.youtube_id : false"
>
<a :href="item.route">{{ item.label || __(item.name) }}</a>
<span class="open-notification global hide"
@click="item.doctype || item.name ? frappe.ui.notifications.show_open_count_list(item.doctype || item.name) : false"
:data-doctype="item.doctype || item.name"></span>
</p>
</div>
</div>
</template>

<script>
export default {
props: ['module_name'],
data() {
return {
stats: {},
sections: []
}
},
created() {
this.get_sections();
this.get_stats();
},
updated() {
frappe.app.update_notification_count_in_modules();
},
methods: {
get_sections() {
return frappe.call({
method: "frappe.desk.moduleview.get",
args: {
module: this.module_name,
},
callback: (r) => {
var m = frappe.get_module(this.module_name);
this.sections = r.message.data;
this.process_data(this.module_name, this.sections);
// setTimeout(() => {}, 500);
},
freeze: true,
});
},
get_stats() {
//
},
process_data(module_name, data) {
frappe.module_links[module_name] = [];
console.log(data);
data.forEach(function(section) {
section.items.forEach(function(item) {
item.style = '';
if(item.type==="doctype") {
item.doctype = item.name;

// map of doctypes that belong to a module
frappe.module_links[module_name].push(item.name);
}
if(!item.route) {
if(item.link) {
item.route=strip(item.link, "#");
}
else if(item.type==="doctype") {
if(frappe.model.is_single(item.doctype)) {
item.route = 'Form/' + item.doctype;
} else {
if (item.filters) {
frappe.route_options=item.filters;
}
item.route="List/" + item.doctype;
//item.style = 'font-weight: 500;';
}
// item.style = 'font-weight: bold;';
}
else if(item.type==="report" && item.is_query_report) {
item.route="query-report/" + item.name;
}
else if(item.type==="report") {
item.route="List/" + item.doctype + "/Report/" + item.name;
}
else if(item.type==="page") {
item.route=item.name;
}
}

if(item.route_options) {
item.route += "?" + $.map(item.route_options, function(value, key) {
return encodeURIComponent(key) + "=" + encodeURIComponent(value); }).join('&');
}

if(item.type==="page" || item.type==="help" || item.type==="report" ||
(item.doctype && frappe.model.can_read(item.doctype))) {
item.shown = true;
}
});
});
console.log('2', data);
}
}
}
</script>
<style lang="less" scoped>
.sections-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 15px;
row-gap: 15px;
}

.section-box {
padding: 10px 20px;
border-radius: 4px;

p {
line-height: 1.5em;
}
}

.h4 {
margin-bottom: 15px;
}

a:hover, a:focus {
text-decoration: underline;
}

</style>

+ 134
- 0
frappe/public/js/frappe/modules/Modules.vue ファイルの表示

@@ -0,0 +1,134 @@
<template>
<div class="modules-page-container">
<div v-if="route_str === 'home'" >
<div v-for="category in module_categories"
:key="category">

<div v-if="category.length" class="module-category h6 uppercase">
{{ category }}
</div>

<div class="modules-container">
<div v-for="module in modules_by_categories[category]"
:key="module.name"
class="border module-box level"
@click="update_state(module.module_name, module.label)"
>
<div class="icon-box">
<span><i class="icon text-extra-muted" :class="module.icon"></i></span>
</div>
<div class="module-box-content">
<h4 class="h4"> {{ module.label }} </h4>
<p class="small"> {{ module.description }} </p>
</div>
</div>
</div>

</div>
</div>

<keep-alive v-else-if="modules.map(m => m.module_name).includes(route_str)">
<module-detail :module_name="route_str"></module-detail>
</keep-alive>
</div>
</template>

<script>
import ModuleDetail from './ModuleDetail.vue';

export default {
components: {
ModuleDetail
},
data() {
return {
route_str: frappe.get_route()[1],
module_label: '',
module_categories: ["", "Domains", "Places", "Administration"],
modules_by_categories: {},
modules: frappe.get_desktop_icons(true)
.filter(d => (d.type==='module' || d.category==='Places') && !d.blocked),
};
},
created() {
this.module_categories.map(category => {
this.modules_by_categories[category] = this.modules.filter(m => m.category === category );
});
this.modules_by_categories[""] = this.modules.filter(m => !m.category);
},
mounted() {
frappe.module_links = {};
frappe.route.on('change', () => {
let module = frappe.get_route()[1];
this.update_module(module);
});
},
methods: {
update_state(name, label) {
this.module_label = label;
frappe.set_route(['modules', name]);
},
update_module(module) {
this.route_str = module;
let title = this.module_label ? this.module_label : module;
title = module!=='home' ? title : 'Modules';
frappe.modules.home.page.set_title(title);
}
}
}
</script>

<style lang="less" scoped>
.modules-page-container {
padding: 15px 0px;
padding-bottom: 30px;
}

.module-category {
margin-top: 20px;
border-bottom: 1px solid #d0d8dd;
}

.modules-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 15px;
row-gap: 15px;
}

.module-box {
border-radius: 4px;
cursor: pointer;
}

.module-box:hover {
background-color: #fafbfc;
}

.module-box-content {
padding-right: 15px;
flex: 1;

h4 {
margin-bottom: 5px
}

p {
margin-top: 5px;
font-size: 80%;
}
}

.icon-box {
padding: 0px 30px;
width: 62px;
display: flex;
justify-content: center;
}

.icon {
font-size: 24px;
}

</style>


+ 21
- 0
frappe/public/js/frappe/modules/modules_factory.js ファイルの表示

@@ -0,0 +1,21 @@
frappe.views.ModulesFactory = class ModulesFactory extends frappe.views.Factory {
show() {
if (frappe.pages.modules) {
frappe.container.change_to('modules');
} else {
this.make('modules');
}
}

make(page_name) {
const assets = [
'/assets/js/modules.min.js'
];

frappe.require(assets, () => {
frappe.modules.home = new frappe.modules.Home({
parent: this.make_page(true, page_name)
});
});
}
};

+ 26
- 0
frappe/public/js/frappe/modules/modules_home.js ファイルの表示

@@ -0,0 +1,26 @@
import Modules from './Modules.vue';

frappe.provide('frappe.social');

frappe.modules.Home = class {
constructor({ parent }) {
this.$parent = $(parent);
this.page = parent.page;
this.setup_header();
this.make_body();
}
make_body() {
this.$modules_container = this.$parent.find('.layout-main');
frappe.require('/assets/js/frappe-vue.min.js', () => {
Vue.prototype.__ = window.__;
Vue.prototype.frappe = window.frappe;
new Vue({
el: this.$modules_container[0],
render: h => h(Modules)
});
});
}
setup_header() {
this.page.set_title(__('Modules'));
}
};

読み込み中…
キャンセル
保存