Parcourir la source

feat(desk): Make all desk modules links, make Detail view dumb

version-14
Prateeksha Singh il y a 6 ans
Parent
révision
aeebf1edf2
8 fichiers modifiés avec 310 ajouts et 220 suppressions
  1. +1
    -1
      frappe/config/desktop.py
  2. +3
    -0
      frappe/public/build.json
  3. +165
    -0
      frappe/public/js/frappe/views/components/Desktop.vue
  4. +1
    -84
      frappe/public/js/frappe/views/components/ModuleDetail.vue
  5. +100
    -101
      frappe/public/js/frappe/views/components/Modules.vue
  6. +25
    -0
      frappe/public/js/frappe/views/modules_home.js
  7. +15
    -29
      frappe/public/js/frappe/views/pageview.js
  8. +0
    -5
      frappe/public/less/desktop.less

+ 1
- 1
frappe/config/desktop.py Voir le fichier

@@ -99,7 +99,7 @@ def get_data():
"label": _('Social'),
"icon": "octicon octicon-heart",
"type": 'link',
"link": 'social/home',
"link": '#social/home',
"color": '#FF4136',
'standard': 1,
'idx': 15,


+ 3
- 0
frappe/public/build.json Voir le fichier

@@ -381,5 +381,8 @@
],
"js/social.min.js": [
"public/js/frappe/social/social_home.js"
],
"js/modules.min.js": [
"public/js/frappe/views/modules_home.js"
]
}

+ 165
- 0
frappe/public/js/frappe/views/components/Desktop.vue Voir le fichier

@@ -0,0 +1,165 @@
<template>
<div class="modules-page-container">
<div v-for="category in module_categories"
:key="category">

<div v-if="modules.filter(m => m.category === category).length" class="module-category h6 uppercase">
{{ category }}
</div>

<div class="modules-container">
<a v-for="module in modules.filter(m => m.category === category )"
:key="module.name"
:href="module.type === 'module' ? '#modules/' + module.module_name : module.link"
class="border module-box"
>
<div class="flush-top">
<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 }}
<span v-if="module.count" class="open-notification global">{{ module.count }}</span>
</h4>
<p class="small text-muted"> {{ module.description }} </p>
</div>
</div>
</a>
</div>

</div>

</div>
</template>

<script>

export default {
data() {
return {
route_str: frappe.get_route()[1],
module_label: '',
module_categories: ["Modules", "Domains", "Places", "Administration"],
modules: []
};
},
created() {
this.get_modules();
},
methods: {
get_modules() {
let res = frappe.call({
method: 'frappe.desk.doctype.desktop_icon.desktop_icon.get_modules_from_all_apps',
});

res.then(r => {
if (r.message) {
let modules_list = r.message;

modules_list = modules_list
.filter(d => (d.type==='module' || d.category==='Places') && !d.blocked);

modules_list.forEach(module => {
module.count = this.get_module_count(module.module_name);
});

this.modules = modules_list;
}
});
},

get_module_count(module_name) {
var module_doctypes = frappe.boot.notification_info.module_doctypes[module_name];
var sum = 0;

if(module_doctypes && frappe.boot.notification_info.open_count_doctype) {
// sum all doctypes for a module
for (var j=0, k=module_doctypes.length; j < k; j++) {
var doctype = module_doctypes[j];
let count = (frappe.boot.notification_info.open_count_doctype[doctype] || 0);
count = typeof count == "string" ? parseInt(count) : count;
sum += count;
}
}

if(frappe.boot.notification_info.open_count_doctype
&& frappe.boot.notification_info.open_count_doctype[module_name]!=null) {
// notification count explicitly for doctype
let count = frappe.boot.notification_info.open_count_doctype[module_name] || 0;
count = typeof count == "string" ? parseInt(count) : count;
sum += count;
}

if(frappe.boot.notification_info.open_count_module
&& frappe.boot.notification_info.open_count_module[module_name]!=null) {
// notification count explicitly for module
let count = frappe.boot.notification_info.open_count_module[module_name] || 0;
count = typeof count == "string" ? parseInt(count) : count;
sum += count;
}

sum = sum > 99 ? "99+" : sum;

return sum;
}
}
}
</script>

<style lang="less" scoped>
.modules-page-container {
margin: 70px 85px;
}

.module-category {
margin-top: 30px;
margin-bottom: 15px;
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;
padding: 5px 0px;
display: block;
}

.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: 15px;
width: 54px;
display: flex;
justify-content: center;
}

.icon {
font-size: 24px;
}

</style>


+ 1
- 84
frappe/public/js/frappe/views/components/ModuleDetail.vue Voir le fichier

@@ -20,92 +20,9 @@

<script>
export default {
props: ['module_name'],
data() {
return {
stats: {},
sections: []
}
},
created() {
this.get_sections();
this.get_stats();
},
props: ['module_name', 'sections'],
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;
}

item.route = '#' + item.route;
}

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;
}
});
});
}
}
}
</script>


+ 100
- 101
frappe/public/js/frappe/views/components/Modules.vue Voir le fichier

@@ -1,38 +1,6 @@
<template>
<div class="modules-page-container">
<div v-if="!route_str" >
<div v-for="category in module_categories"
:key="category">

<div v-if="modules.filter(m => m.category === category).length" class="module-category h6 uppercase">
{{ category }}
</div>

<div class="modules-container">
<div v-for="module in modules.filter(m => m.category === category )"
:key="module.name"
class="border module-box flush-top"
@click="update_state(module.module_name, module.label, module.type, module.link)"
>
<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 }}
<span v-if="module.count" class="open-notification global">{{ module.count }}</span>
</h4>
<p class="small text-muted"> {{ 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>
<module-detail v-if="this.route && modules_list.map(m => m.module_name).includes(route[1])" :module_name="route[1]" :sections="current_module_sections"></module-detail>
</div>
</template>

@@ -45,95 +13,126 @@ export default {
},
data() {
return {
route_str: frappe.get_route()[1],
module_label: '',
module_categories: ["Modules", "Domains", "Places", "Administration"],
modules: []
route: frappe.get_route(),
current_module_label: '',
current_module_sections: [],
modules_data_cache: {},
modules_list: [],
};
},
created() {
this.get_modules();
this.get_modules_list();
this.update_current_module();
},
mounted() {
frappe.module_links = {};
frappe.route.on('change', () => {
if(frappe.get_route()[0] === 'modules' || !frappe.get_route()[0]) {
let module = frappe.get_route()[1];
this.update_module(module);
}
this.update_current_module();
});
},
methods: {
update_state(name, label, type, link) {
if(type === "module") {
this.module_label = label;
frappe.set_route(['modules', name]);
} else if(type === "link") {
frappe.set_route(link);
update_current_module() {
let route = frappe.get_route();
if(route[0] === 'modules' || !route[0]) {
this.route = route;
let module_name = route[1];
let title = this.current_module_label ? this.current_module_label : module_name;
title = module_name!=='home' ? title : 'Modules';

frappe.modules.home && frappe.modules.home.page.set_title(title);

if(module_name) {
this.get_module_sections(module_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);
},

get_modules() {
let res = frappe.call({
method: 'frappe.desk.doctype.desktop_icon.desktop_icon.get_modules_from_all_apps',
});
get_modules_list() {
let res = frappe.call({
method: 'frappe.desk.doctype.desktop_icon.desktop_icon.get_modules_from_all_apps',
});

res.then(r => {
if (r.message) {
res.then(r => {
if (r.message) {
let modules_list = r.message;

modules_list = modules_list
this.modules_list = modules_list
.filter(d => (d.type==='module' || d.category==='Places') && !d.blocked);

modules_list.forEach(module => {
module.count = this.get_module_count(module.module_name);
});

this.modules = modules_list;
}
});
},

get_module_count(module_name) {
var module_doctypes = frappe.boot.notification_info.module_doctypes[module_name];
var sum = 0;

if(module_doctypes && frappe.boot.notification_info.open_count_doctype) {
// sum all doctypes for a module
for (var j=0, k=module_doctypes.length; j < k; j++) {
var doctype = module_doctypes[j];
let count = (frappe.boot.notification_info.open_count_doctype[doctype] || 0);
count = typeof count == "string" ? parseInt(count) : count;
sum += count;
}
get_module_sections(module_name) {
let cache = this.modules_data_cache[module_name];
if(cache) {
this.current_module_sections = cache;
} else {
return frappe.call({
method: "frappe.desk.moduleview.get",
args: {
module: module_name,
},
callback: (r) => {
var m = frappe.get_module(module_name);
this.current_module_sections = r.message.data;
this.process_data(module_name, this.current_module_sections);
this.modules_data_cache[module_name] = this.current_module_sections;
},
freeze: true,
});
}

if(frappe.boot.notification_info.open_count_doctype
&& frappe.boot.notification_info.open_count_doctype[module_name]!=null) {
// notification count explicitly for doctype
let count = frappe.boot.notification_info.open_count_doctype[module_name] || 0;
count = typeof count == "string" ? parseInt(count) : count;
sum += count;
}

if(frappe.boot.notification_info.open_count_module
&& frappe.boot.notification_info.open_count_module[module_name]!=null) {
// notification count explicitly for module
let count = frappe.boot.notification_info.open_count_module[module_name] || 0;
count = typeof count == "string" ? parseInt(count) : count;
sum += count;
}

sum = sum > 99 ? "99+" : sum;

return sum;
},
process_data(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;
}

item.route = '#' + item.route;
}

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;
}
});
});
}
}
}
@@ -161,6 +160,7 @@ export default {
border-radius: 4px;
cursor: pointer;
padding: 5px 0px;
display: block;
}

.module-box:hover {
@@ -193,4 +193,3 @@ export default {
}

</style>


+ 25
- 0
frappe/public/js/frappe/views/modules_home.js Voir le fichier

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

frappe.provide('frappe.modules');

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.__;
new Vue({
el: this.$modules_container[0],
render: h => h(Modules)
});
});
}
setup_header() {
this.page.set_title(__('Modules'));
}
};

+ 15
- 29
frappe/public/js/frappe/views/pageview.js Voir le fichier

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

import Modules from './components/Modules.vue';
import Desktop from './components/Desktop.vue';

frappe.provide('frappe.views.pageview');
frappe.provide("frappe.standard_pages");
@@ -44,16 +44,16 @@ frappe.views.pageview = {

if(name === "desktop") {
let page = frappe.container.add_page('desktop');
console.log('frappe.container.page',JSON.parse(JSON.stringify(page)), JSON.parse(JSON.stringify(frappe.container.page)));
frappe.container.change_to('desktop');

let container = $('<div class="modules-container"></div>').appendTo(page);
let container = $('<div></div>').appendTo(page);
container = $('<div class="layout-main-section"></div>').appendTo(container);
frappe.container.change_to('desktop');
frappe.require('/assets/js/frappe-vue.min.js', () => {
Vue.prototype.__ = window.__;
new Vue({
el: container[0],
render: h => h(Modules)
render: h => h(Desktop)
});
});
return;
@@ -173,30 +173,16 @@ frappe.views.ModulesFactory = class ModulesFactory extends frappe.views.Factory
}

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)
});
});
}
};
// frappe.provide('frappe.modules');

// 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.__;
// new Vue({
// el: this.$modules_container[0],
// render: h => h(Modules)
// });
// });
// }
// setup_header() {
// this.page.set_title(__('Modules'));
// }
// };


+ 0
- 5
frappe/public/less/desktop.less Voir le fichier

@@ -3,11 +3,6 @@
@icon-color: @light-bg;
@icon-hover: #fff;

body[data-route=""] .navbar-default, body[data-route="desktop"] .navbar-default {
background-color: rgba(255, 255, 255, 0.9);
border-color: rgba(54, 65, 76, 0.1);
}

#page-desktop {
min-width: 100%;
margin-top: 0px;


Chargement…
Annuler
Enregistrer