environment.modules["demo-dashboard"].configuration.environment) as EnvironmentConfigurationSchema);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/styles/_sockets-table.scss:
--------------------------------------------------------------------------------
1 |
2 | [role="socketsTable"] {
3 | display: flex;
4 | flex-direction: row;
5 | padding: 0.5rem;
6 | background-color: rgba(83, 43, 43, .2);
7 | overflow: hidden;
8 |
9 | > * {
10 | flex: 1;
11 | }
12 |
13 | [role="consumerSocketList"] {
14 | text-align: left;
15 |
16 | }
17 |
18 | [role="producerSocketList"] {
19 | text-align: right;
20 |
21 | }
22 |
23 | [role="nodeSocket" ] {
24 | border-radius: 1rem;
25 |
26 | &:hover {
27 | background-color: rgba(255, 255, 3, .2);
28 | }
29 | }
30 |
31 | }
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/nodeflow-studio-compositor.scss:
--------------------------------------------------------------------------------
1 | @namespace svg url(http://www.w3.org/2000/svg);
2 |
3 | :host {
4 | display: block;
5 | position: absolute; // taken out of flow for under pinning
6 | width: 100%;
7 | height: 100%;
8 | }
9 |
10 | [role="canvas"] {
11 |
12 | // consider theme without distracting colors
13 | background-image: linear-gradient( rgba(12,12,12,.2), rgba(255,255,255, .2));
14 |
15 | position: absolute;
16 |
17 | top: 0;
18 | left: 0;
19 | bottom: 0;
20 | right: 0;
21 |
22 | width: inherit;
23 | height: inherit;
24 | }
25 |
26 |
27 | @import "views/styles/socket-connector-relation";
28 | @import "views/styles/node-socket";
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/serialize-model/toolbar-serialize-model.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: flex;
3 | flex: 0;
4 | align-items: flex-end;
5 |
6 |
7 | [role="newDocumentIdentifier"] {
8 | margin-bottom: 0.5rem;
9 | }
10 |
11 | [role="errorsList"] {
12 | background-color: rgba(255, 2, 2, .15);
13 | }
14 |
15 | [role="processingErrorMessage"] {
16 | padding: 0.2rem;
17 | border-radius: 0.5rem;
18 | border: 1px solid rgba(0, 0, 0, .2);
19 | background-color: rgba(255, 2, 2, .3);
20 | }
21 |
22 | [role="serializedDocumentContent"] {
23 | font-family: monospace;
24 | font-size: 10pt;
25 | height: 4rem;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/tabs-container/toolbar-tabs-container.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input, ViewContainerRef } from "@angular/core";
2 | import { FormGroup } from "@angular/forms";
3 |
4 | const resources = {};
5 |
6 | @Component({
7 | selector: 'nodeflow-toolbar-tabs-container',
8 | templateUrl: './toolbar-tabs-container.html',
9 | styleUrls: ['./toolbar-tabs-container.scss']
10 | })
11 | export class ToolbarTabsContainerComponent {
12 |
13 | @Input() nodeflow: ViewContainerRef; // loose coupling for nodeflow studio backing component
14 | @Input() toolbarForm: FormGroup; // top level form container that wraps all toolbar action items
15 |
16 | constructor() {
17 |
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/menu-overlay/nodeflow-studio-menu-overlay.html:
--------------------------------------------------------------------------------
1 | App Menu items
2 |
3 |
4 |
5 |
6 |
7 |
8 | Grid Item Menu
9 |
10 |
11 | Node/Grid Item name: ........
12 |
13 |
14 |
15 |
16 | Node Connector Menu
17 |
18 |
19 | node path info: ........
20 |
21 |
22 |
23 |
24 | Socket Menu
25 |
26 |
27 | socket info: ...
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/tabs-container/toolbar-tabs-container.scss:
--------------------------------------------------------------------------------
1 |
2 | :host {
3 | display: flex;
4 | overflow-x: auto;
5 | $separator-color: rgba(44,44,66,.1);
6 | // $separator-color: rgba(255,255,255,.9);
7 | $separator-width: 4px;
8 |
9 | > * {
10 | border-right: $separator-width solid $separator-color;
11 | margin-right: 0.2rem;
12 | transition: background-color .2s;
13 | background-color: $separator-color;
14 |
15 | &:hover {
16 | background-color: transparentize($separator-color, .15);
17 | transition: background-color .2s;
18 | }
19 |
20 | &:last-child {
21 | border-right: 0;
22 | margin-right: 0;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/state/model/relation/delivery-message.model.ts:
--------------------------------------------------------------------------------
1 | import { MessageModelState } from "../message.model";
2 |
3 | export enum DeliveryMessageChangeType {
4 | initialize = 1, // assign first time state ( which could be new or retrieved from serialized form)
5 | update, // all state changes are considered updates
6 | delete, // message model terminates and shuts down
7 | restore, // re-initialize state, used when a new connector joins and existing route relation group. Message cannot be called with initialize twice
8 | }
9 |
10 | // packaging for a message with delivery capability
11 | export class DeliveryMessage {
12 |
13 | constructor(public payload: MessageModelState, public type: DeliveryMessageChangeType) {
14 |
15 | }
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // The file contents for the current environment will overwrite these during build.
2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do
3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead.
4 | // The list of which env maps to which file can be found in `.angular-cli.json`.
5 | import * as DemoDashboardMetadataConfiguration from "../../config/deployments/development/environment.json";
6 |
7 | export const environment = {
8 | production: false,
9 | modules: {
10 | // initial paths relevant watch mode
11 | "demo-dashboard": {
12 | configuration: {
13 | environment: DemoDashboardMetadataConfiguration.default
14 | }
15 |
16 | }
17 |
18 | }
19 |
20 | };
21 |
22 |
--------------------------------------------------------------------------------
/src/app/home/home.component.html:
--------------------------------------------------------------------------------
1 |
2 | Schematics and Overview of high level modules used to assemble this demonstration portion of the dashboard widget
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Client Demo Configuration and Components modules Map. Structural relationships between client-side (Demo) and public (Angular / dashboard engine ) APIs
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Sample and designs
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample1/views/card-templates/components/demo-client-metrics-billboard/demo-client-metrics-billboard-template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/nodeflow-studio-overlay-template.interface.ts:
--------------------------------------------------------------------------------
1 | import { TemplateRef } from "@angular/core";
2 |
3 | // reassign template
4 | export interface ContentProjectionProxyCommand {
5 | clientContext?: any; // preserve state at the time of invocation
6 |
7 | onLayout(): void;
8 |
9 | close(): boolean;
10 | }
11 |
12 | export type ContentProjectionProxyReplacerType = (outletTemplateRefName: string, contentTemplate: TemplateRef, templateBoundContext: object, replacementPropertiesMap: object) => ContentProjectionProxyCommand;
13 |
14 |
15 | export interface OverlayViewProjectable {
16 |
17 | proxyCommand: ContentProjectionProxyCommand | undefined;
18 |
19 | show(...args: Array): boolean;
20 |
21 | hide(...args: Array): boolean;
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/add-nodeflow/pipes/asset-type-order-by.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from "@angular/core";
2 | import { AssetTypeConfigurationSchema } from "../../../../client/organizers/nodeflow/views/card-assembly-plugins/asset-node/nodeflow-asset-node.model";
3 |
4 | // organizes list
5 | @Pipe({
6 | name: "assetTypeOrderBy"
7 | })
8 | export class AssetTypeOrderByPipe implements PipeTransform {
9 | transform(items: Array): Array {
10 |
11 | return items.sort((a: AssetTypeConfigurationSchema, b: AssetTypeConfigurationSchema) =>
12 | a.localization.name.text < b.localization.name.text
13 | ? -1
14 | : a.localization.name.text === b.localization.name.text ? 0 : 1);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/serialize-model/toolbar-serialize-model.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { ReactiveFormsModule } from "@angular/forms";
4 | import { ToolbarSerializeModelAgentService } from "./toolbar-serialize-model-agent.service";
5 | import { ToolbarSerializeModelComponent } from "./toolbar-serialize-model.component";
6 |
7 | @NgModule({
8 | imports: [
9 | CommonModule,
10 | ReactiveFormsModule
11 | ],
12 |
13 | providers: [
14 | ToolbarSerializeModelAgentService
15 | ],
16 |
17 | declarations: [
18 | ToolbarSerializeModelComponent,
19 | ],
20 |
21 | exports: [
22 | ToolbarSerializeModelComponent
23 | ]
24 | })
25 | export class ToolbarSerializeModelModule {
26 | }
27 |
--------------------------------------------------------------------------------
/src/app/home/home.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {async, ComponentFixture, TestBed} from '@angular/core/testing';
2 |
3 | import {HomeComponent} from './home.component';
4 | import {ClrTabsModule} from "@clr/angular";
5 |
6 | describe('HomeComponent', () => {
7 | let component: HomeComponent;
8 | let fixture: ComponentFixture;
9 |
10 | beforeEach(async(() => {
11 | TestBed.configureTestingModule({
12 | imports: [
13 | ClrTabsModule
14 | ],
15 |
16 | declarations: [HomeComponent]
17 | })
18 | .compileComponents();
19 | }));
20 |
21 | beforeEach(() => {
22 | fixture = TestBed.createComponent(HomeComponent);
23 | component = fixture.componentInstance;
24 | fixture.detectChanges();
25 | });
26 |
27 | it('should create', () => {
28 | expect(component).toBeTruthy();
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/standard/organizer/standard-dashboard-organizer-package.class.ts:
--------------------------------------------------------------------------------
1 | import { getEnumeratedKeyString } from "ngx-card-deck";
2 |
3 | export enum StandardDashboardOrganizerPackageEnumeration {
4 | // CLONE from engine `OrganizerPackageEnumerationBase`
5 | // internal,
6 |
7 | // enhanced projects to showcase the power of the dashboard engine
8 |
9 | // represents the APIs and services to render a node flow based rendering toolkit
10 | nodeflow = 1000
11 | }
12 |
13 |
14 | // string-based enumeration key resolution
15 | export function getOrganizerPackageKey(enumeration: StandardDashboardOrganizerPackageEnumeration): string {
16 | return (getEnumeratedKeyString
17 | (StandardDashboardOrganizerPackageEnumeration, enumeration));
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /target
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | /node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | *.launch
16 | .settings/
17 | *.sublime-workspace
18 |
19 | # IDE - VSCode
20 | .vscode/*
21 | !.vscode/settings.json
22 | !.vscode/tasks.json
23 | !.vscode/launch.json
24 | !.vscode/extensions.json
25 |
26 | # library
27 | /src/app/modules/dashboard/.ng-pkg-build/*
28 | /src/app/modules/dashboard/dist.tgz
29 | /src/app/modules/dashboard/dist
30 |
31 | # misc
32 | /.sass-cache
33 | /connect.lock
34 | /coverage
35 | /libpeerconnection.log
36 | npm-debug.log
37 | yarn-error.log
38 | testem.log
39 | /typings
40 |
41 | # e2e
42 | /e2e/*.js
43 | /e2e/*.map
44 |
45 | # System Files
46 | .DS_Store
47 | Thumbs.db
48 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/pipes/nodeflow-socket-connector-type.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from "@angular/core";
2 | import { SocketModel } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/socket.model";
3 | import { NodeLinkModel } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/node.model";
4 |
5 | // organizes sockets consistently by a deterministic ordering business rule, separating disabled ports to the end
6 | @Pipe({
7 | name: "orderedSocketList"
8 | })
9 | export class NodeflowSocketConnectorTypePipe implements PipeTransform {
10 | transform(items: Set): Array {
11 | // same ordering as the socket renderings
12 | return NodeLinkModel.sortCollection(items);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample2/plugins/deck1/cards/remote-plugin2/view/embed.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Loading Video preferences...
16 |
17 |
18 |
19 |
20 |
23 |
24 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/standard/card-outlet/standard-dashboard-vendor-classification.class.ts:
--------------------------------------------------------------------------------
1 | import { StandardDashboardOrganizerPackageEnumeration } from "../organizer/standard-dashboard-organizer-package.class";
2 | import { StandardDashboardVendorClassificationMap } from "./standard-dashboard-card-outlet-render-definitions.interface";
3 |
4 | // used in template mappings
5 | export const standardDashboardVendorClassificationMap: StandardDashboardVendorClassificationMap = {
6 |
7 | // Journal 2 represents the second dashboard view created under the vendor
8 | 'nodeflow_sample': {
9 | organizerPackage: StandardDashboardOrganizerPackageEnumeration.nodeflow,
10 | organization: 'nodeflow_sample', // per card metadata "templates > body > organization"
11 | description: 'Node flow sample group 1'
12 | }
13 |
14 | };
15 |
16 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/metadata/projects/project1/catalog.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "project1-catalog",
3 | "label": "Sample Team's Catalog - Project 1",
4 | "resources": [
5 | {
6 | "id": "deck3",
7 | "label": "Simple nodeflow",
8 | "sourceFile": "deck3.json",
9 | "encodingType": "card",
10 | "interaction": {
11 | "selected": false
12 | }
13 | },
14 | {
15 | "id": "deck4",
16 | "label": "Advanced nodeflow",
17 | "sourceFile": "deck4.json",
18 | "encodingType": "card",
19 | "interaction": {
20 | "selected": false
21 | }
22 | }
23 | ],
24 | "references": {
25 | "projectItemId": "generic-nodeflow-project-1"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/remove-nodeflow/toolbar-remove-nodeflow.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { ReactiveFormsModule } from "@angular/forms";
4 | import { ToolbarRemoveNodeflowComponent } from "./toolbar-remove-nodeflow.component";
5 | import { ToolbarRemoveNodeflowAgentService } from "./toolbar-remove-nodeflow-agent.service";
6 |
7 | @NgModule({
8 |
9 | imports: [
10 | CommonModule,
11 | ReactiveFormsModule
12 | ],
13 |
14 | providers: [
15 | ToolbarRemoveNodeflowAgentService
16 | ],
17 |
18 | declarations: [
19 | ToolbarRemoveNodeflowComponent
20 | ],
21 |
22 |
23 | exports: [
24 | ToolbarRemoveNodeflowComponent
25 | ]
26 |
27 |
28 | })
29 | export class ToolbarRemoveNodeflowModule {
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/styles/_arrow.scss:
--------------------------------------------------------------------------------
1 | $arrow-default-foreground-color: #fff;
2 |
3 | [role="segmentConnectorArrowVectorGroup"] {
4 |
5 | // centroid directional vector tangential to edge
6 | .segmentConnectorArrow {
7 | fill: $arrow-default-foreground-color;
8 | stroke: $connector-outline-stroke-color; // inherit
9 |
10 | // too hard for visualizing
11 | .smallZoomLevel & {
12 | display: none;
13 | }
14 | }
15 |
16 | [role="segmentConnectorPathGroup"] & {
17 |
18 | &:hover {
19 | // *** warning: pipe has NO white surrounding it
20 | > svg|polygon:last-of-type {
21 | fill: gold;
22 | cursor: pointer;
23 | stroke-width: 2px;
24 | }
25 | }
26 | }
27 |
28 | }
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/add-nodeflow/pipes/find-nodeflow-card-project-package.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from "@angular/core";
2 | import { NodeflowCardProjectPackageSchema } from "../../../../client/organizers/nodeflow/metadata/schema/nodeflow-card-project.interface";
3 |
4 |
5 | // filters the catalogs that would server the current dashboard configuration. should be exactly one match
6 | @Pipe({
7 | name: "findNodeflowCardProjectPackage"
8 | })
9 | export class FindNodeflowCardProjectPackagePipe implements PipeTransform {
10 | transform(
11 | items: Array,
12 | id: string
13 | ): NodeflowCardProjectPackageSchema | undefined {
14 |
15 | return (id
16 | ? items.filter((projectPackage) => projectPackage.project.item.id === id)[0]
17 | : undefined);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/serialize-model/toolbar-serialize-model.model.ts:
--------------------------------------------------------------------------------
1 | export enum ToolbarSerializedDocumentEntityPackagingType {
2 | nativeDashboardResourceJson = 1,
3 | nodeflowConfigurationSchemaJson = 2
4 | }
5 |
6 | export class ToolbarSerializedDocumentContent {
7 | documentType: string;
8 |
9 | //var typedArray = new Uint8Array([1, 2, 3, 4]),
10 | //normalArray = Array.prototype.slice.call(typedArray);
11 | content: string; // internal doc payload
12 | }
13 |
14 | export class ToolbarSerializedDocumentEntityReference {
15 | documentId: string; // global ID to reference the document from a CMS
16 | filename: string;
17 | packagingFormatType: ToolbarSerializedDocumentEntityPackagingType;
18 | createdDate: Date;
19 |
20 | // loaded contents
21 | document?: ToolbarSerializedDocumentContent;
22 | }
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample2/plugins/deck1/cards/remote-plugin1/view/styles/page.css:
--------------------------------------------------------------------------------
1 |
2 | html {
3 | font-family: Arial, Helvetica, serif;
4 | }
5 |
6 | body {
7 | padding: 3px;
8 | margin: 0;
9 | }
10 |
11 | h5 {
12 | font-size: 14pt;
13 | text-align:center;
14 | }
15 |
16 | #chartApplication {
17 |
18 | }
19 |
20 | /* ------- themes ---------- */
21 |
22 | /* ------- light theme ---------- */
23 | html.light body {
24 | color: #333;
25 | background-color: transparent;
26 | }
27 |
28 | html.light h5 {
29 | color: #225;
30 | }
31 |
32 | html.light #chartApplication {
33 |
34 | }
35 |
36 |
37 | /* ------- dark theme ---------- */
38 | html.dark body {
39 | color: #cccccc;
40 | background-color: #333;
41 | }
42 |
43 | html.dark h5 {
44 | color: #ff3;
45 | }
46 |
47 | html.dark #chartApplication {
48 | background-color: #666;
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/core/com.company.group/views/card-assembly-plugins/metrics-billboard/directives/progress-meter.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, AfterViewInit, AfterContentInit, ElementRef } from "@angular/core";
2 |
3 | @Directive({
4 | // tslint:disable-next-line:directive-selector
5 | selector: '[progressMeter]'
6 | })
7 | export class ProgressMeterDirective implements AfterViewInit, AfterContentInit {
8 |
9 | constructor(private element: ElementRef) {
10 | // IE11 safety, upon deprecation, combine lines
11 | this.element.nativeElement.classList.add("progress-meter");
12 | this.element.nativeElement.classList.add("render");
13 |
14 | }
15 |
16 | ngAfterViewInit() {
17 |
18 |
19 | }
20 |
21 | ngAfterContentInit() {
22 |
23 | // setTimeout( ()=> { this.element.nativeElement.classList.add("start"); }, 1* 1000);
24 |
25 | }
26 |
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample1/views/card-templates/components/demo-client-grid-card/demo-client-grid-card-template.scss:
--------------------------------------------------------------------------------
1 | @import "~ngx-card-deck/styles/theme";
2 |
3 | ::ng-deep {
4 |
5 | CLR-DATAGRID {
6 | > .datagrid > .datagrid-table-wrapper > [role="grid"] {
7 |
8 |
9 | > [role="rowgroup"] > [role="row"] [role="gridcell"] {
10 |
11 | @import "styles/bar-graph";
12 | @import "styles/inventory-summary-grid-column";
13 |
14 | }
15 |
16 | }
17 | }
18 | }
19 |
20 | // header icon
21 | @include selectCardLayoutAspectByComponentType("*", "card-datagrid", "header") {
22 | ::ng-deep I.headerIcon {
23 | background-size: cover;
24 |
25 | &.datastore {
26 | background-image: url("//cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/svgs/fi-skull.svg");
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/app-navigation-links.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": [
3 | {
4 | "label": "Grid",
5 | "links": [
6 | {"path": ["/dashboard/dashboard-page/com_company_sample2/deck1"], "label": "Deck 1", "subtitle": "Advanced + Lazy Load"},
7 | {"path": ["/dashboard/dashboard-page/com_company_sample2/deck2"], "label": "Deck 2", "subtitle": "1-card deck"},
8 | {"path": ["/dashboard/dashboard-page/com_company_sample3/deck3"], "label": "Deck 3", "subtitle": "Simple configuration"}
9 | ]
10 | },
11 | {
12 | "label": "Nodeflow",
13 | "links": [
14 | {"path": ["/dashboard/dashboard-page/nodeflow/deck3"], "label": "Graph 3", "subtitle": "4-node diagram"},
15 | {"path": ["/dashboard/dashboard-page/nodeflow/deck4"], "label": "Graph 4", "subtitle" : "7-node diagram"}
16 | ]
17 | }
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample3/plugins/deck3/cards/my-simple-embed/view/styles/page.css:
--------------------------------------------------------------------------------
1 |
2 | html {
3 | font-family: Arial, Helvetica, serif;
4 | }
5 |
6 | body {
7 | padding: 3px;
8 | margin: 0;
9 | }
10 |
11 | h5 {
12 | font-size: 12pt;
13 | font-weight:normal;
14 | text-align:center;
15 | margin:0;
16 | }
17 |
18 | #chartApplication {
19 |
20 | }
21 |
22 | /* ------- themes ---------- */
23 |
24 | /* ------- light theme ---------- */
25 | html.light body {
26 | color: #333;
27 | background-color: transparent;
28 | }
29 |
30 | html.light h5 {
31 | color: #225;
32 | }
33 |
34 | html.light #chartApplication {
35 |
36 | }
37 |
38 |
39 | /* ------- dark theme ---------- */
40 | html.dark body {
41 | color: #cccccc;
42 | background-color: #333;
43 | }
44 |
45 | html.dark h5 {
46 | color: #ff3;
47 | }
48 |
49 | html.dark #chartApplication {
50 | background-color: #666;
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./src",
5 | "outDir": "./dist/out-tsc",
6 | "allowSyntheticDefaultImports": true,
7 | "noImplicitReturns": true,
8 | "suppressImplicitAnyIndexErrors": true,
9 | "downlevelIteration": true,
10 | "importHelpers": true,
11 | "strict": true,
12 | "skipLibCheck": true,
13 | "stripInternal": true,
14 | "sourceMap": true,
15 | "declaration": false,
16 | "moduleResolution": "node",
17 | "emitDecoratorMetadata": true,
18 | "experimentalDecorators": true,
19 | "strictPropertyInitialization": false,
20 | "target": "es2017",
21 | "typeRoots": [
22 | "node_modules/@types"
23 | ],
24 | "lib": [
25 | "es2017",
26 | "dom"
27 | ],
28 | "paths": {
29 | "@ssue-ui/dashboard/*": [
30 | "./zzzapp/modules/dashboard/*"
31 | ]
32 | },
33 | "module": "es2015"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/add-nodeflow/pipes/find-card-catalog-resources-package.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from "@angular/core";
2 | import { CardCatalogResourcesPackage } from "../../../../client/organizers/nodeflow/metadata/schema/card-catalog-resources.interface";
3 |
4 |
5 | // filters the catalogs that would server the current dashboard configuration. should be exactly one match
6 | @Pipe({
7 | name: "findCardCatalogResourcesPackage"
8 | })
9 | export class FindCardCatalogResourcesPackagePipe implements PipeTransform {
10 | transform(
11 | items: Array,
12 | id: string
13 | ): CardCatalogResourcesPackage | undefined {
14 |
15 | return (id
16 | ? items.filter((cardCatalogConfig) => cardCatalogConfig.resources
17 | .filter((cardCatalogResourceItem) => cardCatalogResourceItem.id === id))[0]
18 | : undefined);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/demo-dashboard.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {async, ComponentFixture, TestBed} from '@angular/core/testing';
2 |
3 | import {DemoDashboardComponent} from './demo-dashboard.component';
4 | import {RouterTestingModule} from '@angular/router/testing';
5 |
6 | describe('DemoDashboardComponent', () => {
7 | let component: DemoDashboardComponent;
8 | let fixture: ComponentFixture;
9 |
10 | beforeEach(async(() => {
11 | TestBed.configureTestingModule({
12 | imports: [
13 | RouterTestingModule
14 | ],
15 | declarations: [DemoDashboardComponent]
16 | })
17 | .compileComponents();
18 | }));
19 |
20 | beforeEach(() => {
21 | fixture = TestBed.createComponent(DemoDashboardComponent);
22 | component = fixture.componentInstance;
23 | fixture.detectChanges();
24 | });
25 |
26 | it('should create place holder', () => {
27 | expect(component).toBeTruthy();
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/add-nodeflow/pipes/limit-message-by-socket.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from "@angular/core";
2 | import { NodeflowProjectCardMessageModelSchema } from "../../../../client/organizers/nodeflow/metadata/schema/nodeflow-card-project.interface";
3 | import { SocketModel } from "../../../../../studio/nodeflow-studio-compositor/state/model/socket.model";
4 |
5 | // filters the message possibilities if a socket is selected - they have to match
6 | @Pipe({
7 | name: "limitMessageBySocket"
8 | })
9 | export class LimitMessageBySocketPipe implements PipeTransform {
10 | transform(
11 | items: Array,
12 | constrainingSocket: SocketModel): Array {
13 |
14 | return constrainingSocket
15 | ? items.filter((cardMessageTemplate) => cardMessageTemplate.topic === constrainingSocket.topic)
16 | : items;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample3/lib/views/card-templates/modules/com_company_sample3_template.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from "@angular/common";
2 | import { NgModule } from "@angular/core";
3 | import { ClrDatepickerModule, ClrIconModule, ClrTabsModule } from "@clr/angular";
4 | import { SimpleIntroductionTemplateComponent } from "../components/simple-introduction/simple-introduction-template.component";
5 |
6 | // statically discoverable module block
7 | @NgModule({
8 | imports: [
9 | CommonModule,
10 | ClrIconModule,
11 | ClrDatepickerModule,
12 | ClrTabsModule,
13 | ],
14 | // compiler needs
15 | declarations: [
16 | SimpleIntroductionTemplateComponent
17 | ],
18 |
19 | // dynamic injection
20 | entryComponents: [
21 | SimpleIntroductionTemplateComponent
22 | ],
23 |
24 | providers: []
25 |
26 | })
27 | export class ComCompanySample3TemplateModule {
28 | }
29 |
30 |
31 |
--------------------------------------------------------------------------------
/e2e/demo-dashboard.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { DemoDashboardPage } from './demo-dashboard.po';
2 |
3 | describe('dashboard demo page', () => {
4 | let page: DemoDashboardPage;
5 |
6 | beforeEach(() => {
7 | page = new DemoDashboardPage();
8 | page.navigateTo();
9 | });
10 |
11 | it('verify 7-card layout with sample titles on deck', async () => {
12 |
13 | expect(await page.getCardCount()).toEqual(7);
14 |
15 | const expectedTitleList: Array = [
16 | 'Frozen Landscapes',
17 | 'Consumer Insights',
18 | 'Hardware Health Insights',
19 | 'Remote ~ Plugin 1',
20 | 'Remote ~ Video Streams Plugin 2',
21 | 'Remote ~ Banking Agent Plugin 3',
22 | 'Satellite Weather'
23 | ];
24 |
25 | expect((await page.getCardTitleTextList()).sort()).toEqual(expectedTitleList.sort());
26 | expect((await page.getCardTitleTextList()).sort()).not.toContain("garbage title"); // negative
27 |
28 | });
29 |
30 | });
31 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample1/views/card-templates/components/demo-client-metrics-billboard/demo-client-metrics-billboard-template.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from "@angular/core";
2 | import { CommonModule } from "@angular/common";
3 | import { ProgressMeterDirective } from "../../../../../../core/com.company.group/views/card-assembly-plugins/metrics-billboard/directives/progress-meter.directive";
4 | import { DemoClientMetricsBillboardTemplateComponent } from "./demo-client-metrics-billboard-template.component";
5 |
6 | @NgModule({
7 | imports: [
8 | CommonModule
9 | ],
10 | // compiler needs
11 | declarations: [
12 | ProgressMeterDirective,
13 | DemoClientMetricsBillboardTemplateComponent
14 | ],
15 |
16 | // dynamic injection
17 | entryComponents: [
18 | DemoClientMetricsBillboardTemplateComponent
19 | ],
20 |
21 | providers: []
22 |
23 | })
24 | export class DemoClientMetricsBillboardTemplateModule {
25 | }
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/remove-socket-connector-relation/socket-connector-relation-model-state-filter.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from "@angular/core";
2 | import {
3 | SocketConnectorRelationModel,
4 | SocketConnectorRelationStateType
5 | } from "../../../../studio/nodeflow-studio-compositor/state/model/relation/socket-connector-relation.model";
6 |
7 |
8 | // restricts possible connectors by connector link state
9 | @Pipe({
10 | name: "socketConnectorRelationStateFilter"
11 | })
12 | export class SocketConnectorRelationModelStateFilterPipe implements PipeTransform {
13 | transform(items: Array, stateType: SocketConnectorRelationStateType | null): Array {
14 | if (Array.isArray(items)) {
15 | return items.filter((scr) => stateType !== null ? scr.state === stateType : true);
16 |
17 | } else {
18 | return items; // leave as is
19 | }
20 |
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/add-nodeflow/toolbar-add-nodeflow.interface.ts:
--------------------------------------------------------------------------------
1 | import { SocketModel } from "../../../../studio/nodeflow-studio-compositor/state/model/socket.model";
2 | import { NodeflowProjectCardMessageModelSchema } from "../../../client/organizers/nodeflow/metadata/schema/nodeflow-card-project.interface";
3 | import { SocketConnectorRelationStateType } from "../../../../studio/nodeflow-studio-compositor/state/model/relation/socket-connector-relation.model";
4 |
5 | // common relation for each socket-message definition rule
6 | export interface SocketRelationFormModel {
7 | socket: SocketModel | null;
8 | message: NodeflowProjectCardMessageModelSchema | null;
9 | isMessageStateSynchronized: boolean; // upon nodeflow creation, last known message state is synchronized on both ends
10 | isSocketLinked: boolean;
11 | isSocketMulticast: boolean;
12 | linkStateType: SocketConnectorRelationStateType; // new socket connector relation link assumes a state
13 | }
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/metadata/schema/card-project.interface.ts:
--------------------------------------------------------------------------------
1 | export interface CardProjectPackageSchematicInteractable {
2 | // selected within a list?
3 | selected: boolean;
4 | }
5 |
6 | export interface CardProjectPackageSchematicIdentifiable {
7 | id: string;
8 | label: string;
9 | interaction: CardProjectPackageSchematicInteractable;
10 | }
11 |
12 | export interface CardProjectPackageSchematicTemplatable extends CardProjectPackageSchematicIdentifiable {
13 | data: {
14 | [identifier: string]: {
15 | organization: string;
16 | template: string;
17 | }
18 | };
19 | }
20 |
21 | // the decorative schema for the overview of a project. UI to ingest and use for promoting constraints
22 | // contents of `project.json`
23 | export interface CardProjectPackage {
24 | project: {
25 | item: CardProjectPackageSchematicIdentifiable;
26 | organization: CardProjectPackageSchematicIdentifiable;
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/e2e/demo-dashboard.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from "protractor";
2 | import { promise } from "selenium-webdriver";
3 |
4 | const resources = {
5 | mainComponentSelector: "ngx-card-deck",
6 | route: {
7 | test: "#/dashboard/dashboard-page/com_company_sample2/deck1"
8 | }
9 | };
10 |
11 | export class DemoDashboardPage {
12 | navigateTo() {
13 | return browser.get(resources.route.test);
14 | }
15 |
16 | getHeaderText(): promise.Promise {
17 | return element(by.css(resources.mainComponentSelector + " section[role='headerLayout'] > SPAN")).getText();
18 | }
19 |
20 | getCardTitleTextList(): promise.Promise> {
21 | return element.all(by.css(resources.mainComponentSelector + " dash-card-outlet > article > header > [role='tab']")).getText() as any as promise.Promise>;
22 | }
23 |
24 | getCardCount(): promise.Promise {
25 | return element.all(by.css(resources.mainComponentSelector + " dash-card-outlet")).count();
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/integration/card-outlet/demo-dashboard-organizer-package.class.ts:
--------------------------------------------------------------------------------
1 | import { getEnumeratedKeyString } from "ngx-card-deck";
2 |
3 | export enum DemoDashboardOrganizerPackageEnumeration {
4 | // hardcode: must statically CLONE from engine `OrganizerPackageEnumerationBase`
5 | internal = 1,
6 |
7 | // customized
8 | com_company_acme_shared_library, // team shared framework, shared stuff
9 | com_company_sample1, // Example group 1: client is one of the "vendor" consumer of the specification
10 | com_company_sample2, // Example group 2: extension samples, how to roll a new grouping
11 | com_company_sample3 // Example group 3: show simple preprocessing
12 |
13 | }
14 |
15 |
16 | // string-based enumeration key resolution
17 | export function getOrganizerPackageKey(enumeration: DemoDashboardOrganizerPackageEnumeration): string {
18 | return getEnumeratedKeyString(DemoDashboardOrganizerPackageEnumeration, enumeration);
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/standard/card-outlet/card-assembly-plugins/base/standard-card-plugin-template-base.ts:
--------------------------------------------------------------------------------
1 | import { CardPluginTemplateBase } from "ngx-card-deck";
2 | import { StandardFieldRenderTemplate } from "../../../organizer/standard-template.interface";
3 |
4 |
5 | export abstract class StandardCardPluginTemplateBase extends CardPluginTemplateBase {
6 | // +++++++++++++++++++ implementations over base class +++++++++++++++++++++++
7 | // via metadata : only this organization can consume and deal with the templates matching owner of card's organization.
8 | // placed here for sample validation. The rules must be asserted and implemented by the team
9 | public validateRenderTemplateMetadata(metadata: StandardFieldRenderTemplate): boolean {
10 | // example rule: template organization must share common stem from the organization as class defined one
11 | return metadata && metadata.organization.indexOf(this.templateOrganization.classification.organization) === 0;
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/state/config/nodeflow-studio-compositor-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "asset": {
3 | "arrow": {
4 | "layout": {
5 | "scalable": false,
6 | "width": 15,
7 | "height": 15
8 | }
9 | },
10 | "socket": {
11 | "layout": {
12 | "size": 15,
13 | "padding": 1,
14 | "smallCondensingFactor": 2
15 | }
16 | },
17 | "connector": {
18 | "layout": {
19 | "lineProximityThreshold": 100
20 | }
21 | },
22 | "plug": {
23 | "layout": {
24 | "size": 10
25 | }
26 | }
27 | },
28 | "component": {
29 | "compositor": {
30 | "node": {
31 | },
32 | "connector": {
33 | },
34 | "socket": {
35 | "orientation": "horizontal"
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample3/lib/views/card-assembly-plugins/introduction/data/configuration.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "assetTypeId": "1",
4 | "iconDecoratorClass": "symbol1",
5 | "localization": {
6 | "name": {
7 | "text": "Message Layout"
8 | }
9 | }
10 | },
11 | {
12 | "assetTypeId": "2",
13 | "iconDecoratorClass": "symbol105",
14 | "localization": {
15 | "name": {
16 | "text": "Security Monitor"
17 | }
18 | }
19 | },
20 | {
21 | "assetTypeId": "3",
22 | "iconDecoratorClass": "symbol6",
23 | "localization": {
24 | "name": {
25 | "text": "Workflow"
26 | }
27 | }
28 | },
29 | {
30 | "assetTypeId": "4",
31 | "iconDecoratorClass": "symbol8",
32 | "localization": {
33 | "name": {
34 | "text": "Streamed Event"
35 | }
36 | }
37 | }
38 | ]
39 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample1/data-server/web-services/resources-report-summary.json:
--------------------------------------------------------------------------------
1 | {
2 | "provider": {
3 | "serverGuid": "company-resource-provider-2017-11-12",
4 | "type": "Folder",
5 | "value": "group-d1"
6 | },
7 | "summaryItems": [
8 | {
9 | "label": "summary.vmCount",
10 | "value": 83
11 | },
12 | {
13 | "label": "summary.hostCount",
14 | "value": 28
15 | }
16 | ],
17 | "resourceMeters": [
18 | {
19 | "title": "CpuResourceDataItem.CpuLabel",
20 | "free": "450 Packages",
21 | "used": "7.33 GHz",
22 | "capacity": "93.45 GHz",
23 | "progress": 7
24 | },
25 | {
26 | "title": "MemoryResourceDataItem.MemoryLabel",
27 | "free": "323 Resources",
28 | "used": "23.95 GB",
29 | "capacity": "109.77 GB",
30 | "progress": 21
31 | },
32 | {
33 | "title": "StorageResourceDataItem.StorageLabel",
34 | "free": "44 Orders",
35 | "used": "378.48 GB",
36 | "capacity": "824.08 GB",
37 | "progress": 45
38 | }
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample2/plugins/deck1/cards/local-plugin3/data/summary.json:
--------------------------------------------------------------------------------
1 | {
2 | "provider": {
3 | "serverGuid": "acme-resource-provider-2017-06-22",
4 | "type": "Folder",
5 | "value": "group-d1"
6 | },
7 | "summaryItems": [
8 | {
9 | "label": "summary.vmCount",
10 | "value": 83
11 | },
12 | {
13 | "label": "summary.hostCount",
14 | "value": 28
15 | }
16 | ],
17 | "resourceMeters": [
18 | {
19 | "title": "CpuResourceDataItem.CpuLabel",
20 | "free": "400 Packages",
21 | "used": "100 Prepared",
22 | "capacity": "300 Pending",
23 | "progress": 33
24 | },
25 | {
26 | "title": "MemoryResourceDataItem.MemoryLabel",
27 | "free": "777 Bottles",
28 | "used": "100 barrels",
29 | "capacity": "2000 liters",
30 | "progress": 25
31 | },
32 | {
33 | "title": "StorageResourceDataItem.StorageLabel",
34 | "free": "69 Nodes",
35 | "used": "19 workers",
36 | "capacity": "50 people",
37 | "progress": 28
38 | }
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample2/plugins/deck2/cards/local-plugin3/data/summary.json:
--------------------------------------------------------------------------------
1 | {
2 | "provider": {
3 | "serverGuid": "acme-resource-provider-2017-12-20",
4 | "type": "Folder",
5 | "value": "group-d1"
6 | },
7 | "summaryItems": [
8 | {
9 | "label": "summary.vmCount",
10 | "value": 83
11 | },
12 | {
13 | "label": "summary.hostCount",
14 | "value": 28
15 | }
16 | ],
17 | "resourceMeters": [
18 | {
19 | "title": "CpuResourceDataItem.CpuLabel",
20 | "free": "350 Servers",
21 | "used": "30 CPUs",
22 | "capacity": "33 stored",
23 | "progress": 7
24 | },
25 | {
26 | "title": "MemoryResourceDataItem.MemoryLabel",
27 | "free": "323 Processes",
28 | "used": "100 threads",
29 | "capacity": "50 standby",
30 | "progress": 21
31 | },
32 | {
33 | "title": "StorageResourceDataItem.StorageLabel",
34 | "free": "150 Monitors",
35 | "used": "12 showing",
36 | "capacity": "1000 reserved",
37 | "progress": 45
38 | }
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/metadata/schema/nodeflow-card-project.interface.ts:
--------------------------------------------------------------------------------
1 | import {
2 | CardProjectPackage,
3 | CardProjectPackageSchematicIdentifiable,
4 | CardProjectPackageSchematicTemplatable
5 | } from "./card-project.interface";
6 |
7 | interface NodeflowProjectCardMessageStateSchema {
8 | classifier: string;
9 | data: any; // user defined
10 | }
11 |
12 | export interface NodeflowProjectCardMessageModelSchema {
13 | topic: string;
14 | form: { component: string };
15 | state: NodeflowProjectCardMessageStateSchema;
16 | }
17 |
18 |
19 | export interface NodeflowCardProjectPackageSchema extends CardProjectPackage {
20 |
21 | schematic: {
22 |
23 | card: {
24 | components: Array;
25 | assetTypes: Array;
26 | messages: Array;
27 | templates: Array;
28 |
29 | };
30 | };
31 |
32 | }
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/state/config/nodeflow-studio-compositor-configuration.interface.ts:
--------------------------------------------------------------------------------
1 | export interface StudioCompositorConfigurationSchema {
2 |
3 | asset: {
4 | arrow: {
5 | layout: {
6 | scalable: boolean;
7 | width: number;
8 | height: number;
9 | };
10 | };
11 | socket: {
12 | layout: {
13 | size: number;
14 | padding: number;
15 | smallCondensingFactor: number;
16 | };
17 | };
18 | connector: {
19 | layout: {
20 | lineProximityThreshold: number
21 | };
22 | };
23 |
24 | plug: {
25 | layout: {
26 | size: number
27 | };
28 | };
29 | };
30 | component: {
31 | compositor: {
32 | node: {};
33 | connector: {};
34 | socket: {
35 | orientation: "horizontal" | "vertical"
36 | };
37 | };
38 | };
39 | }
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/add-socket-connector-relation/toolbar-add-socket-connector-relation.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { ReactiveFormsModule } from "@angular/forms";
4 | import { ToolbarAddSocketConnectorRelationComponent } from "./toolbar-add-socket-connector-relation.component";
5 | import { ToolbarAddSocketConnectorRelationAgentService } from "./toolbar-add-socket-connector-relation-agent.service";
6 | import { NodeModelMessageSocketCompatiblePipe } from "./node-model-message-socket-compatible.pipe";
7 |
8 | @NgModule({
9 | imports: [
10 | CommonModule,
11 | ReactiveFormsModule
12 | ],
13 |
14 | providers: [
15 | ToolbarAddSocketConnectorRelationAgentService
16 | ],
17 |
18 | declarations: [
19 | ToolbarAddSocketConnectorRelationComponent,
20 | NodeModelMessageSocketCompatiblePipe
21 | ],
22 |
23 | exports: [
24 | ToolbarAddSocketConnectorRelationComponent
25 | ]
26 | })
27 | export class ToolbarAddSocketConnectorRelationModule {
28 | }
29 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/pipes/extract-socket-connector-relation-list-by-socket.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from "@angular/core";
2 | import { MessageConnectorsRouteRelationModel } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/relation/message-connectors-route-relation.model";
3 | import { SocketConnectorRelationModel } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/relation/socket-connector-relation.model";
4 | import { SocketModel } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/socket.model";
5 |
6 | // filters the socket connectors by a socket
7 | @Pipe({
8 | name: "extractSocketConnectorRelationListBySocket"
9 | })
10 | export class ExtractSocketConnectorRelationListBySocketPipe implements PipeTransform {
11 |
12 | transform(routeRelation: MessageConnectorsRouteRelationModel, filterBySocket: SocketModel): Array {
13 | return routeRelation.getSocketConnectorRelationListBySocket(filterBySocket);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/menu-overlay/nodeflow-studio-menu-overlay.component.ts:
--------------------------------------------------------------------------------
1 | import {
2 | AfterViewInit,
3 | ChangeDetectionStrategy,
4 | ChangeDetectorRef,
5 | Component,
6 | ElementRef,
7 | NgZone,
8 | OnInit,
9 | Renderer2,
10 | ViewContainerRef
11 | } from "@angular/core";
12 |
13 |
14 | // asset definitions
15 | const resources = {};
16 |
17 | @Component({
18 | selector: 'nodeflow-studio-menu-overlay',
19 | templateUrl: './nodeflow-studio-menu-overlay.html',
20 | styleUrls: ['./nodeflow-studio-menu-overlay.scss'],
21 | changeDetection: ChangeDetectionStrategy.OnPush
22 | })
23 | export class NodeflowStudioMenuOverlayComponent implements OnInit, AfterViewInit {
24 |
25 |
26 | constructor(
27 | private element: ElementRef,
28 | private vcr: ViewContainerRef,
29 | private renderer: Renderer2,
30 | private zone: NgZone,
31 | private cdr: ChangeDetectorRef) {
32 |
33 | }
34 |
35 |
36 | ngOnInit() {
37 |
38 |
39 | }
40 |
41 | ngAfterViewInit() {
42 |
43 | }
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/extensions/forms/simulator-producer-form-view.interface.ts:
--------------------------------------------------------------------------------
1 | import { Observable } from "rxjs";
2 | import { MessageConnectorsRouteRelationModel } from "../../../../../../../../../studio/nodeflow-studio-compositor/state/model/relation/message-connectors-route-relation.model";
3 | import { MessageModel } from "../../../../../../../../../studio/nodeflow-studio-compositor/state/model/message.model";
4 | import { NodeModel } from "../../../../../../../../../studio/nodeflow-studio-compositor/state/model/node.model";
5 |
6 | export interface SimulatorProducerFormViewProviderMessageBroadcastHistory {
7 | publishedDate: Date; // when was message emitted to subscribers
8 | receivedDate: Date | null; // when was message finally received by all subscribers
9 | matchedRouteRelation: MessageConnectorsRouteRelationModel; // sent to these recipients
10 | messageRecord: MessageModel; // state of the message
11 | ownerNode: NodeModel; // origination
12 | deliveryStatus$: Observable; // delivery triggered, waiting for status
13 | }
14 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, 'coverage'), reports: ['html'],
20 | fixWebpackSourcePaths: true
21 | },
22 |
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['ChromeHeadless'],
29 | singleRun: false
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample2/plugins/deck1/cards/remote-plugin5/view/styles/page.css:
--------------------------------------------------------------------------------
1 |
2 | html, body {
3 | font-family: Arial, Helvetica, serif;
4 | margin: 0;
5 | padding: 0;
6 | width: 100vw;
7 | height: 100vh;
8 | }
9 |
10 | main {
11 | width: inherit;
12 | height: inherit;
13 | }
14 |
15 | #earth {
16 | width: 100%;
17 | height: 100%;
18 | background-size: contain;
19 | background: url("https://cdn.star.nesdis.noaa.gov/GOES16/ABI/CONUS/GEOCOLOR/625x375.jpg") no-repeat center;
20 | x-background: url("https://cdn.star.nesdis.noaa.gov/GOES16/ABI/GIFS/GOES16-CONUS-GEOCOLOR-625x375.gif") no-repeat center;
21 |
22 | border-radius: 1rem;
23 | box-sizing: border-box;
24 | border: 1px solid;
25 | }
26 |
27 |
28 | /* ------- themes ---------- */
29 |
30 | /* ------- light theme ---------- */
31 | html.light body {
32 | color: #333;
33 | }
34 |
35 | html.light #earth {
36 | border-color: #ccc;
37 | }
38 |
39 |
40 | /* ------- dark theme ---------- */
41 | html.dark body {
42 | color: #777;
43 | }
44 |
45 | html.dark #earth {
46 | border-color: #004d8a;
47 | }
48 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-assembly-plugins/asset-node/styles/_toggle-arrow.scss:
--------------------------------------------------------------------------------
1 | @mixin toggleArrowIcon() {
2 |
3 | // header toolbar icon to expand/shrink vertically
4 | $icon-dimension: 0.7rem;
5 | width: $icon-dimension;
6 | height: $icon-dimension;
7 | border-radius: 1rem;
8 | user-select: none;
9 | border: 1px solid rgba(1, 1, 1, .2);
10 | opacity: 0.8;
11 |
12 | &:hover {
13 | opacity: 1;
14 | cursor: pointer;
15 | }
16 |
17 | &::before {
18 | position: absolute;
19 | display: inline-block;
20 | font-size: $icon-dimension;
21 | line-height: $icon-dimension;
22 | color: rgba(0, 0, 0, .5);
23 | }
24 |
25 | &[data-minimized="true"] {
26 | background-color: lighten(#f55, 10%);
27 | // small
28 | &::before {
29 | content: "\25bc";
30 | }
31 | }
32 | &[data-minimized="false"] {
33 | // normal
34 | background-color: lighten(#919fab, 10%);
35 |
36 | &::before {
37 | content: "\25b2";
38 | }
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | const {SpecReporter} = require('jasmine-spec-reporter');
5 | const localPort = process.env.PORT || 4200;
6 |
7 |
8 |
9 | exports.config = {
10 | allScriptsTimeout: 11000,
11 | specs: [
12 | './e2e/**/*.e2e-spec.ts'
13 | ],
14 | capabilities: {
15 | 'browserName': 'chrome',
16 | "chromeOptions": {
17 | "args": [
18 | "--no-sandbox", "--headless", "--disable-gpu", "--window-size=1920x800"
19 | ]
20 | }
21 | },
22 | directConnect: true,
23 | baseUrl: "http://localhost:" + localPort + "/",
24 | framework: 'jasmine',
25 | jasmineNodeOpts: {
26 | showColors: true,
27 | defaultTimeoutInterval: 30000,
28 | print: function () {
29 | }
30 | },
31 |
32 | beforeLaunch: function () {
33 |
34 |
35 | require('ts-node').register({
36 | project: 'e2e/tsconfig.e2e.json'
37 | });
38 | },
39 | onPrepare: function () {
40 | jasmine.getEnv().addReporter(new SpecReporter({spec: {displayStacktrace: true}}));
41 | }
42 |
43 | };
44 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/pipes/extract-socket-connector-relation-list-by-state-type.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from "@angular/core";
2 | import { MessageConnectorsRouteRelationModel } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/relation/message-connectors-route-relation.model";
3 | import {
4 | SocketConnectorRelationModel,
5 | SocketConnectorRelationStateType
6 | } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/relation/socket-connector-relation.model";
7 |
8 | // organizes sockets consistently by a deterministic ordering business rule, separating disabled ports to the end
9 | @Pipe({
10 | name: "extractSocketConnectorRelationListByStateType"
11 | })
12 | export class ExtractSocketConnectorRelationListByStateTypePipe implements PipeTransform {
13 |
14 | transform(routeRelation: MessageConnectorsRouteRelationModel, linkStateType: SocketConnectorRelationStateType): Array {
15 | return routeRelation.getSocketConnectorRelationListByStateType(linkStateType);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/add-socket-connector-relation/toolbar-add-socket-connector-relation.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: flex;
3 | flex: 0;
4 | align-items: flex-end;
5 |
6 | [role="errorsList"] {
7 | background-color: rgba(255, 2, 2, .15);
8 | }
9 |
10 | [role="processingErrorMessage"] {
11 | padding: 0.2rem;
12 | border-radius: 0.5rem;
13 | border: 1px solid rgba(0, 0, 0, .2);
14 | background-color: rgba(255, 2, 2, .3);
15 | }
16 |
17 | SELECT.socketSelection {
18 | min-width: 20ch;
19 | }
20 |
21 |
22 |
23 | // filtered by socket connector state type dropdown ( duplicate style )
24 | SELECT[role="stateType"], SELECT[role="stateType"] OPTION {
25 | &.default-state {
26 | background-color: white;
27 | }
28 |
29 | &.invalid-state {
30 | background-color: lighten(#e89e97, 10%);
31 | }
32 | &.valid-state {
33 | background-color: lighten(#b1e17a, 10%);
34 | }
35 | &.unknown-state {
36 | background-color: lighten(#b9bbb2, 10%);
37 | }
38 | }
39 |
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample2/metadata/configurations/simple-deck.inline.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "simple-deck",
3 | "cards": [
4 | {
5 | "id": "my-simple-plugin1",
6 | "component": "card-metrics-billboard",
7 | "header": {
8 | "title": "Simple Card",
9 | "icon": "datastore"
10 | },
11 | "layout": {
12 | "x": 0,
13 | "y": 0,
14 | "width": 3,
15 | "height": 1
16 | },
17 | "services": [
18 | {
19 | "network": {
20 | "url": "/network/vendors/extension/com.company.sample2/plugins/deck1/cards/local-plugin3/data/summary.json"
21 | }
22 | }
23 | ],
24 | "templates": [
25 | {
26 | "body": {
27 | "organization": "project2",
28 | "template": "metricsBillboardProgressWidget"
29 | }
30 | }
31 | ]
32 | }
33 | ]
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/remove-socket-connector-relation/toolbar-remove-socket-connector-relation.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: flex;
3 | flex: 0;
4 | align-items: flex-end;
5 |
6 | [role="errorsList"] {
7 | background-color: rgba(255, 2, 2, .15);
8 | }
9 |
10 | [role="processingErrorMessage"] {
11 | padding: 0.2rem;
12 | border-radius: 0.5rem;
13 | border: 1px solid rgba(0, 0, 0, .2);
14 | background-color: rgba(255, 2, 2, .3);
15 | }
16 |
17 | SELECT.socketConnectorRelationSelection {
18 | min-width: 20ch;
19 | }
20 |
21 |
22 | // filtered by socket connector state type dropdown ( duplicate style )
23 | SELECT[role="stateType"], SELECT[role="stateType"] OPTION {
24 | &.default-state {
25 | background-color: white;
26 | }
27 |
28 | &.invalid-state {
29 | background-color: lighten(#e89e97, 10%);
30 | }
31 | &.valid-state {
32 | background-color: lighten(#b1e17a, 10%);
33 | }
34 | &.unknown-state {
35 | background-color: lighten(#b9bbb2, 10%);
36 | }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/long-stack-trace-zone';
4 | import 'zone.js/dist/proxy.js';
5 | import 'zone.js/dist/sync-test';
6 | import 'zone.js/dist/jasmine-patch';
7 | import 'zone.js/dist/async-test';
8 | import 'zone.js/dist/fake-async-test';
9 | import { getTestBed } from '@angular/core/testing';
10 | import {
11 | BrowserDynamicTestingModule,
12 | platformBrowserDynamicTesting
13 | } from '@angular/platform-browser-dynamic/testing';
14 |
15 |
16 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
17 | declare const __karma__: any;
18 | declare const require: any;
19 |
20 | // Prevent Karma from running prematurely.
21 | __karma__.loaded = function () {};
22 |
23 | // First, initialize the Angular testing environment.
24 | getTestBed().initTestEnvironment(
25 | BrowserDynamicTestingModule,
26 | platformBrowserDynamicTesting()
27 | );
28 | // Then we find all the tests.
29 | const context = require.context('./', true, /\.spec\.ts$/);
30 | // And load the modules.
31 | context.keys().map(context);
32 | // Finally, start Karma to run the tests.
33 | __karma__.start();
34 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/standard/card-outlet/standard-dashboard-card-outlet-render-definitions.interface.ts:
--------------------------------------------------------------------------------
1 | import {
2 | CardOutletExtensionViewRender,
3 | VendorClassificationItem,
4 | VendorClassificationMap
5 | } from "ngx-card-deck";
6 | import { StandardDashboardOrganizerPackageEnumeration } from "../organizer/standard-dashboard-organizer-package.class";
7 | import { OrganizerPackageEnumerationBase } from "ngx-card-deck";
8 |
9 |
10 | export interface StandardDashboardCardOutletExtensionViewRender extends CardOutletExtensionViewRender {
11 | organizerPackage: StandardDashboardOrganizerPackageEnumeration | OrganizerPackageEnumerationBase;
12 | }
13 |
14 | export interface StandardDashboardVendorClassificationItem extends VendorClassificationItem {
15 | organizerPackage: StandardDashboardOrganizerPackageEnumeration | OrganizerPackageEnumerationBase;
16 | }
17 |
18 |
19 | /* used in card outlet render definitions */
20 | export interface StandardDashboardVendorClassificationMap extends VendorClassificationMap {
21 |
22 | nodeflow_sample: StandardDashboardVendorClassificationItem;
23 |
24 | [identifier: string]: StandardDashboardVendorClassificationItem;
25 | }
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample3/lib/views/card-assembly-plugins/introduction/introduction.html:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 | AssetTypeId error:
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
23 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/extensions/views/producer/nodeflow-asset-messages-producer-collection.html:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/core/com.company.group/lib/services/sample-product/dataservice/data-collection-parser-base.ts:
--------------------------------------------------------------------------------
1 | import { StandardResponseParserTransformable } from "../../../../../../common/standard/card-outlet/card-assembly-plugins/base/standard-response-parser-base";
2 | import { ParsedResponseTransformBase } from "./parsed-response-transform-base.class";
3 |
4 | interface StrategyTransformerSchema {
5 | [identifier: string]: StandardResponseParserTransformable;
6 | }
7 |
8 | export class DataCollectionParserBase {
9 |
10 | strategyTransformerMap: StrategyTransformerSchema = {/* injectables map */};
11 |
12 | constructor(args: any) {
13 | // initialize
14 | this.applyInjection(args);
15 | }
16 |
17 |
18 | // as many customized data transformers, add them here as DI
19 | private applyInjection(args: any) {
20 |
21 | // map of tagged by metadata
22 | const injectableList = Array.prototype.slice.call(args);
23 |
24 | injectableList.filter((inject: any) => {
25 | if (inject instanceof ParsedResponseTransformBase) {
26 | this.strategyTransformerMap[inject.getStrategyIdentifier()] = inject;
27 | }
28 | });
29 |
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/core/com.company.group/lib/services/sample-product/platform/demo-app-terminology.interface.ts:
--------------------------------------------------------------------------------
1 | export interface ManagedObjectReferenceType {
2 | value: string;
3 | type: string;
4 | serverGuid: string; // unique hashing
5 | }
6 |
7 |
8 | // data elements per monitored aspect
9 | export interface ResourceMetersModelItemSchema {
10 | title: string;
11 | capacity: string;
12 | free: string;
13 | progress: number;
14 | used: string;
15 | }
16 |
17 |
18 | // essential data response schema marker
19 | // tslint:disable-next-line:no-empty-interface
20 | export interface BaseModelSchema {
21 | }
22 |
23 | // base marker
24 | // tslint:disable-next-line:no-empty-interface
25 | export interface BaseModelItemSchema {
26 |
27 | }
28 |
29 | // marker for containing view-specific items
30 | // tslint:disable-next-line:no-empty-interface
31 | export interface BaseViewItemSchema {
32 | } // dump anything
33 |
34 |
35 | // client to transform ModelItemSchema into a view-capable representation
36 | export interface NumericTransformValueItem {
37 | model: BaseModelItemSchema; // server supplied
38 | view: BaseViewItemSchema; // view transformed variables
39 | message: string; // localized
40 | data: number; // transformed
41 | }
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/nodeflow-studio-overlays.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from "@angular/core";
2 | import { NodeflowStudioMenuOverlayModule } from "./menu-overlay/nodeflow-studio-menu-overlay.module";
3 | import { NodeflowStudioTooltipOverlayModule } from "./tooltip-overlay/nodeflow-studio-tooltip-overlay.module";
4 | import { NodeflowStudioNotificationOverlayModule } from "./notification-overlay/nodeflow-studio-notification-overlay.module";
5 | import { NodeflowStudioMenuOverlayComponent } from "./menu-overlay/nodeflow-studio-menu-overlay.component";
6 | import { NodeflowStudioTooltipOverlayComponent } from "./tooltip-overlay/nodeflow-studio-tooltip-overlay.component";
7 | import { NodeflowStudioNotificationOverlayComponent } from "./notification-overlay/nodeflow-studio-notification-overlay.component";
8 |
9 | @NgModule({
10 |
11 | imports: [
12 | NodeflowStudioMenuOverlayModule,
13 | NodeflowStudioTooltipOverlayModule,
14 | NodeflowStudioNotificationOverlayModule
15 | ],
16 |
17 | exports: [
18 | NodeflowStudioMenuOverlayComponent,
19 | NodeflowStudioTooltipOverlayComponent,
20 | NodeflowStudioNotificationOverlayComponent
21 | ]
22 |
23 |
24 | })
25 | export class NodeflowStudioOverlaysModule {
26 | }
27 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/tabs-container/toolbar-tabs-container.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { ToolbarAddNodeflowModule } from "../add-nodeflow/toolbar-add-nodeflow.module";
3 | import { ToolbarRemoveNodeflowModule } from "../remove-nodeflow/toolbar-remove-nodeflow.module";
4 | import { ToolbarAddSocketConnectorRelationModule } from "../add-socket-connector-relation/toolbar-add-socket-connector-relation.module";
5 | import { ToolbarRemoveSocketConnectorRelationModule } from "../remove-socket-connector-relation/toolbar-remove-socket-connector-relation.module";
6 | import { ToolbarSerializeModelModule } from "../serialize-model/toolbar-serialize-model.module";
7 | import { ToolbarTabsContainerComponent } from "./toolbar-tabs-container.component";
8 |
9 | @NgModule({
10 |
11 | imports: [
12 | ToolbarAddNodeflowModule,
13 | ToolbarRemoveNodeflowModule,
14 | ToolbarAddSocketConnectorRelationModule,
15 | ToolbarRemoveSocketConnectorRelationModule,
16 | ToolbarSerializeModelModule
17 | ],
18 |
19 | declarations: [
20 | ToolbarTabsContainerComponent
21 | ],
22 |
23 | exports: [
24 | ToolbarTabsContainerComponent
25 | ]
26 |
27 |
28 | })
29 | export class ToolbarTabsContainerModule {
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/extensions/views/producer/nodeflow-asset-messages-producer-collection.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | }
3 |
4 | /*
5 | * Ability to view, edit and dispatch message objects across the virtual connectors to listeners
6 | */
7 | [role="messagesProducerTable"] {
8 | display: flex;
9 | flex-direction: row;
10 | overflow: hidden;
11 | flex-wrap: wrap;
12 | background-color: rgba(83, 43, 143, .1);
13 |
14 | > * {
15 | flex: 1;
16 | }
17 |
18 | [role="messageModelTopicLabel"] {
19 | text-align: center;
20 | }
21 |
22 | [role="messageModelStateClassifier"] {
23 | font-weight: normal;
24 | text-align: center;
25 | &::before {
26 | content: "\00ab";
27 | }
28 | &::after {
29 | content: "\00bb";
30 | }
31 | }
32 |
33 | // individual subforms per message extracted from NodeProducer collection
34 | [role="messageModelSubformsContainer"] {
35 | border: 2px rgba(1, 1, 1, .2) solid;
36 | margin: 3px;
37 | padding: 3px;
38 |
39 | &:hover {
40 | // emphasis while focused
41 | background-color: rgba(83, 43, 143, .1);
42 | }
43 | }
44 |
45 |
46 |
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/remove-socket-connector-relation/toolbar-remove-socket-connector-relation.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { ReactiveFormsModule } from "@angular/forms";
4 | import { ToolbarRemoveSocketConnectorRelationComponent } from "./toolbar-remove-socket-connector-relation.component";
5 | import { ToolbarRemoveSocketConnectorRelationAgentService } from "./toolbar-remove-socket-connector-relation-agent.service";
6 | import { SocketConnectorRelationModelStateFilterPipe } from "./socket-connector-relation-model-state-filter.pipe";
7 | import { ComposeNodeToSocketConnectorRelationPipe } from "./compose-node-to-socket-connector-relation.pipe";
8 |
9 | @NgModule({
10 | imports: [
11 | CommonModule,
12 | ReactiveFormsModule
13 | ],
14 |
15 | providers: [
16 | ToolbarRemoveSocketConnectorRelationAgentService
17 | ],
18 |
19 | declarations: [
20 | ToolbarRemoveSocketConnectorRelationComponent,
21 | ComposeNodeToSocketConnectorRelationPipe,
22 | SocketConnectorRelationModelStateFilterPipe
23 | ],
24 |
25 | exports: [
26 | ToolbarRemoveSocketConnectorRelationComponent
27 | ]
28 | })
29 | export class ToolbarRemoveSocketConnectorRelationModule {
30 | }
31 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/tabs-container/toolbar-tabs-container.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
14 |
15 |
16 |
20 |
21 |
22 |
26 |
27 |
28 |
32 |
33 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample1/views/card-templates/components/demo-client-grid-card/demo-client-grid-card-icon.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, AfterViewInit, ElementRef, Input } from "@angular/core";
2 |
3 | interface PrivateServerStoredTypedValue {
4 | value: string;
5 | type: string;
6 | serverGuid: string;
7 | }
8 |
9 | // map back to the notion of CSS classes used from sprite
10 | const iconsMap = {
11 | Folder: "demo-icon-folder",
12 | HostSystem: "demo-icon-host",
13 | };
14 |
15 | /**
16 | * prepare business icon for the list
17 | */
18 | @Directive({
19 | // tslint:disable-next-line:directive-selector
20 | selector: '[demoInventoryIcon]'
21 | })
22 | export class DemoClientGridCardIconDirective implements AfterViewInit {
23 |
24 | // marks the object that holds one of the important fields: type
25 | @Input() entity: PrivateServerStoredTypedValue;
26 |
27 | constructor(public elem: ElementRef) {
28 |
29 | }
30 |
31 | ngAfterViewInit() {
32 | const c = this.determineIconClass();
33 | // conditional icon
34 | if (c) {
35 | this.elem.nativeElement.classList.add(c);
36 | }
37 | }
38 |
39 | // -------- internal ------------
40 | private determineIconClass(): string {
41 | return iconsMap[this.entity.type];
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample3/plugins/deck3/cards/my-simple-plugin1/data/summary.json:
--------------------------------------------------------------------------------
1 | {
2 | "provider": {
3 | "serverGuid": "deck3-server",
4 | "type": "Folder",
5 | "value": "animals"
6 | },
7 | "summaryItems": [
8 | {
9 | "label": "Dogs",
10 | "value": 100
11 | },
12 | {
13 | "label": "Cats",
14 | "value": 200
15 | }
16 | ],
17 | "resourceMeters": [
18 | {
19 | "title": "felines",
20 | "free": "40 Cats",
21 | "used": "10 kittens",
22 | "capacity": "30 litters",
23 | "progress": 20
24 | },
25 | {
26 | "title": "canines",
27 | "free": "77 Dogs",
28 | "used": "50 puppies",
29 | "capacity": "10 litters",
30 | "progress": 59
31 | },
32 | {
33 | "title": "headcount",
34 | "free": "8 Staff",
35 | "used": "3 groomers",
36 | "capacity": "5 veterinarians",
37 | "progress": 34
38 | },
39 | {
40 | "title": "foods",
41 | "free": "60 Treats",
42 | "used": "30 catnips",
43 | "capacity": "90 bones",
44 | "progress": 30
45 | }
46 | ]
47 | }
48 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/add-nodeflow/toolbar-add-nodeflow.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { ReactiveFormsModule } from "@angular/forms";
4 | import { ToolbarAddNodeflowComponent } from "./toolbar-add-nodeflow.component";
5 | import { ToolbarAddNodeflowAgentService } from "./toolbar-add-nodeflow-agent.service";
6 | import { FindNodeflowCardProjectPackagePipe } from "./pipes/find-nodeflow-card-project-package.pipe";
7 | import { FindCardCatalogResourcesPackagePipe } from "./pipes/find-card-catalog-resources-package.pipe";
8 | import { LimitMessageBySocketPipe } from "./pipes/limit-message-by-socket.pipe";
9 | import { AssetTypeOrderByPipe } from "./pipes/asset-type-order-by.pipe";
10 |
11 | @NgModule({
12 |
13 | imports: [
14 | CommonModule,
15 | ReactiveFormsModule
16 | ],
17 |
18 | providers: [
19 | ToolbarAddNodeflowAgentService
20 | ],
21 |
22 | declarations: [
23 | ToolbarAddNodeflowComponent,
24 | FindCardCatalogResourcesPackagePipe,
25 | FindNodeflowCardProjectPackagePipe,
26 | LimitMessageBySocketPipe,
27 | AssetTypeOrderByPipe
28 | ],
29 |
30 |
31 | exports: [
32 | ToolbarAddNodeflowComponent
33 | ]
34 |
35 |
36 | })
37 | export class ToolbarAddNodeflowModule {
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample1/views/card-templates/modules/com_company_sample1_template.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from "@angular/common";
2 | import { NgModule } from "@angular/core";
3 | import { ClrDatagridModule, ClrIconModule } from "@clr/angular";
4 | import { DemoClientGridCardIconDirective } from "../components/demo-client-grid-card/demo-client-grid-card-icon.directive";
5 | import { DemoClientGridCardTemplateComponent } from "../components/demo-client-grid-card/demo-client-grid-card-template.component";
6 | import { DemoClientSummaryBillboardTemplateComponent } from "../components/demo-client-summary-billboard/demo-client-summary-billboard-template.component";
7 |
8 | @NgModule({
9 | imports: [
10 | CommonModule,
11 | ClrIconModule,
12 | ClrDatagridModule // simple grid
13 | ],
14 | // compiler needs
15 | declarations: [
16 | DemoClientGridCardIconDirective, // simple grid
17 | DemoClientSummaryBillboardTemplateComponent,
18 | DemoClientGridCardTemplateComponent
19 | ],
20 |
21 | // dynamic injection
22 | entryComponents: [
23 | DemoClientSummaryBillboardTemplateComponent,
24 | DemoClientGridCardTemplateComponent
25 | ],
26 |
27 | providers: [],
28 |
29 | exports: [ClrDatagridModule] // for grid card clients
30 |
31 | })
32 | export class ComCompanySample1TemplateModule {
33 | }
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/tooltip-overlay/nodeflow-studio-tooltip-overlay.scss:
--------------------------------------------------------------------------------
1 | $tooltip-color-background: #fff;
2 | $tooltip-color-border: #567;
3 | $tooltip-color-foreground: #000;
4 |
5 | :host {
6 | display: block;
7 | position: absolute; // removed from flow
8 | background: $tooltip-color-background;
9 | color: $tooltip-color-foreground;
10 | border: 1px $tooltip-color-border solid;
11 | border-radius: 0.5rem;
12 | box-shadow: 0px 5px 4px 2px rgba(0, 0, 0, .3);
13 | padding: 0.5rem;
14 | white-space: nowrap;
15 | transition: opacity .2s;
16 | opacity: 0;
17 |
18 | &.show {
19 | opacity: 1;
20 | }
21 |
22 | &::before {
23 | $pointer-size: .7rem;
24 | content: "";
25 | position: absolute;
26 | // should accommodate pointer-size
27 | left: 50%;
28 | width: $pointer-size;
29 | height: $pointer-size;
30 | bottom: -1 * $pointer-size/2;
31 | clip-path: polygon(100% 20%, 100% 100%, 20% 100%);
32 | background: $tooltip-color-background;
33 | border: 1px darken($tooltip-color-border, 20%) solid;
34 | padding: 3px;
35 | transform: rotate(45deg);
36 | transform-origin: top;
37 | pointer-events: none;
38 | }
39 | }
40 |
41 | UL {
42 | padding: 0;
43 | margin: 0 1rem;
44 |
45 | LI {
46 | font-size: 10pt;
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample3/plugins/deck3/cards/my-advanced-introduction/data/introduction-model.json:
--------------------------------------------------------------------------------
1 | {
2 | "product": "ABC-1234-000",
3 | "organization": "Computing",
4 | "name": "Apollo workstation",
5 | "collections": {
6 | "devices": [
7 | {
8 | "id": "device1",
9 | "name": "monitor",
10 | "categoryId": "category3"
11 | },
12 | {
13 | "id": "device2",
14 | "name": "router",
15 | "categoryId": "category2"
16 | },
17 | {
18 | "id": "device3",
19 | "name": "terminal",
20 | "categoryId": "category1"
21 | },
22 | {
23 | "id": "device4",
24 | "name": "keyboard",
25 | "categoryId": "category1"
26 | },
27 | {
28 | "id": "device5",
29 | "name": "trackball",
30 | "categoryId": "category1"
31 | }
32 | ],
33 | "categories": [
34 | {
35 | "id": "category1",
36 | "name": "peripheral"
37 | },
38 | {
39 | "id": "category2",
40 | "name": "networking"
41 | },
42 | {
43 | "id": "category3",
44 | "name": "visual"
45 | }
46 | ]
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { APP_INITIALIZER, NgModule } from '@angular/core';
2 | import { BrowserModule } from '@angular/platform-browser';
3 | import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
4 | import { ClrIconModule, ClrTabsModule, ClrTooltipModule } from "@clr/angular";
5 | import { AppRoutingModule } from './app-routing.module';
6 | import { AppComponent } from './app.component';
7 | import { HomeComponent } from './home/home.component';
8 | import { AboutComponent } from "./about/about.component";
9 | import { AppThemeService, ThemePreloadFactory } from "./app-theme.service";
10 | import { environment } from "../environments/environment";
11 |
12 |
13 | @NgModule({
14 | imports: [
15 | BrowserModule,
16 | BrowserAnimationsModule,
17 | AppRoutingModule,
18 | ClrIconModule,
19 | ClrTooltipModule,
20 | ClrTabsModule
21 | ],
22 | declarations: [
23 | AppComponent,
24 | HomeComponent,
25 | AboutComponent
26 | ],
27 | providers: [
28 | AppThemeService,
29 | {
30 | provide: "APP_ENVIRONMENT", // string token to promote loose coupling
31 | useValue: environment
32 | },
33 | {
34 | provide: APP_INITIALIZER,
35 | useFactory: ThemePreloadFactory,
36 | multi: true,
37 | deps: [AppThemeService, "APP_ENVIRONMENT"]
38 | }
39 | ],
40 | bootstrap: [AppComponent]
41 | })
42 | export class AppModule {
43 | }
44 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/extensions/views/producer/nodeflow-asset-messages-producer-collection.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, forwardRef, Inject, Input, OnInit } from "@angular/core";
2 | import { NodeModel } from "../../../../../../../../../../studio/nodeflow-studio-compositor/state/model/node.model";
3 | import { NodeflowAssetNodeTemplateComponent } from "../../../nodeflow-asset-node-template.component";
4 |
5 | @Component({
6 | selector: "nodeflow-asset-messages-producer-collection",
7 | templateUrl: "./nodeflow-asset-messages-producer-collection.html",
8 | styleUrls: ["./nodeflow-asset-messages-producer-collection.scss"],
9 | // not onpush so far...
10 | // changeDetection: ChangeDetectionStrategy.OnPush
11 | })
12 | export class NodeflowAssetMessagesProducerCollectionComponent implements OnInit {
13 | @Input() nodeModel: NodeModel;
14 |
15 | constructor(
16 | @Inject(forwardRef(() => NodeflowAssetNodeTemplateComponent)) public integrator: NodeflowAssetNodeTemplateComponent,
17 | ) {
18 | this.initialize();
19 | }
20 |
21 | ngOnInit() {
22 | }
23 |
24 |
25 | private initialize() {
26 |
27 | // synchronized
28 | this.integrator.cardAssemblyPlugin.viewModel.onNodeConsumerRelationsChange$.subscribe((nodeOwnedRouteRelationList) => {
29 | this.integrator.simulatorProducerFormView.onSocketConnectorRelationCollectionChange();
30 | });
31 |
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/extensions/views/delivery/default/nodeflow-asset-default-consumer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/extensions/topics/color/consumer/nodeflow-asset-topics-color-consumer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Color Streaming
4 |
5 |
6 |
7 |
8 |
9 |
10 |
14 |
15 |
16 |
17 |
18 | |
19 | color
20 | |
21 |
22 | {{ showMessageData(deliveryMessage.payload.data) }}
23 | |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | Invalid color:
33 | {{ deliveryMessage.payload.data | json }}
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/integration/platform/demo-dashboard-platform-communicator.service.ts:
--------------------------------------------------------------------------------
1 | import { Inject, Injectable } from "@angular/core";
2 | import { DemoDashboardDeploymentConfigurationService } from "../environment/demo-dashboard-deployment-configuration.service";
3 | import { DemoDashboardGlobalStateService } from "../environment/demo-dashboard-global-state.service";
4 | import { HttpClient } from "@angular/common/http";
5 | import { PlatformCommunicatorBase } from "ngx-card-deck";
6 | import { DeploymentConfigurationBase, GlobalStateBase } from "ngx-card-deck";
7 |
8 | @Injectable()
9 | export class DemoDashboardPlatformCommunicatorService extends PlatformCommunicatorBase {
10 |
11 | constructor(protected _http: HttpClient,
12 | @Inject(GlobalStateBase) protected _appGlobalState: DemoDashboardGlobalStateService,
13 | @Inject(DeploymentConfigurationBase) protected _deploymentConfiguration: DemoDashboardDeploymentConfigurationService) {
14 | super();
15 |
16 | }
17 |
18 | // strictness
19 | getDeploymentConfiguration(): DemoDashboardDeploymentConfigurationService {
20 | // super.getDeploymentConfiguration() as DemoDashboardDeploymentConfigurationService;
21 | return this._deploymentConfiguration;
22 | }
23 |
24 | getGlobalState(): DemoDashboardGlobalStateService {
25 | // super.getGlobalState() as DemoDashboardGlobalStateService;
26 | return this._appGlobalState;
27 | }
28 |
29 |
30 | // extend custom ingest via `streamRestResource()`
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/pipes/nodeflow-message-connectors-route-relation-by-socket-filter.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from "@angular/core";
2 | import { SocketModel } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/socket.model";
3 | import { MessageConnectorsRouteRelationModel } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/relation/message-connectors-route-relation.model";
4 |
5 | // show only route relations if the socket is participating within a linked connector
6 | @Pipe({
7 | name: "routeRelationBySocketFilter",
8 | pure: true
9 | })
10 | export class NodeflowMessageConnectorsRouteRelationBySocketFilterPipe implements PipeTransform {
11 |
12 | transform(items: Array, filterBySocket: SocketModel): Array | undefined {
13 | return items.filter((rr) => rr.getSocketConnectorRelationListBySocket(filterBySocket).length > 0);
14 | }
15 |
16 | // keep in chase jumping back to async
17 | /*
18 | transform(stream: Observable>, filterBySocket: SocketModel): Observable> {
19 | // console.log("coming in", filterBySocket.id);
20 | return stream.pipe(map((messageConnectorsList) => messageConnectorsList.filter((rr) => rr.getSocketConnectorRelationListBySocket(filterBySocket).length > 0)));
21 | */
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/demo-dashboard-transaction-agent.service.ts:
--------------------------------------------------------------------------------
1 | import { DemoDashboardPageComponent } from "./demo-dashboard-page.component";
2 | import {
3 | DashboardConfigurationFacadeService,
4 | ViewAssemblyTypeStateResourceLayoutItemSchema
5 | } from "ngx-card-deck";
6 | import { Injectable } from "@angular/core";
7 |
8 | //import { NodeflowConfigurationPreprocessor } from "./client/organizers/nodeflow/lib/models/parsers/dashboard/integration/nodeflow-configuration-preprocessor.class";
9 |
10 | const resources = {
11 | action: {}
12 | };
13 |
14 |
15 | @Injectable()
16 | export class DemoDashboardTransactionAgentService {
17 |
18 |
19 | private component: DemoDashboardPageComponent;
20 |
21 | // to decide if the card preprocessor is needed? probably should not hardcode the Nodeflow implementation
22 | // private cardConfigurationPreprocessor: NodeflowConfigurationPreprocessor;
23 | // this.cardConfigurationPreprocessor = new NodeflowConfigurationPreprocessor();
24 |
25 | constructor(private configurationFacadeService: DashboardConfigurationFacadeService) {
26 | }
27 |
28 | setComponent(c: DemoDashboardPageComponent) {
29 | this.component = c;
30 | }
31 |
32 |
33 | // ======================= Standard card Actions ===================
34 |
35 | onShowVisibleCardsInfo(itemList: Array, evt: MouseEvent) {
36 | const msg = itemList.map((item) => `* ${item.resourceId}`).join("\n");
37 | alert(msg);
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/core/com.company.group/views/card-assembly-plugins/summary-billboard/summary-billboard.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | {{ library.alias.cardI18n["card.footer"] }}
30 |
31 |
32 |
33 |
34 |
36 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/extensions/views/delivery/default/nodeflow-asset-default-consumer.component.ts:
--------------------------------------------------------------------------------
1 | import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, Inject, OnInit } from "@angular/core";
2 | import {
3 | NODEFLOW_PROJECT1_CONSUMER_TOPIC_COMPONENT_RESOURCE_TOKEN,
4 | NodeflowProject1ConsumerStateInjectable
5 | } from "../../../../nodeflow-asset-node-token";
6 |
7 | @Component({
8 | selector: "nodeflow-asset-default-consumer",
9 | templateUrl: "./nodeflow-asset-default-consumer.html",
10 | styleUrls: ["./nodeflow-asset-default-consumer.scss"],
11 | changeDetection: ChangeDetectionStrategy.OnPush
12 | })
13 | export class NodeflowAssetDefaultConsumerComponent implements OnInit {
14 |
15 | constructor(
16 | @Inject(forwardRef(() => NODEFLOW_PROJECT1_CONSUMER_TOPIC_COMPONENT_RESOURCE_TOKEN)) public resourceState: NodeflowProject1ConsumerStateInjectable,
17 | private _cdr: ChangeDetectorRef
18 | ) {
19 | this.initialize();
20 | }
21 |
22 | ngOnInit() {
23 | }
24 |
25 | private initialize() {
26 |
27 | /*
28 | this.integrator.cardAssemblyPlugin.viewModel.onNodeConsumerRelationsChange$.subscribe((nodeOwnedRouteRelationList) => {
29 | // keep for debugging state mutation
30 | // console.log("a route relation changed", nodeOwnedRouteRelationList, "for node", this.integrator.cardAssemblyPlugin.viewModel.nodeModel.id);
31 | });
32 | */
33 |
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { ModuleWithProviders, NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { HomeComponent } from './home/home.component';
4 | import { AboutComponent } from "./about/about.component";
5 |
6 |
7 | const routes: Routes = [
8 | {path: 'home', component: HomeComponent},
9 | {path: 'about', component: AboutComponent},
10 | {
11 | path: 'dashboard',
12 | loadChildren: () => import('./pages/dashboard/demo-dashboard.module').then(m => m.DemoDashboardModule)
13 | },
14 |
15 | /*
16 | {
17 | path: 'dashboard',
18 | component: DemoDashboardComponent,
19 | children: [
20 | {
21 | path: 'dashboard-page/:organizer/:configuration',
22 | component: DemoDashboardPageComponent,
23 | resolve: {configuration: DemoDashboardRouting}
24 | }
25 | ]
26 | },
27 | */
28 |
29 | {path: '**', redirectTo: ''}
30 | ];
31 |
32 | export const ROUTING: ModuleWithProviders = RouterModule.forRoot(routes,
33 | {
34 | // Note: the HTML5 strategy is highly recommended. It requires server rewrites to be configured
35 |
36 | // For purposes of this demo, the simple ( always works ) hashing strategy is applied for routing
37 | useHash: true,
38 |
39 | // enableTracing: true,
40 | // preloadingStrategy: PreloadSelectedModulesList
41 | }
42 | );
43 |
44 |
45 | @NgModule({
46 | imports: [ROUTING],
47 | exports: [RouterModule]
48 | })
49 | export class AppRoutingModule {
50 | }
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, async } from '@angular/core/testing';
2 | import { RouterTestingModule } from '@angular/router/testing';
3 | import { ClarityModule, ClrTabsModule, ClrTooltipModule } from "@clr/angular";
4 | import { AppComponent } from './app.component';
5 | import * as appNavigationLinksResourceJson from "./app-navigation-links.json";
6 |
7 | describe('AppComponent', () => {
8 | beforeEach(async(() => {
9 |
10 | TestBed.configureTestingModule({
11 | imports: [
12 | RouterTestingModule,
13 | ClarityModule,
14 | ClrTooltipModule,
15 | ClrTabsModule,
16 | ],
17 | declarations: [
18 | AppComponent
19 | ],
20 | }).compileComponents();
21 | }));
22 | it('should create the app', async(() => {
23 | const fixture = TestBed.createComponent(AppComponent);
24 | fixture.componentInstance.navigationLayout = appNavigationLinksResourceJson;
25 |
26 | const app = fixture.debugElement.componentInstance;
27 | expect(app).toBeTruthy();
28 | }));
29 |
30 | it(`should have as title 'ngx Card Deck Demo'`, async(() => {
31 | const fixture = TestBed.createComponent(AppComponent);
32 | fixture.componentInstance.navigationLayout = appNavigationLinksResourceJson;
33 |
34 | fixture.detectChanges();
35 | const app = fixture.debugElement.componentInstance;
36 | const title = 'ngx Card Deck Demo';
37 | expect(app.title).toEqual(title);
38 | }));
39 |
40 | });
41 |
42 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample2/plugins/deck1/cards/remote-plugin2/view/styles/page.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | html {
6 | font-family: Arial, Helvetica, serif;
7 | overflow: hidden;
8 | width: 100%;
9 | height: 100%;
10 | border-radius: 2rem;
11 | }
12 |
13 | body {
14 | padding: 0;
15 | margin: 0;
16 | color: #222;
17 | xbackground-color: rgba(0, 0, 0, .1);
18 |
19 | height: 100%;
20 | width: 100%;
21 | }
22 |
23 | #toast {
24 | display: block;
25 | margin: 0 auto;
26 | color: #c23;
27 | }
28 |
29 | #toast[role="heading"] {
30 | color: #555;
31 | position: absolute;
32 | left: 25%;
33 | background-color: rgba(255, 255, 255, .9);
34 | padding: 0.5rem;
35 | border-bottom-right-radius: 1rem;
36 | border-bottom-left-radius: 1rem;
37 | border: 2px #000000 solid;
38 | border-top: none;
39 | }
40 |
41 | main {
42 | display: flex;
43 | flex-direction: row;
44 |
45 | width: 100%;
46 | height: 100%;
47 |
48 | }
49 |
50 | main section {
51 | flex: 0 1 100%;
52 | }
53 |
54 | main section iframe {
55 | width: 100%;
56 | height: 100%;
57 | padding: 0.5rem;
58 | background-color: rgba(0, 0, 0, .1);
59 |
60 | border: 3px rgba(1, 1, 1, .2) solid;
61 | border-radius: 2rem;
62 | }
63 |
64 | main section:focus {
65 | border-color: #00ff00;
66 | }
67 |
68 | main section:focus-within {
69 | border-color: rgba(233, 1, 1, .5);
70 | }
71 |
72 | main section iframe.video {
73 | border: 3px rgba(0, 0, 0, .3) solid;
74 | }
75 |
76 | h5 {
77 | margin: 0;
78 | text-align: center;
79 | }
80 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample3/plugins/deck3/cards/my-simple-introduction/data/introduction-model.json:
--------------------------------------------------------------------------------
1 | {
2 | "product": "XYZ-9876-000",
3 | "organization": "Automotive",
4 | "name": "Lowrider Car 10x",
5 | "collections": {
6 | "devices": [
7 | {
8 | "id": "device1",
9 | "name": "engine",
10 | "categoryId": "category2"
11 | },
12 | {
13 | "id": "device3",
14 | "name": "core",
15 | "categoryId": "category2"
16 | },
17 | {
18 | "id": "device4",
19 | "name": "battery",
20 | "categoryId": "category2"
21 | },
22 | {
23 | "id": "device5",
24 | "name": "steering",
25 | "categoryId": "category1"
26 | },
27 | {
28 | "id": "device7",
29 | "name": "shifter",
30 | "categoryId": "category1"
31 | },
32 | {
33 | "id": "device6",
34 | "name": "wheel",
35 | "categoryId": "category3"
36 | }
37 | ],
38 | "categories": [
39 | {
40 | "id": "category1",
41 | "name": "driver"
42 | },
43 | {
44 | "id": "category2",
45 | "name": "transmission"
46 | },
47 | {
48 | "id": "category3",
49 | "name": "exterior"
50 | }
51 | ]
52 | }
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/views/toolbar/add-socket-connector-relation/node-model-message-socket-compatible.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from "@angular/core";
2 | import {
3 | SocketConnectorType,
4 | SocketModel
5 | } from "../../../../studio/nodeflow-studio-compositor/state/model/socket.model";
6 | import { NodeModel } from "../../../../studio/nodeflow-studio-compositor/state/model/node.model";
7 |
8 | const emptiness: Array = [];
9 |
10 | // restricts possible nodes based upon a criteria to restrict to only showing nodes that are topic compatible
11 | @Pipe({
12 | name: "nodeModelMessageSocketCompatible"
13 | })
14 | export class NodeModelMessageSocketCompatiblePipe implements PipeTransform {
15 | transform(items: Array, socket: SocketModel, socketType: SocketConnectorType): Array {
16 | if (items && socket) {
17 | const topic = socket.topic;
18 | if (topic) {
19 |
20 | return (items
21 | .filter((d) => d.link && Array.from(d.link.getCollectionByType(socketType))
22 | .filter((iteratorSocket) => iteratorSocket.topic === topic).length > 0));
23 | } else {
24 |
25 | console.error("no other socket compatibility test", socket);
26 | return emptiness; // no strategy possible to generalize compatibility
27 | }
28 |
29 | } else if (!socket && socketType === SocketConnectorType.input) {
30 | return emptiness; // no producer assigned yet
31 |
32 | } else {
33 | return items; // leave as is
34 | }
35 |
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample1/views/card-assembly-plugins/simple-grid-card/parser/installed-plugins-dashboard-transformer.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from "@angular/core";
2 | import { ParsedResponseTransformBase } from "../../../../../../core/com.company.group/lib/services/sample-product/dataservice/parsed-response-transform-base.class";
3 | import { RelationalDataFieldMetadata } from "../../../../../../core/com.company.group/views/card-assembly-plugins/simple-grid-card/grid-relational-data-field-model.interface";
4 |
5 | // ~~~~~~~~~~~~~~~~~~~~ Plugins data segmentation and extraction ~~~~~~~~~~~~~~~~~~~
6 | @Injectable()
7 | export class InstalledPluginsDashboardTransformerService extends ParsedResponseTransformBase {
8 |
9 | constructor() {
10 | super();
11 | }
12 |
13 | public getStrategyIdentifier() {
14 | return "InstalledPluginsDashboardTransformerService";
15 | }
16 |
17 | // step 1 extract collection
18 | public extract(serverResponse: any): Array {
19 | return serverResponse.response.entity;
20 | }
21 |
22 | // step 2 transform collection to view DAO
23 | // view helper: create subset of only visible columns, localize the displayed label
24 | public transform(dataItems: Array): Array {
25 |
26 | return dataItems.map((item) => {
27 |
28 | const entity: any = {
29 | "id": item.id,
30 | "plugin_name": item.name,
31 | "installed_status": item.state === "enabled"
32 | };
33 | return entity;
34 | });
35 |
36 | }
37 |
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample3/lib/views/card-assembly-plugins/introduction/parser/introduction-parser.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from "@angular/core";
2 | import {
3 | DashboardConfigurationResourceCardSchema,
4 | DashboardConfigurationResourceFacade
5 | } from "ngx-card-deck";
6 | import { TemplateLibraryManager } from "ngx-card-deck";
7 | import {
8 | ResponseParserRegisterable,
9 | StandardResponseParserTransformable
10 | } from "../../../../../../standard/card-outlet/card-assembly-plugins/base/standard-response-parser-base";
11 | import { StandardFieldMetadata } from "../../../../../../standard/organizer/standard-template.interface";
12 | import { IntroductionListTransformerService } from "./introduction-list-transformer.service";
13 |
14 | @Injectable({providedIn: "root"})
15 | export class IntroductionParserService implements ResponseParserRegisterable {
16 |
17 | // as many customized data transformers, add them here as DI
18 | constructor(private transformer1: IntroductionListTransformerService) {
19 | }
20 |
21 | // strategy implementation, pull out the correct parser and prepare it for data handling
22 | public register(card: DashboardConfigurationResourceFacade,
23 | libraryStateManager: TemplateLibraryManager,
24 | fieldMetadataList: Array): StandardResponseParserTransformable {
25 | return this.transformer1; // sample: more complex registration processes can be setup to leverage providers declarations
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/core/com.company.group/lib/services/sample-product/dataservice/parsed-response-transform-base.class.ts:
--------------------------------------------------------------------------------
1 | import {
2 | DashboardConfigurationResourceCardSchema,
3 | DashboardConfigurationResourceFacade
4 | } from "ngx-card-deck";
5 | import { TemplateLibraryManager } from "ngx-card-deck";
6 | import { StandardResponseParserTransformable } from "../../../../../../common/standard/card-outlet/card-assembly-plugins/base/standard-response-parser-base";
7 | import { FieldBaseMetadata } from "ngx-card-deck";
8 |
9 |
10 | // supplied RelationalDataFieldMetadata
11 | export abstract class ParsedResponseTransformBase implements StandardResponseParserTransformable {
12 | protected card: DashboardConfigurationResourceFacade;
13 | protected fieldMetadataList: Array;
14 | protected libraryStateManager: TemplateLibraryManager;
15 |
16 |
17 | public prepare(card: DashboardConfigurationResourceFacade,
18 | fieldMetadataList: Array,
19 | libraryStateManager: TemplateLibraryManager) {
20 | this.card = card;
21 | this.fieldMetadataList = fieldMetadataList;
22 | this.libraryStateManager = libraryStateManager;
23 | }
24 |
25 |
26 | // internal to interface
27 | public abstract extract(responseMessage: object): Array;
28 |
29 | public abstract transform(data: Array): Array;
30 |
31 | public abstract getStrategyIdentifier(): string;
32 |
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/styles/design-themes/standard/_demo-iconography.scss:
--------------------------------------------------------------------------------
1 | // specific icons and styles for use in the dashboard
2 |
3 | // common iconography
4 | [class ^= "icon"] {
5 | background-repeat: no-repeat;
6 | display: inline-block;
7 | }
8 |
9 | // within outlet card header
10 | // ----------- header bar icons --------------------
11 |
12 | // icon contrast swaps to white
13 | :host-context(.standard-dark-theme) {
14 | ::ng-deep I.headerIcon {
15 | filter: invert(1);
16 | }
17 | }
18 |
19 |
20 | ::ng-deep I.headerIcon {
21 | background-size: cover;
22 | flex-shrink: 0;
23 |
24 | &.datastore {
25 | background-image: url("//cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/svgs/fi-skull.svg");
26 | }
27 |
28 | &.book-bookmark {
29 | background-image: url("//cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/svgs/fi-book-bookmark.svg");
30 | }
31 |
32 | &.lightbulb {
33 | background-image: url("//cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/svgs/fi-lightbulb.svg");
34 | }
35 |
36 | &.social-treehouse {
37 | background-image: url("//cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/svgs/fi-social-treehouse.svg");
38 | }
39 |
40 | &.loading {
41 | background-image: url("//cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/svgs/fi-sheriff-badge.svg");
42 | }
43 |
44 | &.mountain {
45 | background-image: url("//cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/svgs/fi-mountains.svg");
46 | }
47 |
48 | &.map {
49 | background-image: url("//cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/svgs/fi-map.svg");
50 | }
51 |
52 | }
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
38 |
39 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample1/views/card-assembly-plugins/summary-billboard/summary-parser.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from "@angular/core";
2 | import { SummaryBillboardDataModelItemSchema } from "../../../../../core/com.company.group/views/card-assembly-plugins/summary-billboard/summary-billboard.interface";
3 | import { NumericTransformValueItem } from "../../../../../core/com.company.group/lib/services/sample-product/platform/demo-app-terminology.interface";
4 | import { TemplateLibraryManager } from "ngx-card-deck";
5 |
6 |
7 | @Injectable()
8 | export class SummaryParserService {
9 |
10 | constructor(private _library: TemplateLibraryManager) {
11 |
12 | }
13 |
14 |
15 | // view helper: create subset of only visible columns, localize the displayed label
16 | public deriveVisibleModelItemsList(dataItems: Array): Array {
17 |
18 | const i18n = this._library.alias.cardI18n;
19 | // post transformed decorated structure
20 | const results: Array = [];
21 |
22 | dataItems.forEach((dataItem) => {
23 |
24 | const isProcessableFlag = true;
25 | if (isProcessableFlag) {
26 |
27 | const valueItem: NumericTransformValueItem = {
28 | model: dataItem,
29 | view: {}, // no special parameter
30 | message: i18n[dataItem.label],
31 | data: parseInt(dataItem.value, 10)
32 | };
33 |
34 | results.push(valueItem);
35 | }
36 | });
37 |
38 | return results;
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/extensions/views/consumer/nodeflow-asset-messages-consumer-collection.component.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ChangeDetectionStrategy,
3 | ChangeDetectorRef,
4 | Component,
5 | forwardRef,
6 | Inject,
7 | Input,
8 | OnInit
9 | } from "@angular/core";
10 | import { NodeModel } from "../../../../../../../../../../studio/nodeflow-studio-compositor/state/model/node.model";
11 | import { NodeflowAssetNodeTemplateComponent } from "../../../nodeflow-asset-node-template.component";
12 |
13 | @Component({
14 | selector: "nodeflow-asset-messages-consumer-collection",
15 | templateUrl: "./nodeflow-asset-messages-consumer-collection.html",
16 | styleUrls: ["./nodeflow-asset-messages-consumer-collection.scss"],
17 | changeDetection: ChangeDetectionStrategy.OnPush
18 | })
19 | export class NodeflowAssetMessagesConsumerCollectionComponent implements OnInit {
20 | @Input() nodeModel: NodeModel;
21 |
22 | constructor(
23 | @Inject(forwardRef(() => NodeflowAssetNodeTemplateComponent)) public integrator: NodeflowAssetNodeTemplateComponent,
24 | private _cdr: ChangeDetectorRef
25 | ) {
26 | this.initialize();
27 | }
28 |
29 | ngOnInit() {
30 | }
31 |
32 | private initialize() {
33 |
34 |
35 | this.integrator.cardAssemblyPlugin.viewModel.onNodeConsumerRelationsChange$.subscribe((nodeOwnedRouteRelationList) => {
36 | // keep for debugging state mutation
37 | // console.log("a route relation changed", nodeOwnedRouteRelationList, "for node", this.integrator.cardAssemblyPlugin.viewModel.nodeModel.id);
38 | });
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample1/data-server/session/usersession.json:
--------------------------------------------------------------------------------
1 | {
2 | "userName": "Administrator@company.LOCAL",
3 | "locale": "en_US",
4 | "serversInfo": [
5 | {
6 | "name": "Group (1)",
7 | "serviceUrl": "https://server.eng.company.com:443/sdk",
8 | "serviceGuid": "2017-abcd-server-service",
9 | "version": "6.5.0",
10 | "sessionKey": "52d16adf-956c-48a5-3b3f-1910f480a95b",
11 | "hostId": null
12 | }
13 | ],
14 | "clientId": "4025f609-d90e-4f54-b319-7118376e64a3",
15 | "linkedServersInfo": [
16 | [
17 | {
18 | "name": "server.eng.company.com (Mock)",
19 | "serviceUrl": "https://server.eng.company.com:443/sdk",
20 | "serviceGuid": "2017-abcd-server-service",
21 | "version": "6.5.0",
22 | "sessionKey": "52d16adf-956c-48a5-3b3f-1910f480a95b",
23 | "sessionCookie": "\"a3275176a3546aad67115a08001d771d2369d090\"",
24 | "hostId": null,
25 | "serviceInstance": {
26 | "serverGuid": "2017-abcd-server-service",
27 | "type": "ServiceInstance",
28 | "value": "ServiceInstance"
29 | },
30 | "content": {
31 | "rootFolder": {
32 | "serverGuid": "2017-abcd-server-service",
33 | "type": "Folder",
34 | "value": "group-d1"
35 | }
36 | }
37 | }
38 | ]
39 | ],
40 | "clientRef": "company:client:0",
41 | "hashedClientId": "200068",
42 | "groups": [
43 | "company.local\\CAAdmins",
44 | "company.local\\LicenseService.Administrators",
45 | "company.local\\SystemConfiguration.BashShellAdministrators"
46 | ],
47 | "systemDomains": [
48 | "company.local"
49 | ]
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/integration/card-outlet/demo-dashboard-card-outlet-render-definitions.interface.ts:
--------------------------------------------------------------------------------
1 | import { DemoDashboardOrganizerPackageEnumeration } from "./demo-dashboard-organizer-package.class";
2 | import {
3 | CardOutletExtensionViewRender,
4 | VendorClassificationItem,
5 | VendorClassificationMap
6 | } from "ngx-card-deck";
7 | import { OrganizerPackageEnumerationBase } from "ngx-card-deck";
8 | import { StandardDashboardOrganizerPackageEnumeration } from "../../client/common/standard/organizer/standard-dashboard-organizer-package.class";
9 |
10 |
11 | export interface DemoDashboardCardOutletExtensionViewRender extends CardOutletExtensionViewRender {
12 | organizerPackage: DemoDashboardOrganizerPackageEnumeration | StandardDashboardOrganizerPackageEnumeration | OrganizerPackageEnumerationBase;
13 | }
14 |
15 | export interface DemoDashboardVendorClassificationItem extends VendorClassificationItem {
16 | organizerPackage: DemoDashboardOrganizerPackageEnumeration | StandardDashboardOrganizerPackageEnumeration | OrganizerPackageEnumerationBase;
17 | }
18 |
19 |
20 | /* used in card outlet render definitions */
21 | export interface DemoDashboardVendorClassificationMap extends VendorClassificationMap {
22 |
23 | // recommended safety - provide known template classifications
24 | 0: DemoDashboardVendorClassificationItem;
25 | 1: DemoDashboardVendorClassificationItem;
26 | 2: DemoDashboardVendorClassificationItem;
27 | 3: DemoDashboardVendorClassificationItem;
28 | custom_sample: DemoDashboardVendorClassificationItem;
29 | nodeflow_sample: DemoDashboardVendorClassificationItem;
30 |
31 | [identifier: string]: DemoDashboardVendorClassificationItem;
32 | }
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/notification-overlay/nodeflow-studio-notification-overlay.component.ts:
--------------------------------------------------------------------------------
1 | import { AfterViewInit, Component, ElementRef, Input, OnDestroy, Renderer2 } from "@angular/core";
2 | import { ContentProjectionProxyCommand } from "../nodeflow-studio-overlay-template.interface";
3 |
4 |
5 | const resources = {
6 |
7 | layout: {
8 | offsetFromTrigger: 5,
9 | showingClass: "show",
10 | triggerShowingDelay: 100,
11 | width: 50,
12 | maxWidth: 100,
13 | height: 20,
14 | maxHeight: 40
15 | }
16 | };
17 |
18 | @Component({
19 | selector: 'nodeflow-studio-notification-overlay',
20 | templateUrl: './nodeflow-studio-notification-overlay.html',
21 | styleUrls: ['./nodeflow-studio-notification-overlay.scss']
22 | })
23 | export class NodeflowStudioNotificationOverlayComponent implements OnDestroy, AfterViewInit {
24 | contentBoundingBox: ClientRect;
25 |
26 | @Input() title: string | undefined;
27 | @Input() messages: Array | undefined;
28 | @Input() overlayCommand: ContentProjectionProxyCommand; // standard by contract
29 |
30 |
31 | constructor(
32 | private element: ElementRef,
33 | private renderer: Renderer2
34 | ) {
35 |
36 | }
37 |
38 | ngAfterViewInit() {
39 | this.contentBoundingBox = (this.element.nativeElement as HTMLDivElement).getBoundingClientRect();
40 |
41 | // slight wait before showing tooltip
42 | setTimeout(() => {
43 | this.renderer.addClass(this.element.nativeElement, resources.layout.showingClass);
44 | }, resources.layout.triggerShowingDelay);
45 |
46 | }
47 |
48 | ngOnDestroy() {
49 |
50 | }
51 |
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/styles/_pane-header.scss:
--------------------------------------------------------------------------------
1 | .pane-header {
2 | $expando-size: 0.7rem;
3 | padding: 0 0.2rem;
4 | border-radius: $expando-size;
5 | border: 1px solid rgba(0, 0, 0, .2);
6 | margin: 1px;
7 | background-color: rgba(255, 255, 255, .3);
8 | user-select: none;
9 |
10 | &:hover {
11 | text-decoration: underline;
12 | background-color: rgba(255, 255, 255, .3);
13 | border: 1px solid rgba(0, 0, 0, .3);
14 | }
15 |
16 | .pane-expando {
17 | display: inline-block;
18 |
19 | &::before {
20 | display: inline-block;
21 | background-color: rgba(0, 0, 0, .1);
22 | width: $expando-size;
23 | height: $expando-size;
24 | border-radius: 1rem;
25 | content: "\25b6";
26 | padding: 0.1rem;
27 | border: 1px rgba(0, 0, 0, .5) solid;
28 |
29 | text-align: center;
30 | margin: auto;
31 | vertical-align: middle;
32 | line-height: 1;
33 | }
34 |
35 | &:hover {
36 | &::before {
37 | background-color: rgba(0, 0, 0, .3);
38 | }
39 |
40 | cursor: pointer;
41 |
42 | }
43 |
44 | }
45 |
46 | &.pane-expanded .pane-expando {
47 | &::before {
48 | width: $expando-size;
49 | height: $expando-size;
50 | background-color: rgba(0, 0, 33, .1);
51 | content: "\25bc";
52 | }
53 |
54 | &:hover {
55 | &::before {
56 | background-color: rgba(0, 0, 0, .3);
57 | }
58 | }
59 |
60 | }
61 |
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-assembly-plugins/asset-node/nodeflow-asset-node.html:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
17 | header def
18 |
19 |
20 |
21 | AssetTypeId error:
22 |
23 |
24 |
25 |
26 |
27 |
29 |
30 |
31 |
32 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-assembly-plugins/asset-node/nodeflow-asset-node.service.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFactoryResolver, forwardRef, Inject, Injectable, Injector } from "@angular/core";
2 | import { StandardCardPluginServiceBase } from "../../../../../common/standard/card-outlet/card-assembly-plugins/base/standard-card-plugin-service-base";
3 | import { Observable, of } from "rxjs";
4 | import { NodeflowAssetNodeDataRecordEntitySchema } from "./nodeflow-asset-node.interface";
5 | import { NodeflowAssetNodeDataModel } from "./nodeflow-asset-node.model";
6 | import { CARD_OUTLET_COMPONENTS_CONFIG_TOKEN } from "ngx-card-deck";
7 | import { CardOutletExtensionViewRender } from "ngx-card-deck";
8 | import { TemplateTransporterService } from "ngx-card-deck";
9 |
10 |
11 | @Injectable()
12 | export class NodeflowAssetNodeService extends StandardCardPluginServiceBase {
13 |
14 | constructor(@Inject(forwardRef(() => CARD_OUTLET_COMPONENTS_CONFIG_TOKEN))
15 | protected staticConfigurationList: Array>,
16 | protected _templateTransporter: TemplateTransporterService,
17 | protected compResolver: ComponentFactoryResolver,
18 | protected _injector: Injector) {
19 | super(_injector);
20 | super.initialize();
21 | }
22 |
23 |
24 | getSummaryData$(resourceId: string): Observable {
25 | const data: NodeflowAssetNodeDataRecordEntitySchema = {name: "testing"};
26 | const model: NodeflowAssetNodeDataModel = {response: {entity: data}};
27 | // export class AssetNodeComponent (model as any));
29 | }
30 |
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample3/lib/views/card-assembly-plugins/introduction/introduction.scss:
--------------------------------------------------------------------------------
1 | @import "~ngx-card-deck/styles/theme";
2 |
3 | $componentType: "card-introduction";
4 | $widgetType: "introduction-widget";
5 | $gridResizeHandleSize: 10px;
6 |
7 | %filled-layout {
8 | content: "";
9 | position: absolute;
10 | top: 0;
11 | left: 0;
12 | right: 0;
13 | bottom: 0;
14 | }
15 |
16 | @mixin box-outline($size, $color, $alpha) {
17 | box-shadow: 0 0 0px $size rgba($color, $alpha);
18 | }
19 |
20 | :host {
21 | @import "../../../../../standard/card-outlet/card-assembly-plugins/base/styles/standard-card-assembly-plugin-base";
22 |
23 | // slightly darker
24 | background: rgba(0, 0, 0, .1);
25 | padding: $gridResizeHandleSize; // accommodate bounding handles around perimeter of card
26 |
27 | > .#{$widgetType} {
28 |
29 | // /++++++ RWD +++++++
30 | @include respond-to-rwd-list(('medium', 'large', 'maximum')) {
31 | // flex-wrap: nowrap;
32 | }
33 | // ++++++ RWD +++++++
34 |
35 | }
36 |
37 | }
38 |
39 | // highlight grid item with a defined shadow
40 | @include selectGridLayoutItemByComponentType("*", $componentType) {
41 | border: 1px solid rgba(0, 0, 0, .2);
42 | border-radius: 0.5rem;
43 | }
44 |
45 | // common style applied to header of all instances of the introduction card
46 | @include selectCardLayoutAspectByComponentType("*", $componentType, "header") {
47 | padding: .125rem .25rem;
48 | box-shadow: inset 0 -2px 0px 0px rgba(0, 0, 0, .2);
49 | }
50 |
51 | // common style applied to body of all instances of the introduction card
52 | @include selectCardLayoutAspectByComponentType("*", $componentType, "body") {
53 | padding: 0;
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/standard/organizer/standard-template.interface.ts:
--------------------------------------------------------------------------------
1 | import {
2 | FieldBaseMetadata,
3 | FieldRenderTemplateBaseMetadata
4 | } from "ngx-card-deck";
5 |
6 | export interface StandardFieldLocalized {
7 | key: string;
8 | }
9 |
10 | export interface StandardFieldDimension {
11 | value: number;
12 | metric: "%" | "px" | "rem" | "vw" | "vh";
13 | }
14 |
15 | export interface StandardFieldResponsiveDimension {
16 | minimum: StandardFieldDimension;
17 | initial: StandardFieldDimension;
18 | maximum: StandardFieldDimension;
19 | }
20 |
21 |
22 | // adds some additional fields
23 | export interface StandardFieldRenderTemplate extends FieldRenderTemplateBaseMetadata {
24 | organization: string; // project/group responsible for template construction
25 |
26 | }
27 |
28 | export type StandardFieldLayoutAlignmentType = "left" | "right" | "top" | "bottom" | "middle";
29 |
30 | export interface StandardFieldDataType {
31 | classifier: "string" | "number" | "boolean" | "date" | "datetime";
32 | specifier?: string; // floating point, currency, duration, timezone agnostic date plan
33 | collection?: boolean; // is the value a set of the same type or single value
34 | }
35 |
36 | // field level resource structure
37 |
38 | export interface StandardFieldMetadata extends FieldBaseMetadata {
39 | type: StandardFieldDataType;
40 |
41 | text: {
42 | header: StandardFieldLocalized;
43 | };
44 |
45 | layout: {
46 | alignment: StandardFieldLayoutAlignmentType;
47 | dimensions: {
48 | width?: StandardFieldResponsiveDimension;
49 | };
50 | };
51 |
52 | view: {
53 | header: StandardFieldRenderTemplate;
54 | body: StandardFieldRenderTemplate;
55 | };
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/core/com.company.group/views/card-assembly-plugins/summary-billboard/summary-billboard.scss:
--------------------------------------------------------------------------------
1 | @import "~ngx-card-deck/styles/theme";
2 |
3 | :host {
4 |
5 | @import '../base/styles/card-assembly-plugin-base';
6 |
7 | width: 100%;
8 | padding: 0 2rem;
9 |
10 | SECTION {
11 |
12 | $chartWidgetGutterWidth: 10%;
13 |
14 | &[role="chart-widget"] {
15 | justify-content: center;
16 | display: flex;
17 | flex-wrap: wrap;
18 | flex-direction: row;
19 | margin: 12px 0;
20 |
21 | // UX: strict conformance of having text fit, despite clippage
22 | overflow: hidden;
23 | // however, algorithms for wrap
24 |
25 | // sub layout / inner "cards"
26 | [role="chart-metric"] {
27 | display: flex;
28 | flex-direction: column;
29 | align-items: center;
30 | padding: 0.5rem 1rem;
31 | //background-color: rgba(0,0,0,.05);
32 |
33 | [role="chart-metric-value"] {
34 | margin: 0;
35 | }
36 |
37 | [role="chart-metric-label"] {
38 | margin: 0;
39 | }
40 |
41 | /*
42 | // intra-spacing
43 | &:not(:first-child) {
44 | margin-left: $chartWidgetGutterWidth / 2;
45 | }
46 |
47 | &:not(:last-child) {
48 | margin-right: $chartWidgetGutterWidth / 2;
49 | }
50 | //=========
51 | */
52 |
53 | }
54 |
55 | }
56 |
57 | }
58 |
59 | // /++++++ RWD +++++++
60 | @include respond-to-rwd-list(('medium', 'large', 'maximum')) {
61 | // flex-wrap: nowrap;
62 | }
63 | // ++++++ RWD +++++++
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample1/views/card-assembly-plugins/simple-grid-card/parser/inventory-summary-transformer.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from "@angular/core";
2 | import { ParsedResponseTransformBase } from "../../../../../../core/com.company.group/lib/services/sample-product/dataservice/parsed-response-transform-base.class";
3 | import { RelationalDataFieldMetadata } from "../../../../../../core/com.company.group/views/card-assembly-plugins/simple-grid-card/grid-relational-data-field-model.interface";
4 |
5 |
6 | // strategies based upon some token
7 | @Injectable()
8 | export class InventorySummaryTransformerService extends ParsedResponseTransformBase {
9 |
10 | // constructor() { super(); }
11 |
12 | public getStrategyIdentifier() {
13 | return "InventorySummaryTransformerService";
14 | }
15 |
16 |
17 | // step 1 extract collection
18 | public extract(serverResponse: any): Array {
19 |
20 | const dashboardServiceAllocatedCollectionName = "breakdownData";
21 | // service embeds collection with
22 | return serverResponse.response.entity[dashboardServiceAllocatedCollectionName];
23 | }
24 |
25 |
26 | // step 2 transform collection to view DAO
27 | // view helper: create subset of only visible columns, localize the displayed label
28 | public transform(dataItems: Array): Array {
29 |
30 |
31 | return dataItems.map((item) => {
32 | const entity: any = {
33 | // column :: server field
34 | "inventory_entity_name": item.name,
35 | "inventory_entity_count": item.necount,
36 | "inventory_entity_percentage": item.precentage
37 | };
38 |
39 |
40 | return entity;
41 | });
42 |
43 | }
44 |
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/extensions/views/consumer/nodeflow-asset-messages-consumer-collection.scss:
--------------------------------------------------------------------------------
1 |
2 | :host {
3 |
4 | }
5 |
6 | /*
7 | * present incoming message / socket details
8 | */
9 | [role="messagesConsumerTable"] {
10 | display: flex;
11 | flex-direction: row;
12 | overflow: hidden;
13 | flex-wrap: wrap;
14 | background-color: rgba(33, 143, 43, .08);
15 |
16 | > * {
17 | flex: 1;
18 | }
19 |
20 | TABLE[role="messageMetadataGrid"] {
21 |
22 | TBODY > TR > TH {
23 | background-color: rgba(88, 88, 88, .1);
24 | text-align: left;
25 | }
26 |
27 | TBODY > TR > TD {
28 | // background-color: rgba(188,88,88, .1);
29 | padding: 0 5px;
30 |
31 | &.wrap-identifier {
32 | word-break: break-all;
33 | }
34 |
35 | }
36 |
37 | }
38 |
39 | [role="messageConsumer"] {
40 | padding: 3px;
41 | margin: 3px;
42 | border: 1px solid rgba(88, 88, 88, .5);
43 | }
44 |
45 | [role="messageModelTopicLabel"] {
46 | text-align: center;
47 | }
48 |
49 | [role="messageModelStateClassifier"] {
50 | font-weight: normal;
51 | text-align: center;
52 | &::before {
53 | content: "\00ab";
54 | }
55 | &::after {
56 | content: "\00bb";
57 | }
58 | }
59 |
60 | // individual subforms per message extracted from node collection
61 | [role="messageModelSubform"] {
62 | border: 2px rgba(1, 1, 1, .2) solid;
63 | margin: 3px;
64 | padding: 3px;
65 |
66 | &:hover {
67 | // emphasis while focused
68 | background-color: rgba(83, 43, 143, .1);
69 | }
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/nodeflow-asset-node-token.ts:
--------------------------------------------------------------------------------
1 | import { InjectionToken, Type } from "@angular/core";
2 | import { MessageModel } from "../../../../../../../studio/nodeflow-studio-compositor/state/model/message.model";
3 | import { SocketConnectorRelationModel } from "../../../../../../../studio/nodeflow-studio-compositor/state/model/relation/socket-connector-relation.model";
4 | import { NodeflowAssetNodeTemplateComponent } from "./nodeflow-asset-node-template.component";
5 | import { NodeModel } from "../../../../../../../studio/nodeflow-studio-compositor/state/model/node.model";
6 |
7 | export interface NodeflowProject1ConsumerStateInjectable {
8 | nodeModel: NodeModel;
9 | message: MessageModel;
10 | socketConnectorRelation: SocketConnectorRelationModel;
11 | integrator: NodeflowAssetNodeTemplateComponent; // parent view component
12 | }
13 |
14 | export interface NodeflowProject1ProducerStateInjectable {
15 | nodeModel: NodeModel;
16 | message: MessageModel;
17 | integrator: NodeflowAssetNodeTemplateComponent; // parent view component
18 | }
19 |
20 |
21 | export const NODEFLOW_PROJECT1_CONSUMER_TOPIC_COMPONENT_RESOURCE_TOKEN = new InjectionToken('project 1 Topic Consumer Component State');
22 | export const NODEFLOW_PROJECT1_PRODUCER_TOPIC_COMPONENT_RESOURCE_TOKEN = new InjectionToken('project 1 Topic Producer Component State');
23 |
24 | export const NODEFLOW_PROJECT1_EXTENSION_CONSUMER_TOPIC_COMPONENT_MAP = new InjectionToken<{ [identifier: string]: Type }>("project1 extension consumer topic component");
25 | export const NODEFLOW_PROJECT1_EXTENSION_PRODUCER_TOPIC_COMPONENT_MAP = new InjectionToken<{ [identifier: string]: Type }>("project1 extension producer topic component");
26 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/state/model/message.model.ts:
--------------------------------------------------------------------------------
1 | import { SocketModel } from "./socket.model";
2 | import { BehaviorSubject, Observable, Subject } from "rxjs";
3 |
4 |
5 | export interface MessageModelForm {
6 | component: string; // nomenclature for identifying a view representation
7 | }
8 |
9 | export interface MessageModelState {
10 | classifier: string; // define the format of data. The `topic` attribute is only a "channel", not a payload schematic
11 | data: any | null; // business specifics
12 | }
13 |
14 | export class MessageModel {
15 | topic: string; //binding link to the producer socket
16 | form: MessageModelForm;
17 | // outbound message passed over stream
18 | socket: SocketModel;
19 | private _messageStateDataChangeSubject$ = new BehaviorSubject(null as any); // when nodeProducer get a new message state assigned
20 | private readonly _messageStateDataChange$: Subject; // when nodeProducer get a new message state assigned
21 |
22 | // actor associations
23 | private _state: MessageModelState;
24 |
25 | constructor() {
26 | this._messageStateDataChange$ = this._messageStateDataChangeSubject$;
27 | }
28 |
29 | // alias
30 | // get topic() { return this.socket.topic; }
31 |
32 | // not recommended to observe the message directly.
33 | // may deprecate if no real use case
34 | get selectMessageStateData$(): Observable {
35 | return this._messageStateDataChange$;
36 | }
37 |
38 | get state(): MessageModelState {
39 | return this._state;
40 | }
41 |
42 | // when state is assigned synchronously, consider this an initialization
43 | set state(modelState: MessageModelState) {
44 | this._state = modelState;
45 | this._messageStateDataChangeSubject$.next(this);
46 | }
47 |
48 | }
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/com.company.sample3/lib/views/card-templates/components/simple-introduction/styles/_icons.scss:
--------------------------------------------------------------------------------
1 | // -------- copy and paste --- do not use as is ------------
2 | $icon-descriptor-tag: "introduction-icon";
3 |
4 | [class^="introduction-icon-"], [class*=" introduction-icon-"] {
5 | background: url("/assets/organizers/com.company.sample3/introduction/simple/icons.svg") no-repeat;
6 | width: 16px;
7 | height: 16px;
8 | display: inline-block;
9 | box-sizing: content-box;
10 | }
11 |
12 | .introduction-icon- {
13 |
14 | &symbol6 {
15 | background-position: 0 0;
16 | }
17 | &symbol5 {
18 | background-position: -32px 0;
19 | }
20 | &symbol3 {
21 | background-position: -64px 0;
22 | }
23 | &symbol8 {
24 | background-position: -97px 0;
25 | }
26 | &symbol9 {
27 | background-position: -130px 0;
28 | }
29 | &symbol16 {
30 | background-position: -160px 0;
31 | }
32 | &symbol18 {
33 | background-position: -192px 0;
34 | }
35 | &symbol4 {
36 | background-position: -224px 0;
37 | }
38 | &symbol19 {
39 | background-position: -256px 0;
40 | }
41 | &symbol13 {
42 | background-position: -288px 0;
43 | }
44 | &symbol1 {
45 | background-position: -320px 0;
46 | }
47 | &symbol12 {
48 | background-position: -351px 0;
49 | }
50 | &symbol15 {
51 | background-position: -416px 0;
52 | }
53 | &symbol17 {
54 | background-position: -446px 0;
55 | }
56 | &symbol11 {
57 | background-position: -481px 0;
58 | }
59 | &symbol14 {
60 | background-position: -64px -32px;
61 | }
62 | &symbol105 {
63 | background-position: -130px -32px;
64 | }
65 | &symbol9 {
66 | background-position: -160px -32px;
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/styles/_nodeflow-icons.scss:
--------------------------------------------------------------------------------
1 | // -------- copy and paste --- do not use as is ------------
2 | $icon-descriptor-tag: "nodeflow-studio-canvas-icon";
3 |
4 |
5 | [class^="nodeflow-studio-canvas-icon-"], [class*=" nodeflow-studio-canvas-icon-"] {
6 | background: url("/assets/organizers/nodeflow/nodeflow-asset-node/sprite.svg") no-repeat;
7 | width: 16px;
8 | height: 16px;
9 | display: inline-block;
10 | box-sizing: content-box;
11 | }
12 |
13 | .nodeflow-studio-canvas-icon- {
14 |
15 | &symbol6 {
16 | background-position: 0 0;
17 | }
18 | &symbol5 {
19 | background-position: -32px 0;
20 | }
21 | &symbol3 {
22 | background-position: -64px 0;
23 | }
24 | &symbol8 {
25 | background-position: -97px 0;
26 | }
27 | &symbol9 {
28 | background-position: -130px 0;
29 | }
30 | &symbol16 {
31 | background-position: -160px 0;
32 | }
33 | &symbol18 {
34 | background-position: -192px 0;
35 | }
36 | &symbol4 {
37 | background-position: -224px 0;
38 | }
39 | &symbol19 {
40 | background-position: -256px 0;
41 | }
42 | &symbol13 {
43 | background-position: -288px 0;
44 | }
45 | &symbol1 {
46 | background-position: -320px 0;
47 | }
48 | &symbol12 {
49 | background-position: -351px 0;
50 | }
51 | &symbol15 {
52 | background-position: -416px 0;
53 | }
54 | &symbol17 {
55 | background-position: -446px 0;
56 | }
57 | &symbol11 {
58 | background-position: -481px 0;
59 | }
60 | &symbol14 {
61 | background-position: -64px -32px;
62 | }
63 | &symbol105 {
64 | background-position: -130px -32px;
65 | }
66 | &symbol9 {
67 | background-position: -160px -32px;
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/pipes/node-socket-list-by-socket-connector-relation-async.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from "@angular/core";
2 | import { SocketConnectorRelationModel } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/relation/socket-connector-relation.model";
3 | import { NodeModel } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/node.model";
4 | import {
5 | SocketConnectorType,
6 | SocketModel
7 | } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/socket.model";
8 | import { Observable } from "rxjs";
9 | import { map } from "rxjs/operators";
10 |
11 | // organizes sockets consistently by a deterministic ordering business rule, separating disabled ports to the end
12 | @Pipe({
13 | name: "nodeSocketListBySocketConnectorRelationAsync"
14 | })
15 | export class NodeSocketListBySocketConnectorRelationAsyncPipe implements PipeTransform {
16 |
17 | transform(stream$: Observable, ownerNode: NodeModel): Observable> {
18 | const socketType: SocketConnectorType = SocketConnectorType.input;
19 |
20 | return stream$.pipe(map((scr) => {
21 |
22 | if (ownerNode.link) {
23 | switch (socketType) {
24 |
25 | case SocketConnectorType.input:
26 | return Array.from(ownerNode.link!.consumerSocketCollection);
27 |
28 | // case SocketConnectorType.output:
29 | // return Array.from(ownerNode.link!.producerSocketCollection);
30 |
31 | default:
32 | return [];
33 | }
34 | } else {
35 | return [];
36 | }
37 |
38 | })
39 | );
40 |
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-assembly-plugins/asset-node/nodeflow-asset-node.model.ts:
--------------------------------------------------------------------------------
1 | import { NodeflowAssetNodeDataRecordEntitySchema } from "./nodeflow-asset-node.interface";
2 | import { DashboardCardModelSchema } from "ngx-card-deck";
3 | import { AssetNodeConfigurationCardSchema } from "../../../lib/models/parsers/dashboard/integration/nodeflow-configuration-preprocessor.interface";
4 | import { BusinessNodeflowCardProviderSchema } from "../../../lib/models/parsers/dashboard/provider/business-nodeflow-card-provider.interface";
5 |
6 |
7 | // structure of entity in `asset-type-list` json
8 | export interface AssetTypeConfigurationSchema {
9 | assetTypeId: string;
10 | iconDecoratorClass: string;
11 | localization: {
12 | name: {
13 | text: string;
14 | };
15 | };
16 | }
17 |
18 | // component links via `cardMetadata`
19 | export interface AssetNodeCardMetadataSchema {
20 | schema: AssetNodeConfigurationCardSchema;
21 | // business interface for provider linked on card
22 | businessProvider: BusinessNodeflowCardProviderSchema;
23 |
24 | assetType: AssetTypeConfigurationSchema;
25 | derived: {
26 | assetTypeIconClass: string;
27 | };
28 | }
29 |
30 |
31 | // potential segment drag/reassign states
32 | export enum NodeflowAssetNodeComponentInteractionSelectingState {
33 | none = 0,
34 | focused // setting while selecting from a dropdown menu to highlight which socket might take some action upon
35 | }
36 |
37 | export interface NodeflowAssetNodeComponentInteractionRules {
38 | selecting: NodeflowAssetNodeComponentInteractionSelectingState;
39 | }
40 |
41 |
42 | // able to transform and mutate, based upon business rule strategies
43 | export class NodeflowAssetNodeDataModel implements DashboardCardModelSchema {
44 | // envelope holding records
45 | response: {
46 | entity: NodeflowAssetNodeDataRecordEntitySchema;
47 | };
48 | }
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/styles/_node-socket.scss:
--------------------------------------------------------------------------------
1 | $socketFill: #0a8;
2 |
3 | $producerFill: $socketFill;
4 | $consumerFill: $socketFill;
5 |
6 | $disabledFill: #777777;
7 | $emptyStroke: #ffffff;
8 | $hoverStroke: #222333;
9 | $focusStroke: #ffffff;
10 |
11 | [role="nodeSocket"] {
12 | paint-order: stroke;
13 |
14 | &.nodeSocketProducer {
15 | fill: $producerFill;
16 | stroke: darken($producerFill, 80%);
17 |
18 | // forced highlighting producer, by an indirect interaction
19 | &.nodeSocketFocusedAction {
20 | fill: lighten($producerFill, 5%);
21 | }
22 |
23 | }
24 |
25 | &.nodeSocketConsumer {
26 | fill: $consumerFill;
27 | stroke: darken($consumerFill, 80%);
28 |
29 | // forced highlighting consumer, by an indirect interaction
30 | &.nodeSocketFocusedAction {
31 | fill: lighten($consumerFill, 5%);
32 | }
33 |
34 | }
35 |
36 | &.nodeSocketDisabled {
37 | fill: $disabledFill;
38 | }
39 |
40 | // no attached subscribers
41 | &.nodeSocketEmpty {
42 | stroke-opacity: 0.4;
43 | stroke: $emptyStroke;
44 | fill-opacity: 0.2;
45 | }
46 |
47 | // has connection(s)
48 | &:not(.nodeSocketEmpty) {
49 | stroke-opacity: 1;
50 | }
51 |
52 | // forced highlighting producer, by an indirect interaction
53 | &.nodeSocketFocusedAction {
54 | stroke-opacity: 1;
55 | stroke-width: 3px;
56 | stroke: $focusStroke;
57 | animation: glowingFadeInOut 2s infinite;
58 | }
59 |
60 | &:hover {
61 | stroke-opacity: 1;
62 | stroke: $hoverStroke;
63 | }
64 |
65 | @keyframes glowingFadeInOut {
66 | 0% {
67 | stroke-width: 1px;
68 | stroke-opacity: 1;
69 | }
70 | 50%, 100% {
71 | stroke-width: 10px;
72 | stroke-opacity: 0;
73 | }
74 |
75 | }
76 |
77 | }
78 |
79 |
80 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/integration/card-outlet/demo-dashboard-outlet-shared-provider.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from "@angular/common";
2 | import { NgModule } from "@angular/core";
3 | import { DEMO_CONFIG_STATIC_INTEGRATION } from "../platform/demo-dashboard-module-integration-token.service";
4 | import {
5 | CARD_OUTLET_COMPONENTS_CONFIG_TOKEN,
6 | defaultAllocatedCardOutletExtensionViewRenderDefinitionsList
7 | } from "ngx-card-deck";
8 | import { CardOutletService } from "ngx-card-deck";
9 |
10 | // Demo version - CardOutletProviderSharedModule
11 | // provision custom integration dependencies for dashboard engine to use for the view
12 | // shared between external consumer project and internal engine
13 | @NgModule({
14 |
15 | imports: [
16 | CommonModule,
17 | // client code
18 | ...DEMO_CONFIG_STATIC_INTEGRATION.getAllocatedModulesList()
19 | ],
20 |
21 | entryComponents: [
22 | ...DEMO_CONFIG_STATIC_INTEGRATION.getAllocatedComponentsList()
23 | ],
24 |
25 | declarations: [
26 |
27 | // client code
28 | ...DEMO_CONFIG_STATIC_INTEGRATION.getAllocatedComponentsList(),
29 | ...DEMO_CONFIG_STATIC_INTEGRATION.getAllocatedDirectivesList()
30 | ],
31 |
32 | providers: [
33 | // ------- configurable phase
34 | {
35 | provide: CARD_OUTLET_COMPONENTS_CONFIG_TOKEN,
36 | useValue: [...DEMO_CONFIG_STATIC_INTEGRATION.allocatedCardOutletExtensionViewRenderDefinitionsList, ...defaultAllocatedCardOutletExtensionViewRenderDefinitionsList]
37 | },
38 |
39 | {
40 | provide: CardOutletService,
41 | useClass: CardOutletService,
42 | deps: [CARD_OUTLET_COMPONENTS_CONFIG_TOKEN] // actual config token must be provided in the enclosing module
43 | },
44 | // ------- /configurable phase
45 |
46 | // client code
47 | ...DEMO_CONFIG_STATIC_INTEGRATION.getAllocatedServicesList()
48 | ]
49 |
50 | })
51 | export class DemoDashboardOutletSharedProviderModule {
52 |
53 | constructor() {
54 | }
55 |
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/core/com.company.group/views/card-assembly-plugins/simple-grid-card/grid-relational-data-field-model.interface.ts:
--------------------------------------------------------------------------------
1 | // server message format
2 |
3 | import {
4 | FieldBaseMetadata,
5 | FieldRenderTemplateBaseMetadata
6 | } from "ngx-card-deck";
7 |
8 | export interface RelationalDataFieldLocalized {
9 | key: string;
10 | }
11 |
12 |
13 | export interface RelationalDataFieldDimension {
14 | clipping: boolean; // when set, restrained content to fit within cell width, overflow preventer
15 | value: number;
16 | metric: "%" | "px" | "rem" | "vw" | "vh";
17 | }
18 |
19 | export interface RelationalDataFieldResponsiveDimension {
20 | minimum: RelationalDataFieldDimension;
21 | initial: RelationalDataFieldDimension;
22 | maximum: RelationalDataFieldDimension;
23 | }
24 |
25 |
26 | // adds some additional fields
27 | export interface RelationalDataFieldRenderTemplate extends FieldRenderTemplateBaseMetadata {
28 | organization: string; // team responsible for template construction
29 |
30 | }
31 |
32 | export type RelationalDataFieldLayoutAlignmentType = "left" | "right" | "top" | "bottom" | "middle";
33 |
34 | export interface RelationalDataFieldDataType {
35 | classifier: "string" | "number" | "boolean" | "date" | "datetime";
36 | // opt in
37 | specifier?: string; // floating point, currency, duration, timezone agnostic date plan
38 | collection?: boolean; // is the value a set of the same type or single value
39 | }
40 |
41 | // field level resource structure
42 |
43 | export interface RelationalDataFieldMetadata extends FieldBaseMetadata {
44 | type: RelationalDataFieldDataType;
45 |
46 | text: {
47 | header: RelationalDataFieldLocalized;
48 | };
49 |
50 | layout: {
51 | alignment: RelationalDataFieldLayoutAlignmentType;
52 | dimensions: {
53 | width?: RelationalDataFieldResponsiveDimension;
54 | };
55 | };
56 |
57 | view: {
58 | header: RelationalDataFieldRenderTemplate;
59 | body: RelationalDataFieldRenderTemplate;
60 | };
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/config/deployments/local/environment.json:
--------------------------------------------------------------------------------
1 | {
2 | "deployment": {
3 | "page": {
4 | "embedded": false,
5 | "sandboxed": false
6 | }
7 | },
8 | "services": {
9 | "dashboardMetadata": {
10 | "mocked": false,
11 | "transport": "network",
12 | "publicPath": null,
13 | "route": {
14 | "protocol": null,
15 | "host": null,
16 | "port": null,
17 | "path": "/network/vendors/extension/{{ dashboardOrganizerPath }}/metadata/dashboard",
18 | "extension": ".json",
19 | "authentication": null
20 | }
21 | },
22 | "session": {
23 | "transport": "service",
24 | "mocked": true,
25 | "publicPath": null,
26 | "route": {
27 | "protocol": null,
28 | "host": null,
29 | "port": null,
30 | "path": "/network/vendors/extension/{{ dashboardOrganizerPath }}/acme/session/usersession",
31 | "extension": ".json",
32 | "authentication": null
33 | }
34 | },
35 | "remote-served-service": {
36 | "transport": "service",
37 | "mocked": false,
38 | "publicPath": null,
39 | "route": {
40 | "protocol": null,
41 | "host": null,
42 | "port": null,
43 | "path": "",
44 | "authentication": {
45 | "sameOriginPolicyEnabled": true
46 | },
47 | "extension": null
48 | }
49 | },
50 | "rest": {
51 | "transport": "service",
52 | "mocked": true,
53 | "publicPath": null,
54 | "route": {
55 | "protocol": null,
56 | "host": null,
57 | "port": null,
58 | "path": "",
59 | "extension": null,
60 | "authentication": null
61 | }
62 | },
63 | "network": {
64 | "transport": "network",
65 | "mocked": false,
66 | "publicPath": null,
67 | "route": {
68 | "protocol": null,
69 | "host": null,
70 | "port": null,
71 | "path": "",
72 | "extension": null,
73 | "authentication": null
74 | }
75 | }
76 | }
77 | }
78 |
79 |
--------------------------------------------------------------------------------
/mock/network/vendors/extension/com.company.sample1/data-server/web-services/plugins-catalog-list.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "com.company.samples.network-wssdk-html",
4 | "version": "6.5.0",
5 | "name": "network WSSDK",
6 | "vendor": "company",
7 | "description": "SDK sample using WSSDK to access network data",
8 | "state": "enabled"
9 | },
10 | {
11 | "id": "com.company.remotePluginExample",
12 | "version": "1.0.0",
13 | "name": "",
14 | "vendor": "",
15 | "description": "",
16 | "state": "enabled"
17 | },
18 | {
19 | "id": "com.company.samples.customobject",
20 | "version": "1.0.0",
21 | "name": "custom-object",
22 | "vendor": "Add vendor",
23 | "description": "Add plugin description",
24 | "state": "enabled"
25 | },
26 | {
27 | "id": "com.company.samples.globalview-html",
28 | "version": "6.5.0",
29 | "name": "Global View",
30 | "vendor": "company",
31 | "description": "SDK sample adding a global view and a java service",
32 | "state": "enabled"
33 | },
34 | {
35 | "id": "com.company.network.client.html",
36 | "version": "6.5.0",
37 | "name": "UI Platform application",
38 | "vendor": "company",
39 | "description": "Application hosting company web clients",
40 | "state": "enabled"
41 | },
42 | {
43 | "id": "com.company.ssoadminui",
44 | "version": "6.5.0",
45 | "name": "SSO Admin UI plugin",
46 | "vendor": "company",
47 | "description": "SSO Admin UI plugin",
48 | "state": "enabled"
49 | },
50 | {
51 | "id": "com.company.samples.chassisA.html",
52 | "version": "6.5.0",
53 | "name": "ChassisA Client",
54 | "vendor": "company",
55 | "description": "SDK sample adding chassis objects (simple version)",
56 | "state": "enabled"
57 | },
58 | {
59 | "id": "com.company.samples.chassisB.html",
60 | "version": "6.5.0",
61 | "name": "ChassisB Client",
62 | "vendor": "company",
63 | "description": "SDK sample adding chassis objects and relations (advanced version)",
64 | "state": "enabled"
65 | }
66 | ]
67 |
68 |
--------------------------------------------------------------------------------
/src/app/pages/dashboard/dashboard-page/client/common/standard/card-outlet/card-assembly-plugins/base/standard-card-plugin-service-base.ts:
--------------------------------------------------------------------------------
1 | import { Observable, of } from "rxjs";
2 | import { CardPluginBaseClassService } from "ngx-card-deck";
3 | import {
4 | CardOutletExtensionViewRender,
5 | DashboardCardDataReadable,
6 | DashboardDataReaderResponseDeliverable
7 | } from "ngx-card-deck";
8 | import { OrganizerPackageEnumerationBase } from "ngx-card-deck";
9 | import {
10 | DashboardConfigurationResourceCardSchema,
11 | DashboardConfigurationResourceFacade
12 | } from "ngx-card-deck";
13 | import { DashboardComponent } from "ngx-card-deck";
14 |
15 |
16 | export abstract class StandardCardPluginServiceBase extends CardPluginBaseClassService implements DashboardCardDataReadable {
17 |
18 | // injected from subclass
19 | protected staticConfigurationList: Array>;
20 | protected internalOrganizersList: Array;
21 |
22 | // subclass can define fetch and data assembly
23 | streamInitialDataModel(dcrf: DashboardConfigurationResourceFacade,
25 | dashboardFacade: DashboardComponent): Observable> {
26 | return of({});
27 | }
28 |
29 | protected initialize() {
30 |
31 | // setup internal defaults
32 | this.internalOrganizersList = [OrganizerPackageEnumerationBase.internal];
33 | // rule: is internal
34 | const isInternallyOrganizedLambda = (o: CardOutletExtensionViewRender) =>
35 | this.internalOrganizersList.indexOf(o.organizerPackage) >= 0;
36 |
37 | // extract permitted and resolved team templates
38 | this.staticConfigurationList
39 | .filter((o) => !isInternallyOrganizedLambda(o))
40 | .forEach((o) => this.templatableClassesListMap!.set(o.identifier, o.resolveTemplatableClassesList!));
41 | }
42 |
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/config/deployments/development/environment.json:
--------------------------------------------------------------------------------
1 | {
2 | "deployment": {
3 | "page": {
4 | "embedded": false,
5 | "sandboxed": false
6 | }
7 | },
8 | "services": {
9 | "dashboardMetadata": {
10 | "mocked": false,
11 | "transport": "network",
12 | "publicPath": "/dashboard",
13 | "route": {
14 | "protocol": null,
15 | "host": null,
16 | "port": null,
17 | "path": "/network/vendors/extension/{{ dashboardOrganizerPath }}/metadata/dashboard",
18 | "extension": ".json",
19 | "authentication": null
20 | }
21 | },
22 | "session": {
23 | "transport": "service",
24 | "mocked": true,
25 | "publicPath": "/dashboard",
26 | "route": {
27 | "protocol": null,
28 | "host": null,
29 | "port": null,
30 | "path": "/network/vendors/extension/{{ dashboardOrganizerPath }}/acme/session/usersession",
31 | "extension": ".json",
32 | "authentication": null
33 | }
34 | },
35 | "remote-served-service": {
36 | "transport": "service",
37 | "mocked": false,
38 | "publicPath": null,
39 | "route": {
40 | "protocol": null,
41 | "host": null,
42 | "port": null,
43 | "path": "",
44 | "authentication": {
45 | "sameOriginPolicyEnabled": true
46 | },
47 | "extension": null
48 | }
49 | },
50 | "rest": {
51 | "transport": "service",
52 | "mocked": true,
53 | "publicPath": "/dashboard",
54 | "route": {
55 | "protocol": null,
56 | "host": null,
57 | "port": null,
58 | "path": "",
59 | "extension": null,
60 | "authentication": null
61 | }
62 | },
63 | "network": {
64 | "transport": "network",
65 | "mocked": false,
66 | "publicPath": "/dashboard",
67 | "route": {
68 | "protocol": null,
69 | "host": null,
70 | "port": null,
71 | "path": "",
72 | "extension": null,
73 | "authentication": null
74 | }
75 | }
76 |
77 | }
78 | }
79 |
80 |
--------------------------------------------------------------------------------