Framework WIP:

- Missing placeholder icons for app dropdown
This commit is contained in:
nathan 2024-05-10 11:21:39 -06:00
parent 8864d6ed49
commit 1d6aa8e793
3 changed files with 81 additions and 13 deletions

View File

@ -1,6 +1,7 @@
<?php <?php
use EGroupware\Api; use EGroupware\Api;
use EGroupware\Api\Image;
class kdots_framework extends Api\Framework\Ajax class kdots_framework extends Api\Framework\Ajax
{ {
@ -27,9 +28,23 @@ class kdots_framework extends Api\Framework\Ajax
*/ */
protected function _get_header(array $extra = array()) protected function _get_header(array $extra = array())
{ {
// Skip making a mess for iframe apps, they're on their own
if($extra['check-framework'] == true)
{
$extra['check-framework'] = false;
return [];
}
$data = parent::_get_header($extra); $data = parent::_get_header($extra);
if($extra['navbar-apps']) if($extra['navbar-apps'])
{ {
// Fix wrong icon type
array_walk($extra['navbar-apps'], function (&$item, $key)
{
if(!$item['icon'] || !str_ends_with($item['icon'], 'svg'))
{
$item['icon'] = Image::find('api', 'navbar');
}
});
$data['application-list'] = htmlentities(json_encode($extra['navbar-apps'], JSON_HEX_QUOT | JSON_HEX_AMP), ENT_QUOTES, 'UTF-8'); $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) $open_app = current(array_filter($extra['navbar-apps'], function ($app)
{ {

View File

@ -152,6 +152,10 @@ export default css`
::slotted(*) { ::slotted(*) {
height: 100%; height: 100%;
} }
::slotted(iframe) {
width: 100%;
}
} }
@media (max-width: 599px) { @media (max-width: 599px) {
.egw_fw_app__main { .egw_fw_app__main {
@ -202,4 +206,6 @@ export default css`
grid-column: start / end; grid-column: start / end;
} }
} }
` `

View File

@ -129,6 +129,9 @@ export class EgwFrameworkApp extends LitElement
protected loadingPromise = Promise.resolve(); protected loadingPromise = Promise.resolve();
/** The application's content must be in an iframe instead of handled normally */
protected useIframe = false;
connectedCallback() connectedCallback()
{ {
super.connectedCallback(); super.connectedCallback();
@ -163,7 +166,7 @@ export class EgwFrameworkApp extends LitElement
return; return;
} }
let targetUrl = ""; let targetUrl = "";
let useIframe = false; this.useIframe = true;
let matches = url.match(/\/index.php\?menuaction=([A-Za-z0-9_\.]*.*&ajax=true.*)$/); let matches = url.match(/\/index.php\?menuaction=([A-Za-z0-9_\.]*.*&ajax=true.*)$/);
if(matches) if(matches)
{ {
@ -172,7 +175,7 @@ export class EgwFrameworkApp extends LitElement
// jdots_framework ajax_exec function which will be called by the code // jdots_framework ajax_exec function which will be called by the code
// below as we set useIframe to false. // below as we set useIframe to false.
targetUrl = "index.php?menuaction=" + matches[1]; targetUrl = "index.php?menuaction=" + matches[1];
useIframe = false; this.useIframe = false;
} }
// Destroy application js // Destroy application js
@ -181,18 +184,38 @@ export class EgwFrameworkApp extends LitElement
window.app[this.name].destroy(); window.app[this.name].destroy();
delete window.app[this.name]; // really delete it, so new object get constructed and registered for push delete window.app[this.name]; // really delete it, so new object get constructed and registered for push
} }
return this.loadingPromise = this.egw.request( if(!this.useIframe)
this.framework.getMenuaction('ajax_exec', targetUrl, this.name),
[targetUrl]
).then((data : string[]) =>
{ {
// Load request returns HTML. Shove it in. return this.loadingPromise = this.egw.request(
render(html`${unsafeHTML(data.join(""))}`, this); this.framework.getMenuaction('ajax_exec', targetUrl, this.name),
[targetUrl]
).then((data : string[]) =>
{
// Load request returns HTML. Shove it in.
render(html`${unsafeHTML(data.join(""))}`, this);
// Might have just slotted aside content, hasSlotController will requestUpdate() // Might have just slotted aside content, hasSlotController will requestUpdate()
// but we need to do it anyway // but we need to do it anyway for translation
this.requestUpdate();
});
}
else
{
this.loadingPromise = new Promise((resolve, reject) =>
{
const timeout = setTimeout(() => reject(this.name + " load failed"), 5000);
this.addEventListener("load", () =>
{
clearTimeout(timeout);
resolve()
}, {once: true});
render(this._iframeTemplate(), this);
});
// Might have just changed useIFrame, need to update to show that
this.requestUpdate(); this.requestUpdate();
}); return this.loadingPromise;
}
} }
public showLeft() public showLeft()
@ -296,12 +319,33 @@ export class EgwFrameworkApp extends LitElement
*/ */
protected _loadingTemplate() protected _loadingTemplate()
{ {
// Don't show loader for iframe, it will not resolve
if(this.useIframe)
{
return nothing;
}
return html` return html`
<div class="egw_fw_app__loading"> <div class="egw_fw_app__loading">
<sl-spinner></sl-spinner> <sl-spinner></sl-spinner>
</div>`; </div>`;
} }
/**
* If we have to use an iframe, this is where it is made
* @returns {typeof nothing | typeof nothing}
* @protected
*/
protected _iframeTemplate()
{
if(!this.useIframe)
{
return nothing;
}
return html`
<iframe src="${this.url}"></iframe>`;
}
protected _asideTemplate(parentSlot, side, label?) protected _asideTemplate(parentSlot, side, label?)
{ {
const asideClassMap = classMap({ const asideClassMap = classMap({
@ -392,7 +436,10 @@ export class EgwFrameworkApp extends LitElement
</header> </header>
<div slot="start" class="egw_fw_app__main_content content" part="content" <div slot="start" class="egw_fw_app__main_content content" part="content"
aria-label="${this.name}" tabindex="0"> aria-label="${this.name}" tabindex="0">
<slot>${this._loadingTemplate()}<span class="placeholder">main</span></slot> <slot>
${this._loadingTemplate()}
<span class="placeholder">main</span>
</slot>
</div> </div>
<footer slot="start" class="egw_fw_app__footer footer" part="footer"> <footer slot="start" class="egw_fw_app__footer footer" part="footer">
<slot name="footer"><span class="placeholder">main-footer</span></slot> <slot name="footer"><span class="placeholder">main-footer</span></slot>