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
14 changes: 13 additions & 1 deletion demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@300&family=Roboto:wght@300;400;500&display=swap"
/>
<link
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL@20..48,100..700,0..1"
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Material+Symbols+Outlined&display=block"
/>

<link rel="stylesheet" href="./colors.css" />
<link rel="stylesheet" href="./theming.css" />
</head>
Expand All @@ -21,6 +22,17 @@
await import('@webcomponents/scoped-custom-element-registry');
await import('../dist/oscd-shell.js');
await import('./index.js');

const _customElementsDefine = window.customElements.define;
window.customElements.define = (name, cl, conf) => {
if (!customElements.get(name)) {
try {
_customElementsDefine.call(window.customElements, name, cl, conf);
} catch (e) {
console.warn(e);
}
}
};
</script>
</body>
</html>
117 changes: 99 additions & 18 deletions demo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,35 +54,116 @@ const plugins = {
],
editor: [
{
name: 'SLD Designer',
translations: {
de: 'SLD entwerfen',
},
name: 'SLD',
icon: 'add_box',
requireDoc: true,
src: 'https://omicronenergyoss.github.io/oscd-editor-sld/oscd-editor-sld.js',
plugins: [
{
name: 'Design SLD',
icon: 'add_box',
requireDoc: true,
src: 'https://omicronenergyoss.github.io/oscd-editor-sld/oscd-editor-sld.js',
},
{
name: 'Edit Substation',
icon: 'margin',
requireDoc: true,
src: 'https://OpenEnergyTools.github.io/scl-substation-editor/scl-substation-editor.js',
},
],
},

{
name: 'Source Editor',
translations: { de: 'Source Editor' },
icon: 'code',
name: 'View GOOSE/SMV',
icon: 'hub',
requireDoc: true,
tagName: 'oscd-editor-source',
plugins: [
{
name: 'Edit Communication',
icon: 'hub',
requireDoc: true,
src: 'https://danyill.github.io/scl-communication-editor/scl-communication-editor.js',
},
{
name: 'Explore Communication',
icon: 'lan',
requireDoc: true,
src: 'https://sprinteins.github.io/oscd-plugins/oscd-plugins.js',
},
],
},
{
name: 'Subscriptions & Supervisions',
icon: 'add_box',
requireDoc: true,
plugins: [
{
name: 'Subscribe (Later Binding)',
icon: 'link',
requireDoc: true,
src: 'https://danyill.github.io/oscd-subscriber-later-binding/oscd-subscriber-later-binding.js',
},
{
name: 'Supervise',
icon: 'ecg',
requireDoc: true,
src: 'https://danyill.github.io/oscd-supervision/oscd-supervision.js',
},
],
},
{
name: 'Publish and Address',
icon: 'network_node',
requireDoc: true,
plugins: [
{
name: 'Publish',
icon: 'publish',
requireDoc: true,
src: 'https://com-pas.github.io/oscd-publisher/oscd-publisher.js',
},
{
name: 'Address Multicast (TP)',
icon: 'auto_fix_normal',
requireDoc: true,
src: 'https://danyill.github.io/oscd-tp-multicast-naming/oscd-tp-multicast-naming.js',
},
{
name: 'Communicate',
icon: 'network_node',
requireDoc: true,
src: 'https://openenergytools.github.io/scl-communication/scl-communication.js',
},
],
},
],
background: [
{
name: 'EditV1 Events Listener',
icon: 'none',
name: 'Configure Network (TP)',
icon: 'news',
requireDoc: true,
src: 'https://danyill.github.io/oscd-network-config/oscd-network-config.js',
},
{
name: 'Compare',
icon: 'compare',
requireDoc: true,
src: 'https://OMICRONEnergyOSS.github.io/oscd-editor-diff/oscd-editor-diff.js',
},
{
name: 'Stencil',
icon: 'draw_collage',
requireDoc: true,
src: 'https://danyill.github.io/oscd-stencil/oscd-stencil.js',
},
{
name: 'Source Editor',
icon: 'code',
requireDoc: true,
tagName: 'oscd-background-editv1',
src: 'https://OMICRONEnergyOSS.github.io/oscd-editor-source/oscd-editor-source.js',
},
{
name: 'EditV1 Events Listener',
icon: 'none',
name: 'Describe',
icon: 'description',
requireDoc: true,
tagName: 'oscd-background-editv1',
src: 'https://danyill.github.io/oscd-description/oscd-description.js',
},
],
};
Expand Down
Binary file modified screenshots/Chromium/baseline/app-bar-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/app-bar-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/document-name-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/document-name-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/editor-plugins-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/editor-plugins-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/editor-plugins-selected-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/editor-plugins-selected-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/menu-drawer-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/menu-drawer-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/menu-plugins-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/menu-plugins-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/menu-plugins-triggered-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/Chromium/baseline/menu-plugins-triggered-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/localization/de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@
<source>Menu</source>
<target>Menü</target>
</trans-unit>
<trans-unit id="s7293d04c5979a8ad">
<source>Expand sidebar</source>
<target>Menü erweitern</target>
</trans-unit>
<trans-unit id="s8f10b4e57121e256">
<source>Collapse sidebar</source>
<target>Menü einklappen</target>
</trans-unit>
</body>
</file>
</xliff>
14 changes: 14 additions & 0 deletions src/menus/plugins-menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ describe('plugins-menu', () => {
await pluginsMenu.updateComplete;
});

it('renders an img when appIcon is set', async () => {
pluginsMenu.appIcon =
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PC9zdmc+';
await pluginsMenu.updateComplete;
const img = pluginsMenu.shadowRoot?.querySelector('img');
expect(img).to.exist;
expect(img!.getAttribute('alt')).to.equal('logo');
});

it('does not render an img when appIcon is not set', async () => {
const img = pluginsMenu.shadowRoot?.querySelector('img');
expect(img).to.not.exist;
});

it('displays a menu item for each menu plugin', async () => {
const menuOpenButton = findMenuOpenButton(pluginsMenu);
menuOpenButton?.click();
Expand Down
10 changes: 7 additions & 3 deletions src/oscd-shell-design-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,11 @@ export const oscdShellDesignTokens = css`
/* Editor plugins panel */
--editor-plugins-panel-width: var(
--oscd-shell-editor-plugins-panel-width,
280px
320px
);
--editor-plugins-panel-collapsed-width: var(
--oscd-shell-editor-plugins-panel-width,
280px
--oscd-shell-editor-plugins-panel-collapsed-width,
72px
);
--editor-plugins-panel-padding-top: var(
--oscd-shell-editor-plugins-panel-padding-top,
Expand Down Expand Up @@ -248,6 +248,10 @@ export const oscdShellDesignTokens = css`
--oscd-shell-editor-plugins-panel-item-active-bg,
var(--oscd-primary)
);
--editor-plugins-panel-group-active-bg: var(
--oscd-shell-editor-plugins-panel-group-active-bg,
var(--oscd-secondary)
);
--side-panel-width: var(--editor-plugins-panel-width);

/* Main editor container */
Expand Down
3 changes: 2 additions & 1 deletion src/oscd-shell.plugging.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { html } from 'lit';
import '../oscd-shell.js';
import sinon from 'sinon';
import type { OscdShell } from './oscd-shell.js';
import { flattenEditors } from './oscd-shell.js';
import {
TestBackgroundPlugin,
TestMenuPlugin1,
Expand Down Expand Up @@ -208,7 +209,7 @@ describe('OscdShell Plugin Handling', () => {
const { editor } = oscdShell.plugins;
expect(editor).to.have.lengthOf(1);
const editorPluginElement = oscdShell.shadowRoot?.querySelector(
editor[0].tagName,
flattenEditors(editor)[0].tagName,
);
expect(editorPluginElement, 'Editor Plugin Element').to.exist;
expect(editorPluginElement?.querySelector('h1')?.textContent).to.contain(
Expand Down
76 changes: 47 additions & 29 deletions src/oscd-shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { OscdFilledIconButton } from '@omicronenergy/oscd-ui/iconbutton/OscdFill
import { XMLEditor } from '@omicronenergy/oscd-editor';
import { EditEventV2, OpenEvent } from '@openscd/oscd-api';

import { loadSourcedPlugins } from './utils/plugin-utils.js';
import { loadSourcedPlugins, loadEditorPlugins } from './utils/plugin-utils.js';
import {
getLocale,
LocaleTag,
Expand Down Expand Up @@ -45,12 +45,41 @@ export type SourcedPluginEntry = {
icon: string;
requireDoc?: boolean;
};
export type PluginSet<P = PluginEntry> = {
menu: P[];
editor: P[];
background: P[];

/** A named grouping of editor plugins. Has no `src`/`tagName` — it is not itself renderable. */
export type PluginGroup = {
name: string;
translations?: Translations;
icon: string;
requireDoc?: boolean;
plugins: (PluginEntry | SourcedPluginEntry)[];
};

/** A `PluginGroup` after sourced children have been resolved to `PluginEntry` items. */
export type ResolvedPluginGroup = {
name: string;
translations?: Translations;
icon: string;
requireDoc?: boolean;
plugins: PluginEntry[];
};

/** A flat editor plugin or a resolved plugin group. */
export type EditorPluginEntry = PluginEntry | ResolvedPluginGroup;

export type PluginSet = {
menu: PluginEntry[];
editor: EditorPluginEntry[];
background: PluginEntry[];
};

/** Flattens groups so callers can work with a simple indexed list of leaf plugins. */
export function flattenEditors(editors: EditorPluginEntry[]): PluginEntry[] {
return editors.flatMap(e =>
'plugins' in e ? (e as ResolvedPluginGroup).plugins : [e as PluginEntry],
);
}

@localized()
@customElement('oscd-shell')
export class OscdShell extends ScopedElementsMixin(LitElement) {
Expand Down Expand Up @@ -117,16 +146,17 @@ export class OscdShell extends ScopedElementsMixin(LitElement) {
}

set plugins(
plugins: Partial<PluginSet<Partial<PluginEntry | SourcedPluginEntry>>>,
plugins: Partial<{
menu: Partial<PluginEntry | SourcedPluginEntry>[];
editor: (Partial<PluginEntry | SourcedPluginEntry> | PluginGroup)[];
background: Partial<PluginEntry | SourcedPluginEntry>[];
}>,
) {
this._plugins = Object.entries(plugins).reduce(
(acc, [pluginType, kind]) => {
const convertedPlugins = loadSourcedPlugins(kind, this.registry!);
acc[pluginType as keyof PluginSet] = convertedPlugins;
return acc;
},
{ menu: [], editor: [], background: [] } as PluginSet,
);
this._plugins = {
menu: loadSourcedPlugins(plugins.menu ?? [], this.registry!),
editor: loadEditorPlugins(plugins.editor ?? [], this.registry!),
background: loadSourcedPlugins(plugins.background ?? [], this.registry!),
};
}

/*
Expand All @@ -144,7 +174,7 @@ export class OscdShell extends ScopedElementsMixin(LitElement) {

@state()
get editor() {
return this.plugins.editor[this.editorIndex]?.tagName ?? '';
return flattenEditors(this.plugins.editor)[this.editorIndex]?.tagName ?? '';
}

@state()
Expand Down Expand Up @@ -519,26 +549,14 @@ export class OscdShell extends ScopedElementsMixin(LitElement) {
main {
grid-area: main;
display: grid;
grid-template-columns: var(--side-panel-width) 1fr;
grid-template-columns: auto 1fr;
grid-template-areas: 'sidebar editor';
overflow: hidden;
}

/* Side panel collapsed state */
main.sidebar-collapsed {
grid-template-columns: 0 1fr;
}

section.editors-side-panel-section {
grid-area: sidebar;
overflow-y: auto;
overflow-x: hidden;
transition: transform 0.3s ease-in-out;
}

/* Hide side panel when collapsed */
main.sidebar-collapsed section.editors-side-panel-section {
transform: translateX(-100%);
overflow: hidden;
}

section.editor-container {
Expand Down
Loading