ngx-edu-sharing-ui 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/.browserslistrc +16 -0
  2. package/.eslintrc.json +44 -0
  3. package/README.md +40 -0
  4. package/assets/scss/mixins.scss +95 -0
  5. package/assets/scss/variables.scss +33 -0
  6. package/karma.conf.js +42 -0
  7. package/ng-package.json +10 -0
  8. package/package.json +19 -0
  9. package/src/lib/actionbar/actionbar.component.html +59 -0
  10. package/src/lib/actionbar/actionbar.component.scss +123 -0
  11. package/src/lib/actionbar/actionbar.component.ts +174 -0
  12. package/src/lib/common/edu-sharing-ui-common.module.ts +80 -0
  13. package/src/lib/directives/border-box-observer.directive.ts +75 -0
  14. package/src/lib/directives/check-text-overflow.directive.ts +61 -0
  15. package/src/lib/directives/drag-nodes/drag-nodes.ts +32 -0
  16. package/src/lib/directives/drag-nodes/nodes-drag-source.directive.ts +79 -0
  17. package/src/lib/directives/drag-nodes/nodes-drag.directive.ts +43 -0
  18. package/src/lib/directives/drag-nodes/nodes-drop-target.directive.ts +116 -0
  19. package/src/lib/directives/focus-state.directive.ts +34 -0
  20. package/src/lib/directives/icon.directive.ts +142 -0
  21. package/src/lib/directives/nodes-drop-target-legacy.directive.ts +155 -0
  22. package/src/lib/dropdown/dropdown.component.html +32 -0
  23. package/src/lib/dropdown/dropdown.component.scss +67 -0
  24. package/src/lib/dropdown/dropdown.component.ts +71 -0
  25. package/src/lib/edu-sharing-ui-configuration.ts +47 -0
  26. package/src/lib/edu-sharing-ui.module.ts +49 -0
  27. package/src/lib/list-items/available-widgets.ts +30 -0
  28. package/src/lib/list-items/format-duration.pipe.ts +17 -0
  29. package/src/lib/list-items/list-base/list-base.component.html +52 -0
  30. package/src/lib/list-items/list-base/list-base.component.ts +44 -0
  31. package/src/lib/list-items/list-collection-info/list-collection-info.component.html +48 -0
  32. package/src/lib/list-items/list-collection-info/list-collection-info.component.scss +8 -0
  33. package/src/lib/list-items/list-collection-info/list-collection-info.component.ts +24 -0
  34. package/src/lib/list-items/list-counts/list-counts.component.html +1 -0
  35. package/src/lib/list-items/list-counts/list-counts.component.scss +3 -0
  36. package/src/lib/list-items/list-counts/list-counts.component.ts +59 -0
  37. package/src/lib/list-items/list-items.module.ts +33 -0
  38. package/src/lib/list-items/list-node-license/list-node-license.component.html +8 -0
  39. package/src/lib/list-items/list-node-license/list-node-license.component.ts +47 -0
  40. package/src/lib/list-items/list-node-replication-source/list-node-replication-source.component.html +11 -0
  41. package/src/lib/list-items/list-node-replication-source/list-node-replication-source.component.ts +60 -0
  42. package/src/lib/list-items/list-node-workflow/list-node-workflow.component.html +3 -0
  43. package/src/lib/list-items/list-node-workflow/list-node-workflow.component.ts +21 -0
  44. package/src/lib/list-items/list-text/list-text.component.html +176 -0
  45. package/src/lib/list-items/list-text/list-text.component.scss +3 -0
  46. package/src/lib/list-items/list-text/list-text.component.ts +107 -0
  47. package/src/lib/list-items/list-widget.ts +52 -0
  48. package/src/lib/list-items/node-row/node-row.component.html +31 -0
  49. package/src/lib/list-items/node-row/node-row.component.scss +50 -0
  50. package/src/lib/list-items/node-row/node-row.component.ts +16 -0
  51. package/src/lib/list-items/node-source.pipe.ts +48 -0
  52. package/src/lib/node-entries/combined-data-source.ts +51 -0
  53. package/src/lib/node-entries/custom-templates-data-source.ts +6 -0
  54. package/src/lib/node-entries/drag-preview/drag-preview.component.html +6 -0
  55. package/src/lib/node-entries/drag-preview/drag-preview.component.scss +35 -0
  56. package/src/lib/node-entries/drag-preview/drag-preview.component.ts +15 -0
  57. package/src/lib/node-entries/entries-model.ts +120 -0
  58. package/src/lib/node-entries/items-cap.ts +54 -0
  59. package/src/lib/node-entries/list-item-label.pipe.ts +28 -0
  60. package/src/lib/node-entries/mixins.scss +23 -0
  61. package/src/lib/node-entries/node-cache.spec.ts +199 -0
  62. package/src/lib/node-entries/node-cache.ts +81 -0
  63. package/src/lib/node-entries/node-data-source-remote.ts +33 -0
  64. package/src/lib/node-entries/node-data-source.ts +148 -0
  65. package/src/lib/node-entries/node-entries-card/node-entries-card.component.html +167 -0
  66. package/src/lib/node-entries/node-entries-card/node-entries-card.component.scss +28 -0
  67. package/src/lib/node-entries/node-entries-card/node-entries-card.component.ts +132 -0
  68. package/src/lib/node-entries/node-entries-card/node-entries-card.main.scss +261 -0
  69. package/src/lib/node-entries/node-entries-card-grid/node-entries-card-grid.component.html +205 -0
  70. package/src/lib/node-entries/node-entries-card-grid/node-entries-card-grid.component.scss +181 -0
  71. package/src/lib/node-entries/node-entries-card-grid/node-entries-card-grid.component.ts +361 -0
  72. package/src/lib/node-entries/node-entries-card-small/node-entries-card-small.component.html +100 -0
  73. package/src/lib/node-entries/node-entries-card-small/node-entries-card-small.component.scss +46 -0
  74. package/src/lib/node-entries/node-entries-card-small/node-entries-card-small.component.ts +40 -0
  75. package/src/lib/node-entries/node-entries-global-options/node-entries-global-options.component.html +23 -0
  76. package/src/lib/node-entries/node-entries-global-options/node-entries-global-options.component.scss +58 -0
  77. package/src/lib/node-entries/node-entries-global-options/node-entries-global-options.component.ts +16 -0
  78. package/src/lib/node-entries/node-entries-global.service.ts +79 -0
  79. package/src/lib/node-entries/node-entries-table/column-chooser/column-chooser.component.html +25 -0
  80. package/src/lib/node-entries/node-entries-table/column-chooser/column-chooser.component.scss +32 -0
  81. package/src/lib/node-entries/node-entries-table/column-chooser/column-chooser.component.ts +31 -0
  82. package/src/lib/node-entries/node-entries-table/node-entries-table.component.html +270 -0
  83. package/src/lib/node-entries/node-entries-table/node-entries-table.component.scss +169 -0
  84. package/src/lib/node-entries/node-entries-table/node-entries-table.component.ts +333 -0
  85. package/src/lib/node-entries/node-entries-templates.service.ts +31 -0
  86. package/src/lib/node-entries/node-entries-wrapper.component.ts +363 -0
  87. package/src/lib/node-entries/node-entries.component.html +33 -0
  88. package/src/lib/node-entries/node-entries.component.scss +13 -0
  89. package/src/lib/node-entries/node-entries.component.ts +151 -0
  90. package/src/lib/node-entries/node-entries.module.ts +93 -0
  91. package/src/lib/node-entries/node-rating/node-rating.component.html +53 -0
  92. package/src/lib/node-entries/node-rating/node-rating.component.scss +31 -0
  93. package/src/lib/node-entries/node-rating/node-rating.component.ts +105 -0
  94. package/src/lib/node-entries/node-stats-badges/node-stats-badges.component.html +39 -0
  95. package/src/lib/node-entries/node-stats-badges/node-stats-badges.component.scss +44 -0
  96. package/src/lib/node-entries/node-stats-badges/node-stats-badges.component.ts +43 -0
  97. package/src/lib/node-entries/node-type-badge/node-type-badge.component.html +31 -0
  98. package/src/lib/node-entries/node-type-badge/node-type-badge.component.scss +5 -0
  99. package/src/lib/node-entries/node-type-badge/node-type-badge.component.ts +36 -0
  100. package/src/lib/node-entries/option-button/option-button.component.ts +42 -0
  101. package/src/lib/node-entries/preview-image/preview-image.component.html +19 -0
  102. package/src/lib/node-entries/preview-image/preview-image.component.scss +31 -0
  103. package/src/lib/node-entries/preview-image/preview-image.component.ts +47 -0
  104. package/src/lib/node-entries/sort-select-panel/sort-select-panel.component.html +27 -0
  105. package/src/lib/node-entries/sort-select-panel/sort-select-panel.component.scss +9 -0
  106. package/src/lib/node-entries/sort-select-panel/sort-select-panel.component.ts +26 -0
  107. package/src/lib/node-url/node-url.component.html +66 -0
  108. package/src/lib/node-url/node-url.component.scss +32 -0
  109. package/src/lib/node-url/node-url.component.ts +136 -0
  110. package/src/lib/pipes/file-size.pipe.ts +24 -0
  111. package/src/lib/pipes/format-date.pipe.ts +39 -0
  112. package/src/lib/pipes/node-icon.pipe.ts +11 -0
  113. package/src/lib/pipes/node-image-size.pipe.ts +18 -0
  114. package/src/lib/pipes/node-image.pipe.ts +71 -0
  115. package/src/lib/pipes/node-person-name.pipe.ts +41 -0
  116. package/src/lib/pipes/node-title.pipe.ts +12 -0
  117. package/src/lib/pipes/option-tooltip.pipe.ts +32 -0
  118. package/src/lib/pipes/replace-chars.pipe.ts +21 -0
  119. package/src/lib/pipes/vcard-name.pipe.ts +11 -0
  120. package/src/lib/services/abstract/app.service.ts +4 -0
  121. package/src/lib/services/abstract/keyboard-shortcuts.service.ts +10 -0
  122. package/src/lib/services/abstract/options-helper.service.ts +29 -0
  123. package/src/lib/services/abstract/toast.service.ts +5 -0
  124. package/src/lib/services/accessibility.service.ts +101 -0
  125. package/src/lib/services/local-events.service.ts +29 -0
  126. package/src/lib/services/node-entries.service.ts +172 -0
  127. package/src/lib/services/node-helper.service.ts +239 -0
  128. package/src/lib/services/nodes-drag-drop.service.ts +165 -0
  129. package/src/lib/services/options-helper-data.service.ts +186 -0
  130. package/src/lib/services/repo-url.service.ts +46 -0
  131. package/src/lib/services/temporary-storage.service.ts +58 -0
  132. package/src/lib/services/ui.service.ts +182 -0
  133. package/src/lib/sort-dropdown/sort-dropdown.component.html +22 -0
  134. package/src/lib/sort-dropdown/sort-dropdown.component.scss +47 -0
  135. package/src/lib/sort-dropdown/sort-dropdown.component.ts +42 -0
  136. package/src/lib/spinner/spinner.component.html +14 -0
  137. package/src/lib/spinner/spinner.component.scss +141 -0
  138. package/src/lib/spinner/spinner.component.ts +12 -0
  139. package/src/lib/translations/README.md +44 -0
  140. package/src/lib/translations/fallback-translation-handler.ts +7 -0
  141. package/src/lib/translations/languages.ts +6 -0
  142. package/src/lib/translations/translation-loader.spec.ts +352 -0
  143. package/src/lib/translations/translation-loader.ts +189 -0
  144. package/src/lib/translations/translation-source.ts +9 -0
  145. package/src/lib/translations/translations.module.ts +49 -0
  146. package/src/lib/translations/translations.service.spec.ts +152 -0
  147. package/src/lib/translations/translations.service.ts +188 -0
  148. package/src/lib/types/accessibillity.ts +15 -0
  149. package/src/lib/types/api-models.ts +4 -0
  150. package/src/lib/types/drag-drop.ts +22 -0
  151. package/src/lib/types/keyboard-shortcuts.ts +29 -0
  152. package/src/lib/types/list-item.ts +67 -0
  153. package/src/lib/types/option-item.ts +247 -0
  154. package/src/lib/types/workflow.ts +35 -0
  155. package/src/lib/util/DateHelper.spec.ts +112 -0
  156. package/src/lib/util/DateHelper.ts +197 -0
  157. package/src/lib/util/VCard.ts +277 -0
  158. package/src/lib/util/color-helper.ts +125 -0
  159. package/src/lib/util/duration-helper.spec.ts +35 -0
  160. package/src/lib/util/duration-helper.ts +98 -0
  161. package/src/lib/util/functions.ts +15 -0
  162. package/src/lib/util/helper.ts +60 -0
  163. package/src/lib/util/isNumeric.ts +13 -0
  164. package/src/lib/util/rest-helper.ts +28 -0
  165. package/src/lib/util/ui-animation.ts +154 -0
  166. package/src/lib/util/ui-constants.ts +20 -0
  167. package/src/module.ts +76 -0
  168. package/src/test.ts +28 -0
  169. package/tsconfig.lib.json +15 -0
  170. package/tsconfig.lib.prod.json +10 -0
  171. package/tsconfig.spec.json +17 -0
@@ -0,0 +1,79 @@
1
+ import { Injectable, TemplateRef } from '@angular/core';
2
+ import { Node } from 'ngx-edu-sharing-api';
3
+ import { ListItemType } from '../types/list-item';
4
+ import { Scope } from '../types/option-item';
5
+
6
+ export type CustomField = {
7
+ type: ListItemType;
8
+ name: string | CustomFieldSpecialType;
9
+ };
10
+ export enum CustomFieldSpecialType {
11
+ preview,
12
+ type,
13
+ }
14
+ export type CustomFieldInfo = {
15
+ type: ListItemType;
16
+ /**
17
+ * Either the property name (i.e. "cm:name") or a special value.
18
+ */
19
+ name: string | CustomFieldSpecialType;
20
+
21
+ /**
22
+ * Custom callback which should return true if the template should be used for the given item.
23
+ */
24
+ useCallback?: (node: Node) => boolean;
25
+ templateRef: TemplateRef<unknown>;
26
+ };
27
+
28
+ export type PaginationStrategy = 'infinite-scroll' | 'paginator';
29
+
30
+ type PaginationScope = Scope | 'DEFAULT';
31
+ /**
32
+ * this service is intended to add custom behaviour to the global tables & grid views
33
+ */
34
+ @Injectable({
35
+ providedIn: 'root',
36
+ })
37
+ export class NodeEntriesGlobalService {
38
+ private customFields: CustomFieldInfo[] = [];
39
+ private paginationStrategy: { [key in PaginationScope]?: PaginationStrategy } = {
40
+ [Scope.WorkspaceList]: 'infinite-scroll',
41
+ [Scope.Search]: 'infinite-scroll',
42
+ DEFAULT: 'infinite-scroll',
43
+ };
44
+ private paginatorSizeOptions: { [key in PaginationScope]?: number[] } = {
45
+ DEFAULT: [25, 50, 75, 100],
46
+ };
47
+
48
+ constructor() {}
49
+
50
+ public setPaginationStrategy(scope: PaginationScope, strategy: PaginationStrategy) {
51
+ this.paginationStrategy[scope] = strategy;
52
+ }
53
+ public getPaginationStrategy(scope: Scope) {
54
+ return this.paginationStrategy[scope] ?? this.paginationStrategy['DEFAULT'];
55
+ }
56
+ public setPaginatorSizeOptions(scope: PaginationScope, size: number[]) {
57
+ this.paginatorSizeOptions[scope] = size;
58
+ }
59
+ public getPaginatorSizeOptions(scope: Scope) {
60
+ return this.paginatorSizeOptions[scope] ?? this.paginatorSizeOptions['DEFAULT'];
61
+ }
62
+ public getCustomFieldTemplate(item: CustomField, node: Node) {
63
+ return this.customFields.filter(
64
+ (c) =>
65
+ c.type === item.type &&
66
+ c.name === item.name &&
67
+ (!c.useCallback || c.useCallback(node)),
68
+ )?.[0]?.templateRef;
69
+ }
70
+
71
+ /**
72
+ * Registers a custom (node) attribute you want to render via the given template.
73
+ *
74
+ * You may also override existing attributes if you want to provide a custom view.
75
+ */
76
+ registerCustomFieldRendering(customFieldInfo: CustomFieldInfo) {
77
+ this.customFields.push(customFieldInfo);
78
+ }
79
+ }
@@ -0,0 +1,25 @@
1
+ <ng-template
2
+ cdkConnectedOverlay
3
+ [cdkConnectedOverlayOrigin]="origin"
4
+ [cdkConnectedOverlayOpen]="columnChooserVisible"
5
+ [cdkConnectedOverlayHasBackdrop]="true"
6
+ [cdkConnectedOverlayFlexibleDimensions]="true"
7
+ [cdkConnectedOverlayViewportMargin]="5"
8
+ (backdropClick)="columnChooserVisibleChange.emit(false)"
9
+ cdkConnectedOverlayBackdropClass="column-chooser-backdrop"
10
+ >
11
+ <div
12
+ cdkDropList
13
+ class="column-chooser mat-elevation-z2"
14
+ (cdkDropListDropped)="columnChooserDrop($event)"
15
+ >
16
+ <div class="column-chooser-item" *ngFor="let column of columns; index as index" cdkDrag>
17
+ <mat-checkbox [checked]="column.visible" (change)="columnChooserToggle(index)">
18
+ {{ column | esListItemLabel | async }}
19
+ </mat-checkbox>
20
+ <div class="drag-handle" cdkDragHandle>
21
+ <i esIcon="drag_handle"></i>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </ng-template>
@@ -0,0 +1,32 @@
1
+ .column-chooser {
2
+ max-width: 100%;
3
+ border: solid 1px #ccc;
4
+ min-height: 60px;
5
+ display: block;
6
+ background: white;
7
+ border-radius: 4px;
8
+ overflow: auto;
9
+ }
10
+
11
+ .column-chooser-item {
12
+ border-bottom: solid 1px #ccc;
13
+ color: rgba(0, 0, 0, 0.87);
14
+ display: flex;
15
+ flex-direction: row;
16
+ align-items: center;
17
+ background: white;
18
+ font-size: 14px;
19
+ justify-content: space-between;
20
+ mat-checkbox {
21
+ margin: 0 12px;
22
+ }
23
+ .drag-handle {
24
+ color: rgba(0, 0, 0, 0.5);
25
+ cursor: move;
26
+ padding: 20px;
27
+ }
28
+ }
29
+
30
+ .column-chooser-backdrop {
31
+ background: none;
32
+ }
@@ -0,0 +1,31 @@
1
+ import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
2
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
3
+ import { CdkOverlayOrigin } from '@angular/cdk/overlay';
4
+ import { ListItem } from '../../../types/list-item';
5
+
6
+ @Component({
7
+ selector: 'es-column-chooser',
8
+ templateUrl: './column-chooser.component.html',
9
+ styleUrls: ['./column-chooser.component.scss'],
10
+ })
11
+ export class ColumnChooserComponent {
12
+ @Input() origin: CdkOverlayOrigin;
13
+ @Input() columnChooserVisible = false;
14
+ @Output() columnChooserVisibleChange = new EventEmitter<boolean>();
15
+
16
+ @Input() columns: ListItem[];
17
+ @Output() columnsChange = new EventEmitter<ListItem[]>();
18
+
19
+ constructor() {}
20
+
21
+ columnChooserDrop(event: CdkDragDrop<string[]>) {
22
+ moveItemInArray(this.columns, event.previousIndex, event.currentIndex);
23
+ this.columnsChange.emit(this.columns);
24
+ }
25
+
26
+ columnChooserToggle(columnIndex: number): void {
27
+ const column = this.columns[columnIndex];
28
+ column.visible = !column.visible;
29
+ this.columnsChange.emit(this.columns);
30
+ }
31
+ }
@@ -0,0 +1,270 @@
1
+ <es-dropdown #dropdown [options]="entriesService.options?.[Target.ListDropdown]"></es-dropdown>
2
+ <button
3
+ #menuTrigger="matMenuTrigger"
4
+ mat-button
5
+ class="dropdown-dummy cdk-visually-hidden"
6
+ [style.left.px]="dropdownLeft"
7
+ [style.top.px]="dropdownTop"
8
+ [matMenuTriggerFor]="dropdown.menu"
9
+ tabindex="-1"
10
+ aria-hidden="true"
11
+ ></button>
12
+ <es-node-entries-global-options
13
+ *ngIf="entriesService.globalOptions?.length"
14
+ [displayType]="NodeEntriesDisplayType.Table"
15
+ >
16
+ </es-node-entries-global-options>
17
+ <mat-table
18
+ [dataSource]="entriesService.dataSource"
19
+ matSort
20
+ [matSortDisableClear]="true"
21
+ [matSortActive]="entriesService.sort?.active"
22
+ [matSortDirection]="entriesService.sort?.direction"
23
+ esInfiniteScroll
24
+ (scrolled)="loadData('scroll')"
25
+ >
26
+ <!-- Checkbox Column -->
27
+ <ng-container matColumnDef="select">
28
+ <mat-header-cell *matHeaderCellDef>
29
+ <mat-checkbox
30
+ [ngModel]="entriesService.selection.selected.length > 0"
31
+ [indeterminate]="
32
+ entriesService.selection.selected.length > 0 &&
33
+ entriesService.selection.selected.length !== entriesService.dataSource.getData().length
34
+ "
35
+ (ngModelChange)="toggleAll($event)"
36
+ aria-label="{{ 'LIST_TABLE.TOGGLE_ALL' | translate }}"
37
+ ></mat-checkbox>
38
+ </mat-header-cell>
39
+ <mat-cell *matCellDef="let node">
40
+ <mat-checkbox
41
+ [checked]="entriesService.selection.isSelected(node)"
42
+ (change)="entriesService.onCheckboxChanged(node, $event.checked)"
43
+ aria-label="{{ 'SELECT' | translate : { element: (node | nodeTitle) } }}"
44
+ ></mat-checkbox>
45
+ </mat-cell>
46
+ </ng-container>
47
+ <div matColumnDef="icon">
48
+ <mat-header-cell *matHeaderCellDef class="cell-icon cell-count">
49
+ ({{ entriesService.selection.selected.length
50
+ }}<ng-container *ngIf="entriesService.dataSource?.getTotal() !== undefined">
51
+ / {{ entriesService.dataSource?.getTotal() }}</ng-container
52
+ >)
53
+ </mat-header-cell>
54
+ <mat-cell *matCellDef="let node" class="cell-icon">
55
+ <ng-container
56
+ *ngIf="entriesService.elementInteractionType === InteractionType.DefaultActionLink"
57
+ >
58
+ <ng-container *ngTemplateOutlet="icon; context: { node: this.node }"></ng-container>
59
+ </ng-container>
60
+ <div
61
+ *ngIf="entriesService.elementInteractionType !== InteractionType.DefaultActionLink"
62
+ (click)="
63
+ entriesService.onClicked({ event: $event, element: node, source: ClickSource.Icon })
64
+ "
65
+ (dblclick)="entriesService.dblClickItem.emit({ element: node, source: ClickSource.Icon })"
66
+ >
67
+ <ng-container
68
+ *ngTemplateOutlet="icon; context: { node: this.node }"
69
+ (click)="
70
+ entriesService.onClicked({ event: $event, element: node, source: ClickSource.Icon })
71
+ "
72
+ (dblclick)="entriesService.dblClickItem.emit({ element: node, source: ClickSource.Icon })"
73
+ ></ng-container>
74
+ </div>
75
+ </mat-cell>
76
+ </div>
77
+ <ng-container matColumnDef="actions">
78
+ <mat-header-cell *matHeaderCellDef>
79
+ <button
80
+ *ngIf="entriesService.configureColumns"
81
+ mat-icon-button
82
+ (click)="columnChooserVisible = !columnChooserVisible"
83
+ cdkOverlayOrigin
84
+ #columnChooserTrigger="cdkOverlayOrigin"
85
+ [matTooltip]="'LIST_TABLE.CONFIGURE_COLUMNS' | translate"
86
+ [attr.aria-label]="'LIST_TABLE.CONFIGURE_COLUMNS' | translate"
87
+ >
88
+ <i esIcon="settings"></i>
89
+ </button>
90
+ </mat-header-cell>
91
+ <mat-cell *matCellDef="let node">
92
+ <button
93
+ mat-icon-button
94
+ *ngIf="entriesService.options?.[Target.List]?.length"
95
+ color="primary"
96
+ (click)="openMenu(node)"
97
+ [matMenuTriggerFor]="dropdown.menu"
98
+ >
99
+ <i esIcon="more_vert" [aria]="true"></i>
100
+ </button>
101
+ </mat-cell>
102
+ </ng-container>
103
+ <!-- Data Columns -->
104
+ <ng-container
105
+ *ngFor="let column of visibleDataColumns$ | async; let first = first"
106
+ [matColumnDef]="column.name"
107
+ >
108
+ <ng-container>
109
+ <mat-header-cell
110
+ *matHeaderCellDef
111
+ mat-sort-header
112
+ [disabled]="!(entriesService.sort?.allowed && isSortable(column))"
113
+ [class.mat-column-primary]="first"
114
+ >{{ column | esListItemLabel | async }}</mat-header-cell
115
+ >
116
+ </ng-container>
117
+ <mat-cell
118
+ *matCellDef="let node"
119
+ #cell
120
+ [class.mat-column-primary]="first"
121
+ attr.data-test="table-cell-{{ column.name }}"
122
+ >
123
+ <ng-container
124
+ *ngIf="entriesService.elementInteractionType === InteractionType.DefaultActionLink"
125
+ >
126
+ <es-node-url cdkMonitorSubtreeFocus [node]="node" [mode]="first ? 'link' : 'wrapper'">
127
+ <es-list-base
128
+ [forceText]="true"
129
+ [node]="node"
130
+ [item]="column"
131
+ esCheckTextOverflow
132
+ #text="esCheckTextOverflow"
133
+ [matTooltip]="text.hasTextOverflow() ? cell.innerText : null"
134
+ matTooltipTouchGestures="off"
135
+ ></es-list-base>
136
+ </es-node-url>
137
+ </ng-container>
138
+ <es-list-base
139
+ *ngIf="entriesService.elementInteractionType !== InteractionType.DefaultActionLink"
140
+ [forceText]="true"
141
+ [node]="node"
142
+ [item]="column"
143
+ (click)="
144
+ entriesService.onClicked({
145
+ event: $event,
146
+ element: node,
147
+ source: ClickSource.Metadata,
148
+ attribute: column
149
+ })
150
+ "
151
+ (dblclick)="
152
+ entriesService.dblClickItem.emit({
153
+ element: node,
154
+ source: ClickSource.Metadata,
155
+ attribute: column
156
+ })
157
+ "
158
+ esCheckTextOverflow
159
+ #text="esCheckTextOverflow"
160
+ [matTooltip]="text.hasTextOverflow() ? cell.innerText : null"
161
+ matTooltipTouchGestures="off"
162
+ ></es-list-base>
163
+ <ng-container *ngIf="first">
164
+ <div class="childobjects" *ngIf="node.properties?.['virtual:childobjectcount'] > 0">
165
+ <div
166
+ class="childobject-count"
167
+ matTooltip="{{
168
+ 'CHILDOBJECT_COUNT'
169
+ | translate : { count: node.properties['virtual:childobjectcount'] * 1 + 1 }
170
+ }}"
171
+ >
172
+ <span>{{ node.properties['virtual:childobjectcount'] * 1 + 1 }}</span
173
+ ><i esIcon="filter_none"></i>
174
+ </div>
175
+ </div>
176
+ </ng-container>
177
+ </mat-cell>
178
+ </ng-container>
179
+ <mat-header-row mat-header-row *matHeaderRowDef="visibleColumnNames$ | async"></mat-header-row>
180
+ <mat-row
181
+ mat-row
182
+ matRipple
183
+ cdkDrag
184
+ esNodesDrag
185
+ [cdkDragDisabled]="!entriesService.dragDrop?.dragAllowed || ui.isMobile()"
186
+ [cdkDragData]="getDragData(node)"
187
+ (cdkDragStarted)="onDragStarted(node)"
188
+ (cdkDragEnded)="onDragEnded()"
189
+ [esNodesDropTarget]="node"
190
+ [canDropNodes]="canDrop"
191
+ (nodeDropped)="drop($event)"
192
+ class="mat-row"
193
+ [class.mat-row-selected]="entriesService.selection.isSelected(node)"
194
+ [class.selected-when-dragging]="isDragging && entriesService.selection.isSelected(node)"
195
+ [class.mat-row-virtual]="node.virtual"
196
+ [class.mat-row-virtual-first]="
197
+ node.virtual && !$any(entriesService.dataSource.getData()[i - 1])?.virtual
198
+ "
199
+ [class.mat-row-virtual-last]="
200
+ node.virtual && !$any(entriesService.dataSource.getData()[i + 1])?.virtual
201
+ "
202
+ [class.dynamic-single-click]="entriesService.singleClickHint === 'dynamic'"
203
+ *matRowDef="let node; let i = index; let last = last; columns: visibleColumnNames$ | async"
204
+ (contextmenu)="onRowContextMenu({ event: $event, node: node })"
205
+ (keydown.ContextMenu)="onRowContextMenu({ event: $event, node: node })"
206
+ >
207
+ <es-drag-preview
208
+ *cdkDragPreview
209
+ [node]="node"
210
+ [selected]="entriesService.selection.selected"
211
+ [item]="(visibleDataColumns$ | async)[0]"
212
+ ></es-drag-preview>
213
+ </mat-row>
214
+ </mat-table>
215
+ <ng-container
216
+ *ngIf="
217
+ (entriesService.dataSource.isLoadingSubject | async) === false &&
218
+ entriesService.dataSource.hasMore() &&
219
+ entriesService.paginationStrategy === 'infinite-scroll'
220
+ "
221
+ >
222
+ <div class="load-more">
223
+ <button mat-button color="primary" (click)="loadData('button')">
224
+ <i esIcon="refresh"></i>
225
+ <span>{{ 'LOAD_MORE' | translate }}</span>
226
+ </button>
227
+ </div>
228
+ </ng-container>
229
+ <ng-container *ngIf="entriesService.dataSource.isLoadingSubject | async">
230
+ <ng-container *ngTemplateOutlet="loading"> </ng-container>
231
+ </ng-container>
232
+ <!--
233
+ <mat-paginator #paginator [pageSizeOptions]="pageSizeOptions"></mat-paginator>
234
+ -->
235
+
236
+ <!-- Wait for ready state to avoid changed-after-checked error when `columnChooserTrigger` becomes
237
+ available. -->
238
+ <es-column-chooser
239
+ *ngIf="columnChooserTriggerReady"
240
+ [(columns)]="entriesService.columns"
241
+ [(columnChooserVisible)]="columnChooserVisible"
242
+ [origin]="columnChooserTrigger"
243
+ (columnsChange)="entriesService.columnsChange.emit($event)"
244
+ ></es-column-chooser>
245
+ <ng-template #loading>
246
+ <es-spinner></es-spinner>
247
+ </ng-template>
248
+ <ng-template #icon let-node="node">
249
+ <div class="icon-bg">
250
+ <img
251
+ *ngIf="node.iconURL"
252
+ [src]="node | esNodeIcon | async"
253
+ [alt]="
254
+ node.mediatype
255
+ ? ('NODE.mediatype' | translate) + ': ' + ('MEDIATYPE.' + node.mediatype | translate)
256
+ : ''
257
+ "
258
+ [matTooltip]="
259
+ node.mediatype
260
+ ? ('NODE.mediatype' | translate) + ': ' + ('MEDIATYPE.' + node.mediatype | translate)
261
+ : ''
262
+ "
263
+ matTooltipTouchGestures="off"
264
+ />
265
+ <i
266
+ *ngIf="!node.iconURL"
267
+ [esIcon]="node.authorityType ? (node.authorityType === 'GROUP' ? 'group' : 'person') : null"
268
+ ></i>
269
+ </div>
270
+ </ng-template>
@@ -0,0 +1,169 @@
1
+ @use 'sass:color';
2
+ @import '../../../../assets/scss/mixins';
3
+
4
+ $defaultColumnWidth: 145px;
5
+ $minColumnWidth: 30%;
6
+ $rowHeight: 58px;
7
+
8
+ :host {
9
+ display: flex;
10
+ flex-direction: column;
11
+ ::ng-deep {
12
+ mat-header-cell {
13
+ color: var(--textMediumLight);
14
+ }
15
+ mat-cell,
16
+ mat-header-cell {
17
+ margin: 0 !important;
18
+ }
19
+ mat-cell es-node-url {
20
+ width: 100%;
21
+ a {
22
+ color: #000;
23
+ }
24
+ &.cdk-keyboard-focused {
25
+ @include setGlobalKeyboardFocus('border');
26
+ }
27
+ }
28
+ es-list-base {
29
+ white-space: nowrap;
30
+ text-overflow: ellipsis;
31
+ overflow: hidden;
32
+ display: flex;
33
+ width: 100%;
34
+ height: $rowHeight;
35
+ align-items: center;
36
+ }
37
+ }
38
+ }
39
+ mat-header-cell,
40
+ mat-cell {
41
+ margin: 0 3px;
42
+ // do not fix the "primary/title" column
43
+ &:not(.mat-column-primary) {
44
+ flex: 0 $defaultColumnWidth;
45
+ }
46
+ &.mat-column-primary {
47
+ min-width: $minColumnWidth;
48
+ }
49
+ &.mat-column-select {
50
+ flex: 0 58px;
51
+ min-width: 58px;
52
+ padding-left: 14px;
53
+ }
54
+ &.mat-column-icon {
55
+ flex: 0 85px;
56
+ min-width: 85px;
57
+ justify-content: center;
58
+ }
59
+ &.mat-column-actions {
60
+ flex: 0 58px;
61
+ min-width: 58px;
62
+ display: flex;
63
+ justify-content: flex-end;
64
+ padding-right: 5px;
65
+ }
66
+ }
67
+
68
+ .mat-row {
69
+ &.dynamic-single-click {
70
+ cursor: pointer;
71
+ &:hover {
72
+ background-color: rgb(var(--palette-primary-50));
73
+ }
74
+ }
75
+ &.mat-row-selected {
76
+ background: var(--listItemSelectedBackgroundEffect);
77
+ .mat-mdc-cell {
78
+ background: transparent;
79
+ }
80
+ }
81
+ // Overrides `.mat-row-selected` background by order
82
+ &.mat-row-virtual {
83
+ background: linear-gradient(to right, var(--nodeVirtualColor) 5px, transparent 5px)
84
+ no-repeat;
85
+ border-right: 2px dashed var(--nodeVirtualColorLight);
86
+ .mat-mdc-cell {
87
+ background: transparent;
88
+ }
89
+ &.mat-row-selected {
90
+ background: linear-gradient(
91
+ to right,
92
+ var(--nodeVirtualColor) 0,
93
+ var(--nodeVirtualColor) 5px,
94
+ var(--listItemSelectedBackground) 5px,
95
+ var(--listItemSelectedBackground) 5px
96
+ );
97
+ }
98
+ }
99
+ &.mat-row-virtual-first {
100
+ border-top: 2px dashed var(--nodeVirtualColorLight);
101
+ }
102
+ &.mat-row-virtual-last {
103
+ border-bottom: 2px dashed var(--nodeVirtualColorLight);
104
+ }
105
+ &.selected-when-dragging {
106
+ opacity: 0.5; // Same as .cdk-drag-placeholder
107
+ }
108
+ }
109
+ .dropdown-dummy {
110
+ position: fixed;
111
+ }
112
+ .childobjects {
113
+ background-color: rgba(0, 0, 0, 0.05);
114
+ border-radius: 15px;
115
+ display: inline-flex;
116
+ align-items: center;
117
+ min-width: 51px;
118
+ min-height: 26px;
119
+ justify-content: center;
120
+ cursor: default;
121
+ user-select: none;
122
+ padding: 2px 8px;
123
+ margin-left: 5px;
124
+ > .childobject-count {
125
+ display: inline-flex;
126
+ align-items: center;
127
+ > i {
128
+ font-size: 13px;
129
+ margin-left: 4px;
130
+ }
131
+ }
132
+ }
133
+ .cell-icon {
134
+ .icon-bg {
135
+ width: 36px;
136
+ height: 36px;
137
+ padding: 3px;
138
+ margin: 1px 0;
139
+ background-color: #fff;
140
+ border-radius: 50%;
141
+ display: flex;
142
+ justify-content: center;
143
+ align-items: center;
144
+ @include materialShadowSmall();
145
+ > img {
146
+ width: 18px;
147
+ height: auto;
148
+ }
149
+ > i {
150
+ color: #666;
151
+ font-size: 18px;
152
+ }
153
+ }
154
+ }
155
+ .mat-column-link {
156
+ flex: 0 60px;
157
+ a {
158
+ display: flex;
159
+ justify-content: center;
160
+ }
161
+ }
162
+
163
+ .load-more {
164
+ display: flex;
165
+ justify-content: center;
166
+ }
167
+ es-node-entries-global-options {
168
+ padding-bottom: 20px;
169
+ }