Skip to content

Commit 65ddbed

Browse files
mlopezFCjavier-godoy
authored andcommitted
feat: add fusion layout web component
add new web component wrapping the complexities of calling menu item endpoint
1 parent a6e8b9d commit 65ddbed

File tree

1 file changed

+217
-0
lines changed

1 file changed

+217
-0
lines changed
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
import { CSSModule } from '@vaadin/flow-frontend/css-utils';
2+
import { css, customElement, html, LitElement, state, property, query } from 'lit-element';
3+
import "@flowingcode/fc-applayout";
4+
import {FcAppLayoutElement} from "@flowingcode/fc-applayout/src/fc-applayout";
5+
import "@flowingcode/fc-menuitem";
6+
import * as menuItemEndpoint from '@vaadin/flow-frontend/generated/MenuEndpoint';
7+
import MenuItemDto from '@vaadin/flow-frontend/generated/com/flowingcode/addons/applayout/endpoint/MenuItemDto';
8+
import { EndpointError } from 'Frontend/../target/flow-frontend';
9+
import { Router } from '@vaadin/router';
10+
11+
@customElement('fc-fusion-layout')
12+
export class FusionLayout extends LitElement {
13+
static get is() { return 'fc-fusion-layout'; }
14+
15+
@query("#fusionLayout")
16+
fcAppLayout!: FcAppLayoutElement;
17+
18+
@state()
19+
private menuItems: MenuItemDto[] = [];
20+
21+
@property({type: String})
22+
title = "My Application";
23+
24+
@property({type: String})
25+
profilePicture = "./images/user.svg";
26+
27+
@property({type: String})
28+
profilePictureAlt = "Profile picture";
29+
30+
@property({type: String})
31+
appLogo = "./icons/icon.png";
32+
33+
@property({type: String})
34+
appLogoAlt = "Logo";
35+
36+
@property({type: String})
37+
userName = "User";
38+
39+
@property({type: Boolean})
40+
reveals = true;
41+
42+
@property({type: Boolean})
43+
swipeOpen = true;
44+
45+
@property({type: Boolean})
46+
fixed = false;
47+
48+
49+
constructor() {
50+
super();
51+
this.addEventListener("menuitem-clicked-event", (e:Event) => {
52+
let fcmi: any = e.composedPath()[0];
53+
if (!fcmi.isSubmenu) {
54+
this.fcAppLayout.drawer.close();
55+
}
56+
});
57+
}
58+
59+
static get styles() {
60+
return [
61+
CSSModule('lumo-typography'),
62+
CSSModule('lumo-color'),
63+
css`
64+
:host {
65+
display: block;
66+
height: 100%;
67+
}
68+
69+
header {
70+
align-items: center;
71+
box-shadow: var(--lumo-box-shadow-s);
72+
display: flex;
73+
height: var(--lumo-size-xl);
74+
width: 100%;
75+
}
76+
77+
header h1 {
78+
font-size: var(--lumo-font-size-l);
79+
margin: 0;
80+
}
81+
82+
header img {
83+
border-radius: 50%;
84+
height: var(--lumo-size-s);
85+
margin-left: auto;
86+
margin-right: var(--lumo-space-m);
87+
overflow: hidden;
88+
background-color: var(--lumo-contrast);
89+
}
90+
91+
#logo {
92+
align-items: center;
93+
box-sizing: border-box;
94+
display: flex;
95+
padding: var(--lumo-space-s) var(--lumo-space-m);
96+
}
97+
98+
#logo img {
99+
height: calc(var(--lumo-size-l) * 1.5);
100+
}
101+
102+
#logo span {
103+
font-size: var(--lumo-font-size-xl);
104+
font-weight: 600;
105+
margin: 0 var(--lumo-space-s);
106+
}
107+
108+
.other {
109+
background-color: white;
110+
}
111+
.current {
112+
background-color: green;
113+
}
114+
115+
116+
`,
117+
];
118+
}
119+
120+
render() {
121+
return html`
122+
<fc-applayout reveals=${this.reveals} swipeOpen=${this.swipeOpen} fixed=${this.fixed} title=${this.title} id="fusionLayout">
123+
<div slot="profile" style="text-align: center;">
124+
<img src=${this.profilePicture} alt=${this.profilePictureAlt} style="width: 80px; margin-top: 20px;">
125+
<h4 slot="profile">${this.userName}</h4>
126+
</div>
127+
<img slot="title" class="applogo" src=${this.appLogo} alt=${this.appLogoAlt} style="width:50px">
128+
<div slot="title" main-title="">${this.title}</div>
129+
<slot name="toolbar" slot="toolbar"></slot>
130+
<div slot="menu" tabindex="0" aria-selected="false">
131+
${this.menuItems.map(item => this.generateFcMenuItem(item))}
132+
</div>
133+
<div slot="content">
134+
<slot></slot>
135+
</div>
136+
</fc-applayout>
137+
`;
138+
}
139+
140+
connectedCallback() {
141+
super.connectedCallback();
142+
this.buildMenu();
143+
window.addEventListener('requestRefreshMenu',
144+
this.buildMenuEventListener,
145+
false
146+
);
147+
window.addEventListener("message", function(event) {
148+
if (event.data == 'redirect-welcome') {
149+
Router.go("welcome");
150+
}
151+
});
152+
}
153+
154+
private buildMenuEventListener = () => {
155+
this.buildMenu();
156+
}
157+
158+
disconnectedCallback() {
159+
super.disconnectedCallback();
160+
// desregistrar el listener
161+
window.removeEventListener('requestRefreshMenu',
162+
this.buildMenuEventListener,
163+
false
164+
);
165+
}
166+
167+
private currentLocationClass(route: string): string {
168+
return ""; /*Router.urlForPath(route) === Router.location.pathname?"current":"other";*/
169+
}
170+
171+
private buildMenu(){
172+
this.updateMenuItems();
173+
}
174+
175+
private async updateMenuItems(){
176+
await menuItemEndpoint.getMenuItems().then((mi: any[]) =>{
177+
this.menuItems = mi!
178+
} ).catch((error: { detail: any; message: any; })=>{
179+
if (error instanceof EndpointError) {
180+
console.error("EndpointError");
181+
console.error(error.detail);
182+
console.error(error.message);
183+
} else {
184+
console.error("Not EndpointError");
185+
console.error(error);
186+
}
187+
})
188+
}
189+
190+
private generateFcMenuItem(item: MenuItemDto): any {
191+
let routerLink = item.href;
192+
let ret;
193+
// TODO: Add attrs: key, src, icon(if hasIcon), disabled, (isSubmenu?), onMenuItemClicked
194+
if(item.children.length>0) {
195+
ret = html`
196+
<fc-menuitem
197+
class="sub-menu"
198+
slot="menu-item"
199+
label="${item.label}"
200+
>
201+
${item.children.length>0 ? item.children.map((i: any) => this.generateFcMenuItem(i)) : ""}
202+
</fc-menuitem>
203+
`;
204+
} else {
205+
ret = html`
206+
<fc-menuitem
207+
slot="menu-item"
208+
class=${this.currentLocationClass(""+item.href)}
209+
href="${routerLink}"
210+
label="${item.label}"
211+
>
212+
</fc-menuitem>
213+
`;
214+
}
215+
return ret;
216+
}
217+
}

0 commit comments

Comments
 (0)