PMCORE-3052
more chages fox code style restore menu settings remove debugger add documentation
This commit is contained in:
5
package-lock.json
generated
5
package-lock.json
generated
@@ -9698,6 +9698,11 @@
|
||||
"is-plain-obj": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"sortablejs": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.13.0.tgz",
|
||||
"integrity": "sha512-RBJirPY0spWCrU5yCmWM1eFs/XgX2J5c6b275/YyxFRgnzPhKl/TDeU2hNR8Dt7ITq66NRPM4UlOt+e5O4CFHg=="
|
||||
},
|
||||
"source-list-map": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"npm-font-open-sans": "^1.1.0",
|
||||
"popper.js": "^1.12",
|
||||
"promise-polyfill": "8.1.3",
|
||||
"sortablejs": "^1.13.0",
|
||||
"uiv": "^0.28.0",
|
||||
"vue": "^2.6.12",
|
||||
"vue-awesome-swiper": "^3.1.3",
|
||||
@@ -55,6 +56,7 @@
|
||||
"vue-split-panel": "^1.0.4",
|
||||
"vue-tables-2": "^2.1.46",
|
||||
"vue-upload-component": "^2.8.20",
|
||||
"vuedraggable": "^2.24.3",
|
||||
"vuejs-auto-complete": "^0.9.0",
|
||||
"vuejs-datepicker": "^1.5.4",
|
||||
"vuejs-paginate": "^2.0.1",
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
|
||||
<script>
|
||||
import api from "./../../api/index";
|
||||
import CustomSidebarMenuItem from "./CustomSidebarMenuItem";
|
||||
export default {
|
||||
name: "CustomSidebar",
|
||||
props: ["menu"],
|
||||
|
||||
data() {
|
||||
return {
|
||||
collapsed: false,
|
||||
@@ -61,8 +63,8 @@ export default {
|
||||
onItemClick(event, item, node) {
|
||||
this.$emit("OnClickSidebarItem", { item });
|
||||
},
|
||||
/**
|
||||
* On resize event handler id the windows is resized
|
||||
/**
|
||||
* On resize event handler id the windows is resized
|
||||
* collase and isMobile proerty will be updated
|
||||
*/
|
||||
onResize() {
|
||||
@@ -74,7 +76,7 @@ export default {
|
||||
this.collapsed = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<component
|
||||
:is="icon.element ? icon.element : 'i'"
|
||||
class="vsm--icon"
|
||||
:class="
|
||||
typeof icon === 'string' || icon instanceof String
|
||||
? icon
|
||||
: icon.class
|
||||
"
|
||||
v-bind="icon.attributes"
|
||||
>
|
||||
{{ icon.text }}
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "CustomSidebarMenuIcon",
|
||||
props: {
|
||||
icon: {
|
||||
type: [String, Object],
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
497
resources/assets/js/components/menu/CustomSidebarMenuItem.vue
Normal file
497
resources/assets/js/components/menu/CustomSidebarMenuItem.vue
Normal file
@@ -0,0 +1,497 @@
|
||||
<template>
|
||||
<div id="my-container">
|
||||
<div
|
||||
v-if="item.header && !isItemHidden"
|
||||
class="vsm--header"
|
||||
:class="item.class"
|
||||
v-bind="item.attributes"
|
||||
>
|
||||
{{ item.title }} <b-icon icon="pie-chart-fill"></b-icon>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="!isItemHidden"
|
||||
class="vsm--item"
|
||||
:class="[{ 'vsm--item_open': show }]"
|
||||
@mouseover="mouseOverEvent"
|
||||
@mouseout="mouseOutEvent"
|
||||
>
|
||||
<custom-sidebar-menu-link
|
||||
:item="item"
|
||||
:class="itemLinkClass"
|
||||
:attributes="item.attributes"
|
||||
@click.native="clickEvent"
|
||||
>
|
||||
<custom-sidebar-menu-icon
|
||||
v-if="item.icon && !isMobileItem"
|
||||
:icon="item.icon"
|
||||
/>
|
||||
<transition name="fade-animation" :appear="isMobileItem">
|
||||
<template
|
||||
v-if="
|
||||
(isCollapsed && !isFirstLevel) ||
|
||||
!isCollapsed ||
|
||||
isMobileItem
|
||||
"
|
||||
>
|
||||
<span class="vsm--title">
|
||||
{{ item.title }}
|
||||
<b-icon
|
||||
v-if="item.sortable"
|
||||
:icon="item.sortIcon"
|
||||
@click="onClickSortSettings"
|
||||
></b-icon>
|
||||
</span>
|
||||
</template>
|
||||
</transition>
|
||||
<template
|
||||
v-if="
|
||||
(isCollapsed && !isFirstLevel) ||
|
||||
!isCollapsed ||
|
||||
isMobileItem
|
||||
"
|
||||
>
|
||||
<sidebar-menu-badge v-if="item.badge" :badge="item.badge" />
|
||||
<div
|
||||
v-if="itemHasChild"
|
||||
class="vsm--arrow"
|
||||
:class="[
|
||||
{ 'vsm--arrow_open': show },
|
||||
{ 'vsm--arrow_slot': $slots['dropdown-icon'] },
|
||||
]"
|
||||
>
|
||||
<slot name="dropdown-icon" />
|
||||
</div>
|
||||
</template>
|
||||
</custom-sidebar-menu-link>
|
||||
|
||||
<template v-if="itemHasChild">
|
||||
<template
|
||||
v-if="
|
||||
(isCollapsed && !isFirstLevel) ||
|
||||
!isCollapsed ||
|
||||
isMobileItem
|
||||
"
|
||||
>
|
||||
<transition
|
||||
:appear="isMobileItem"
|
||||
name="expand"
|
||||
@enter="expandEnter"
|
||||
@afterEnter="expandAfterEnter"
|
||||
@beforeLeave="expandBeforeLeave"
|
||||
>
|
||||
<div
|
||||
v-if="show"
|
||||
class="vsm--dropdown"
|
||||
:class="isMobileItem && 'vsm--dropdown_mobile-item'"
|
||||
:style="isMobileItem && mobileItemStyle.dropdown"
|
||||
>
|
||||
<div class="vsm--list">
|
||||
<custom-sidebar-menu-item
|
||||
v-for="(subItem, index) in item.child"
|
||||
:key="index"
|
||||
:item="subItem"
|
||||
:level="level + 1"
|
||||
:show-child="showChild"
|
||||
:rtl="rtl"
|
||||
:is-collapsed="isCollapsed"
|
||||
>
|
||||
<slot
|
||||
slot="dropdown-icon"
|
||||
name="dropdown-icon"
|
||||
/>
|
||||
</custom-sidebar-menu-item>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<b-modal
|
||||
ref="modal"
|
||||
v-if="item.sortable"
|
||||
id="my-modal"
|
||||
static
|
||||
title="Custom Case List Order"
|
||||
>
|
||||
<draggable
|
||||
:list="item.child"
|
||||
:disabled="!enabled"
|
||||
class="list-group"
|
||||
ghost-class="ghost"
|
||||
@end="checkMove"
|
||||
@start="dragging = true"
|
||||
handle=".handle"
|
||||
>
|
||||
<div
|
||||
class="list-group-item"
|
||||
v-for="element in item.child"
|
||||
:key="element.title"
|
||||
>
|
||||
<b-row>
|
||||
<b-col
|
||||
><b-icon icon="check-circle"></b-icon>
|
||||
</b-col>
|
||||
<b-col cols="9">{{ element.title }}</b-col>
|
||||
<b-col
|
||||
><i class="fa fa-align-justify handle"></i
|
||||
></b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</draggable>
|
||||
|
||||
<template #modal-footer="{ ok, cancel, hide }">
|
||||
<b-button size="sm" variant="danger" @click="cancel()">
|
||||
Cancel
|
||||
</b-button>
|
||||
</template>
|
||||
</b-modal>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from "vuedraggable";
|
||||
import CustomSidebarMenuLink from "./CustomSidebarMenuLink";
|
||||
import CustomSidebarMenuIcon from "./CustomSidebarMenuIcon";
|
||||
export default {
|
||||
name: "CustomSidebarMenuItem",
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
level: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
isMobileItem: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
mobileItem: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
activeShow: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
showChild: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
showOneChild: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
rtl: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disableHover: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
mobileItemStyle: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
draggable,
|
||||
CustomSidebarMenuLink,
|
||||
CustomSidebarMenuIcon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
enabled: true,
|
||||
dragging: false,
|
||||
itemShow: false,
|
||||
itemHover: false,
|
||||
exactActive: false,
|
||||
active: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isCollapsed() {
|
||||
return this.$parent.isCollapsed;
|
||||
},
|
||||
itemLinkClass() {
|
||||
return [
|
||||
"vsm--link",
|
||||
!this.isMobileItem ? `vsm--link_level-${this.level}` : "",
|
||||
{ "vsm--link_mobile-item": this.isMobileItem },
|
||||
{ "vsm--link_hover": this.hover },
|
||||
{ "vsm--link_active": this.active },
|
||||
{ "vsm--link_exact-active": this.exactActive },
|
||||
{ "vsm--link_disabled": this.item.disabled },
|
||||
this.item.class,
|
||||
];
|
||||
},
|
||||
draggingInfo() {
|
||||
return this.dragging ? "under drag" : "";
|
||||
},
|
||||
show: {
|
||||
get() {
|
||||
if (!this.itemHasChild) return false;
|
||||
if (this.showChild || this.isMobileItem) return true;
|
||||
return this.itemShow;
|
||||
},
|
||||
set(show) {
|
||||
if (this.showOneChild) {
|
||||
show
|
||||
? this.emitActiveShow(this.item)
|
||||
: this.emitActiveShow(null);
|
||||
}
|
||||
this.itemShow = show;
|
||||
},
|
||||
},
|
||||
isFirstLevel() {
|
||||
return this.level === 1;
|
||||
},
|
||||
itemHasChild() {
|
||||
return !!(this.item.child && this.item.child.length > 0);
|
||||
},
|
||||
isItemHidden() {
|
||||
return false;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
setTimeout(() => {
|
||||
if (this.item.header || this.item.component) return;
|
||||
this.initState();
|
||||
}, 1);
|
||||
},
|
||||
item(newItem, item) {
|
||||
this.emitItemUpdate(newItem, item);
|
||||
},
|
||||
activeShow() {
|
||||
this.itemShow = this.item === this.activeShow;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.initState();
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Match the route to ensure the correct location
|
||||
* @param {string} href
|
||||
* @param {string} exactPath
|
||||
* @return {boolean}
|
||||
*/
|
||||
matchRoute({ href, exactPath }) {
|
||||
if (!href) return false;
|
||||
if (this.$router) {
|
||||
const { route } = this.$router.resolve(href);
|
||||
return exactPath
|
||||
? route.path === this.$route.path
|
||||
: this.matchExactRoute(href);
|
||||
} else {
|
||||
return exactPath
|
||||
? href === window.location.pathname
|
||||
: this.matchExactRoute(href);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Match the exact route with the current location
|
||||
* @param {string} href
|
||||
* @return {boolean}
|
||||
*/
|
||||
matchExactRoute(href) {
|
||||
if (!href) return false;
|
||||
if (this.$router) {
|
||||
const { route } = this.$router.resolve(href);
|
||||
return route.fullPath === this.$route.fullPath;
|
||||
} else {
|
||||
return (
|
||||
href ===
|
||||
window.location.pathname +
|
||||
window.location.search +
|
||||
window.location.hash
|
||||
);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Check if the child is active
|
||||
* @param {object} child
|
||||
* @return {boolean}
|
||||
*/
|
||||
isChildActive(child) {
|
||||
if (!child) return false;
|
||||
return child.some((item) => {
|
||||
return this.isLinkActive(item);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Validate if the Alias is active
|
||||
* @param {object} item
|
||||
* @return {boobleam}
|
||||
*/
|
||||
isAliasActive(item) {
|
||||
if (item.alias) {
|
||||
const current = this.$router
|
||||
? this.$route.fullPath
|
||||
: window.location.pathname +
|
||||
window.location.search +
|
||||
window.location.hash;
|
||||
if (Array.isArray(item.alias)) {
|
||||
return item.alias.some((alias) => {
|
||||
return pathToRegexp(alias).test(current);
|
||||
});
|
||||
} else {
|
||||
return pathToRegexp(item.alias).test(current);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
/**
|
||||
* Validate if the link is active
|
||||
* @param {object} item
|
||||
* @return {boolean}
|
||||
*/
|
||||
isLinkActive(item) {
|
||||
return (
|
||||
this.matchRoute(item) ||
|
||||
this.isChildActive(item.child) ||
|
||||
this.isAliasActive(item)
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Ensurre if the link exact is active
|
||||
* @param {object} item
|
||||
* @return {boolean}
|
||||
*/
|
||||
isLinkExactActive(item) {
|
||||
return this.matchExactRoute(item.href);
|
||||
},
|
||||
/**
|
||||
* Initialize the state of the menu item
|
||||
*/
|
||||
initState() {
|
||||
this.initActiveState();
|
||||
this.initShowState();
|
||||
},
|
||||
/**
|
||||
* Initalize the active state of the menu item
|
||||
*/
|
||||
initActiveState() {
|
||||
this.active = this.isLinkActive(this.item);
|
||||
this.exactActive = this.isLinkExactActive(this.item);
|
||||
},
|
||||
/**
|
||||
* Initialize and show active state menu item
|
||||
*/
|
||||
initShowState() {
|
||||
if (!this.itemHasChild || this.showChild) return;
|
||||
if (
|
||||
(this.showOneChild && this.active && !this.show) ||
|
||||
(this.active && !this.show)
|
||||
) {
|
||||
this.show = true;
|
||||
} else if (this.showOneChild && !this.active && this.show) {
|
||||
this.show = false;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Handler to check if the item is moving
|
||||
* @param {object} e
|
||||
*/
|
||||
checkMove: function(e) {
|
||||
let aux = this.item.child.splice(e.newIndex, 1);
|
||||
this.item.child.splice(e.newIndex, 0, aux[0]);
|
||||
},
|
||||
/**
|
||||
* Click event Handler
|
||||
* @param {object} event
|
||||
*/
|
||||
clickEvent(event) {
|
||||
if (this.item.disabled) return;
|
||||
if (!this.item.href) {
|
||||
event.preventDefault();
|
||||
}
|
||||
this.emitItemClick(event, this.item, this);
|
||||
this.emitMobileItem(event, event.currentTarget.offsetParent);
|
||||
if (!this.itemHasChild || this.showChild || this.isMobileItem)
|
||||
return;
|
||||
if (!this.item.href || this.exactActive) {
|
||||
this.show = !this.show;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Mouse over event handler
|
||||
* @param {object} event
|
||||
*/
|
||||
mouseOverEvent(event) {
|
||||
if (this.item.disabled) return;
|
||||
event.stopPropagation();
|
||||
this.itemHover = true;
|
||||
if (!this.disableHover) {
|
||||
this.emitMobileItem(event, event.currentTarget);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Mouse out event handler
|
||||
* @param {object} event
|
||||
*/
|
||||
mouseOutEvent(event) {
|
||||
event.stopPropagation();
|
||||
this.itemHover = false;
|
||||
},
|
||||
/**
|
||||
* Expand sidebar menu item handler
|
||||
* @param {object} el
|
||||
*/
|
||||
expandEnter(el) {
|
||||
el.style.height = el.scrollHeight + "px";
|
||||
},
|
||||
/**
|
||||
* Expand after enter menu item handler
|
||||
* @param {object} el
|
||||
*/
|
||||
expandAfterEnter(el) {
|
||||
el.style.height = "auto";
|
||||
},
|
||||
/**
|
||||
* Expand before leace handler
|
||||
* @param {object} el
|
||||
*/
|
||||
expandBeforeLeave(el) {
|
||||
if (this.isCollapsed && this.isFirstLevel) {
|
||||
el.style.display = "none";
|
||||
return;
|
||||
}
|
||||
el.style.height = el.scrollHeight + "px";
|
||||
},
|
||||
/**
|
||||
* Emit Mobile item handler
|
||||
* @param {object} event
|
||||
* @param {object} itemEl
|
||||
*/
|
||||
emitMobileItem(event, itemEl) {
|
||||
if (this.hover) return;
|
||||
if (!this.isCollapsed || !this.isFirstLevel || this.isMobileItem)
|
||||
return;
|
||||
this.$emit("unset-mobile-item", true);
|
||||
setTimeout(() => {
|
||||
if (this.mobileItem !== this.item) {
|
||||
this.$emit("set-mobile-item", { item: this.item, itemEl });
|
||||
}
|
||||
if (event.type === "click" && !this.itemHasChild) {
|
||||
this.$emit("unset-mobile-item", false);
|
||||
}
|
||||
}, 0);
|
||||
},
|
||||
/**
|
||||
* Click Sort settings event handler
|
||||
* @param {object} event
|
||||
*/
|
||||
onClickSortSettings(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.$refs["modal"].show();
|
||||
},
|
||||
},
|
||||
inject: ["emitActiveShow", "emitItemClick", "emitItemUpdate"],
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<component
|
||||
:is="tag"
|
||||
v-bind="[isRouterLink ? { to: href } : { href: href }, attributes]"
|
||||
:tabindex="item.disabled && -1"
|
||||
:target="target"
|
||||
>
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "CustomSidebarMenuLink",
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
attributes: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isRouterLink() {
|
||||
return !!this.$router && this.item.href && !this.item.external;
|
||||
},
|
||||
tag() {
|
||||
return this.isRouterLink ? "router-link" : "a";
|
||||
},
|
||||
href() {
|
||||
if (!this.item.href) return "#";
|
||||
return this.item.href;
|
||||
},
|
||||
target() {
|
||||
if (this.item.external) return "_blank";
|
||||
return "_self";
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -4,6 +4,7 @@ import VueSidebarMenu from "vue-sidebar-menu";
|
||||
import VueI18n from 'vue-i18n';
|
||||
import { BootstrapVue, BootstrapVueIcons } from 'bootstrap-vue';
|
||||
import { ServerTable, Event, ClientTable} from 'vue-tables-2';
|
||||
import Sortable from 'sortablejs';
|
||||
import "@fortawesome/fontawesome-free/css/all.css";
|
||||
import "@fortawesome/fontawesome-free/js/all.js";
|
||||
import 'bootstrap/dist/css/bootstrap-grid.css';
|
||||
@@ -16,6 +17,7 @@ Vue.use(VueSidebarMenu);
|
||||
Vue.use(BootstrapVue);
|
||||
Vue.use(BootstrapVueIcons);
|
||||
Vue.use(VueI18n);
|
||||
|
||||
Vue.use(ServerTable, {}, false, 'bootstrap3', {});
|
||||
Vue.use(ClientTable, {}, false, 'bootstrap3', {});
|
||||
window.ProcessMaker = {
|
||||
|
||||
@@ -16273,7 +16273,7 @@
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.1.1",
|
||||
"version": "16.1.1",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.1.tgz",
|
||||
"integrity": "sha512-wz/+HFg/3SBayHWAlZXARcnDTl3VOChrfW9YnxvAweiuyKX/7IGx1ad/4yJHmwhgWlOVYMAbTiI7GV8G33PfGQ==",
|
||||
"dev": true,
|
||||
|
||||
@@ -16273,7 +16273,7 @@
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.1.1",
|
||||
"version": "16.1.1",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.1.tgz",
|
||||
"integrity": "sha512-wz/+HFg/3SBayHWAlZXARcnDTl3VOChrfW9YnxvAweiuyKX/7IGx1ad/4yJHmwhgWlOVYMAbTiI7GV8G33PfGQ==",
|
||||
"dev": true,
|
||||
|
||||
@@ -16273,7 +16273,7 @@
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.1.1",
|
||||
"version": "16.1.1",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.1.tgz",
|
||||
"integrity": "sha512-wz/+HFg/3SBayHWAlZXARcnDTl3VOChrfW9YnxvAweiuyKX/7IGx1ad/4yJHmwhgWlOVYMAbTiI7GV8G33PfGQ==",
|
||||
"dev": true,
|
||||
|
||||
Reference in New Issue
Block a user