mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-21 23:43:17 +01:00
Framework WIP:
- Apps loading
This commit is contained in:
parent
c1db022fb8
commit
c6c8de0a3b
@ -48,14 +48,8 @@
|
||||
<!-- status app is looking for this -->
|
||||
<div slot="aside" id="egw_fw_sidebar_r"></div>
|
||||
|
||||
<!-- Fake app -->
|
||||
<egw-app name="fake app" class="placeholder">
|
||||
<div style="border: 1px dotted">Something inside the app - main</div>
|
||||
<div slot="left">Left content</div>
|
||||
<div slot="right">right content</div>
|
||||
<div slot="right-header">
|
||||
</div>
|
||||
</egw-app>
|
||||
<!-- Currently open app -->
|
||||
<egw-app name="{open_app_name}" url="{open_app_url}" active></egw-app>
|
||||
</egw-framework>
|
||||
|
||||
|
||||
|
@ -29,7 +29,12 @@ class kdots_framework extends Api\Framework\Ajax
|
||||
{
|
||||
$data = parent::_get_header($extra);
|
||||
$data['application-list'] = htmlentities(json_encode($extra['navbar-apps'], JSON_HEX_QUOT | JSON_HEX_AMP), ENT_QUOTES, 'UTF-8');
|
||||
|
||||
$open_app = current(array_filter($extra['navbar-apps'], function ($app)
|
||||
{
|
||||
return $app['active'] ?? false;
|
||||
})) ?? [];
|
||||
$data['open_app_name'] = $open_app['name'];
|
||||
$data['open_app_url'] = $open_app['url'];
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
@ -131,4 +131,12 @@ export default css`
|
||||
.egw_fw__open_applications sl-tab:hover::part(close-button), .egw_fw__open_applications sl-tab[active]::part(close-button) {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
::slotted(egw-app) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
::slotted(egw-app[active]) {
|
||||
display: flex;
|
||||
}
|
||||
`
|
@ -1,4 +1,4 @@
|
||||
import {css, html, LitElement} from "lit";
|
||||
import {css, html, LitElement, nothing} from "lit";
|
||||
import {customElement} from "lit/decorators/custom-element.js";
|
||||
import {property} from "lit/decorators/property.js";
|
||||
import {classMap} from "lit/directives/class-map.js";
|
||||
@ -6,7 +6,7 @@ import {repeat} from "lit/directives/repeat.js";
|
||||
import "@shoelace-style/shoelace/dist/components/split-panel/split-panel.js";
|
||||
import styles from "./EgwFramework.styles";
|
||||
import {egw} from "../../api/js/jsapi/egw_global";
|
||||
import {SlTab, SlTabGroup} from "@shoelace-style/shoelace";
|
||||
import {SlDropdown, SlTab, SlTabGroup} from "@shoelace-style/shoelace";
|
||||
import {EgwFrameworkApp} from "./EgwFrameworkApp";
|
||||
|
||||
/**
|
||||
@ -93,9 +93,16 @@ export class EgwFramework extends LitElement
|
||||
@property()
|
||||
layout = "default";
|
||||
|
||||
/**
|
||||
* This is the list of all applications we know about
|
||||
*
|
||||
* @type {any[]}
|
||||
*/
|
||||
@property({type: Array, attribute: "application-list"})
|
||||
applicationList = [];
|
||||
|
||||
private get tabs() : SlTabGroup { return this.shadowRoot.querySelector("sl-tab-group");}
|
||||
|
||||
get egw() : typeof egw
|
||||
{
|
||||
return window.egw ?? <typeof egw>{
|
||||
@ -131,16 +138,30 @@ export class EgwFramework extends LitElement
|
||||
(menuaction ? '.' + menuaction[1] : '');
|
||||
};
|
||||
|
||||
public loadApp(appname)
|
||||
public loadApp(appname, active = false)
|
||||
{
|
||||
const app = this.applicationList.find(a => a.name == appname);
|
||||
let appComponent = <EgwFrameworkApp>document.createElement("egw-app");
|
||||
appComponent.id = appname;
|
||||
appComponent.name = appname;
|
||||
appComponent.url = app?.url;
|
||||
|
||||
this.append(appComponent);
|
||||
app.opened = this.shadowRoot.querySelectorAll("sl-tab").length;
|
||||
// App was not in the tab list
|
||||
if(typeof app.opened == "undefined")
|
||||
{
|
||||
app.opened = this.shadowRoot.querySelectorAll("sl-tab").length;
|
||||
this.requestUpdate("applicationList");
|
||||
}
|
||||
|
||||
// Wait until new tab is there to activate it
|
||||
if(active)
|
||||
{
|
||||
this.updateComplete.then(() =>
|
||||
{
|
||||
this.tabs.show(appname);
|
||||
})
|
||||
}
|
||||
|
||||
return appComponent;
|
||||
}
|
||||
@ -214,17 +235,28 @@ export class EgwFramework extends LitElement
|
||||
*/
|
||||
protected _applicationListAppTemplate(app)
|
||||
{
|
||||
if(app.status !== "1")
|
||||
{
|
||||
return nothing;
|
||||
}
|
||||
|
||||
return html`
|
||||
<sl-tooltip placement="bottom" role="menuitem" content="${app.title}">
|
||||
<et2-button-icon src="${app.icon}" aria-label="${app.title}" role="menuitem" noSubmit
|
||||
helptext="${app.title}"></et2-button-icon>
|
||||
helptext="${app.title}"
|
||||
@click=${() =>
|
||||
{
|
||||
this.loadApp(app.name, true);
|
||||
(<SlDropdown>this.shadowRoot.querySelector(".egw_fw__app_list")).hide();
|
||||
}}
|
||||
></et2-button-icon>
|
||||
</sl-tooltip>`;
|
||||
}
|
||||
|
||||
protected _applicationTabTemplate(app)
|
||||
{
|
||||
return html`
|
||||
<sl-tab slot="nav" panel="${app.name}" closable aria-label="${app.title}">
|
||||
<sl-tab slot="nav" panel="${app.name}" closable aria-label="${app.title}" ?active=${app.active}>
|
||||
<sl-tooltip placement="bottom" content="${app.title}" hoist>
|
||||
<et2-image src="${app.icon}"></et2-image>
|
||||
</sl-tooltip>
|
||||
@ -260,7 +292,9 @@ export class EgwFramework extends LitElement
|
||||
@sl-tab-show=${this.handleApplicationTabShow}
|
||||
@sl-close=${this.handleApplicationTabClose}
|
||||
>
|
||||
${repeat(this.applicationList.filter(app => app.opened).sort((a, b) => a.opened - b.opened), (app) => this._applicationTabTemplate(app))}
|
||||
${repeat(this.applicationList
|
||||
.filter(app => typeof app.opened !== "undefined")
|
||||
.sort((a, b) => a.opened - b.opened), (app) => this._applicationTabTemplate(app))}
|
||||
</sl-tab-group>
|
||||
<slot name="header"><span class="placeholder">header</span></slot>
|
||||
<slot name="header-right"><span class="placeholder">header-right</span></slot>
|
||||
|
@ -122,6 +122,20 @@ export default css`
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.egw_fw_app {
|
||||
--application-color: var(--primary-background-color);
|
||||
}
|
||||
|
||||
.egw_fw_app__loading {
|
||||
text-align: center;
|
||||
|
||||
sl-spinner {
|
||||
--track-width: 1rem;
|
||||
font-size: 10rem;
|
||||
--indicator-color: var(--application-color, var(--primary-background-color, var(--sl-color-primary-600)));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 600px) {
|
||||
.egw_fw_app__main {
|
||||
grid-template-columns: [start left] min-content [ main] 1fr [right] min-content [end];
|
||||
|
@ -1,8 +1,9 @@
|
||||
import {css, html, LitElement, nothing} from "lit";
|
||||
import {css, html, LitElement, nothing, render} from "lit";
|
||||
import {customElement} from "lit/decorators/custom-element.js";
|
||||
import {property} from "lit/decorators/property.js";
|
||||
import {state} from "lit/decorators/state.js";
|
||||
import {classMap} from "lit/directives/class-map.js";
|
||||
import {unsafeHTML} from "lit/directives/unsafe-html.js";
|
||||
|
||||
import styles from "./EgwFrameworkApp.styles";
|
||||
import {SlSplitPanel} from "@shoelace-style/shoelace";
|
||||
@ -138,15 +139,11 @@ export class EgwFrameworkApp extends LitElement
|
||||
{
|
||||
this.rightPanelInfo.preferenceWidth = parseInt(width) ?? this.rightPanelInfo.defaultWidth;
|
||||
});
|
||||
|
||||
// Register the "data" plugin
|
||||
this.egw.registerJSONPlugin(this.jsonDataHandler, this, 'data');
|
||||
}
|
||||
|
||||
disconnectedCallback()
|
||||
{
|
||||
super.disconnectedCallback();
|
||||
this.egw.unregisterJSONPlugin(this.jsonDataHandler, this, "data", false)
|
||||
}
|
||||
|
||||
firstUpdated()
|
||||
@ -186,16 +183,11 @@ export class EgwFrameworkApp extends LitElement
|
||||
return this.loadingPromise = this.egw.request(
|
||||
this.framework.getMenuaction('ajax_exec', targetUrl, this.name),
|
||||
[targetUrl]
|
||||
);
|
||||
}
|
||||
|
||||
protected jsonDataHandler(type, res, req)
|
||||
{
|
||||
if(req.context !== this)
|
||||
).then((data : string[]) =>
|
||||
{
|
||||
return;
|
||||
}
|
||||
debugger;
|
||||
// Load request returns HTML. Shove it in.
|
||||
render(html`${unsafeHTML(data.join(""))}`, this);
|
||||
});
|
||||
}
|
||||
|
||||
public showLeft()
|
||||
@ -275,6 +267,20 @@ export class EgwFrameworkApp extends LitElement
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displayed for the time between when the application is added and when the server responds with content
|
||||
*
|
||||
* @returns {TemplateResult<1>}
|
||||
* @protected
|
||||
*/
|
||||
protected _loadingTemplate()
|
||||
{
|
||||
return html`
|
||||
<div class="egw_fw_app__loading">
|
||||
<sl-spinner></sl-spinner>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
protected _asideTemplate(parentSlot, side, label?)
|
||||
{
|
||||
const asideClassMap = classMap({
|
||||
@ -367,7 +373,7 @@ export class EgwFrameworkApp extends LitElement
|
||||
</header>
|
||||
<div slot="start" class="egw_fw_app__main_content content" part="content"
|
||||
aria-label="${this.name}" tabindex="0">
|
||||
<slot><span class="placeholder">main</span></slot>
|
||||
<slot>${this._loadingTemplate()}<span class="placeholder">main</span></slot>
|
||||
</div>
|
||||
<footer slot="start" class="egw_fw_app__footer footer" part="footer">
|
||||
<slot name="footer"><span class="placeholder">main-footer</span></slot>
|
||||
|
Loading…
Reference in New Issue
Block a user