Dashboard in custom hybrid application - pass mo or context

What product/components do you use and which version/fix level are you on?

angular - 12.2.14
c8y/client: “1014.0.232”,
c8y/ngx-components: “1014.0.232”,
c8y/ng1-modules: “1014.0.232”,

Is your question related to the free trial, or to a production (customer) instance?

production

What are you trying to achieve? Please describe it in detail.

We are creating own application (not extending existing like cockpit/device management), and we would like to include Dashboard in our view, pass device data and show same dashboard as in cockpit.
We have created Hybrid application, added c8y-content-dashboard, added ng1.ts to have all default widgets visible.

Now we are struggling to pass either managed object or context to the dashboard. Now when showing the dashboard it throws an error (probably for not having context).

In the documentation for websdk/ngx-components/components/ContextDashboardComponent it says you can put mo (ManagedObject) and show a dashboard for it but it was not working for us ( Can’t bind to ‘mo’ since it isn’t a known property of ‘c8y-context-dashboard’.)

Is there any documentation/example on how to either pass managedObject to dashboard or create routing like in cockpit that will pass necessery context to dashboard?

Do you get any error messages? Please provide a full error message screenshot and log file.

Have you installed all the latest fixes for the products and systems you are using?

Yes

Hi Damian,

can you show the content of your app.module.ts? Might be that you need to import DashboardUpgradeModule from @c8y/ngx-components/upgrade into your app module. And you might need to import ContextDashboardModule from @c8y/ngx-components/context-dashboard.

Best regards
Christian

Hi Damian,

The input on the ContextDashboardComponent is called: context, see: Web SDK documentation

You can take a look at the tutorial application where this component is used for more details.
context should have the following structure:

{
  "contextData": {"id": "", ...}
}

contextData should have the managedObject as value.

Regards,
Tristan

1 Like

I have both already in app.module.ts.

import { NgModule } from "@angular/core";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { RouterModule as NgRouterModule } from "@angular/router";
import { CoreModule, RouterModule, HOOK_COMPONENTS } from "@c8y/ngx-components";
import { CollapseModule } from "ngx-bootstrap/collapse";
import { TooltipModule } from "ngx-bootstrap/tooltip";
import { CreateEditUsecaseConfigModal } from "./components/ai-analytics/modals/create-usecase-config/create-edit-usecase-config.modal";
import { RemoveConfirmationModal } from "./components/modals/remove-confirmation-modal/remove-confirmation.modal";
import { Main } from "./components/main/main.component";
import { Dashboard } from "./components/dashboards/dashboard.component";
import { Navigation } from "./components/navigation/navigation.component";
import { StationSelectionEventService } from "./components/station-tree/StationSelectionEventService";
import { ContextDashboardModule } from "@c8y/ngx-components/context-dashboard";
import { UpgradeModule as NgUpgradeModule } from "@angular/upgrade/static";
import {
  UpgradeModule,
  HybridAppModule,
  UPGRADE_ROUTES,
  DashboardUpgradeModule,
} from "@c8y/ngx-components/upgrade";
@NgModule({
  imports: [
    BrowserAnimationsModule,
    RouterModule.forRoot(),
    NgRouterModule.forRoot(
      [
        {
          path: "",
          component: Main,
        },
        ...UPGRADE_ROUTES,
      ],
      {
        enableTracing: false,
        useHash: true,
      }
    ),
    CoreModule.forRoot(),
    DashboardUpgradeModule,
    CollapseModule.forRoot(),
    TooltipModule.forRoot(),
    ContextDashboardModule,
    NgUpgradeModule,
    UpgradeModule,
  ],
  declarations: [
    Main,
    CreateEditUsecaseConfigModal,
    RemoveConfirmationModal,
    Dashboard,
    Navigation,
  ],
  providers: [StationSelectionEventService],
})
export class AppModule extends HybridAppModule {
  constructor(protected upgrade: NgUpgradeModule) {
    super();
  }
}

Yes, I see. Then refer to Tristan’s response.

Thanks for reply.
Where can i find this tutorial?

I tried passing context widh contextData like this:

<c8y-context-dashboard
  [context]="context"
  title="test"
></c8y-context-dashboard>

where context is:

{
    "contextData":{
			"additionParents": {
			},
			"owner": "",
			"childDevices": {
			},
			"childAssets": {
			},
			"creationTime": "2023-01-31T10:47:12.728Z",
			"lastUpdated": "2023-01-31T13:26:59.093Z",
			"childAdditions": {
			},
			"deviceParents": {
			},
			"assetParents": {
			},
			"self": "",
			"id": "12941492",
			"c8y_Global": {},
			"c8y_Dashboard": {
				"children": {
					"9333271380630574": {
						"configTemplateUrl": "imageWidget/views/componentConfig.html",
						"componentId": "Image",
						"classes": {
							"image": true,
							"dashboard-theme-light": true,
							"card-dashboard": true,
							"panel-title-regular": true,
							"card": true
						},
						"_x": 0,
						"_y": 0,
						"id": "9333271380630574",
						"title": "Image",
						"_width": 6,
						"config": {
							"imageBinaryId": "12947374"
						},
						"_height": 4,
						"templateUrl": "imageWidget/views/component.html"
					}
				},
				"widgetClasses": {
					"dashboard-theme-light": true,
					"panel-title-regular": true
				}
			},
			"c8y_Dashboard!name!c8y_Dashboard": {}
		}
}

It still throws an error because at start it tries to load c8y_Dashboard property from managed object from route context:

image

In code i see that there if name is passed the behaviour is different and it does not throw error. It works but only but the dashboard is not the same as cockpit one.

Is it possible to show dashboard same as in cockpit?

Hi Damian,

You can create an instance of the tutorial app by executing: c8ycli new <<your-app-name>> tutorial as mentioned here: Getting started - Cumulocity IoT Guides

Context is supposed to be the device/group managedObject, the dashboard managedObject is taken from the routes data.

If you would like to have a similar setup as in cockpit, try importing the ContextDashboardModule with this configuration:

ContextDashboardModule.config({
      routes: [
        {
          path: 'dashboard/:dashboardId',
          component: ContextDashboardComponent,
          canActivate: [DeviceDashboardGuard],
          context: ViewContext.Device
        },
        {
          path: 'dashboard/:dashboardId',
          component: ContextDashboardComponent,
          canActivate: [GroupDashboardGuard],
          context: ViewContext.Group
        }
      ]
    })

Hi, thank you for your reply. I tried to do it without routing by named dashboard.
So now i have it like this:

image

With context beeing

const managedObject = await (
        await this.inventoryService.detail(this.station.id)
      ).data;

      if (managedObject) {
        this.context = {
          contextData: managedObject,
        };
      }

Dashboard show fine but the problem is its not taking context and passing it to widgets.
What i mean is dataPoints in widget configuration are for all possible devices not for my device passed in context.

Is it doable that way by named dashboard? Or do i have to use context with routing like you described? If I use context with routing is there any documentation/tutorial on routing in custom app or this is standard angular stuff??

I just wanted to share with everyone that i managed to make it work.
Context seems to be properly used in widgets on version 1015.0.280.
The only difference is that the passed context seems to be just ManagedObject.
Final solution:

<c8y-context-dashboard
          [name]="dashboardName"
          [context]="context"
></c8y-context-dashboard>

Where dashboard name is unique for every device:

get dashboardName() {
    return "custom_dashboard_" + this.station?.id;
  }

And context is managed object.

const managedObject = await (
    await this.inventoryService.detail(deviceId)
).data;
      
if (managedObject) {
    this.context = managedObject;
}

Result working dashboard with proper context and assets to select:

Thanks for you help.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.