Skip to content

Commit

Permalink
feat: Added SSR support to f-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
siarheihuzarevich committed Sep 12, 2024
1 parent ba73083 commit a3d6595
Show file tree
Hide file tree
Showing 33 changed files with 240 additions and 97 deletions.
4 changes: 3 additions & 1 deletion angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"prerender": {
"routesFile": "routes.txt"
},
"outputPath": "dist/f-flow-portal",
"index": "src/index.html",
"browser": "src/main.ts",
Expand All @@ -31,7 +34,6 @@
],
"scripts": [],
"server": "src/main.server.ts",
"prerender": true,
"ssr": {
"entry": "server.ts"
}
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@
"@angular/platform-server": "^18.2.0",
"@angular/router": "^18.2.0",
"@angular/ssr": "^18.2.3",
"@foblex/core": "^1.2.3",
"@foblex/platform": "1.0.1",
"@foblex/f-docs": "^1.2.7",
"@foblex/core": "1.2.5",
"@foblex/platform": "1.0.2",
"@foblex/f-docs": "1.2.9",
"dagre": "^0.8.5",
"elkjs": "^0.9.3",
"express": "^4.18.2",
Expand Down
4 changes: 2 additions & 2 deletions projects/f-flow/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
"peerDependencies": {
"@angular/common": ">=12.0.0",
"@angular/core": ">=12.0.0",
"@foblex/core": ">=1.2.3",
"@foblex/platform": "1.0.1",
"@foblex/core": "1.2.5",
"@foblex/platform": "1.0.2",
"rxjs": ">=6.6.0"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { sanitizeElementId } from '@foblex/core';
import { Injectable } from '@angular/core';
import { CreateConnectionMarkersRequest } from './create-connection-markers-request';
import { FConnectionBase, FMarkerBase } from '../../f-connection';
import { FExecutionRegister, IExecution } from '../../infrastructure';
import { createSVGElement } from '../create-dom-element';
import { BrowserService } from '@foblex/platform';
import { sanitizeElementId } from '../sanitize-element-id';

@Injectable()
@FExecutionRegister(CreateConnectionMarkersRequest)
Expand Down
64 changes: 64 additions & 0 deletions projects/f-flow/src/domain/deep-clone-node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
export function deepCloneNode<T extends (HTMLElement | SVGElement)>(node: T): T {
const clone = node.cloneNode(true) as T;
const descendantsWithId = clone.querySelectorAll('[id]');
const nodeName = node.nodeName.toLowerCase();

clone.removeAttribute('id');

for (let i = 0; i < descendantsWithId.length; i++) {
descendantsWithId[ i ].removeAttribute('id');
}

if (nodeName === 'canvas') {
transferCanvasData(node as HTMLCanvasElement, clone as HTMLCanvasElement);
} else if (nodeName === 'input' || nodeName === 'select' || nodeName === 'textarea') {
transferInputData(node as HTMLInputElement, clone as HTMLInputElement);
}

transferData('canvas', node, clone, transferCanvasData);
transferData('input, textarea, select', node, clone, transferInputData);
return clone;
}

function transferData<T extends Element>(
selector: string,
node: HTMLElement | SVGElement,
clone: HTMLElement | SVGElement,
callback: (source: T, clone: T) => void,
) {
const descendantElements = node.querySelectorAll<T>(selector);

if (descendantElements.length) {
const cloneElements = clone.querySelectorAll<T>(selector);

for (let i = 0; i < descendantElements.length; i++) {
callback(descendantElements[ i ], cloneElements[ i ]);
}
}
}

let cloneUniqueId = 0;

function transferInputData(
source: Element & { value: string },
clone: Element & { value: string; name: string; type: string },
) {
if (clone.type !== 'file') {
clone.value = source.value;
}

if (clone.type === 'radio' && clone.name) {
clone.name = `mat-clone-${ clone.name }-${ cloneUniqueId++ }`;
}
}

function transferCanvasData(source: HTMLCanvasElement, clone: HTMLCanvasElement) {
const context = clone.getContext('2d');

if (context) {
try {
context.drawImage(source, 0, 0);
} catch {
}
}
}
4 changes: 4 additions & 0 deletions projects/f-flow/src/domain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,13 @@ export * from './cast-to-enum';

export * from './create-dom-element';

export * from './deep-clone-node';

export * from './get-value-from-data-attr';

export * from './is-element-with-class';

export * from './sanitize-element-id';

export * from './providers';

6 changes: 6 additions & 0 deletions projects/f-flow/src/domain/sanitize-element-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function sanitizeElementId(id: string): string {
if (!id.match(/^[a-zA-Z_]/)) {
id = '_' + id;
}
return id.replace(/[^a-zA-Z0-9_\-:.]/g, '_');
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { sanitizeElementId } from '@foblex/core';
import { sanitizeElementId } from '../../domain';

export const F_CONNECTION_IDENTIFIERS = {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { sanitizeElementId } from '@foblex/core';
//import { EFMarkerType } from '../../f-marker';
import { sanitizeElementId } from '../../../domain';

export function getMarkerStartId(fConnectionId: string): string {
return sanitizeElementId(`f-connection-marker-start-${ fConnectionId }`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import { Injectable } from '@angular/core';
import { FExecutionRegister, FFlowMediator, IExecution } from '../../infrastructure';
import { SingleSelectRequest } from './single-select.request';
import { UpdateItemAndChildrenLayersRequest } from '../../domain';
import { IPointerEvent, MouseEventExtensions, PlatformService } from '@foblex/core';
import { IPointerEvent } from '@foblex/core';
import { FConnectionBase, ISelectable } from '../../f-connection';
import { FComponentsStore } from '../../f-storage';
import { FDraggableDataContext } from '../f-draggable-data-context';
import { EOperationSystem, PlatformService } from '@foblex/platform';

@Injectable()
@FExecutionRegister(SingleSelectRequest)
export class SingleSelectExecution implements IExecution<SingleSelectRequest, void> {

constructor(
private platform: PlatformService,
private fPlatform: PlatformService,
private fComponentsStore: FComponentsStore,
private fDraggableDataContext: FDraggableDataContext,
private fMediator: FFlowMediator
Expand All @@ -39,8 +40,16 @@ export class SingleSelectExecution implements IExecution<SingleSelectRequest, vo
}

private isMultiselectEnabled(event: IPointerEvent): boolean {
return MouseEventExtensions.isCommandButton(this.platform.getOS()!, event.originalEvent) ||
MouseEventExtensions.isShiftPressed(event.originalEvent);
return this.isCommandButton(this.fPlatform.getOS()!, event.originalEvent) ||
this.isShiftPressed(event.originalEvent);
}

private isShiftPressed(event: { shiftKey: boolean }): boolean {
return event.shiftKey;
}

private isCommandButton(platform: EOperationSystem, event: { metaKey: boolean, ctrlKey: boolean }): boolean {
return platform === EOperationSystem.MAC_OS ? event.metaKey : event.ctrlKey;
}

private singleSelect(item: ISelectable | undefined): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { DomElementExtensions, IPoint, IRect, Point, PointExtensions, RectExtensions } from '@foblex/core';
import { IPoint, IRect, Point, PointExtensions, RectExtensions } from '@foblex/core';
import { FExternalItemBase } from '../../f-external-item';
import { IDraggableItem } from '../../f-draggable';
import { BrowserService } from '@foblex/platform';
import { deepCloneNode } from '../../domain';

export class ExternalItemDragHandler implements IDraggableItem {

Expand All @@ -23,7 +24,7 @@ export class ExternalItemDragHandler implements IDraggableItem {

public initialize(): void {
this.onPointerDownRect = this.getExternalItemRect();
this.placeholder = DomElementExtensions.deepCloneNode(this.externalItem.hostElement);
this.placeholder = deepCloneNode(this.externalItem.hostElement);
this.placeholder.setAttribute('style', this.getStyle(Point.fromPoint(this.onPointerDownRect)));
this.fBrowser.document.body.appendChild(this.placeholder);
}
Expand Down
6 changes: 3 additions & 3 deletions projects/f-flow/src/f-flow/f-flow.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
RedrawConnectionsRequest,
SelectAllRequest, SelectRequest, SortItemLayersRequest,
} from '../domain';
import { IPoint, IRect, PlatformService } from '@foblex/core';
import { IPoint, IRect } from '@foblex/core';
import { FFlowMediator } from '../infrastructure';
import {
F_DRAGGABLE_PROVIDERS,
Expand Down Expand Up @@ -65,7 +65,7 @@ export class FFlowComponent extends FFlowBase implements OnInit, AfterContentIni
private elementReference: ElementRef<HTMLElement>,
private fComponentsStore: FComponentsStore,
private fMediator: FFlowMediator,
private fPlatform: PlatformService,
private fBrowser: BrowserService,
) {
super();
}
Expand All @@ -75,7 +75,7 @@ export class FFlowComponent extends FFlowBase implements OnInit, AfterContentIni
}

public ngAfterContentInit(): void {
if(!this.fPlatform.isBrowser) {
if(!this.fBrowser.isBrowser()) {
return;
}
this.subscription$.add(
Expand Down
7 changes: 6 additions & 1 deletion projects/f-flow/src/f-node/f-group.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from '../f-connectors';
import { FFlowMediator } from '../infrastructure';
import { EmitTransformChangesRequest } from '../domain';
import { BrowserService } from '@foblex/platform';

let uniqueId: number = 0;

Expand Down Expand Up @@ -92,7 +93,8 @@ export class FGroupDirective extends FNodeBase
private elementReference: ElementRef<HTMLElement>,
private renderer: Renderer2,
private fComponentsStore: FComponentsStore,
private fMediator: FFlowMediator
private fMediator: FFlowMediator,
private fBrowser: BrowserService
) {
super();
}
Expand All @@ -118,6 +120,9 @@ export class FGroupDirective extends FNodeBase
}

public ngAfterViewInit(): void {
if(!this.fBrowser.isBrowser()) {
return;
}
this.subscriptions$.add(
this.subscribeOnResizeChanges()
);
Expand Down
7 changes: 4 additions & 3 deletions projects/f-flow/src/f-node/f-node.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
Output,
Renderer2,
} from "@angular/core";
import { IHasHostElement, IPoint, IRect, ISize, PlatformService, PointExtensions } from '@foblex/core';
import { IHasHostElement, IPoint, IRect, ISize, PointExtensions } from '@foblex/core';
import { BrowserService } from '@foblex/platform';
import { debounceTime, merge, startWith, Subscription } from 'rxjs';
import { FResizeObserver } from './f-resize-observer';
import { FComponentsStore } from '../f-storage';
Expand Down Expand Up @@ -97,7 +98,7 @@ export class FNodeDirective extends FNodeBase implements OnInit, AfterViewInit,
private renderer: Renderer2,
private fComponentsStore: FComponentsStore,
private fMediator: FFlowMediator,
private fPlatform: PlatformService,
private fBrowser: BrowserService
) {
super();
}
Expand All @@ -123,7 +124,7 @@ export class FNodeDirective extends FNodeBase implements OnInit, AfterViewInit,
}

public ngAfterViewInit(): void {
if(!this.fPlatform.isBrowser) {
if(!this.fBrowser.isBrowser()) {
return;
}
this.subscriptions$.add(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Injectable } from '@angular/core';
import { SelectionAreaPreparationRequest } from './selection-area-preparation.request';
import { FValidatorRegister, IValidator } from '../../../infrastructure';
import { MouseEventExtensions } from '@foblex/core';
import { FDraggableDataContext } from '../../../f-draggable';

@Injectable()
Expand All @@ -15,10 +14,14 @@ export class SelectionAreaPreparationValidator implements IValidator<SelectionAr

public handle(request: SelectionAreaPreparationRequest): boolean {
return this.isDragHandlesEmpty()
&& MouseEventExtensions.isShiftPressed(request.event.originalEvent);
&& this.isShiftPressed(request.event.originalEvent);
}

private isDragHandlesEmpty(): boolean {
return !this.fDraggableDataContext.draggableItems.length;
}

private isShiftPressed(event: { shiftKey: boolean }): boolean {
return event.shiftKey;
}
}
48 changes: 24 additions & 24 deletions public/docs/en/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,30 +43,30 @@ function createEnvironment(): IDocsEnvironment {
next: 'Next Page',
},
components: [
{ tag: 'simple-flow', component: import('../../../projects/f-examples/simple-flow/simple-flow.component') },
{ tag: 'draggable-flow', component: import('../../../projects/f-examples/draggable-flow/draggable-flow.component') },
{ tag: 'connection-type', component: import('../../../projects/f-examples/connection-type/connection-type.component') },
{ tag: 'connection-behaviour', component: import('../../../projects/f-examples/connection-behaviour/connection-behaviour.component') },
{ tag: 'custom-connection-type', component: import('../../../projects/f-examples/custom-connection-type/custom-connection-type.component') },
{ tag: 'drag-to-connect', component: import('../../../projects/f-examples/drag-to-connect/drag-to-connect.component') },
{ tag: 'drag-to-reassign', component: import('../../../projects/f-examples/drag-to-reassign/drag-to-reassign.component') },
{ tag: 'connectable-side', component: import('../../../projects/f-examples/connectable-side/connectable-side.component') },
{ tag: 'connection-from-outlet', component: import('../../../projects/f-examples/connection-from-outlet/connection-from-outlet.component') },
{ tag: 'connection-markers', component: import('../../../projects/f-examples/connection-markers/connection-markers.component') },
{ tag: 'zoom-example', component: ZoomExampleComponent },
{ tag: 'background-example', component: BackgroundExampleComponent },
{ tag: 'line-alignment-example', component: LineAlignmentExampleComponent },
{ tag: 'vp-flow', component: import('../../../projects/f-pro-examples/visual-programming/components/flow/vp-flow.component') },
{ tag: 'db-management-flow', component: import('../../../projects/f-pro-examples/db-management-example/components/flow/db-management-flow.component') },
{ tag: 'minimap-basic-example', component: MinimapBasicExampleComponent },
{ tag: 'minimap-scaled-example', component: MinimapScaledExampleComponent },
{ tag: 'dagre-layout-example', component: import('../../../projects/f-examples/layout-and-behaviors/dagre-layout-example/dagre-layout-example.component') },
{ tag: 'elkjs-layout-example', component: import('../../../projects/f-examples/layout-and-behaviors/elkjs-layout-example/elkjs-layout-example.component') },
{ tag: 'node-with-connectors', component: import('../../../projects/f-examples/node-with-connectors/node-with-connectors.component') },
{ tag: 'node-with-position-example', component: import('../../../projects/f-examples/node/node-with-position-example/node-with-position-example.component') },
{ tag: 'adding-dragging-functionality-example', component: import('../../../projects/f-examples/node/adding-dragging-functionality-example/adding-dragging-functionality-example.component') },
{ tag: 'node-with-drag-handle-example', component: import('../../../projects/f-examples/node/node-with-drag-handle-example/node-with-drag-handle-example.component') },
{ tag: 'groups-simple-example', component: import('../../../projects/f-examples/group/groups-simple-example/groups-simple-example.component') },
// { tag: 'simple-flow', component: import('../../../projects/f-examples/simple-flow/simple-flow.component') },
// { tag: 'draggable-flow', component: import('../../../projects/f-examples/draggable-flow/draggable-flow.component') },
// { tag: 'connection-type', component: import('../../../projects/f-examples/connection-type/connection-type.component') },
// { tag: 'connection-behaviour', component: import('../../../projects/f-examples/connection-behaviour/connection-behaviour.component') },
// { tag: 'custom-connection-type', component: import('../../../projects/f-examples/custom-connection-type/custom-connection-type.component') },
// { tag: 'drag-to-connect', component: import('../../../projects/f-examples/drag-to-connect/drag-to-connect.component') },
// { tag: 'drag-to-reassign', component: import('../../../projects/f-examples/drag-to-reassign/drag-to-reassign.component') },
// { tag: 'connectable-side', component: import('../../../projects/f-examples/connectable-side/connectable-side.component') },
// { tag: 'connection-from-outlet', component: import('../../../projects/f-examples/connection-from-outlet/connection-from-outlet.component') },
// { tag: 'connection-markers', component: import('../../../projects/f-examples/connection-markers/connection-markers.component') },
// { tag: 'zoom-example', component: ZoomExampleComponent },
// { tag: 'background-example', component: BackgroundExampleComponent },
// { tag: 'line-alignment-example', component: LineAlignmentExampleComponent },
// { tag: 'vp-flow', component: import('../../../projects/f-pro-examples/visual-programming/components/flow/vp-flow.component') },
// { tag: 'db-management-flow', component: import('../../../projects/f-pro-examples/db-management-example/components/flow/db-management-flow.component') },
// { tag: 'minimap-basic-example', component: MinimapBasicExampleComponent },
// { tag: 'minimap-scaled-example', component: MinimapScaledExampleComponent },
// { tag: 'dagre-layout-example', component: import('../../../projects/f-examples/layout-and-behaviors/dagre-layout-example/dagre-layout-example.component') },
// { tag: 'elkjs-layout-example', component: import('../../../projects/f-examples/layout-and-behaviors/elkjs-layout-example/elkjs-layout-example.component') },
// { tag: 'node-with-connectors', component: import('../../../projects/f-examples/node-with-connectors/node-with-connectors.component') },
// { tag: 'node-with-position-example', component: import('../../../projects/f-examples/node/node-with-position-example/node-with-position-example.component') },
// { tag: 'adding-dragging-functionality-example', component: import('../../../projects/f-examples/node/adding-dragging-functionality-example/adding-dragging-functionality-example.component') },
// { tag: 'node-with-drag-handle-example', component: import('../../../projects/f-examples/node/node-with-drag-handle-example/node-with-drag-handle-example.component') },
// { tag: 'groups-simple-example', component: import('../../../projects/f-examples/group/groups-simple-example/groups-simple-example.component') },
],
socialLinks: [
{ icon: 'github', link: 'https://github.com/Foblex/f-flow' },
Expand Down
21 changes: 21 additions & 0 deletions routes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/
/docs/get-started
/docs/f-flow-component
/docs/f-canvas-component
/docs/f-node-directive
/docs/f-drag-handle-directive
/docs/f-connection-component
/docs/f-connection-for-create-component
/docs/f-connection-marker-directive
/docs/f-node-output-directive
/docs/f-node-input-directive
/docs/f-node-outlet-directive
/docs/f-draggable-directive
/docs/f-zoom-directive
/docs/f-background-component
/docs/f-line-alignment-component
/docs/f-minimap-component
/docs/dagre-layout
/docs/elkjs-layout
/docs/f-visual-programming-flow
/docs/f-db-management-flow
Loading

0 comments on commit a3d6595

Please sign in to comment.