Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ projectName=app.main

version=8.0.0-SNAPSHOT
# xpVersion=version - same as app version
libAdminUiVersion=6.0.0-SNAPSHOT
libAdminUiVersion=0.0.0-webcomponents-SNAPSHOT

# Optimizations
org.gradle.parallel=true
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/admin/extensions/launcher/launcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ exports.get = function(req) {
adminTools[i].cls = adminTools[i].appId === config.appName ? 'active' : '';
}

const userIconUrl = assetLib.assetUrl({ path: 'icons/widgets/user.svg' });
const userIconUrl = assetLib.assetUrl({ path: 'icons/extensions/user.svg' });
const logoutUrl = portal.logoutUrl({
redirect: admin.getHomeToolUrl({ type: 'absolute' })
});
Expand Down
8 changes: 4 additions & 4 deletions src/main/resources/admin/extensions/shortcuts/shortcuts.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<widget id="widget-shortcuts">
<div id="extension-shortcuts">
<script type="module" src="{{jsUrl}}" data-config-script-id="{{configScriptId}}"></script>
<link rel="stylesheet" href="{{stylesUrl}}" type="text/css" media="all"/>
<div class="widget-shortcuts-container">
<div class="extension-shortcuts-container">
{{#dashboardIcons}}
<div class="{{cls}} widget-shortcuts-item" tabindex="0">
<div class="{{cls}} extension-shortcuts-item" tabindex="0">
{{#link}}
<a href="{{link}}" target="_blank" tabindex="-1">
{{/link}}
Expand All @@ -15,4 +15,4 @@
</div>
{{/dashboardIcons}}
</div>
</widget>
</div>
8 changes: 4 additions & 4 deletions src/main/resources/admin/extensions/shortcuts/shortcuts.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const configLib = require('/lib/config');
const assetLib = require('/lib/enonic/asset');

function handleGet(req) {
const iconsPath = 'icons/widgets/';
const iconsPath = 'icons/extensions/';
const infoIconUrl = assetLib.assetUrl({ path: `${iconsPath}info-with-circle.svg` });
const devIconUrl = assetLib.assetUrl({ path: `${iconsPath}developer.svg` });
const forumIconUrl = assetLib.assetUrl({ path: `${iconsPath}discuss.svg` });
Expand All @@ -16,7 +16,7 @@ function handleGet(req) {
const dashboardIcons = [
{
src: infoIconUrl,
cls: 'widget-shortcuts-xp-about',
cls: 'extension-shortcuts-xp-about',
caption: i18n.localize({
key: 'home.dashboard.widget.shortcuts.about',
bundles: ['i18n/phrases'],
Expand Down Expand Up @@ -58,10 +58,10 @@ function handleGet(req) {
const params = {
dashboardIcons: dashboardIcons,
stylesUrl: assetLib.assetUrl({
path: 'styles/widgets/shortcuts.css'
path: 'styles/extensions/shortcuts.css'
}),
jsUrl: assetLib.assetUrl({
path: 'js/widgets/shortcuts.js'
path: 'js/extensions/shortcuts.js'
}),
configScriptId: configLib.configScriptId
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ const createLicenseInfoContainer = (): void => {
outerContainer.appendChildren(button, licenseInfoHeader, licenseInfoContainer);
};

export const createAboutDialog = (): ModalDialogWithConfirmation => {
const aboutDialog: ModalDialogWithConfirmation = new ModalDialogWithConfirmation({skipTabbable: true});
export const createAboutDialog = (container: HTMLElement): ModalDialogWithConfirmation => {
const aboutDialog: ModalDialogWithConfirmation = new ModalDialogWithConfirmation({skipTabbable: true, container: Element.fromHtmlElement(container)});

aboutDialog.onKeyDown((event: KeyboardEvent) => {
if (KeyHelper.isEscKey(event)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {DefaultErrorHandler} from '@enonic/lib-admin-ui/DefaultErrorHandler';
import {Body} from '@enonic/lib-admin-ui/dom/Body';
import {ModalDialogWithConfirmation} from '@enonic/lib-admin-ui/ui/dialog/ModalDialogWithConfirmation';
import {CONFIG} from '@enonic/lib-admin-ui/util/Config';
import {resolveScriptConfig} from '../ConfigResolver';
Expand All @@ -13,7 +12,7 @@ const getElement = (selector: string): Promise<Element> => {
return Promise.resolve(searchedElement);
}

const promise = new Promise<Element>((resolve) => {
return new Promise<Element>((resolve) => {
const intervalId = setInterval(() => {
const searchedElement: Element = document.querySelector(selector);

Expand All @@ -23,8 +22,6 @@ const getElement = (selector: string): Promise<Element> => {
}
}, 200);
});

return promise;
};

const initAboutDialog = () => {
Expand All @@ -34,14 +31,14 @@ const initAboutDialog = () => {
e.preventDefault();

if (!aboutDialog) {
aboutDialog = createAboutDialog();
aboutDialog = createAboutDialog(document.getElementById('extension-shortcuts'));
aboutDialog.render();
}

Body.get().appendChild(aboutDialog);
aboutDialog.open();
aboutDialog.whenRendered(() => aboutDialog.open());
};

getElement('.widget-shortcuts-xp-about').then((aboutContainer: Element) => {
getElement('.extension-shortcuts-xp-about').then((aboutContainer: Element) => {
aboutContainer.addEventListener('click', execute);
aboutContainer.addEventListener('keypress', (e: KeyboardEvent) => {
if (e.key === 'Enter') { execute(e); }
Expand Down
7 changes: 7 additions & 0 deletions src/main/resources/assets/js/home/DashboardExtension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {CustomElement} from '@enonic/lib-admin-ui/dom/CustomElement';

export class DashboardExtension extends CustomElement {
static create<T extends typeof CustomElement>(this: T): InstanceType<T> {
return super.create('dashboard-extension') as InstanceType<T>;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {CustomElement} from '@enonic/lib-admin-ui/dom/CustomElement';

export class DashboardExtensionElement extends CustomElement {
static create<T extends typeof CustomElement>(this: T): InstanceType<T> {
return super.create('dashboard-extension') as InstanceType<T>;
}
}
201 changes: 201 additions & 0 deletions src/main/resources/assets/js/home/DashboardPanel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import {ApplicationEvent, ApplicationEventType} from '@enonic/lib-admin-ui/application/ApplicationEvent';
import {DefaultErrorHandler} from '@enonic/lib-admin-ui/DefaultErrorHandler';
import {DivEl} from '@enonic/lib-admin-ui/dom/DivEl';
import {Element as LibAdminElement} from '@enonic/lib-admin-ui/dom/Element';
import {H5El} from '@enonic/lib-admin-ui/dom/H5El';
import {LoadMask} from '@enonic/lib-admin-ui/ui/mask/LoadMask';
import * as Q from 'q';
import {DashboardExtension} from './resource/extension/DashboardExtension';
import {GetDashboardExtensionsRequest} from './resource/extension/GetDashboardExtensionsRequest';
import {DashboardExtensionElement} from './DashboardExtensionElement';

export class DashboardPanel
extends DivEl {

private static cache: Map<string, string[]> = new Map<string, string[]>();

private extensionCount = 0;

constructor() {
super('dashboard-extension-panel');

this.addApplicationsListeners();
}

appendExtensions(): void {
this.fetchExtensions()
.then((extensions: DashboardExtension[]) => {
if (extensions.length === this.extensionCount) {
return;
}

if (this.extensionCount > 0) {
this.removeChildren();
}
this.extensionCount = extensions.length;
extensions
.sort((w1: DashboardExtension, w2: DashboardExtension) => this.sortByOrder(w1, w2))
.forEach((extension: DashboardExtension) => this.appendExtension(extension));
})
.catch(DefaultErrorHandler.handle);
}

private addApplicationsListeners(): void {
ApplicationEvent.on((e: ApplicationEvent) => {
const applicationKey: string = e.getApplicationKey().toString();
if (this.isApplicationDeactivated(e)) {
this.handleApplicationDeactivated(applicationKey);
} else if (this.isApplicationActivated(e)) {
this.handleApplicationActivated(applicationKey);
}
});
}

private isApplicationDeactivated(e: ApplicationEvent): boolean {
const eventType: ApplicationEventType = e.getEventType();
return ApplicationEventType.STOPPED === eventType || ApplicationEventType.UNINSTALLED === eventType;
}

private handleApplicationDeactivated(applicationKey: string): void {
const extensionKeys: string[] = DashboardPanel.cache.get(applicationKey);
if (extensionKeys) {
this.removeExtensions(extensionKeys);
DashboardPanel.cache.delete(applicationKey);
}
}

private isApplicationActivated(e: ApplicationEvent): boolean {
return ApplicationEventType.STARTED === e.getEventType();
}

private handleApplicationActivated(applicationKey: string): void {
if (DashboardPanel.cache.has(applicationKey)) {
this.updateExtensions(applicationKey);
} else {
this.appendExtensions();
}
}

private removeExtensions(extensionKeys: string[]): void {
extensionKeys.forEach((extensionKey: string) => {
const extensionElement = this.findChildById(extensionKey, true);
if (extensionElement) {
this.extensionCount -= 1;
extensionElement.remove();
}
});
}

private sortByOrder(extension1: DashboardExtension, extension2: DashboardExtension): number {
return extension1.getOrder() - extension2.getOrder();
}

private fetchExtensions(): Q.Promise<DashboardExtension[]> {
return new GetDashboardExtensionsRequest().fetchExtensions();
}

private updateExtensions(applicationKey: string): void {
this.fetchExtensions()
.then((extensions: DashboardExtension[]) => {
if (extensions.length !== this.extensionCount) {
this.appendExtensions();
return;
}

extensions
.filter((extension: DashboardExtension) =>
extension.getDescriptorKey().getApplicationKey().toString() === applicationKey
)
.forEach((extension: DashboardExtension) => this.updateExtension(extension));
})
.catch(DefaultErrorHandler.handle);
}

private appendExtension(extension: DashboardExtension, existingContainer?: LibAdminElement) {
const extensionPlaceholder: LibAdminElement = existingContainer || this.createExtensionPlaceholder(extension);
if (!existingContainer) {
this.appendChild(extensionPlaceholder);
}

extensionPlaceholder.render()
.then(() => this.fetchAndRenderExtension(extension, extensionPlaceholder))
.catch(DefaultErrorHandler.handle);
}

private updateExtension(extension: DashboardExtension) {
const extensionContainer = this.findChildById(extension.getDescriptorKey().toString());
if (!extensionContainer) {
return;
}

const newExtensionContainer = this.createExtensionPlaceholder(extension);
extensionContainer.replaceWith(newExtensionContainer);

this.appendExtension(extension, newExtensionContainer);
}

private createExtensionPlaceholder(extension: DashboardExtension): LibAdminElement {
const widthCls = ` width-${extension.getWidth().toLowerCase()}`;
const heightCls = ` height-${extension.getHeight().toLowerCase()}`;
const styleCls: string = extension.hasCustomStyling() ? ` style-${extension.getStyle().toLowerCase()}` : '';
const extensionPlaceholder: LibAdminElement = new DivEl(`extension-placeholder${widthCls}${heightCls}${styleCls}`);

extensionPlaceholder.setId(extension.getDescriptorKey().toString());

return extensionPlaceholder;
}

private static cacheExtensionKey(extension: DashboardExtension): void {
const applicationKey: string = extension.getDescriptorKey().getApplicationKey().toString();
const extensionKey: string = extension.getDescriptorKey().toString();

const cachedExtensionKeys: string[] = DashboardPanel.cache.get(applicationKey) || [];
if (cachedExtensionKeys.includes(extensionKey)) {
return;
}

cachedExtensionKeys.push(extensionKey);
DashboardPanel.cache.set(applicationKey, cachedExtensionKeys);
}

private fetchAndRenderExtension(extension: DashboardExtension, extensionPlaceholder: LibAdminElement): Promise<void> {
let loading = true;
let loadMask: LoadMask;
setTimeout(() => {
if (loading) {
loadMask = new LoadMask(extensionPlaceholder);
loadMask.show();
}
}, 300);
return fetch(extension.getFullUrl())
.then(response => {
loading = false;
return response.text();
})
.then((html: string) => {
DashboardPanel.cacheExtensionKey(extension);
return this.renderExtension(extension, extensionPlaceholder, html);
})
.catch(() => console.error(`Failed to fetch extension ${extension.getDisplayName()}`))
.finally(() => {
if (loadMask) {
loadMask.hide();
}
});
}

private renderExtension(extension: DashboardExtension, extensionPlaceholder: LibAdminElement, html: string): Promise<void> {
const extensionContainer = new DivEl('extension-container');

if (extension.hasHeader()) {
extensionContainer.appendChild(new H5El('extension-header').setHtml(extension.getDisplayName()));
}

const extensionElement = DashboardExtensionElement.create();
extensionContainer.getHTMLElement().appendChild(extensionElement);
extensionPlaceholder.appendChild(extensionContainer);
extensionPlaceholder.addClass('loaded');

return extensionElement.setHtml(html);
}
}
Loading
Loading