-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6d2177a
commit dbf5584
Showing
173 changed files
with
3,408 additions
and
1,097 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,297 @@ | ||
# API THINKTANK: | ||
|
||
## GIVEN | ||
|
||
layout.addPart(id: string, relativeTo: ReferencePart, options?: {activate?: boolean}): WorkbenchLayout; | ||
|
||
|
||
|
||
ADDITIONAL: addPart(id: string, placeIn: PlaceInRegion, metadata: PartMetaData): WorkbenchLayout; | ||
|
||
ADDITIONAL: addPart(id: string, region: Region): WorkbenchLayout; | ||
|
||
interface RegionOptions { | ||
region: 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom' | 'bottom-left' | 'bottom-right'; | ||
} | ||
|
||
|
||
== VARIANTE 1: | ||
GIVEN: addPart(id: string, relativeTo: ReferencePart, options?: {activate?: boolean}): WorkbenchLayout; | ||
ADDITIONAL: addPart(id: string, placeIn: PlaceInRegion | PlaceInRegionBefore | PlaceInRegionAfter), metadata: PartMetaData): WorkbenchLayout; | ||
|
||
|
||
|
||
interface PlaceInRegion { // Varianten: PlaceInRegion, Region, RegionArea (Favorit kge), RegionPlacement, Placement, PlacementArea, PlacementRegion, | ||
region: 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom' | 'bottom-left' | 'bottom-right'; | ||
align?: 'start' | 'end'; // Vorerst weglassen | ||
} | ||
|
||
|
||
interface PlaceInRegionBefore { | ||
region: 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom' | 'bottom-left' | 'bottom-right'; | ||
before: string; // part id or alternative part id | ||
} | ||
|
||
|
||
interface PlaceInRegionAfter { | ||
region: 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom' | 'bottom-left' | 'bottom-right'; | ||
after: string; // part id or alternative part id | ||
} | ||
|
||
### Usage | ||
layout | ||
.addPart('bottom', {relativeTo: 'part.explorer', align: 'bottom'}) | ||
|
||
// Beispiel mit Metadaten | ||
.addPart('part.explorer', {region: 'left-top'}, {icon: 'xy', label: '%explorer', title: '%explorer'}) | ||
|
||
|
||
.addPart('part.explorer', {region: 'left-top'}, {icon: 'xy', label: '%explorer', title: '%explorer'}) | ||
|
||
|
||
|
||
.addPart('part.explorer', {region: 'left-top'}) // default at the end | ||
.addPart('part.explorer', {region: 'left-top', align: 'start'}) | ||
|
||
.addPart('part.navigator', {region: 'left-top', before: 'part.explorer'}) | ||
.addPart('part.navigator', {region: 'left-top', after: 'part.explorer'}) | ||
|
||
== VARIANTE 2 (analog existierens API): | ||
GIVEN: addPart(id: string, relativeTo: ReferencePart, options?: {activate?: boolean}): WorkbenchLayout; | ||
ADDITIONAL: addPart(id: string, placeIn: PlaceInRegion | PlaceInRegionRelativeTo), metadata: PartMetaData): WorkbenchLayout; | ||
|
||
interface PlaceInRegion { | ||
region: 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom' | 'bottom-left' | 'bottom-right'; | ||
align?: 'start' | 'end'; | ||
} | ||
interface PlaceInRegionRelativeTo { | ||
region: 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom' | 'bottom-left' | 'bottom-right'; | ||
relativeTo: string; | ||
align: 'before' | 'after'; | ||
} | ||
|
||
interface ReferencePart { | ||
relativeTo?: string; | ||
align: 'left' | 'right' | 'top' | 'bottom'; | ||
ratio?: number; | ||
} | ||
|
||
== VARIANTE 3 (Docking Area): | ||
|
||
### Usage | ||
layout.addPart(id: string, relativeTo: ReferencePart, options?: {activate?: boolean}): WorkbenchLayout; | ||
layout.addPart(id: string, dockTo: DockingArea, extras: PartExtras): WorkbenchLayout; | ||
|
||
layout | ||
.addPart('navigator', {relativeTo: 'other', align: 'bottom', ratio: .5}) | ||
.addPart('explorer', {dockTo: 'left-top'}, {icon: 'error', label: '%problems'}) | ||
.addPart('output', {dockTo: 'left-top'}, {icon: 'console', label: '%output'}) | ||
.addPart('output', {dockTo: 'left-top'}, {icon: 'console', label: '%title'}) | ||
.addPart('output', {dockTo: 'left-top'}, {icon: 'console', label: '%output'}) | ||
|
||
```ts | ||
interface DockingArea { | ||
dockTo: 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom' | 'bottom-left' | 'bottom-right'; | ||
} | ||
|
||
interface ReferencePart { | ||
relativeTo?: string; | ||
align: 'left' | 'right' | 'top' | 'bottom'; | ||
ratio?: number; | ||
} | ||
|
||
interface PartExtras { | ||
icon: string; | ||
label: string | `%${string}`; | ||
tooltip?: string | `%${string}`; | ||
cssClass?: string | string[]; | ||
} | ||
|
||
interface WorkbenchConfig { | ||
textProvider?: (key: string) => (() => string | Signal<string>); | ||
iconProvider?: (icon: string) => ComponentType | ComponentDescriptor; | ||
layout?: WorkbenchLayoutFn; | ||
} | ||
|
||
interface ComponentDescriptor { | ||
component: ComponentType; | ||
inputs: {[name: string]: unkown}; | ||
injector: Injector; | ||
} | ||
|
||
interface Part { | ||
title: string | ComponentType | ComponentDescriptor; | ||
} | ||
``` | ||
|
||
|
||
|
||
|
||
|
||
// Beispiel mit Metadaten | ||
.addPart('part.explorer', {region: 'left-top'}, {icon: 'xy', label: {key: 'explorer'}, title: '%explorer'}) | ||
|
||
.addPart('part.explorer', {region: 'left-top'}, {icon: 'xy', label: {value: 'explorer'}, title: {value: 'explorer'}}) | ||
|
||
.addPart('part.explorer', {region: 'left-top'}, {icon: 'xy', label: 'explorer', title: 'explorer'}) | ||
|
||
.addPart('part.explorer', {region: 'left-top'}) // default at the end | ||
.addPart('part.explorer', {region: 'left-top', align: 'start'}) | ||
|
||
.addPart('part.navigator', {region: 'left-top', relativeTo: 'part.explorer', align: 'before'}) | ||
.addPart('part.navigator', {region: 'left-top', relativeTo: 'part.explorer', align: 'after'}) | ||
|
||
|
||
.addPart('part.explorer', {region: 'left-top'}) | ||
|
||
.addPart('part.project-top', {region: 'left-top'}) | ||
.addPart('part.project-bottom', {relativeTo: 'part.project-top', align: 'bottom') | ||
|
||
|
||
.addActivity('activity.explorer', {region: 'left-top'}) | ||
|
||
.addActivity('activity.project-top', {region: 'left-top'}) | ||
.addPart('part.project-bottom', {relativeTo: 'part.project-top', align: 'bottom') | ||
|
||
|
||
# How to provide MetaData | ||
Vorschlag Metadata ins Layout: | ||
% in string | ||
```ts | ||
interface PartMetaData { | ||
icon?: string; | ||
label?: string; | ||
tooltip?: string; | ||
title?: string; | ||
} | ||
``` | ||
|
||
Explizite keys | ||
```ts | ||
interface PartMetaData { | ||
icon?: string; | ||
label?: string | {key: string}; | ||
tooltip?: string | {key: string}; | ||
title?: string | {key: string}; | ||
} | ||
``` | ||
|
||
### Variante 1 Icon/Text Provider | ||
```ts | ||
provideWorkbench({ | ||
textProvider: (key: string): string => '', | ||
iconProvider: (icon: string): Component => {}, | ||
layout: factory => factory.addPart(MAIN_AREA) | ||
}); | ||
``` | ||
|
||
### Variante 2 Icon/Text Provider (via providers) | ||
providers: [ | ||
{provide: WORKBENCH_TEXT_PROVIDER, useValue: (key: string) => }} | ||
{provide: WORKBENCH_ICON_PROVIDER, useValue: (icon: string) => }} | ||
] | ||
|
||
### Variante 3 Icon/Text Provider (via providers, new Angular way) (providerAppInitializer, provideEnvironmentProvider) | ||
provideWorkbenchTextProvider(key => ) | ||
provideWorkbenchIconProvider(key => ) | ||
|
||
### Variante 4 Icon/Text Provider (via WorkbenchService) | ||
inject(WorkbenchService).registerIconProvider((icon: string) => Component); | ||
inject(WorkbenchService).registerTextProvider((text: string) => 'text'); | ||
|
||
### Variante 5 Metadata for specific part | ||
inject(WorkbenchService).registerPartAction | ||
inject(WorkbenchService).registerPartMetadata(partId, | ||
|
||
/** | ||
* Associates metadata with a given part | ||
*/ | ||
inject(WorkbenchService).registerMetadata('part.navigator', () => ({ | ||
icon: IconComponent, | ||
label: 'text', | ||
title: 'title', | ||
tooltip: 'tooltip', | ||
}); | ||
|
||
# Model Thinktank | ||
|
||
## WorkbenchLayout | ||
|
||
```ts | ||
import {MPartGrid} from './workbench-layout.model'; | ||
|
||
interface WorkbenchLayout { | ||
workbenchGrid: MPartGrid; | ||
mainAreaGrid?: MPartGrid; | ||
activityRegions?: ActivityRegions; // Varianten: activityLayout, activityRegions, regions, regionLayout | ||
} | ||
|
||
export interface ActivityRegions { | ||
left?: { | ||
top?: ActivityRegion; | ||
bottom?: ActivityRegion; | ||
width: string; | ||
ratio?: string; | ||
} | ||
right?: { | ||
top?: ActivityRegion; | ||
bottom?: ActivityRegion; | ||
width: string; | ||
ratio?: string; | ||
} | ||
bottom?: { | ||
left?: ActivityRegion; | ||
right?: ActivityRegion; | ||
height: string; | ||
ratio?: string; | ||
} | ||
} | ||
|
||
export interface ActivityRegion { | ||
activities: Activity[]; | ||
activeActivityId?: ActivityId; | ||
} | ||
|
||
export interface Activity { | ||
id: ActivityId; | ||
element: MPart | MPartGrid; // Varianten: element, content, layout | ||
hidden?: boolean; // Needed in first iteration? | ||
} | ||
|
||
type ActivityId = `activity.${string}`; | ||
``` | ||
|
||
```ts | ||
export interface MPerspectiveLayout { | ||
referenceLayout: { | ||
workbenchGrid: string; | ||
activityRegions?: string; | ||
outlets: string; | ||
}; | ||
userLayout: { | ||
workbenchGrid: string; | ||
activityRegions?: string; | ||
outlets: string; | ||
}; | ||
} | ||
``` | ||
|
||
## REVIEW | ||
|
||
|
||
|
||
|
||
|
||
```html | ||
<wb-workbench> | ||
<activity-bar></activity-bar> | ||
<main> | ||
|
||
</main> | ||
<activity-bar></activity-bar> | ||
</wb-workbench> | ||
``` | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
## TODO Phase 1: | ||
[] Separate model layout and serializer for activity layout | ||
[] Rename workbench-layout-xy (serializer, model, version) => workbench-grid-layout | ||
[] Rename workbench-perspective -> workbench-layout | ||
[] Icon Provider | ||
[] Text Provider | ||
[x] Activate activities in initial layout? -> activatePart | ||
[x] Test pages | ||
[x] View Conflict Resolver with activity grids OR make view ids random | ||
[] Maximize (hide activities) | ||
[] Prevent view drag to edge of main grid for layouts with activities | ||
[] Icon & Tooltip | ||
[] Testing App: | ||
[] Drop Down for perspectives | ||
[] Provide 2 Perspectives with activities | ||
[x] @scion/components: Provide sash sizes as object literal instead of array | ||
[] Tests | ||
[] Documentation (JSDoc) | ||
[] HowTo | ||
|
||
|
||
## TODO Phase 2: | ||
[] Drag and Drop (including restrictions) | ||
[] Part Portal (to not lose changes when closing activity) | ||
[] Part Title (consider implementing in phase 1 if choosing microfrontend integration instead of phase 2) | ||
[] Hide Activities & menu to show activities | ||
[] Show Labels | ||
[] Minimize Part (-) | ||
[] Contribute part actions to specific activity (maybe with a context (key/value map)) | ||
[] Remove outlets of hidden activities (maybe not for minimized parts to not reload on reopen, crucial for microfrontend preformance) | ||
|
||
## TODO Phase 3: | ||
[] Merger | ||
|
||
## TO DISCUSS: | ||
|
||
## TO CONSIDER: | ||
[] Consider changing MPart class to interface | ||
[] Consider changing MNode class to interface | ||
[] Change expectView to expectView(ViewPO).toBeActive(selector), expectView(ViewPO).toBeInactive(), expectView(ViewPO).not.toBePresent() | ||
-> refactor PageNotFoundPO if changed expectView | ||
[] Remove null/undefined from WorkbenchLayoutService.layout and WorkbenchService.activePerspective | ||
Rational: not required anymore because startup blocks until layout is loaded | ||
|
||
## IDEAS: | ||
[] Activity icon in form of a component (instead ligature, SVG, or SVG Symbol) => full flexiblity | ||
[] Add `WorkbenchService.getActivity` by any part contained in the activity to set component, title and tooltip | ||
|
||
|
||
## TESTS: | ||
|
||
|
||
## BREAKING CHANGES: | ||
|
||
## THINKTANK | ||
[] How to open part in specific activity? User may have moved views to other (dynamic) part in that activity, | ||
so the initial activity part is not visible anymore (still present because structural). However, the view should | ||
then open in the currently active part of that activty. | ||
-> Variante: addView('view.id', {partId: 'project'}) | ||
Falls Project Part nicht mehr sichtbar (weil keine View mehr drin), dann automatiscsher | ||
Fallback auf active View dieses Grids. | ||
[] Part Actions: How to contribute a part action to a specific activity. (see RegisterPartActionPageComponent) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -614,5 +614,10 @@ | |
} | ||
} | ||
} | ||
}, | ||
"cli": { | ||
"cache": { | ||
"enabled": false | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.