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,16 @@
1
+ # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2
+ # For additional information regarding the format and rule options, please see:
3
+ # https://github.com/browserslist/browserslist#queries
4
+
5
+ # For the full list of supported browsers by the Angular framework, please see:
6
+ # https://angular.io/guide/browser-support
7
+
8
+ # You can see what browsers were selected by your queries by running:
9
+ # npx browserslist
10
+
11
+ last 1 Chrome version
12
+ last 1 Firefox version
13
+ last 2 Edge major versions
14
+ last 2 Safari major versions
15
+ last 2 iOS major versions
16
+ Firefox ESR
package/.eslintrc.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "extends": "../../.eslintrc.json",
3
+ "ignorePatterns": [
4
+ "!**/*"
5
+ ],
6
+ "overrides": [
7
+ {
8
+ "files": [
9
+ "*.ts"
10
+ ],
11
+ "parserOptions": {
12
+ "project": [
13
+ "projects/edu-sharing-ui/tsconfig.lib.json",
14
+ "projects/edu-sharing-ui/tsconfig.spec.json"
15
+ ],
16
+ "createDefaultProgram": true
17
+ },
18
+ "rules": {
19
+ "@angular-eslint/directive-selector": [
20
+ "error",
21
+ {
22
+ "type": "attribute",
23
+ "prefix": "lib",
24
+ "style": "camelCase"
25
+ }
26
+ ],
27
+ "@angular-eslint/component-selector": [
28
+ "error",
29
+ {
30
+ "type": "element",
31
+ "prefix": "lib",
32
+ "style": "kebab-case"
33
+ }
34
+ ]
35
+ }
36
+ },
37
+ {
38
+ "files": [
39
+ "*.html"
40
+ ],
41
+ "rules": {}
42
+ }
43
+ ]
44
+ }
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # EduSharingUi
2
+
3
+ This library bundles base ui components from edu-sharing.
4
+
5
+ This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 13.3.0.
6
+
7
+ ## Required Init tasks
8
+
9
+ Your project must provide a Toast service (for message viewing). You may use a mat-snackbar for displaying.
10
+
11
+ in your app.module.ts:
12
+
13
+ ```ts
14
+ import { Toast as ToastAbstract } from 'ngx-edu-sharing-ui';
15
+ providers: [
16
+ { provide: ToastAbstract, useClass: Toast },
17
+ // ...
18
+ ];
19
+ ```
20
+
21
+ Make sure that your `Toast`-Service extends the abstract Toast service.
22
+
23
+ You might also provide other services for extended functionality, including
24
+ `Toast`, `OptionsHelperService`, `KeyboardShortcutsService`, `AppService`.
25
+
26
+ Check out our sample angular application for a full example
27
+ Check the `app.module.ts` for registration.
28
+
29
+ In one of your primary components (i.e. router) you need to initalize the material theme and translations:
30
+
31
+ ```ts
32
+ async ngOnInit() {
33
+ this.materialCssVarsService.setPrimaryColor('#2e9e9b');
34
+ this.materialCssVarsService.setAccentColor('#2e9e9b');
35
+ await this.translationsService.initialize().toPromise()
36
+ }
37
+ ```
38
+
39
+ In your scss, make sure to include the global variables via
40
+ `@import "node-modules/ngx-edu-sharing-ui/assets/scss/variables";`
@@ -0,0 +1,95 @@
1
+ @mixin clickable() {
2
+ cursor: pointer;
3
+ -webkit-user-select: none;
4
+ -moz-user-select: none;
5
+ -ms-user-select: none;
6
+ user-select: none;
7
+ -webkit-tap-highlight-color: transparent;
8
+ }
9
+ @mixin limitLineCount($count, $lineHeight: 1) {
10
+ overflow: hidden;
11
+ text-overflow: ellipsis;
12
+ display: -webkit-box;
13
+ line-height: $lineHeight + em;
14
+ max-height: $count * $lineHeight + em;
15
+ -webkit-line-clamp: $count; /* number of lines to show */
16
+ -webkit-box-orient: vertical;
17
+ /* autoprefixer: off */
18
+ }
19
+ @mixin materialShadow($important: false) {
20
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3) if($important, !important, null);
21
+ }
22
+ @mixin materialShadowBottom($opacity: 0.1) {
23
+ box-shadow: 0 3px 3px rgba(0, 0, 0, $opacity);
24
+ }
25
+ @mixin materialShadowSmall($important: false) {
26
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.3) if($important, !important, null);
27
+ }
28
+ @mixin materialShadowMediumLarge($important: false, $opacity: 0.6) {
29
+ box-shadow: 0 0 25px rgba(0, 0, 0, $opacity) if($important, !important, null);
30
+ }
31
+ @mixin materialScrollbar() {
32
+ &::-webkit-scrollbar-track {
33
+ -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
34
+ border-radius: 10px;
35
+ background-color: transparent;
36
+ }
37
+ &::-webkit-scrollbar {
38
+ height: 10px;
39
+ background-color: transparent;
40
+ }
41
+ &::-webkit-scrollbar-thumb {
42
+ max-width: 20px;
43
+ border-radius: 10px;
44
+ // -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
45
+ background-color: var(--primary);
46
+ }
47
+ }
48
+ @mixin removeDefaultFocus() {
49
+ outline: none;
50
+ }
51
+ @mixin setGlobalKeyboardFocus($mode: 'outline') {
52
+ //respect element border radius
53
+ @include removeDefaultFocus();
54
+ @if $mode== 'outline' {
55
+ outline: var(--focusWidth) solid var(--palette-primary-300);
56
+ outline-offset: 2px;
57
+ } @else if $mode== 'border' {
58
+ border: var(--focusWidth) solid var(--palette-primary-300);
59
+ }
60
+ }
61
+ // Apply the content styles in contrast mode. This is just enough contrast to be WCAG complient ---
62
+ // not a high-contrast mode.
63
+ //
64
+ // Call without arguments for use in encapsulated component styles, e.g.,
65
+ // @include contrastMode {
66
+ // // Styles to apply in contrast mode
67
+ // }
68
+ // To us in global context, pass 'global' as first argument, e.g.,
69
+ // @include contrastMode(global) { /* ... */ }
70
+ @mixin contrastMode($scope: encapsulated) {
71
+ $contrastModeSelector: 'body.es-contrast-mode';
72
+ @if $scope == encapsulated {
73
+ :host-context(#{$contrastModeSelector}) & {
74
+ @content;
75
+ }
76
+ } @else if $scope == global {
77
+ #{if(&, '#{$contrastModeSelector} &', $contrastModeSelector)} {
78
+ @content;
79
+ }
80
+ } @else {
81
+ @error "Invalid scope #{$scope}.";
82
+ }
83
+ }
84
+ @mixin blurImage($blurStrength: 25px) {
85
+ position: absolute;
86
+ left: -$blurStrength * 2;
87
+ top: -$blurStrength * 2;
88
+ width: calc(100% + #{$blurStrength * 4});
89
+ height: calc(100% + #{$blurStrength * 4});
90
+ z-index: 0;
91
+ overflow: hidden;
92
+ filter: blur($blurStrength);
93
+ object-fit: cover;
94
+ opacity: 0.7;
95
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ declarations of dynamic css variabled
3
+ will only be included once via angular to prevent duplicate :root entries
4
+ */
5
+ :root {
6
+ --primary: var(--palette-primary-500);
7
+ --warning: #cd2457;
8
+ --tableIconSize: 38px;
9
+ --textLight: #585858;
10
+ --textMediumLight: #888;
11
+ --textMain: #383838;
12
+ --cardWidth: 240px;
13
+ --colorStatusPositive: #40bf8e;
14
+ --colorStatusNegative: var(--warning);
15
+ --colorStarActive: #ba7c00;
16
+ --nodeVirtualColor: #42ca8d;
17
+ --nodeVirtualColorLight: #b8fcdd;
18
+ --transitionNormal: 0.2s;
19
+ --focusWidth: 2px;
20
+ --fontSizeXSmall: 85%;
21
+ --mobileWidth: 700px;
22
+ --mobileStage: 100px;
23
+ --itemSelectedTextColor: var(--palette-primary-700);
24
+ --listItemSelectedBackground: var(--palette-primary-50);
25
+ --listItemSelectedBackgroundEffect: linear-gradient(
26
+ to right,
27
+ var(--primary) 0,
28
+ var(--primary) 5px,
29
+ var(--palette-primary-50) 5px,
30
+ var(--palette-primary-50) 5px
31
+ )
32
+ no-repeat;
33
+ }
package/karma.conf.js ADDED
@@ -0,0 +1,42 @@
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'),
13
+ require('@angular-devkit/build-angular/plugins/karma'),
14
+ ],
15
+ client: {
16
+ jasmine: {
17
+ // you can add configuration options for Jasmine here
18
+ // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
19
+ // for example, you can disable the random execution with `random: false`
20
+ // or set a specific seed with `seed: 4321`
21
+ },
22
+ clearContext: false, // leave Jasmine Spec Runner output visible in browser
23
+ },
24
+ jasmineHtmlReporter: {
25
+ suppressAll: true, // removes the duplicated traces
26
+ },
27
+ coverageReporter: {
28
+ dir: require('path').join(__dirname, '../../coverage/edu-sharing-ui'),
29
+ subdir: '.',
30
+ reporters: [{ type: 'html' }, { type: 'text-summary' }],
31
+ },
32
+ reporters: ['progress', 'kjhtml'],
33
+ browsers: ['Chrome'],
34
+ customLaunchers: {
35
+ ChromeHeadlessCI: {
36
+ base: 'ChromeHeadless',
37
+ flags: ['--no-sandbox'],
38
+ },
39
+ },
40
+ restartOnFileChange: true,
41
+ });
42
+ };
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/edu-sharing-ui",
4
+ "assets": [
5
+ "assets/**"
6
+ ],
7
+ "lib": {
8
+ "entryFile": "src/module.ts"
9
+ }
10
+ }
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "ngx-edu-sharing-ui",
3
+ "version": "0.7.0",
4
+ "license": "GNU GPL v2",
5
+ "description": "Angular components for Edu-Sharing UX parts",
6
+ "peerDependencies": {
7
+ "@angular/cdk": "~13.3.9",
8
+ "@angular/common": "^13.3.0",
9
+ "@angular/core": "^13.3.0",
10
+ "@angular/material": "13.3.9",
11
+ "material-design-icons": "^3.0.1",
12
+ "@ngx-translate/core": "^14.0.0",
13
+ "angular-material-css-vars": "^3.0.0",
14
+ "rxjs": "^6.6.7"
15
+ },
16
+ "dependencies": {
17
+ "tslib": "^2.3.0"
18
+ }
19
+ }
@@ -0,0 +1,59 @@
1
+ <es-dropdown
2
+ #dropdownRef
3
+ [options]="optionsMenu"
4
+ [showDisabled]="showDisabled"
5
+ [position]="dropdownPosition"
6
+ ></es-dropdown>
7
+ <div
8
+ class="actionbar"
9
+ [class.actionbar-all-flat]="style === 'flat'"
10
+ [class.actionbar-background-dark]="backgroundType === 'dark'"
11
+ [class.actionbar-background-primary]="backgroundType === 'primary'"
12
+ [class.actionbar-round]="appearance === 'round'"
13
+ [class.actionbar-icon-button]="appearance === 'icon-button'"
14
+ >
15
+ <button
16
+ *ngFor="let option of optionsAlways; let i = index"
17
+ mat-button
18
+ color="primary"
19
+ [disabled]="!option.isEnabled"
20
+ [class.display-none]="!option.isEnabled && !showDisabled"
21
+ [class.mat-flat-button]="shouldHighlight(i, option)"
22
+ matTooltip="{{ option | optionTooltip }}"
23
+ [attr.aria-label]="option.name | translate"
24
+ (click)="click(option)"
25
+ >
26
+ <i [esIcon]="option.icon"></i>
27
+ <span class="action-always-caption" *ngIf="option.showName && appearance === 'button'">
28
+ {{ option.name | translate }}</span
29
+ >
30
+ </button>
31
+ <button
32
+ mat-button
33
+ color="primary"
34
+ class="more"
35
+ [attr.aria-label]="'OPTIONS.SHOW_ALL_OPTIONS' | translate"
36
+ [matMenuTriggerFor]="dropdownRef.menu"
37
+ *ngIf="canShowDropdown()"
38
+ data-test="more-actions-button"
39
+ >
40
+ <i esIcon="more_vert" [aria]="false"></i>
41
+ </button>
42
+ <div
43
+ *ngIf="optionsToggle.length"
44
+ class="actionToggle"
45
+ [class.actionToggleDivider]="optionsAlways.length"
46
+ >
47
+ <button
48
+ *ngFor="let option of optionsToggle"
49
+ mat-icon-button
50
+ matTooltip="{{ option.name | translate }}"
51
+ [attr.aria-label]="option.name | translate"
52
+ (click)="click(option)"
53
+ [class.disabled]="!option.isEnabled"
54
+ attr.data-test="toggle-{{ option.name }}"
55
+ >
56
+ <i [esIcon]="option.icon" [aria]="false"></i>
57
+ </button>
58
+ </div>
59
+ </div>
@@ -0,0 +1,123 @@
1
+ @import '../../../assets/scss/mixins';
2
+
3
+ .actionbar {
4
+ display: flex;
5
+ align-items: center;
6
+ gap: 10px;
7
+ }
8
+ .actionToggle > button {
9
+ color: var(--textLight);
10
+ }
11
+ button {
12
+ min-width: unset;
13
+ }
14
+
15
+ .light {
16
+ color: #fff;
17
+ background: transparent;
18
+ }
19
+ .disabled {
20
+ pointer-events: all;
21
+ }
22
+ .light a {
23
+ color: #fff;
24
+ }
25
+
26
+ .actionToggleDivider {
27
+ padding-left: 10px;
28
+ border-left: 1px solid #ddd;
29
+ }
30
+ .more {
31
+ color: var(--primary);
32
+ background-color: transparent;
33
+ }
34
+ .actionbar-background-dark {
35
+ .mat-button {
36
+ color: rgb(var(--palette-foreground-text-dark));
37
+ &:disabled {
38
+ color: rgba(var(--palette-foreground-text-dark), 0.75);
39
+ }
40
+ }
41
+ }
42
+ .actionbar-background-primary {
43
+ .mat-button {
44
+ color: rgb(var(--palette-foreground-text-dark));
45
+ }
46
+ .mat-flat-button {
47
+ background-color: #fff;
48
+ color: var(--primary);
49
+ &:disabled {
50
+ color: var(--textLight);
51
+ }
52
+ }
53
+ }
54
+ .actionbar-round {
55
+ .mat-button,
56
+ .mat-flat-button {
57
+ width: 45px;
58
+ height: 45px;
59
+ justify-content: center;
60
+ }
61
+ button {
62
+ border-radius: 50%;
63
+ @include materialShadow();
64
+ }
65
+ &.actionbar-background-primary {
66
+ .mat-button {
67
+ background-color: #fff;
68
+ color: var(--primary);
69
+ }
70
+ }
71
+ &.actionbar-all-flat button {
72
+ background: white;
73
+ color: var(--primary);
74
+ &:disabled {
75
+ color: var(--textLight);
76
+ }
77
+ }
78
+ .more,
79
+ .actionAlways {
80
+ background: white;
81
+ color: var(--primary);
82
+ display: flex;
83
+ width: 45px;
84
+ height: 45px;
85
+ line-height: 45px;
86
+ text-align: center;
87
+ align-items: center;
88
+ .edu-icons,
89
+ .material-icons {
90
+ position: relative;
91
+ font-size: 24px;
92
+ }
93
+ span {
94
+ display: none;
95
+ }
96
+ }
97
+ .action-always {
98
+ .edu-icons,
99
+ .material-icons {
100
+ right: 4px !important;
101
+ }
102
+ }
103
+ }
104
+
105
+ @mixin icon-button() {
106
+ .action-always {
107
+ padding: 0 1rem;
108
+ }
109
+ .action-always-caption {
110
+ display: none;
111
+ }
112
+ .mat-flat-button {
113
+ padding: 5px;
114
+ }
115
+ }
116
+
117
+ @media screen and (max-width: (calc(var(--mobileWidth) + var(--mobileStage) * 4))) {
118
+ @include icon-button();
119
+ }
120
+
121
+ .actionbar-icon-button {
122
+ @include icon-button();
123
+ }
@@ -0,0 +1,174 @@
1
+ import { trigger } from '@angular/animations';
2
+ import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
3
+ import { TranslateService } from '@ngx-translate/core';
4
+ import { UIAnimation } from '../util/ui-animation';
5
+ import { UIConstants } from '../util/ui-constants';
6
+ import { OptionItem } from '../types/option-item';
7
+ import { UIService } from '../services/ui.service';
8
+ import { Helper } from '../util/helper';
9
+
10
+ @Component({
11
+ selector: 'es-actionbar',
12
+ templateUrl: 'actionbar.component.html',
13
+ styleUrls: ['actionbar.component.scss'],
14
+ animations: [trigger('openOverlay', UIAnimation.openOverlay(UIAnimation.ANIMATION_TIME_FAST))],
15
+ })
16
+ /**
17
+ * The action bar provides several icons, usually at the top right, with actions for a current context
18
+ */
19
+ export class ActionbarComponent implements OnChanges {
20
+ /**
21
+ * The amount of options which are not hidden inside an overflow menu
22
+ * (default: depending on mobile (1) or not (2))
23
+ * Also use numberOfAlwaysVisibleOptionsMobile to control the amount of mobile options visible
24
+ */
25
+ @Input() numberOfAlwaysVisibleOptions = 2;
26
+ @Input() numberOfAlwaysVisibleOptionsMobile = 1;
27
+ /**
28
+ * Visual style of the actionbar
29
+ *
30
+ * Values:
31
+ * - 'button': material buttons with icons and text on medium to large screens
32
+ * - 'icon-button': material buttons without text
33
+ * - 'round': circular buttons without text
34
+ * @default 'button'
35
+ */
36
+ @Input() appearance: 'round' | 'button' | 'icon-button' = 'button';
37
+ /**
38
+ * dropdownPosition is for position of dropdown (default = left)
39
+ * Values 'left' or 'right'
40
+ */
41
+ @Input() dropdownPosition: 'left' | 'right' = 'left';
42
+
43
+ /**
44
+ * backgroundType for color matching, either bright, dark or primary
45
+ */
46
+ @Input() backgroundType: 'bright' | 'dark' | 'primary' = 'bright';
47
+ /**
48
+ * Style, currently default or 'flat' if all always visible icons should get a flat look
49
+ */
50
+ @Input() style: 'default' | 'flat' = 'default';
51
+ /**
52
+ * Highlight one or more of the always-visible buttons as primary action.
53
+ *
54
+ * - `first`, `last`: The first / last of `optionsAlways` by order.
55
+ * - `manual`: Highlight all options that set `isPrimary = true`.
56
+ */
57
+ @Input() highlight: 'first' | 'last' | 'manual' = 'first';
58
+ /**
59
+ * Should disabled ("greyed out") options be shown or hidden?
60
+ */
61
+ @Input() showDisabled = true;
62
+ /**
63
+ * Set the options, see @OptionItem
64
+ */
65
+ @Input() set options(options: OptionItem[]) {
66
+ this.optionsIn = options;
67
+ this.prepareOptions(options);
68
+ }
69
+
70
+ optionsIn: OptionItem[] = [];
71
+ optionsAlways: OptionItem[] = [];
72
+ optionsMenu: OptionItem[] = [];
73
+ optionsToggle: OptionItem[] = [];
74
+
75
+ constructor(private uiService: UIService, private translate: TranslateService) {}
76
+
77
+ private prepareOptions(options: OptionItem[]) {
78
+ options = this.uiService.filterValidOptions(Helper.deepCopyArray(options));
79
+ if (options == null) {
80
+ this.optionsAlways = [];
81
+ this.optionsMenu = [];
82
+ return;
83
+ }
84
+ this.optionsToggle = this.uiService.filterToggleOptions(options, true);
85
+ this.optionsAlways = this.getActionOptions(
86
+ this.uiService.filterToggleOptions(options, false),
87
+ ).slice(0, this.getNumberOptions());
88
+ if (!this.optionsAlways.length) {
89
+ this.optionsAlways = this.uiService
90
+ .filterToggleOptions(options, false)
91
+ .slice(0, this.getNumberOptions());
92
+ }
93
+ this.optionsMenu = this.hideActionOptions(
94
+ this.uiService.filterToggleOptions(options, false),
95
+ this.optionsAlways,
96
+ );
97
+ // may causes weird looking
98
+ /*if(this.optionsMenu.length<2) {
99
+ this.optionsAlways = this.optionsAlways.concat(this.optionsMenu);
100
+ this.optionsMenu = [];
101
+ }*/
102
+ }
103
+
104
+ public getNumberOptions() {
105
+ if (window.innerWidth < UIConstants.MOBILE_WIDTH) {
106
+ return this.numberOfAlwaysVisibleOptionsMobile;
107
+ }
108
+ return this.numberOfAlwaysVisibleOptions;
109
+ }
110
+
111
+ click(option: OptionItem) {
112
+ if (!option.isEnabled) {
113
+ if (option.disabledCallback) {
114
+ option.disabledCallback();
115
+ }
116
+ return;
117
+ }
118
+ option.callback();
119
+ }
120
+
121
+ private getActionOptions(options: OptionItem[]) {
122
+ const result: OptionItem[] = [];
123
+ for (const option of options) {
124
+ if (option.showAsAction) result.push(option);
125
+ }
126
+ return result;
127
+ }
128
+
129
+ private hideActionOptions(options: OptionItem[], optionsAlways: OptionItem[]) {
130
+ const result: OptionItem[] = [];
131
+ for (const option of options) {
132
+ if (optionsAlways.indexOf(option) === -1) result.push(option);
133
+ }
134
+ return result;
135
+ }
136
+
137
+ /**
138
+ * Invalidate / refreshes all options based on their current callbacks
139
+ */
140
+ public invalidate() {
141
+ this.prepareOptions(this.optionsIn);
142
+ }
143
+
144
+ private filterDisabled(options: OptionItem[]) {
145
+ if (options == null) return null;
146
+ const filtered = [];
147
+ for (const option of options) {
148
+ if (option.isEnabled || this.showDisabled) filtered.push(option);
149
+ }
150
+ return filtered;
151
+ }
152
+
153
+ canShowDropdown() {
154
+ if (!this.optionsMenu.length) {
155
+ return false;
156
+ }
157
+ return this.optionsMenu.filter((o) => o.isEnabled).length > 0;
158
+ }
159
+
160
+ shouldHighlight(optionIndex: number, option: OptionItem): boolean {
161
+ switch (this.highlight) {
162
+ case 'first':
163
+ return optionIndex === 0;
164
+ case 'last':
165
+ return optionIndex === this.optionsAlways.length - 1;
166
+ case 'manual':
167
+ return option.isPrimary;
168
+ }
169
+ }
170
+
171
+ ngOnChanges(changes: SimpleChanges): void {
172
+ this.invalidate();
173
+ }
174
+ }