Framework WIP:

- Fix splitter preferences
- Add some app icons to app header
- Alignment & layout adjustments
This commit is contained in:
nathan 2024-05-02 11:17:15 -06:00
parent 3cb0779e62
commit e880479099
6 changed files with 41 additions and 57 deletions

View File

@ -79,9 +79,8 @@ egw-app {
/*** HEADER ***/ /*** HEADER ***/
#egw_fw_topmenu_info_items { #egw_fw_topmenu_info_items {
display: flex !important; display: flex;
flex-direction: row-reverse; flex-direction: row-reverse;
height: var(--icon-size);
background-color: #fbfbfb; background-color: #fbfbfb;
& > * { & > * {
@ -91,6 +90,9 @@ egw-app {
et2-avatar { et2-avatar {
--size: var(--icon-size); --size: var(--icon-size);
&::part(base) {
vertical-align: initial;
}
} }
.topmenu_info_item { .topmenu_info_item {
@ -112,13 +114,13 @@ egw-app {
#topmenu_info_timer { #topmenu_info_timer {
order: 1; order: 1;
position: relative; position: relative;
display: flex;
align-items: center;
padding: 0px;
#topmenu_timer { #topmenu_timer {
position: relative;
top: 10px !important;
display: block; display: block;
height: 45px; width: 100%;
width: 45px;
} }
&:hover { &:hover {
@ -140,52 +142,14 @@ egw-app {
} }
} }
ul a#topmenu_cats { #topmenu_info_user_avatar {
background-image: url(../../../api/templates/default/images/topmenu_items/category.svg); sl-menu-item et2-image {
width: 1em;
}
} }
button#topmenu_info_search {
ul a#topmenu_password {
background-image: url(../../../api/templates/default/images/topmenu_items/password.svg);
}
ul a#topmenu_search {
background-image: url(../../../api/templates/default/images/topmenu_items/search.svg); background-image: url(../../../api/templates/default/images/topmenu_items/search.svg);
} }
ul a#topmenu_prefs {
background-image: url(../../../api/templates/default/images/topmenu_items/setup.svg);
}
ul a#topmenu_home {
background-image: url(../../../api/templates/default/images/topmenu_items/home.svg);
}
ul a#topmenu_acl {
background-image: url(../../../api/templates/default/images/topmenu_items/access.svg);
}
ul a#topmenu_useraccount {
background-image: url(../../../api/templates/default/images/accounts.svg);
background-repeat: no-repeat;
background-size: 18px;
background-position-x: -2px;
}
ul a#topmenu_calls {
background-image: url(../../../api/templates/default/images/phone.svg);
background-repeat: no-repeat;
background-position-x: -2px;
}
}
#topmenu_info_logout {
background-image: url(../../../api/templates/default/images/logout.svg);
a {
width: 45px;
height: 45px;
display: inline-block;
}
} }
#topmenu_info_print_title { #topmenu_info_print_title {

View File

@ -53,6 +53,8 @@
<div style="border: 1px dotted">Something inside the app - main</div> <div style="border: 1px dotted">Something inside the app - main</div>
<div slot="left">Left content</div> <div slot="left">Left content</div>
<div slot="right">right content</div> <div slot="right">right content</div>
<div slot="right-header">
</div>
</egw-app> </egw-app>
</egw-framework> </egw-framework>

View File

@ -114,6 +114,9 @@ class kdots_framework extends Api\Framework\Ajax
} }
$id = $app_data['id'] ? $app_data['id'] : ($app_data['name'] ? $app_data['name'] : $app_data['title']); $id = $app_data['id'] ? $app_data['id'] : ($app_data['name'] ? $app_data['name'] : $app_data['title']);
$title = htmlspecialchars($alt_label ? $alt_label : $app_data['title']); $title = htmlspecialchars($alt_label ? $alt_label : $app_data['title']);
$this->topmenu_items[] = '<sl-menu-item id="topmenu_' . $id . '" value="' . htmlspecialchars($app_data['url']) . '" title="' . $app_data['title'] . '">' . $title . '</sl-menu-item>'; $this->topmenu_items[] = '<sl-menu-item id="topmenu_' . $id . '" value="' . htmlspecialchars($app_data['url']) . '" title="' . $app_data['title'] . '">' .
"<et2-image slot='prefix' src='${app_data['icon']}'></et2-image>" .
$title .
'</sl-menu-item>';
} }
} }

View File

@ -125,7 +125,7 @@ export default css`
} }
.egw_fw__open_applications sl-tab et2-image { .egw_fw__open_applications sl-tab et2-image {
padding: var(--sl-spacing-small) var(--sl-spacing-3x-small); padding: var(--sl-spacing-2x-small) var(--sl-spacing-3x-small);
} }
.egw_fw__open_applications sl-tab:hover::part(close-button), .egw_fw__open_applications sl-tab[active]::part(close-button) { .egw_fw__open_applications sl-tab:hover::part(close-button), .egw_fw__open_applications sl-tab[active]::part(close-button) {

View File

@ -5,6 +5,7 @@ import {classMap} from "lit/directives/class-map.js";
import "@shoelace-style/shoelace/dist/components/split-panel/split-panel.js"; import "@shoelace-style/shoelace/dist/components/split-panel/split-panel.js";
import styles from "./EgwFramework.styles"; import styles from "./EgwFramework.styles";
import {repeat} from "lit/directives/repeat.js"; import {repeat} from "lit/directives/repeat.js";
import {Function} from "estree";
/** /**
* @summary Accessable, webComponent-based EGroupware framework * @summary Accessable, webComponent-based EGroupware framework
@ -96,8 +97,10 @@ export class EgwFramework extends LitElement
get egw() get egw()
{ {
return window.egw ?? { return window.egw ?? {
// Dummy egw so we don't get failures from missing methods
lang: (t) => t, lang: (t) => t,
preference: (n, app) => "" preference: (n, app, promise? : Function | boolean | undefined) => Promise.resolve(""),
set_preference(_app : string, _name : string, _val : any, _callback? : Function) {}
}; };
} }

View File

@ -7,10 +7,14 @@ import {classMap} from "lit/directives/class-map.js";
import styles from "./EgwFrameworkApp.styles"; import styles from "./EgwFrameworkApp.styles";
import {SlSplitPanel} from "@shoelace-style/shoelace"; import {SlSplitPanel} from "@shoelace-style/shoelace";
import {HasSlotController} from "../../api/js/etemplate/Et2Widget/slot"; import {HasSlotController} from "../../api/js/etemplate/Et2Widget/slot";
import type {EgwFramework} from "./EgwFramework";
/** /**
* @summary Application component inside EgwFramework * @summary Application component inside EgwFramework
* *
* Contain an EGroupware application inside the main framework. It consists of left, main and right areas. Each area
* has a header, content and footer. Side content areas are not shown when there is no content.
*
* @dependency sl-split-panel * @dependency sl-split-panel
* *
* @slot - Main application content. Other slots are normally hidden if they have no content * @slot - Main application content. Other slots are normally hidden if they have no content
@ -121,13 +125,13 @@ export class EgwFrameworkApp extends LitElement
connectedCallback() connectedCallback()
{ {
super.connectedCallback(); super.connectedCallback();
this.egw.preference(this.leftPanelInfo.preference, this.name, true).then((width) => (<Promise<string>>this.egw.preference(this.leftPanelInfo.preference, this.name, true)).then((width) =>
{ {
this.leftPanelInfo.preferenceWidth = parseInt(width ?? this.leftPanelInfo.defaultWidth); this.leftPanelInfo.preferenceWidth = parseInt(width) ?? this.leftPanelInfo.defaultWidth;
}); });
this.egw.preference(this.rightPanelInfo.preference, this.name, true).then((width) => (<Promise<string>>this.egw.preference(this.rightPanelInfo.preference, this.name, true)).then((width) =>
{ {
this.rightPanelInfo.preferenceWidth = parseInt(width ?? this.rightPanelInfo.defaultWidth); this.rightPanelInfo.preferenceWidth = parseInt(width) ?? this.rightPanelInfo.defaultWidth;
}); });
} }
@ -167,7 +171,7 @@ export class EgwFrameworkApp extends LitElement
get egw() get egw()
{ {
return window.egw ?? this.parentElement.egw ?? null; return window.egw ?? (<EgwFramework>this.parentElement).egw ?? null;
} }
/** /**
@ -243,6 +247,14 @@ export class EgwFrameworkApp extends LitElement
<header class="egw_fw_app__header" part="header"> <header class="egw_fw_app__header" part="header">
<slot name="main-header"><span class="placeholder"> ${this.name} main-header</span></slot> <slot name="main-header"><span class="placeholder"> ${this.name} main-header</span></slot>
</header> </header>
<sl-button-group>
<sl-icon-button name="arrow-clockwise"
label=${this.egw.lang("Reload %1", this.egw.lang(this.name))}></sl-icon-button>
<sl-icon-button name="printer"
label=${this.egw.lang("Reload %1", this.egw.lang(this.name))}></sl-icon-button>
<sl-icon-button name="gear-wide"
label=${this.egw.lang("Site configuration for %1", this.egw.lang(this.name))}></sl-icon-button>
</sl-button-group>
</div> </div>
<div class="egw_fw_app__main" part="main"> <div class="egw_fw_app__main" part="main">
<sl-split-panel class=${classMap({"egw_fw_app__outerSplit": true, "no-content": !hasLeftSlots})} <sl-split-panel class=${classMap({"egw_fw_app__outerSplit": true, "no-content": !hasLeftSlots})}