├── src ├── assets │ └── .gitkeep ├── app │ ├── pages │ │ └── dashboard │ │ │ ├── demo-dashboard.html │ │ │ ├── dashboard-page │ │ │ ├── client │ │ │ │ ├── core │ │ │ │ │ └── com.company.group │ │ │ │ │ │ ├── models │ │ │ │ │ │ └── parsers │ │ │ │ │ │ │ └── resolvers │ │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ │ ├── views │ │ │ │ │ │ └── card-assembly-plugins │ │ │ │ │ │ │ ├── base │ │ │ │ │ │ │ └── styles │ │ │ │ │ │ │ │ └── card-assembly-plugin-base.scss │ │ │ │ │ │ │ ├── simple-grid-card │ │ │ │ │ │ │ ├── simple-grid-card.model.ts │ │ │ │ │ │ │ ├── simple-grid-card.scss │ │ │ │ │ │ │ └── grid-relational-data-field-model.interface.ts │ │ │ │ │ │ │ ├── metrics-billboard │ │ │ │ │ │ │ ├── metrics-billboard.scss │ │ │ │ │ │ │ ├── metrics-billboard.model.ts │ │ │ │ │ │ │ └── directives │ │ │ │ │ │ │ │ └── progress-meter.directive.ts │ │ │ │ │ │ │ └── summary-billboard │ │ │ │ │ │ │ ├── summary-billboard.model.ts │ │ │ │ │ │ │ ├── summary-billboard.html │ │ │ │ │ │ │ └── summary-billboard.scss │ │ │ │ │ │ └── lib │ │ │ │ │ │ └── services │ │ │ │ │ │ └── sample-product │ │ │ │ │ │ ├── dataservice │ │ │ │ │ │ ├── data-collection-parser-base.ts │ │ │ │ │ │ └── parsed-response-transform-base.class.ts │ │ │ │ │ │ └── platform │ │ │ │ │ │ └── demo-app-terminology.interface.ts │ │ │ │ ├── common │ │ │ │ │ ├── com.company.sample2 │ │ │ │ │ │ ├── views │ │ │ │ │ │ │ ├── card-assembly-plugins │ │ │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ │ │ └── card-templates │ │ │ │ │ │ │ │ └── components │ │ │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ │ └── metadata │ │ │ │ │ │ │ └── configurations │ │ │ │ │ │ │ ├── simple-deck.inline.json.ts │ │ │ │ │ │ │ ├── standard-deck.inline.json.ts │ │ │ │ │ │ │ └── simple-deck.inline.json │ │ │ │ │ ├── com.company.sample1 │ │ │ │ │ │ └── views │ │ │ │ │ │ │ ├── card-templates │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ ├── demo-client-grid-card │ │ │ │ │ │ │ │ │ ├── styles │ │ │ │ │ │ │ │ │ │ ├── _inventory-summary-grid-column.scss │ │ │ │ │ │ │ │ │ │ └── _bar-graph.scss │ │ │ │ │ │ │ │ │ ├── demo-client-grid-card-template.scss │ │ │ │ │ │ │ │ │ └── demo-client-grid-card-icon.directive.ts │ │ │ │ │ │ │ │ ├── demo-client-summary-billboard │ │ │ │ │ │ │ │ │ └── demo-client-summary-billboard-template.html │ │ │ │ │ │ │ │ └── demo-client-metrics-billboard │ │ │ │ │ │ │ │ │ ├── demo-client-metrics-billboard-template.html │ │ │ │ │ │ │ │ │ └── demo-client-metrics-billboard-template.module.ts │ │ │ │ │ │ │ └── modules │ │ │ │ │ │ │ │ └── com_company_sample1_template.module.ts │ │ │ │ │ │ │ └── card-assembly-plugins │ │ │ │ │ │ │ ├── simple-grid-card │ │ │ │ │ │ │ └── parser │ │ │ │ │ │ │ │ ├── installed-plugins-dashboard-transformer.service.ts │ │ │ │ │ │ │ │ └── inventory-summary-transformer.service.ts │ │ │ │ │ │ │ └── summary-billboard │ │ │ │ │ │ │ └── summary-parser.service.ts │ │ │ │ │ ├── standard │ │ │ │ │ │ ├── card-outlet │ │ │ │ │ │ │ ├── card-assembly-plugins │ │ │ │ │ │ │ │ └── base │ │ │ │ │ │ │ │ │ ├── styles │ │ │ │ │ │ │ │ │ └── standard-card-assembly-plugin-base.scss │ │ │ │ │ │ │ │ │ ├── standard-card-plugin-template-base.ts │ │ │ │ │ │ │ │ │ └── standard-card-plugin-service-base.ts │ │ │ │ │ │ │ ├── standard-dashboard-vendor-classification.class.ts │ │ │ │ │ │ │ └── standard-dashboard-card-outlet-render-definitions.interface.ts │ │ │ │ │ │ └── organizer │ │ │ │ │ │ │ ├── standard-dashboard-organizer-package.class.ts │ │ │ │ │ │ │ └── standard-template.interface.ts │ │ │ │ │ └── com.company.sample3 │ │ │ │ │ │ └── lib │ │ │ │ │ │ └── views │ │ │ │ │ │ ├── card-templates │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ └── simple-introduction │ │ │ │ │ │ │ │ └── styles │ │ │ │ │ │ │ │ ├── _devices.scss │ │ │ │ │ │ │ │ └── _icons.scss │ │ │ │ │ │ └── modules │ │ │ │ │ │ │ └── com_company_sample3_template.module.ts │ │ │ │ │ │ └── card-assembly-plugins │ │ │ │ │ │ └── introduction │ │ │ │ │ │ ├── data │ │ │ │ │ │ └── configuration.json │ │ │ │ │ │ ├── introduction.html │ │ │ │ │ │ ├── parser │ │ │ │ │ │ └── introduction-parser.service.ts │ │ │ │ │ │ └── introduction.scss │ │ │ │ └── organizers │ │ │ │ │ └── nodeflow │ │ │ │ │ ├── views │ │ │ │ │ ├── card-assembly-plugins │ │ │ │ │ │ └── asset-node │ │ │ │ │ │ │ ├── nodeflow-asset-node.interface.ts │ │ │ │ │ │ │ ├── styles │ │ │ │ │ │ │ └── _toggle-arrow.scss │ │ │ │ │ │ │ ├── nodeflow-asset-node.html │ │ │ │ │ │ │ ├── nodeflow-asset-node.service.ts │ │ │ │ │ │ │ └── nodeflow-asset-node.model.ts │ │ │ │ │ └── card-templates │ │ │ │ │ │ └── nodeflow-asset-node │ │ │ │ │ │ ├── extensions │ │ │ │ │ │ ├── topics │ │ │ │ │ │ │ └── color │ │ │ │ │ │ │ │ └── consumer │ │ │ │ │ │ │ │ ├── nodeflow-asset-topics-color-consumer.scss │ │ │ │ │ │ │ │ └── nodeflow-asset-topics-color-consumer.html │ │ │ │ │ │ ├── views │ │ │ │ │ │ │ ├── delivery │ │ │ │ │ │ │ │ └── default │ │ │ │ │ │ │ │ │ ├── nodeflow-asset-default-consumer.scss │ │ │ │ │ │ │ │ │ ├── nodeflow-asset-default-consumer.html │ │ │ │ │ │ │ │ │ └── nodeflow-asset-default-consumer.component.ts │ │ │ │ │ │ │ ├── producer │ │ │ │ │ │ │ │ ├── nodeflow-asset-messages-producer-collection.html │ │ │ │ │ │ │ │ ├── nodeflow-asset-messages-producer-collection.scss │ │ │ │ │ │ │ │ └── nodeflow-asset-messages-producer-collection.component.ts │ │ │ │ │ │ │ └── consumer │ │ │ │ │ │ │ │ ├── nodeflow-asset-messages-consumer-collection.component.ts │ │ │ │ │ │ │ │ └── nodeflow-asset-messages-consumer-collection.scss │ │ │ │ │ │ └── forms │ │ │ │ │ │ │ └── simulator-producer-form-view.interface.ts │ │ │ │ │ │ ├── pipes │ │ │ │ │ │ ├── message-model-state-data-iterable.pipe.ts │ │ │ │ │ │ ├── nodeflow-message-model-state-data-tuples.pipe.ts │ │ │ │ │ │ ├── nodeflow-message-model-has-state.pipe.ts │ │ │ │ │ │ ├── nodeflow-socket-connector-type.pipe.ts │ │ │ │ │ │ ├── extract-socket-connector-relation-list-by-socket.pipe.ts │ │ │ │ │ │ ├── extract-socket-connector-relation-list-by-state-type.pipe.ts │ │ │ │ │ │ ├── nodeflow-message-connectors-route-relation-by-socket-filter.pipe.ts │ │ │ │ │ │ └── node-socket-list-by-socket-connector-relation-async.pipe.ts │ │ │ │ │ │ ├── styles │ │ │ │ │ │ ├── _sockets-table.scss │ │ │ │ │ │ ├── _pane-header.scss │ │ │ │ │ │ └── _nodeflow-icons.scss │ │ │ │ │ │ └── nodeflow-asset-node-token.ts │ │ │ │ │ ├── lib │ │ │ │ │ └── models │ │ │ │ │ │ └── parsers │ │ │ │ │ │ └── dashboard │ │ │ │ │ │ └── provider │ │ │ │ │ │ └── business-nodeflow-card-provider.interface.ts │ │ │ │ │ └── metadata │ │ │ │ │ ├── schema │ │ │ │ │ ├── card-catalog-resources.interface.ts │ │ │ │ │ ├── card-project.interface.ts │ │ │ │ │ └── nodeflow-card-project.interface.ts │ │ │ │ │ └── projects │ │ │ │ │ └── project1 │ │ │ │ │ └── catalog.json │ │ │ ├── integration │ │ │ │ ├── environment │ │ │ │ │ ├── demo-dashboard-business-entity.state.ts │ │ │ │ │ └── demo-dashboard-deployment-configuration.service.ts │ │ │ │ ├── resolvers │ │ │ │ │ └── demo-dashboard-resolver-collaborators.class.ts │ │ │ │ ├── card-outlet │ │ │ │ │ ├── demo-dashboard-organizer-package.class.ts │ │ │ │ │ ├── demo-dashboard-card-outlet-render-definitions.interface.ts │ │ │ │ │ └── demo-dashboard-outlet-shared-provider.module.ts │ │ │ │ └── platform │ │ │ │ │ └── demo-dashboard-platform-communicator.service.ts │ │ │ ├── grid-theme.scss │ │ │ ├── views │ │ │ │ └── toolbar │ │ │ │ │ ├── remove-nodeflow │ │ │ │ │ ├── toolbar-remove-nodeflow.scss │ │ │ │ │ └── toolbar-remove-nodeflow.module.ts │ │ │ │ │ ├── toolbar-nodeflow-action.module.ts │ │ │ │ │ ├── serialize-model │ │ │ │ │ ├── toolbar-serialize-model.scss │ │ │ │ │ ├── toolbar-serialize-model.module.ts │ │ │ │ │ └── toolbar-serialize-model.model.ts │ │ │ │ │ ├── tabs-container │ │ │ │ │ ├── toolbar-tabs-container.component.ts │ │ │ │ │ ├── toolbar-tabs-container.scss │ │ │ │ │ ├── toolbar-tabs-container.module.ts │ │ │ │ │ └── toolbar-tabs-container.html │ │ │ │ │ ├── add-nodeflow │ │ │ │ │ ├── pipes │ │ │ │ │ │ ├── asset-type-order-by.pipe.ts │ │ │ │ │ │ ├── find-nodeflow-card-project-package.pipe.ts │ │ │ │ │ │ ├── find-card-catalog-resources-package.pipe.ts │ │ │ │ │ │ └── limit-message-by-socket.pipe.ts │ │ │ │ │ ├── toolbar-add-nodeflow.interface.ts │ │ │ │ │ └── toolbar-add-nodeflow.module.ts │ │ │ │ │ ├── remove-socket-connector-relation │ │ │ │ │ ├── socket-connector-relation-model-state-filter.pipe.ts │ │ │ │ │ ├── toolbar-remove-socket-connector-relation.scss │ │ │ │ │ └── toolbar-remove-socket-connector-relation.module.ts │ │ │ │ │ └── add-socket-connector-relation │ │ │ │ │ ├── toolbar-add-socket-connector-relation.module.ts │ │ │ │ │ ├── toolbar-add-socket-connector-relation.scss │ │ │ │ │ └── node-model-message-socket-compatible.pipe.ts │ │ │ ├── demo-dashboard-transaction-agent.service.ts │ │ │ └── styles │ │ │ │ └── design-themes │ │ │ │ └── standard │ │ │ │ └── _demo-iconography.scss │ │ │ ├── demo-dashboard.scss │ │ │ ├── studio │ │ │ └── nodeflow-studio-compositor │ │ │ │ ├── state │ │ │ │ ├── config │ │ │ │ │ ├── tokens.ts │ │ │ │ │ ├── nodeflow-studio-compositor-configuration.json │ │ │ │ │ └── nodeflow-studio-compositor-configuration.interface.ts │ │ │ │ ├── model │ │ │ │ │ ├── relation │ │ │ │ │ │ ├── node-socket-connector-relation.model.ts │ │ │ │ │ │ └── delivery-message.model.ts │ │ │ │ │ └── message.model.ts │ │ │ │ └── transform │ │ │ │ │ └── pipe │ │ │ │ │ └── socket-connector-type.pipe.ts │ │ │ │ ├── utils │ │ │ │ └── browser │ │ │ │ │ ├── browser-tooling.module.ts │ │ │ │ │ └── browser-user-agent.service.ts │ │ │ │ ├── views │ │ │ │ ├── overlays │ │ │ │ │ ├── menu-overlay │ │ │ │ │ │ ├── nodeflow-studio-menu-overlay.scss │ │ │ │ │ │ ├── nodeflow-studio-menu-overlay.module.ts │ │ │ │ │ │ ├── nodeflow-studio-menu-overlay.html │ │ │ │ │ │ └── nodeflow-studio-menu-overlay.component.ts │ │ │ │ │ ├── tooltip-overlay │ │ │ │ │ │ ├── nodeflow-studio-tooltip-overlay.module.ts │ │ │ │ │ │ ├── nodeflow-studio-tooltip-overlay.html │ │ │ │ │ │ └── nodeflow-studio-tooltip-overlay.scss │ │ │ │ │ ├── notification-overlay │ │ │ │ │ │ ├── nodeflow-studio-notification-overlay.html │ │ │ │ │ │ ├── nodeflow-studio-notification-overlay.module.ts │ │ │ │ │ │ └── nodeflow-studio-notification-overlay.component.ts │ │ │ │ │ ├── nodeflow-studio-overlay-template.interface.ts │ │ │ │ │ └── nodeflow-studio-overlays.module.ts │ │ │ │ └── styles │ │ │ │ │ ├── _arrow.scss │ │ │ │ │ └── _node-socket.scss │ │ │ │ └── nodeflow-studio-compositor.scss │ │ │ ├── demo-dashboard.component.ts │ │ │ └── demo-dashboard.component.spec.ts │ ├── home │ │ ├── home.component.scss │ │ ├── home.component.ts │ │ ├── home.component.html │ │ └── home.component.spec.ts │ ├── about │ │ ├── about.component.scss │ │ ├── about.component.ts │ │ └── about.component.html │ ├── app.component.ts │ ├── app-navigation-links.json │ ├── app.module.ts │ ├── app-routing.module.ts │ ├── app.component.spec.ts │ └── app.component.html ├── favicon.ico ├── styles.css ├── environments │ ├── environment.e2e.ts │ ├── environment.local.ts │ ├── environment.stage.ts │ ├── environment.prod.ts │ ├── environment.github-pages.ts │ └── environment.ts ├── typings.d.ts ├── index.html ├── main.ts ├── tsconfig.spec.json ├── tsconfig.app.json └── test.ts ├── browserslist ├── mock └── network │ └── vendors │ └── extension │ ├── com.company.sample2 │ ├── metadata │ │ └── dashboard │ │ │ ├── configurations │ │ │ ├── deck1.json.ts │ │ │ └── deck2.json.ts │ │ │ └── translations │ │ │ ├── deck1 │ │ │ ├── en │ │ │ │ ├── cards │ │ │ │ │ ├── remote-plugin4 │ │ │ │ │ │ └── card.json │ │ │ │ │ ├── remote-plugin5 │ │ │ │ │ │ └── card.json │ │ │ │ │ ├── local-plugin3 │ │ │ │ │ │ └── card.json │ │ │ │ │ ├── remote-plugin1 │ │ │ │ │ │ └── card.json │ │ │ │ │ ├── remote-plugin3 │ │ │ │ │ │ └── card.json │ │ │ │ │ ├── remote-plugin2 │ │ │ │ │ │ └── card.json │ │ │ │ │ └── local-grid1 │ │ │ │ │ │ └── card.json │ │ │ │ └── dashboard.json │ │ │ ├── ja │ │ │ │ └── dashboard.json │ │ │ └── es │ │ │ │ └── dashboard.json │ │ │ └── deck2 │ │ │ ├── en │ │ │ ├── cards │ │ │ │ └── local-plugin3 │ │ │ │ │ └── card.json │ │ │ └── dashboard.json │ │ │ ├── ja │ │ │ └── dashboard.json │ │ │ └── es │ │ │ └── dashboard.json │ └── plugins │ │ ├── deck1 │ │ └── cards │ │ │ ├── remote-plugin5 │ │ │ └── view │ │ │ │ ├── embed.html │ │ │ │ └── styles │ │ │ │ └── page.css │ │ │ ├── remote-plugin1 │ │ │ └── view │ │ │ │ ├── embed.html │ │ │ │ └── styles │ │ │ │ └── page.css │ │ │ ├── remote-plugin2 │ │ │ └── view │ │ │ │ ├── embed.html │ │ │ │ └── styles │ │ │ │ └── page.css │ │ │ └── local-plugin3 │ │ │ └── data │ │ │ └── summary.json │ │ └── deck2 │ │ └── cards │ │ └── local-plugin3 │ │ └── data │ │ └── summary.json │ ├── com.company.sample3 │ ├── metadata │ │ └── dashboard │ │ │ └── configurations │ │ │ └── deck3.json.ts │ └── plugins │ │ └── deck3 │ │ └── cards │ │ ├── my-simple-embed │ │ └── view │ │ │ ├── embed.html │ │ │ └── styles │ │ │ └── page.css │ │ ├── my-simple-plugin1 │ │ └── data │ │ │ └── summary.json │ │ ├── my-advanced-introduction │ │ └── data │ │ │ └── introduction-model.json │ │ └── my-simple-introduction │ │ └── data │ │ └── introduction-model.json │ └── com.company.sample1 │ ├── metadata │ └── dashboard │ │ └── translations │ │ ├── journal1 │ │ ├── en │ │ │ ├── dashboard.json │ │ │ └── cards │ │ │ │ └── hardware-type │ │ │ │ └── card.json │ │ ├── ja │ │ │ └── dashboard.json │ │ └── es │ │ │ └── dashboard.json │ │ ├── journal3 │ │ ├── en │ │ │ ├── dashboard.json │ │ │ └── cards │ │ │ │ ├── virtual-network-summary │ │ │ │ └── card.json │ │ │ │ └── resource-metrics │ │ │ │ └── card.json │ │ ├── ja │ │ │ └── dashboard.json │ │ └── es │ │ │ └── dashboard.json │ │ └── journal2 │ │ ├── en │ │ ├── dashboard.json │ │ └── cards │ │ │ ├── virtual-network-summary │ │ │ └── card.json │ │ │ └── resource-metrics │ │ │ └── card.json │ │ ├── ja │ │ └── dashboard.json │ │ └── es │ │ └── dashboard.json │ └── data-server │ ├── web-services │ ├── vm-inventory-summary.json │ ├── resources-report-summary.json │ └── plugins-catalog-list.json │ └── session │ └── usersession.json ├── .editorconfig ├── e2e ├── tsconfig.e2e.json ├── demo-dashboard.e2e-spec.ts └── demo-dashboard.po.ts ├── .x-travis.yml ├── INSTALL.md ├── .gitignore ├── tsconfig.json ├── karma.conf.js ├── protractor.conf.js └── config └── deployments ├── local └── environment.json └── development └── environment.json /src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /browserslist: -------------------------------------------------------------------------------- 1 | last 2 Chrome versions 2 | not IE 9-11 3 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/demo-dashboard.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/home/home.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | background-color: #d7d7d7; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /src/app/about/about.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | background-color: #d7d7d7; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattmutt/ngx-card-deck-seed/HEAD/src/favicon.ico -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/core/com.company.group/models/parsers/resolvers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/common/com.company.sample2/views/card-assembly-plugins/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/common/com.company.sample2/views/card-templates/components/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/configurations/deck1.json.ts: -------------------------------------------------------------------------------- 1 | export default '' as any; 2 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/configurations/deck2.json.ts: -------------------------------------------------------------------------------- 1 | export default '' as any; 2 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample3/metadata/dashboard/configurations/deck3.json.ts: -------------------------------------------------------------------------------- 1 | export default '' as any; 2 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/common/com.company.sample2/metadata/configurations/simple-deck.inline.json.ts: -------------------------------------------------------------------------------- 1 | export default '' as any; 2 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/common/com.company.sample2/metadata/configurations/standard-deck.inline.json.ts: -------------------------------------------------------------------------------- 1 | export default '' as any; 2 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck1/en/cards/remote-plugin4/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "Frozen Landscapes", 3 | "card.subtitle": "Photobook" 4 | } 5 | 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck2/en/cards/local-plugin3/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "Datacenter Statistics", 3 | "card.subtitle": "live stats" 4 | } 5 | 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck1/en/cards/remote-plugin5/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "Satellite Weather", 3 | "card.subtitle": "CONUS GEOColor" 4 | } 5 | 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck1/ja/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "(日本語) Sample organization 1", 3 | "company": "Acme", 4 | "feedbackLink": "アンケート調査" 5 | } 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck2/ja/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "(日本語) Sample organization 1", 3 | "company": "Acme", 4 | "feedbackLink": "アンケート調査" 5 | } 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal1/en/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Dashboard", 3 | "company": "Big Company", 4 | "feedbackLink": "Send user feedback" 5 | } 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal3/en/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Dashboard #3", 3 | "company": "Big Company", 4 | "feedbackLink": "Send us feedback" 5 | } 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck2/en/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Sample Deck 1 extension", 3 | "company": "Acme", 4 | "feedbackLink": "Send us feedback" 5 | } 6 | -------------------------------------------------------------------------------- /src/environments/environment.e2e.ts: -------------------------------------------------------------------------------- 1 | // for reasons unclear protractor and TS needs these RX libraries spelled out 2 | 3 | import {environment as LOCAL} from "./environment.local"; 4 | 5 | export const environment = LOCAL; 6 | 7 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck1/en/cards/local-plugin3/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "Consumer Insights", 3 | "card.subtitle": "Down with billboard metrics" 4 | } 5 | 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck1/en/cards/remote-plugin1/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "Remote ~ Plugin 1", 3 | "card.subtitle": "Quarterly Statement Insights" 4 | } 5 | 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck1/en/cards/remote-plugin3/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "Remote ~ Banking Agent Plugin 3", 3 | "card.subtitle": "Gadget Gauge" 4 | } 5 | 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal2/en/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Dashboard #2", 3 | "company": "Big Company", 4 | "feedbackLink": "Send us positive feedback" 5 | } 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck1/en/cards/remote-plugin2/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "Remote ~ Video Streams Plugin 2", 3 | "card.subtitle": "Lab Research Discovery" 4 | } 5 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck1/en/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Sample Deck 1 extension", 3 | "company": "Acme", 4 | "feedbackLink": "Send us positive feedback" 5 | } 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck1/es/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "(spanish) Team 1 Sample Dashboard Series", 3 | "company": "Acme", 4 | "feedbackLink": "Send us feedback" 5 | } 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck2/es/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "(spanish) Team 1 Sample Dashboard Series", 3 | "company": "Acme", 4 | "feedbackLink": "Send us feedback" 5 | } 6 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | 7 | declare module "*.json" { 8 | const value: any; 9 | export default value; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal1/ja/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "(日本語) organization 1 Sample Dashboard Series", 3 | "company": "Big Company", 4 | "feedbackLink": "アンケート調査" 5 | } 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal2/ja/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "(日本語) organization 1 Sample Dashboard Series", 3 | "company": "Big Company", 4 | "feedbackLink": "アンケート調査" 5 | } 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal3/ja/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "(日本語) organization 1 Sample Dashboard Series", 3 | "company": "Big Company", 4 | "feedbackLink": "アンケート調査" 5 | } 6 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/demo-dashboard.scss: -------------------------------------------------------------------------------- 1 | 2 | :host { 3 | display: flex; 4 | flex-direction: column; 5 | flex: 0 1 100%; 6 | width: 100%; 7 | height: 100%; 8 | box-sizing: border-box; 9 | overflow: hidden; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal1/es/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "(spanish) Team 1 Sample Dashboard Series", 3 | "company": "(Spanish) Big Company", 4 | "feedbackLink": "Send us feedback" 5 | } 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal2/es/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "(spanish) Team 1 Sample Dashboard Series", 3 | "company": "(Spanish) Big Company", 4 | "feedbackLink": "Send us feedback" 5 | } 6 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal3/es/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "(spanish) Team 1 Sample Dashboard Series", 3 | "company": "(Spanish) Big Company", 4 | "feedbackLink": "Send us feedback" 5 | } 6 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-assembly-plugins/asset-node/nodeflow-asset-node.interface.ts: -------------------------------------------------------------------------------- 1 | 2 | // per item in the collection schema 3 | export interface NodeflowAssetNodeDataRecordEntitySchema { 4 | name: string; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/common/com.company.sample1/views/card-templates/components/demo-client-grid-card/styles/_inventory-summary-grid-column.scss: -------------------------------------------------------------------------------- 1 | 2 | // offsets from long label wraps 3 | I[demoInventoryIcon] { 4 | float: left; 5 | padding: 0.3rem; 6 | margin-right: 0.2rem; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/integration/environment/demo-dashboard-business-entity.state.ts: -------------------------------------------------------------------------------- 1 | import { BusinessContextEntityBaseStateful } from "ngx-card-deck"; 2 | 3 | export class DemoDashboardBusinessEntityState implements BusinessContextEntityBaseStateful { 4 | // business specific extensions 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-home', 5 | templateUrl: './home.component.html', 6 | styleUrls: ['./home.component.scss'] 7 | }) 8 | export class HomeComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/grid-theme.scss: -------------------------------------------------------------------------------- 1 | // framework styling link 2 | @import "~ngx-card-deck/styles/theme"; 3 | 4 | @include themifyClarity() { 5 | ::ng-deep GRIDSTER:not(.mobile) { 6 | 7 | // override gridster original themes 8 | > GRIDSTER-PREVIEW { 9 | 10 | } 11 | 12 | } 13 | } 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/app/about/about.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-about', 5 | templateUrl: './about.component.html', 6 | styleUrls: ['./about.component.scss'] 7 | }) 8 | export class AboutComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/core/com.company.group/views/card-assembly-plugins/base/styles/card-assembly-plugin-base.scss: -------------------------------------------------------------------------------- 1 | // chaining back on :host (pseudo - shadowed) 2 | & { 3 | display: block; 4 | overflow: hidden; // must honor containing layout 5 | 6 | &:not(.loaded) { 7 | } 8 | 9 | &.loaded { 10 | 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/integration/resolvers/demo-dashboard-resolver-collaborators.class.ts: -------------------------------------------------------------------------------- 1 | import { resolverAgentClassBaseMap, ResolverAgentClassMapSchema } from "ngx-card-deck"; 2 | 3 | // declare vendor pluggable resolvers 4 | export const demoDashboardResolverAgentClassMap: ResolverAgentClassMapSchema = Object.assign(resolverAgentClassBaseMap, { 5 | 6 | }); 7 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/common/standard/card-outlet/card-assembly-plugins/base/styles/standard-card-assembly-plugin-base.scss: -------------------------------------------------------------------------------- 1 | // chaining back on :host (pseudo - shadowed) 2 | & { 3 | display: block; 4 | overflow: hidden; // must honor containing layout 5 | 6 | &:not(.loaded) { 7 | } 8 | 9 | &.loaded { 10 | 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "sourceMap": true, 5 | "emitDecoratorMetadata": true, 6 | "outDir": "../out-tsc/e2e", 7 | "baseUrl": "./", 8 | "module": "commonjs", 9 | "target": "es5", 10 | "types": [ 11 | "jasmine", 12 | "jasminewd2", 13 | "node" 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/studio/nodeflow-studio-compositor/state/config/tokens.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from "@angular/core"; 2 | import { StudioCompositorConfigurationSchema } from "./nodeflow-studio-compositor-configuration.interface"; 3 | 4 | export const NODEFLOW_STUDIO_COMPOSITOR_CONFIG = new InjectionToken("Compositor Configuration Properties"); 5 | 6 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/demo-dashboard.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'demo-dashboard', 5 | styleUrls: ['./demo-dashboard.scss'], 6 | templateUrl: './demo-dashboard.html', 7 | }) 8 | export class DemoDashboardComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /.x-travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "10" 4 | dist: trusty 5 | addons: 6 | chrome: beta 7 | sudo: required 8 | branches: 9 | only: 10 | - master 11 | cache: 12 | apt: true 13 | directories: 14 | - node_modules 15 | before_script: 16 | - npm install -g @angular/cli 17 | - 18 | script: 19 | - npm run lint 20 | - npm run test -- --no-watch 21 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ngx Card Deck Demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/studio/nodeflow-studio-compositor/utils/browser/browser-tooling.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from "@angular/core"; 2 | import { DomInteractionService } from "./dom-interaction.service"; 3 | import { BrowserUserAgentService } from "./browser-user-agent.service"; 4 | 5 | @NgModule({ 6 | providers: [DomInteractionService, BrowserUserAgentService] 7 | }) 8 | export class BrowserToolingModule { 9 | } 10 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.log(err)); 13 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/studio/nodeflow-studio-compositor/utils/browser/browser-user-agent.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | 3 | 4 | // Cross browser inspection tools 5 | @Injectable() 6 | export class BrowserUserAgentService { 7 | 8 | isMicrosoftBrowser(): boolean { 9 | return window.navigator.appName === "Netscape" && window.navigator.userAgent.indexOf("Edge/") > 0; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": [ 9 | "jasmine", 10 | "node" 11 | ] 12 | }, 13 | "files": [ 14 | "test.ts", 15 | "polyfills.ts" 16 | ], 17 | "include": [ 18 | "**/*.spec.ts", 19 | "**/*.d.ts" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/views/toolbar/remove-nodeflow/toolbar-remove-nodeflow.scss: -------------------------------------------------------------------------------- 1 | 2 | :host { 3 | display: flex; 4 | flex: 0; 5 | align-items: flex-end; 6 | 7 | [role="processingErrorMessage"] { 8 | padding: 0.2rem; 9 | border-radius: 0.5rem; 10 | border: 1px solid rgba(0, 0, 0, .2); 11 | background-color: rgba(255, 2, 2, .3); 12 | } 13 | 14 | // Remove 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import * as appNavigationLinksResourceJson from "./app-navigation-links.json"; 3 | 4 | @Component({ 5 | selector: 'app-root', 6 | templateUrl: './app.component.html', 7 | styleUrls: ['./app.component.scss'] 8 | }) 9 | export class AppComponent { 10 | title = 'ngx Card Deck Demo'; 11 | navigationLayout: any = appNavigationLinksResourceJson.default; 12 | } 13 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/core/com.company.group/views/card-assembly-plugins/simple-grid-card/simple-grid-card.model.ts: -------------------------------------------------------------------------------- 1 | // able to transform and mutate, based upon business rule strategies 2 | import { DashboardCardModelSchema } from "ngx-card-deck"; 3 | 4 | export class SimpleGridDataModel implements DashboardCardModelSchema { 5 | // envelope holding records 6 | response: { 7 | records: Array; 8 | }; 9 | } 10 | 11 | 12 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal2/en/cards/virtual-network-summary/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "Virtual Network Readiness Check", 3 | "card.footer": null, 4 | "card.subtitle": "Resources valid as of May 2017", 5 | 6 | 7 | "field1": "WAN throughput", 8 | "field2": "Telecommunication Costs", 9 | "field3": "MxN Node Separation Timing", 10 | "field4": "Business Value Contracts" 11 | } 12 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal3/en/cards/virtual-network-summary/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "Virtual Network Readiness Check", 3 | "card.footer": null, 4 | "card.subtitle": "Resources valid as of May 2017", 5 | 6 | 7 | "field1": "WAN throughput", 8 | "field2": "Telecommunication Costs", 9 | "field3": "MxN Node Separation Timing", 10 | "field4": "Business Value Contracts" 11 | } 12 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/views/toolbar/toolbar-nodeflow-action.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { ToolbarTabsContainerModule } from "./tabs-container/toolbar-tabs-container.module"; 3 | 4 | @NgModule({ 5 | 6 | imports: [ 7 | ToolbarTabsContainerModule 8 | ], 9 | 10 | exports: [ 11 | ToolbarTabsContainerModule 12 | ] 13 | 14 | 15 | }) 16 | export class ToolbarNodeflowActionModule { 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/environments/environment.local.ts: -------------------------------------------------------------------------------- 1 | import * as DemoDashboardMetadataConfiguration from "../../config/deployments/local/environment.json"; 2 | 3 | export const environment = { 4 | production: false, 5 | 6 | modules: { 7 | // initial paths relevant watch mode 8 | "demo-dashboard": { 9 | configuration: { 10 | environment: DemoDashboardMetadataConfiguration.default 11 | } 12 | 13 | } 14 | 15 | } 16 | 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /src/environments/environment.stage.ts: -------------------------------------------------------------------------------- 1 | import * as DemoDashboardMetadataConfiguration from "../../config/deployments/stage/environment.json"; 2 | 3 | export const environment = { 4 | production: true, 5 | 6 | modules: { 7 | // initial paths relevant watch mode 8 | "demo-dashboard": { 9 | configuration: { 10 | environment: DemoDashboardMetadataConfiguration.default 11 | } 12 | 13 | } 14 | 15 | } 16 | 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | import * as DemoDashboardMetadataConfiguration from "../../config/deployments/production/environment.json"; 2 | 3 | export const environment = { 4 | production: true, 5 | 6 | modules: { 7 | // initial paths relevant watch mode 8 | "demo-dashboard": { 9 | configuration: { 10 | environment: DemoDashboardMetadataConfiguration.default 11 | } 12 | 13 | } 14 | 15 | } 16 | 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/metadata/dashboard/translations/deck1/en/cards/local-grid1/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "Hardware Health Insights", 3 | "card.subtitle": "Hardware Product Type product family", 4 | "grid.empty_results": "No Hardware Type records found", 5 | "inventory_entity_name": "Equipment", 6 | "inventory_entity_count": "Energy (kWh)", 7 | "inventory_entity_total": "Total", 8 | "inventory_entity_percentage": "%" 9 | } 10 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal1/en/cards/hardware-type/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "Hardware Health Insights", 3 | "card.subtitle": "Hardware Product Type product family", 4 | "grid.empty_results": "No Hardware Type records found", 5 | "inventory_entity_name": "Equipment", 6 | "inventory_entity_count": "Energy (kWh)", 7 | "inventory_entity_total": "Total", 8 | "inventory_entity_percentage": "%" 9 | } 10 | -------------------------------------------------------------------------------- /src/environments/environment.github-pages.ts: -------------------------------------------------------------------------------- 1 | import * as DemoDashboardMetadataConfiguration from "../../config/deployments/github-pages/environment.json"; 2 | 3 | export const environment = { 4 | production: true, 5 | 6 | modules: { 7 | // initial paths relevant watch mode 8 | "demo-dashboard": { 9 | configuration: { 10 | environment: DemoDashboardMetadataConfiguration.default 11 | } 12 | 13 | } 14 | 15 | } 16 | 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /src/app/about/about.component.html: -------------------------------------------------------------------------------- 1 |

2 | About 3 |

4 | 5 | The dashboard integrates the ability to organize a layout of custom view containers in any order or size. 6 | 7 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/plugins/deck1/cards/remote-plugin5/view/embed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/common/com.company.sample3/lib/views/card-templates/components/simple-introduction/styles/_devices.scss: -------------------------------------------------------------------------------- 1 | .devicesList { 2 | 3 | // nested table 4 | TABLE { 5 | width: 100%; 6 | border: 1px solid rgba(0, 0, 0, .3); 7 | 8 | THEAD > TH { 9 | background-color: rgba(255, 255, 255, .15); 10 | } 11 | 12 | TBODY > TR > TD { 13 | padding: 0 0.2rem; 14 | 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "baseUrl": "./", 6 | "module": "esnext", 7 | "types": [] 8 | }, 9 | "angularCompilerOptions": { 10 | "enableIvy": false, 11 | "preserveWhitespaces": false, 12 | "fullTemplateTypeCheck": false 13 | }, 14 | "exclude": [ 15 | "test.ts", 16 | "app/modules/ngx-card-deck/lib/mock/**", 17 | "**/*.spec.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/core/com.company.group/views/card-assembly-plugins/metrics-billboard/metrics-billboard.scss: -------------------------------------------------------------------------------- 1 | @import "~ngx-card-deck/styles/theme"; 2 | 3 | :host { 4 | @import '../base/styles/card-assembly-plugin-base'; 5 | 6 | > [role="billboard-widget"] { 7 | 8 | // /++++++ RWD +++++++ 9 | @include respond-to-rwd-list(('medium', 'large', 'maximum')) { 10 | // flex-wrap: nowrap; 11 | } 12 | // ++++++ RWD +++++++ 13 | 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/extensions/topics/color/consumer/nodeflow-asset-topics-color-consumer.scss: -------------------------------------------------------------------------------- 1 | 2 | :host { 3 | display: block; 4 | 5 | } 6 | 7 | [role="canvas"] { 8 | $dimension: 100px; 9 | 10 | width: $dimension; 11 | height: $dimension; 12 | 13 | padding: 2px; 14 | margin: 0 auto; 15 | display: block; 16 | } 17 | 18 | 19 | [role="invalidMessageData"] { 20 | background: rgba(255,1,1,.2); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/menu-overlay/nodeflow-studio-menu-overlay.scss: -------------------------------------------------------------------------------- 1 | 2 | :host { 3 | display: block; 4 | position: absolute; // removed from flow 5 | //width: 100%; 6 | //height: 100%; 7 | background: #fff; 8 | border:1px #003388 solid; 9 | border-radius: 5px; 10 | padding: 0.5rem; 11 | 12 | left: 1rem; 13 | top: 1rem; 14 | //left: 222px; 15 | //top: 111px; 16 | 17 | width: 10rem; 18 | height: 10rem; 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/studio/nodeflow-studio-compositor/state/model/relation/node-socket-connector-relation.model.ts: -------------------------------------------------------------------------------- 1 | import { NodeModel } from "../node.model"; 2 | import { SocketConnectorRelationModel } from "./socket-connector-relation.model"; 3 | 4 | // transient relation. UI may need to aggregate collection in a menu that organizes nodes to socket relations 5 | export class NodeSocketConnectorRelationModelCollection { 6 | node: NodeModel; 7 | socketConnectorRelationCollection: Set = new Set(); 8 | } 9 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # `` developer guide 2 | 3 | 4 | [![ngx card deck](http://i.postimg.cc/kGm8vJWs/card-deck.png)](http://i.postimg.cc/kGm8vJWs/card-deck.png) 5 | 6 | ## Install 7 | 8 | _Todo:_ Apologies for the obviously lackluster documentation. Not forgotten, lots of notes stuck in my head :) 9 | 10 | Want to do it right: start with a high level overview, then lead into design. Core material to cover the steps a developer needs to take to provision a card deck. 11 | 12 | 13 | 14 | 15 | ## Demo Samples 16 | 17 | ### 18 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal2/en/cards/resource-metrics/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "CPU", 3 | "card.subtitle": "Computer processing allocation across the enterprise", 4 | "resource.measured_free": "sent", 5 | "resource.measured_used": "uptime", 6 | "resource.measured_total": "total", 7 | 8 | "CpuResourceDataItem.CpuLabel": "Logistics", 9 | "MemoryResourceDataItem.MemoryLabel": "Workforce", 10 | "StorageResourceDataItem.StorageLabel": "Capacity Planning" 11 | } 12 | 13 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/metadata/dashboard/translations/journal3/en/cards/resource-metrics/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "card.title": "CPU", 3 | "card.subtitle": "Computer processing allocation across the enterprise", 4 | "resource.measured_free": "sent", 5 | "resource.measured_used": "uptime", 6 | "resource.measured_total": "total", 7 | 8 | "CpuResourceDataItem.CpuLabel": "Logistics", 9 | "MemoryResourceDataItem.MemoryLabel": "Workforce", 10 | "StorageResourceDataItem.StorageLabel": "Capacity Planning" 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/common/com.company.sample1/views/card-templates/components/demo-client-summary-billboard/demo-client-summary-billboard-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ summaryEntity }} 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/lib/models/parsers/dashboard/provider/business-nodeflow-card-provider.interface.ts: -------------------------------------------------------------------------------- 1 | // abstract business concepts in the context of a card 2 | // idea is to extend to support any client use case for storing additional data 3 | 4 | export type BusinessNodeflowGlobalIdentifier = string; 5 | 6 | export interface BusinessNodeflowCardProviderSchema { 7 | assetTypeId: string; // numeric like 8 | catalogId: BusinessNodeflowGlobalIdentifier; // GUID 9 | layoutId: BusinessNodeflowGlobalIdentifier; // GUID 10 | } 11 | 12 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/menu-overlay/nodeflow-studio-menu-overlay.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from "@angular/common"; 3 | import { NodeflowStudioMenuOverlayComponent } from "./nodeflow-studio-menu-overlay.component"; 4 | 5 | @NgModule({ 6 | 7 | imports: [ 8 | CommonModule 9 | ], 10 | declarations: [NodeflowStudioMenuOverlayComponent], 11 | exports: [NodeflowStudioMenuOverlayComponent] 12 | 13 | }) 14 | export class NodeflowStudioMenuOverlayModule { 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/core/com.company.group/views/card-assembly-plugins/metrics-billboard/metrics-billboard.model.ts: -------------------------------------------------------------------------------- 1 | import { MetricsBillboardDataRecordEntitySchema } from "./metrics-billboard.interface"; 2 | import { DashboardCardModelSchema } from "ngx-card-deck"; 3 | 4 | 5 | // able to transform and mutate, based upon business rule strategies 6 | export class MetricsBillboardDataModel implements DashboardCardModelSchema { 7 | // envelope holding records 8 | response: { 9 | entity: MetricsBillboardDataRecordEntitySchema; 10 | }; 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/tooltip-overlay/nodeflow-studio-tooltip-overlay.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from "@angular/common"; 3 | import { NodeflowStudioTooltipOverlayComponent } from "./nodeflow-studio-tooltip-overlay.component"; 4 | 5 | @NgModule({ 6 | 7 | imports: [ 8 | CommonModule 9 | ], 10 | declarations: [NodeflowStudioTooltipOverlayComponent], 11 | exports: [NodeflowStudioTooltipOverlayComponent] 12 | 13 | }) 14 | export class NodeflowStudioTooltipOverlayModule { 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/core/com.company.group/views/card-assembly-plugins/summary-billboard/summary-billboard.model.ts: -------------------------------------------------------------------------------- 1 | import { SummaryBillboardDataModelSchema } from "./summary-billboard.interface"; 2 | import { DashboardCardModelSchema } from "ngx-card-deck"; 3 | 4 | 5 | // typed class that holds the data 6 | // able to transform and mutate, based upon business rule strategies 7 | export class SummaryBillboardDataModel implements DashboardCardModelSchema { 8 | // envelope holding records 9 | response: { 10 | entity: SummaryBillboardDataModelSchema 11 | }; 12 | } 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/notification-overlay/nodeflow-studio-notification-overlay.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
X
6 |
7 | 8 |
9 | 10 |
    11 |
  1. 12 | {{ messageDetail }} 13 |
  2. 14 |
15 | 16 | 20 | 21 | 22 |
23 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/notification-overlay/nodeflow-studio-notification-overlay.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from "@angular/common"; 3 | import { NodeflowStudioNotificationOverlayComponent } from "./nodeflow-studio-notification-overlay.component"; 4 | 5 | @NgModule({ 6 | 7 | imports: [ 8 | CommonModule 9 | ], 10 | declarations: [NodeflowStudioNotificationOverlayComponent], 11 | exports: [NodeflowStudioNotificationOverlayComponent] 12 | 13 | }) 14 | export class NodeflowStudioNotificationOverlayModule { 15 | } 16 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/common/com.company.sample1/views/card-templates/components/demo-client-grid-card/styles/_bar-graph.scss: -------------------------------------------------------------------------------- 1 | // bar in grid 2 | [role="bar-graph-widget"] { 3 | display: flex; 4 | height: 0.8rem; 5 | 6 | > [role="label"] { 7 | padding-left: 0.5rem; 8 | font-size: smaller; 9 | } 10 | 11 | > [role="bar-graph"] { 12 | outline: 1px solid rgba(0, 0, 0, .4); 13 | 14 | &:hover { 15 | outline: 1px solid rgba(0, 0, 0, .9); 16 | transform: scale(1.2); 17 | transition: all 200ms 50ms; 18 | } 19 | 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/core/com.company.group/views/card-assembly-plugins/simple-grid-card/simple-grid-card.scss: -------------------------------------------------------------------------------- 1 | // framework styling link 2 | @import "~ngx-card-deck/styles/theme"; 3 | 4 | :host { 5 | @import '../base/styles/card-assembly-plugin-base'; 6 | 7 | > [role="grid-widget"] { 8 | 9 | // peering into grid fixture 10 | ::ng-deep { 11 | @import "clarity_datagrid"; 12 | } 13 | 14 | // /++++++ RWD +++++++ 15 | @include respond-to-rwd-list(('medium', 'large', 'maximum')) { 16 | // flex-wrap: nowrap; 17 | } 18 | // ++++++ RWD +++++++ 19 | 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample2/plugins/deck1/cards/remote-plugin1/view/embed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | Chart Metrics 13 |
14 | 15 |
16 |

17 | Explore embedded remote served plugin 18 |

19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/studio/nodeflow-studio-compositor/state/transform/pipe/socket-connector-type.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | import { SocketModel } from "../../model/socket.model"; 3 | import { NodeLinkModel } from "../../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 SocketConnectorTypePipe implements PipeTransform { 10 | transform(items: Set): Array { 11 | return NodeLinkModel.sortCollection(items); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample3/plugins/deck3/cards/my-simple-embed/view/embed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | Sample ngx-card-deck embedded control 14 |
15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/metadata/schema/card-catalog-resources.interface.ts: -------------------------------------------------------------------------------- 1 | import { CardProjectPackageSchematicIdentifiable } from "./card-project.interface"; 2 | 3 | 4 | export interface CardCatalogResourceItemPackage extends CardProjectPackageSchematicIdentifiable { 5 | sourceFile: string; 6 | encodingType: string; 7 | 8 | } 9 | 10 | // contents of `catalog.json` 11 | export interface CardCatalogResourcesPackage extends CardProjectPackageSchematicIdentifiable { 12 | resources: Array; 13 | references: { 14 | projectItemId: string; // link to project/item/id 15 | }; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/extensions/views/delivery/default/nodeflow-asset-default-consumer.scss: -------------------------------------------------------------------------------- 1 | // holder of fields 2 | [role="messagesConsumerFieldsGrid"] { 3 | background-color: rgba(32, 22, 22, .1); 4 | padding: 0.2rem; 5 | width: 100%; 6 | margin: 10px 0; 7 | 8 | THEAD > TR { 9 | background-color: rgba(83, 43, 43, .15); 10 | } 11 | 12 | TBODY > TR > TD { 13 | width: 50%; 14 | INPUT { 15 | width: 90%; 16 | background-color: rgba(255, 255, 255, .2); 17 | border: none; 18 | } 19 | } 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/pipes/message-model-state-data-iterable.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | 3 | // remap associated array into list for template iterable form 4 | @Pipe({ 5 | name: "messageModelStateDataIterable" 6 | }) 7 | export class MessageModelStateDataIterablePipe implements PipeTransform { 8 | transform(messageStateDataStruct: object): Array { 9 | // same ordering as the socket renderings 10 | 11 | return Object.keys(messageStateDataStruct) 12 | .map((k) => [k as string, messageStateDataStruct[k] as any]); 13 | 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/pipes/nodeflow-message-model-state-data-tuples.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | 3 | // remap associated array into list for template iterable form 4 | @Pipe({ 5 | name: "messageModelStateDataTupleList" 6 | }) 7 | export class NodeflowMessageModelStateDataTuplesPipe implements PipeTransform { 8 | transform(messageStateDataStruct: object): Array { 9 | // same ordering as the socket renderings 10 | 11 | return Object.keys(messageStateDataStruct) 12 | .map((k) => [k as string, messageStateDataStruct[k] as any]); 13 | 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/client/organizers/nodeflow/views/card-templates/nodeflow-asset-node/pipes/nodeflow-message-model-has-state.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | import { MessageModel } from "../../../../../../../../studio/nodeflow-studio-compositor/state/model/message.model"; 3 | 4 | // pre-validation. Won't make a subform unless there are defined messages 5 | @Pipe({ 6 | name: "hasMessageModelState" 7 | }) 8 | export class NodeflowMessageModelHasStatePipe implements PipeTransform { 9 | transform(items: Set): Array { 10 | return Array.from(items).filter((model) => model.state && Object.keys(model.state).length); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /mock/network/vendors/extension/com.company.sample1/data-server/web-services/vm-inventory-summary.json: -------------------------------------------------------------------------------- 1 | { 2 | "provider": { 3 | "serverGuid": "6f965cf2-80cc-49da-8a39-a64265a57c14", 4 | "type": "Folder", 5 | "value": "group-d1" 6 | }, 7 | "dashboardData": [ 8 | { 9 | "label": "field1", 10 | "value": "83", 11 | "nestedProperties": null 12 | }, 13 | { 14 | "label": "field2", 15 | "value": "9", 16 | "nestedProperties": null 17 | }, 18 | { 19 | "label": "field3", 20 | "value": "74", 21 | "nestedProperties": null 22 | }, 23 | { 24 | "label": "field4", 25 | "value": "4", 26 | "nestedProperties": null 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /src/app/pages/dashboard/studio/nodeflow-studio-compositor/views/overlays/tooltip-overlay/nodeflow-studio-tooltip-overlay.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
    4 |
  • Type:
  • 5 |
  • Topic:
  • 6 |
  • Node:
  • 7 |
  • Socket:
  • 8 |
  • Multicast:
  • 9 |
  • Connected:
  • 10 |
11 | 12 | 13 | 14 |
15 | -------------------------------------------------------------------------------- /src/app/pages/dashboard/dashboard-page/integration/environment/demo-dashboard-deployment-configuration.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { environment } from "../../../../../../environments/environment"; 3 | import { 4 | DeploymentConfigurationBase, 5 | EnvironmentConfigurationSchema 6 | } from "ngx-card-deck"; 7 | 8 | @Injectable() 9 | export class DemoDashboardDeploymentConfigurationService extends DeploymentConfigurationBase { 10 | 11 | // supply integration layer 12 | constructor( 13 | 14 | ) { 15 | // provisioned via angular-cli build 16 | super(( 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 |
12 |
13 | 14 |
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 |
21 | 22 |
23 | 24 |
25 | 27 |
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 |
2 | 3 | 4 | 6 | 7 | 8 |
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 |
2 | 8 | 9 |
12 | 13 |
16 | 17 | 19 |
20 | 21 |
22 |
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 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
{{ resourceState.message.topic }}
20 | 23 | 25 | 26 |
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 | 21 | 24 | 25 |
19 | color 20 | 22 | {{ showMessageData(deliveryMessage.payload.data) }} 23 |
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 |
8 |

9 |
10 |
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 |
2 |
3 |
4 |
5 | 6 |
7 | 9 |
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 |
2 | 3 | 4 | 6 | 7 | 8 |
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 | --------------------------------------------------------------------------------