Skip to content

Commit

Permalink
provide activity layout
Browse files Browse the repository at this point in the history
  • Loading branch information
danielwiehl committed Mar 3, 2025
1 parent 6d2177a commit dbf5584
Show file tree
Hide file tree
Showing 173 changed files with 3,408 additions and 1,097 deletions.
297 changes: 297 additions & 0 deletions THINKTANK-ACTIVITY.md
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>
```




63 changes: 63 additions & 0 deletions TODO-ACTIVITY-LAYOUT.md
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)

5 changes: 5 additions & 0 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -614,5 +614,10 @@
}
}
}
},
"cli": {
"cache": {
"enabled": false
}
}
}
5 changes: 3 additions & 2 deletions apps/workbench-client-testing-app/public/manifest-app1.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
"private": false,
"properties": {
"data": {
"label": "Microfrontend Perspective 1",
"tooltip": "Sample Microfrontend Perspective Contributed by App 1"
"label": "Sample Layout 3 - Micro App 1 (Fixed Parts)",
"menuItemLabel": "Sample Layout 3 - Micro App 1",
"menuGroup": "sample-layout-fixed-parts"
},
"layout": [
{
Expand Down
5 changes: 3 additions & 2 deletions apps/workbench-client-testing-app/public/manifest-app2.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
"private": false,
"properties": {
"data": {
"label": "Microfrontend Perspective 2",
"tooltip": "Sample Microfrontend Perspective Contributed by App 2"
"label": "Sample Layout 4 - Micro App 2 (Fixed Parts)",
"menuItemLabel": "Sample Layout 4 - Micro App 2",
"menuGroup": "sample-layout-fixed-parts"
},
"layout": [
{
Expand Down
Loading

0 comments on commit dbf5584

Please sign in to comment.