Skip to content

Commit f240073

Browse files
authored
Merge pull request #8617 from ProcessMaker/bugfix/FOUR-27993
FOUR-27993: Mobile > Processes view is not working correctly
2 parents 33d31b7 + dae6eed commit f240073

File tree

3 files changed

+200
-11
lines changed

3 files changed

+200
-11
lines changed

resources/js/processes-catalogue/components/ProcessesCatalogue.vue

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,21 @@
77
:process="selectedProcess ? selectedProcess.name : ''"
88
:template="guidedTemplates ? 'Guided Templates' : ''"
99
/>
10-
<div class="tw-flex tw-h-full">
11-
<CollapsableContainer
10+
<div class="tw-flex tw-h-full tw-relative">
11+
<component :is="isMobile ? 'mobile-drawer' : 'collapsable-container'"
1212
v-model="showMenu"
13-
class="tw-w-80"
14-
position="right"
15-
@change="hideMenu"
13+
:class="{
14+
'tw-w-80': !isMobile,
15+
'tw-w-full tw-h-full': isMobile && showMenu,
16+
'tw-w-0 tw-h-full': isMobile && !showMenu,
17+
}"
18+
:position="isMobile ? 'left' : 'right'"
1619
>
1720
<MenuCatologue
1821
ref="categoryList"
1922
title="Available Processes"
2023
preicon="fas fa-play-circle"
21-
class="pt-3 menu-catalog"
24+
class="pt-3 menu-catalog tw-bg-white tw-h-full tw-w-full"
2225
show-bookmark="true"
2326
:category-count="categoryCount"
2427
:data="listCategories"
@@ -27,7 +30,7 @@
2730
@categorySelected="selectCategory"
2831
@addCategories="addCategories"
2932
/>
30-
</CollapsableContainer>
33+
</component>
3134

3235
<div
3336
ref="processInfo"
@@ -69,13 +72,15 @@ import MenuCatologue from "./menuCatologue.vue";
6972
import CatalogueEmpty from "./CatalogueEmpty.vue";
7073
import Breadcrumbs from "./Breadcrumbs.vue";
7174
import CollapsableContainer from "../../../jscomposition/base/ui/CollapsableContainer.vue";
75+
import MobileDrawer from "../../../jscomposition/base/ui/MobileDrawer.vue";
7276
7377
export default {
7478
components: {
7579
MenuCatologue,
7680
CatalogueEmpty,
7781
Breadcrumbs,
7882
CollapsableContainer,
83+
MobileDrawer,
7984
},
8085
props: ["currentUserId", "process", "currentUser", "userConfig"],
8186
data() {
@@ -152,15 +157,17 @@ export default {
152157
},
153158
methods: {
154159
defineUserConfiguration() {
155-
this.showMenu = this.userConfiguration.launchpad.isMenuCollapse;
160+
this.showMenu = this.userConfiguration?.launchpad?.isMenuCollapse;
156161
},
157162
hideMenu(value) { // value is the new value of the menu
158-
this.showMenu = value;
163+
this.showMenu = !this.showMenu;
159164
this.$root.$emit("sizeChanged", value);
160165
this.updateUserConfiguration();
161166
},
162167
updateUserConfiguration() {
163-
this.userConfiguration.launchpad.isMenuCollapse = this.showMenu;
168+
if(this.userConfiguration?.launchpad) {
169+
this.userConfiguration.launchpad.isMenuCollapse = this.showMenu;
170+
}
164171
ProcessMaker.apiClient
165172
.put(this.urlConfiguration, {
166173
ui_configuration: this.userConfiguration,
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
<template>
2+
<transition :name="transitionName">
3+
<div class="tw-flex tw-h-full tw-absolute">
4+
<!-- Overlay: semi-transparent background, closes drawer on click -->
5+
<transition name="fade">
6+
<div
7+
v-if="isOpen"
8+
class="tw-absolute tw-inset-0 tw-bg-black tw-bg-opacity-50 tw-z-40 tw-transition-opacity tw-duration-300"
9+
@click.prevent="closeDrawer">
10+
<button
11+
class="tw-absolute tw-top-2 tw-right-2 tw-size-8 tw-flex tw-items-center tw-justify-center tw-rounded-md tw-bg-white hover:tw-bg-gray-100 tw-transition-colors tw-duration-200 tw-cursor-pointer"
12+
@click.prevent="closeDrawer"
13+
aria-label="Close drawer">
14+
<i class="fa fa-times tw-text-base tw-text-gray-600" />
15+
</button>
16+
</div>
17+
</transition>
18+
19+
<!-- Drawer Modal Panel: slides in based on the position prop -->
20+
<div
21+
v-if="isOpen"
22+
class="tw-absolute tw-w-[80%] tw-z-50 tw-shadow-2xl tw-overflow-y-auto tw-transition-transform tw-duration-300"
23+
:class="drawerClass">
24+
<!-- Main Drawer Content -->
25+
<div class="tw-h-full">
26+
<slot name="default"/>
27+
</div>
28+
29+
<!-- Drawer Footer if slot provided -->
30+
<div
31+
v-if="$slots.footer"
32+
class="tw-p-4 tw-border-t tw-border-solid tw-border-gray-200">
33+
<slot name="footer"/>
34+
</div>
35+
</div>
36+
</div>
37+
</transition>
38+
</template>
39+
40+
<script>
41+
import { computed, toRefs, defineComponent } from "vue";
42+
43+
const validPositions = ["left", "right", "top", "bottom"];
44+
const validButtonPositions = [
45+
"top-left",
46+
"top-right",
47+
"bottom-left",
48+
"bottom-right"
49+
];
50+
51+
export default defineComponent({
52+
name: "MobileDrawer",
53+
props: {
54+
value: {
55+
type: Boolean,
56+
default: false,
57+
},
58+
position: {
59+
type: String,
60+
default: "left",
61+
validator: val => validPositions.includes(val),
62+
},
63+
title: {
64+
type: String,
65+
default: "Menu",
66+
},
67+
buttonPosition: {
68+
type: String,
69+
default: "top-left",
70+
validator: val => validButtonPositions.includes(val),
71+
},
72+
},
73+
setup(props, { emit }) {
74+
const { value, position } = toRefs(props);
75+
76+
/**
77+
* Open state, two-way bound to v-model
78+
*/
79+
const isOpen = computed({
80+
get: () => value.value,
81+
set: val => emit("input", val),
82+
});
83+
84+
/**
85+
* Computed classes for drawer position/size
86+
*/
87+
const drawerClass = computed(() => ({
88+
"tw-top-0 tw-left-0 tw-h-full": position.value === "left",
89+
"tw-top-0 tw-right-0 tw-h-full": position.value === "right",
90+
"tw-top-0 tw-left-0 tw-max-h-[50vh]": position.value === "top",
91+
"tw-bottom-0 tw-left-0 tw-max-h-[50vh]": position.value === "bottom",
92+
}));
93+
94+
/**
95+
* Transition name depending on drawer position
96+
*/
97+
const transitionName = computed(() => {
98+
const transitions = {
99+
left: "slide-left",
100+
right: "slide-right",
101+
top: "slide-top",
102+
bottom: "slide-bottom",
103+
};
104+
return transitions[position.value] || "slide-left";
105+
});
106+
107+
/**
108+
* Open the drawer (emit events)
109+
*/
110+
const openDrawer = () => {
111+
isOpen.value = true;
112+
emit("change", true);
113+
emit("open");
114+
};
115+
116+
/**
117+
* Close the drawer (emit events)
118+
*/
119+
const closeDrawer = () => {
120+
isOpen.value = false;
121+
emit("change", false);
122+
emit("close");
123+
};
124+
125+
return {
126+
isOpen,
127+
transitionName,
128+
drawerClass,
129+
openDrawer,
130+
closeDrawer,
131+
};
132+
}
133+
});
134+
</script>
135+
136+
<style scoped>
137+
.slide-left-enter-active,
138+
.slide-left-leave-active,
139+
.slide-right-enter-active,
140+
.slide-right-leave-active,
141+
.slide-top-enter-active,
142+
.slide-top-leave-active,
143+
.slide-bottom-enter-active,
144+
.slide-bottom-leave-active {
145+
transition: transform 0.3s ease;
146+
}
147+
.slide-left-enter-from,
148+
.slide-left-leave-to {
149+
transform: translateX(-100%);
150+
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
151+
-webkit-transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
152+
}
153+
.slide-right-enter-from,
154+
.slide-right-leave-to {
155+
transform: translateX(100%);
156+
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
157+
-webkit-transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
158+
}
159+
.slide-top-enter-from,
160+
.slide-top-leave-to {
161+
transform: translateY(-100%);
162+
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
163+
-webkit-transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
164+
}
165+
.slide-bottom-enter-from,
166+
.slide-bottom-leave-to {
167+
transform: translateY(100%);
168+
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
169+
-webkit-transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
170+
}
171+
.fade-enter-active,
172+
.fade-leave-active {
173+
transition: opacity 0.3s ease;
174+
-webkit-transition: opacity 0.3s ease;
175+
}
176+
.fade-enter-from,
177+
.fade-leave-to {
178+
opacity: 0;
179+
-webkit-opacity: 0;
180+
}
181+
</style>

resources/jscomposition/base/ui/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import Badge from "./Badge.vue";
22
import AppAvatar from "./AppAvatar.vue";
33
import AppPopover from "./AppPopover.vue";
44
import CollapsableContainer from "./CollapsableContainer.vue";
5+
import MobileDrawer from "./MobileDrawer.vue";
56

67
export default {};
78

89
export {
9-
Badge, AppAvatar, AppPopover, CollapsableContainer,
10+
Badge, AppAvatar, AppPopover, CollapsableContainer, MobileDrawer,
1011
};

0 commit comments

Comments
 (0)