context-dashboard/widget-config.component.ts
AfterContentInit
AfterViewInit
OnDestroy
| host | { |
| selector | c8y-widget-config |
| standalone | true |
| imports |
C8yTranslatePipe
|
| templateUrl | ./widget-config.component.html |
FormsModule
IconDirective
C8yTranslateDirective
HighlightComponent
EmptyStateComponent
FormGroupComponent
RequiredInputPlaceholderDirective
C8yComponentOutlet
WidgetPreviewComponent
AppearanceSettingsComponent
ProductExperienceDirective
C8yTranslatePipe
AsyncPipe
ResizableGridComponent
AfterContentInit
AfterViewInit
OnDestroy
<!-- select widget -->
@if (!(widgetConfigService.selected$ | async)) {
<div class="card-header j-c-center separator">
<div
class="h4 text-center"
id="drawerTitle"
>
{{ 'Select widget' | translate }}
</div>
</div>
<div class="card-inner-scroll fit-h bg-level-2">
<div
class="bg-level-0 p-l-24 p-r-24 p-t-8 p-b-8 sticky-header-top-0 elevation-md"
style="z-index: 2"
>
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<div class="input-group input-group-search">
<input
class="form-control"
[attr.aria-label]="'Search' | translate"
placeholder="{{ 'Search…' | translate }}"
type="text"
#searchInput
data-cy="widget-config--Search"
[(ngModel)]="searchTerm"
[ngModelOptions]="{ standalone: true }"
(keydown)="searchChange$.next($event)"
/>
<span class="input-group-btn">
<button
class="btn btn-dot"
title="{{ 'Search' | translate }}"
type="button"
(click)="resetSearch()"
>
<i [c8yIcon]="searchTerm.length === 0 ? 'search' : 'close'"></i>
</button>
</span>
</div>
</div>
</div>
</div>
<div class="card-block">
<div class="card-group p-l-24 p-r-24 d-grid grid__col--auto-300 gap-24 card-select m-b-0">
@for (cmp of searchResult || components; track cmp) {
<button
class="btn-clean d-col card m-b-0"
[title]="cmp.description || cmp.label | translate"
type="button"
data-cy="widget-config--widget-list"
(click)="select(cmp)"
>
<div
class="border-bottom"
role="presentation"
>
@if (!cmp.previewImage) {
<div class="h1"><i c8yIcon="file-image-o"></i></div>
<small translate>Preview not available</small>
} @else {
<img
class="widget-thumbnail"
alt="{{ cmp.label | translate }}"
[src]="cmp.previewImage"
/>
}
</div>
<div class="card-block">
<p class="card-title text-truncate text-medium">
<c8y-highlight
text="{{ cmp.label | translate }}"
[pattern]="searchTerm"
></c8y-highlight>
</p>
<p
class="small text-default"
style="white-space: wrap"
>
{{ cmp.description | translate }}
</p>
</div>
</button>
}
@if (searchResult && searchResult.length === 0) {
<c8y-ui-empty-state
class="p-24 grid__col--fullspan"
[icon]="'search'"
[title]="'No widgets found.' | translate"
[subtitle]="'Rephrase your search term.' | translate"
>
<button
class="btn btn-primary"
title="{{ 'Reset search' | translate }}"
type="button"
(click)="resetSearch()"
>
{{ 'Reset search' | translate }}
</button>
</c8y-ui-empty-state>
}
</div>
</div>
</div>
<div class="card-footer text-center separator flex-no-shrink">
<button
class="btn btn-default"
title="{{ 'Cancel' | translate }}"
type="button"
data-cy="widget-config--cancel-widget"
(click)="close()"
>
{{ 'Cancel' | translate }}
</button>
</div>
}
<!-- widget configuration -->
@if (!!(widgetConfigService.selected$ | async)) {
<div class="card-header d-block separator-bottom flex-no-shrink">
<div
class="h3 p-t-16"
title="{{ selected?.label | translate }}"
>
<span>{{ selected?.label | translate }}</span>
<button
class="btn btn-default btn-sm m-l-8"
[title]="'Change widget' | translate"
(click)="backToWidgetSelection(); (false)"
>
<i c8yIcon="replace"></i>
{{ 'Change widget' | translate }}
</button>
</div>
@if (selected) {
<div class="p-t-8">
<p>
{{ selected.description | translate }}
</p>
</div>
}
</div>
<c8y-resizable-grid
class="min-height-0 flex-grow"
[collapsible]="false"
[trackId]="'c8y-widget-resizable-grid-size-' + (widgetConfigService.instanceId$ | async)"
[leftColumnWidth]="
(widgetConfigService.currentConfig$ | async)?.settings?.configurationViewGridSize ||
WIDGET_CONFIGURATION_GRID_SIZE.DEFAULT
"
>
<div
class="bg-level-1 inner-scroll"
left-pane
>
<div class="p-16 flex-no-shrink separator-bottom bg-level-1">
<c8y-form-group>
<label
for="widgetTitle"
translate
>
Widget title
</label>
<input
class="form-control"
id="widgetTitle"
placeholder="{{ 'e.g.' | translate }} {{ componentLabel | translate }}"
name="widgetTitle"
type="text"
required
[(ngModel)]="widgetTitle"
(ngModelChange)="onWidgetTitleChange($event)"
/>
</c8y-form-group>
</div>
@if (!(widgetConfigService.hasConfig$ | async)) {
<c8y-ui-empty-state
class="p-24"
[icon]="'settings'"
[title]="'No configuration needed.' | translate"
[subtitle]="'This widget does not need any specific configuration.' | translate"
[horizontal]="true"
></c8y-ui-empty-state>
}
<div>
<form
name="form"
#configForm="ngForm"
>
@if (widgetConfigService.hasConfig$ | async) {
@if (widgetConfigService.providers$ | async; as providers) {
<ng-container
*c8yComponentOutlet="widgetConfigRoot; providers: providers"
></ng-container>
}
}
</form>
</div>
</div>
<div
class="inner-scroll d-col flex-grow p-32 p-t-0"
right-pane
>
<c8y-widget-preview [previewClasses]="getStyle(true)"></c8y-widget-preview>
<c8y-appearance-settings
[(themeClass)]="styling.contentClass"
[(headerClass)]="styling.headerClass"
[possibleStylingTheme]="possibleStyling.WIDGET_CONTENT_CLASSES"
[possibleStylingHeader]="possibleStyling.WIDGET_HEADER_CLASSES"
[defaultThemeClass]="defaultStyling.contentClass"
[defaultHeaderClass]="defaultStyling.headerClass"
[columns]="2"
></c8y-appearance-settings>
</div>
</c8y-resizable-grid>
<div class="card-footer separator text-center">
<button
class="btn btn-default"
title="{{ 'Cancel' | translate }}"
type="button"
data-cy="widget-config--cancel-widget"
(click)="close()"
>
{{ 'Cancel' | translate }}
</button>
<button
class="btn btn-primary"
title="{{ 'Save' | translate }}"
type="submit"
data-cy="widget-config--save-widget"
(click)="save()"
[disabled]="(contextDashboardService.formDisabled$ | async) || isSaveDisabled()"
c8yProductExperience
[actionName]="current ? 'editWidget' : 'createWidget'"
[actionData]="{ widgetName: selected && selected.id }"
>
{{ 'Save' | translate }}
</button>
</div>
}