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.
- package/.browserslistrc +16 -0
- package/.eslintrc.json +44 -0
- package/README.md +40 -0
- package/assets/scss/mixins.scss +95 -0
- package/assets/scss/variables.scss +33 -0
- package/karma.conf.js +42 -0
- package/ng-package.json +10 -0
- package/package.json +19 -0
- package/src/lib/actionbar/actionbar.component.html +59 -0
- package/src/lib/actionbar/actionbar.component.scss +123 -0
- package/src/lib/actionbar/actionbar.component.ts +174 -0
- package/src/lib/common/edu-sharing-ui-common.module.ts +80 -0
- package/src/lib/directives/border-box-observer.directive.ts +75 -0
- package/src/lib/directives/check-text-overflow.directive.ts +61 -0
- package/src/lib/directives/drag-nodes/drag-nodes.ts +32 -0
- package/src/lib/directives/drag-nodes/nodes-drag-source.directive.ts +79 -0
- package/src/lib/directives/drag-nodes/nodes-drag.directive.ts +43 -0
- package/src/lib/directives/drag-nodes/nodes-drop-target.directive.ts +116 -0
- package/src/lib/directives/focus-state.directive.ts +34 -0
- package/src/lib/directives/icon.directive.ts +142 -0
- package/src/lib/directives/nodes-drop-target-legacy.directive.ts +155 -0
- package/src/lib/dropdown/dropdown.component.html +32 -0
- package/src/lib/dropdown/dropdown.component.scss +67 -0
- package/src/lib/dropdown/dropdown.component.ts +71 -0
- package/src/lib/edu-sharing-ui-configuration.ts +47 -0
- package/src/lib/edu-sharing-ui.module.ts +49 -0
- package/src/lib/list-items/available-widgets.ts +30 -0
- package/src/lib/list-items/format-duration.pipe.ts +17 -0
- package/src/lib/list-items/list-base/list-base.component.html +52 -0
- package/src/lib/list-items/list-base/list-base.component.ts +44 -0
- package/src/lib/list-items/list-collection-info/list-collection-info.component.html +48 -0
- package/src/lib/list-items/list-collection-info/list-collection-info.component.scss +8 -0
- package/src/lib/list-items/list-collection-info/list-collection-info.component.ts +24 -0
- package/src/lib/list-items/list-counts/list-counts.component.html +1 -0
- package/src/lib/list-items/list-counts/list-counts.component.scss +3 -0
- package/src/lib/list-items/list-counts/list-counts.component.ts +59 -0
- package/src/lib/list-items/list-items.module.ts +33 -0
- package/src/lib/list-items/list-node-license/list-node-license.component.html +8 -0
- package/src/lib/list-items/list-node-license/list-node-license.component.ts +47 -0
- package/src/lib/list-items/list-node-replication-source/list-node-replication-source.component.html +11 -0
- package/src/lib/list-items/list-node-replication-source/list-node-replication-source.component.ts +60 -0
- package/src/lib/list-items/list-node-workflow/list-node-workflow.component.html +3 -0
- package/src/lib/list-items/list-node-workflow/list-node-workflow.component.ts +21 -0
- package/src/lib/list-items/list-text/list-text.component.html +176 -0
- package/src/lib/list-items/list-text/list-text.component.scss +3 -0
- package/src/lib/list-items/list-text/list-text.component.ts +107 -0
- package/src/lib/list-items/list-widget.ts +52 -0
- package/src/lib/list-items/node-row/node-row.component.html +31 -0
- package/src/lib/list-items/node-row/node-row.component.scss +50 -0
- package/src/lib/list-items/node-row/node-row.component.ts +16 -0
- package/src/lib/list-items/node-source.pipe.ts +48 -0
- package/src/lib/node-entries/combined-data-source.ts +51 -0
- package/src/lib/node-entries/custom-templates-data-source.ts +6 -0
- package/src/lib/node-entries/drag-preview/drag-preview.component.html +6 -0
- package/src/lib/node-entries/drag-preview/drag-preview.component.scss +35 -0
- package/src/lib/node-entries/drag-preview/drag-preview.component.ts +15 -0
- package/src/lib/node-entries/entries-model.ts +120 -0
- package/src/lib/node-entries/items-cap.ts +54 -0
- package/src/lib/node-entries/list-item-label.pipe.ts +28 -0
- package/src/lib/node-entries/mixins.scss +23 -0
- package/src/lib/node-entries/node-cache.spec.ts +199 -0
- package/src/lib/node-entries/node-cache.ts +81 -0
- package/src/lib/node-entries/node-data-source-remote.ts +33 -0
- package/src/lib/node-entries/node-data-source.ts +148 -0
- package/src/lib/node-entries/node-entries-card/node-entries-card.component.html +167 -0
- package/src/lib/node-entries/node-entries-card/node-entries-card.component.scss +28 -0
- package/src/lib/node-entries/node-entries-card/node-entries-card.component.ts +132 -0
- package/src/lib/node-entries/node-entries-card/node-entries-card.main.scss +261 -0
- package/src/lib/node-entries/node-entries-card-grid/node-entries-card-grid.component.html +205 -0
- package/src/lib/node-entries/node-entries-card-grid/node-entries-card-grid.component.scss +181 -0
- package/src/lib/node-entries/node-entries-card-grid/node-entries-card-grid.component.ts +361 -0
- package/src/lib/node-entries/node-entries-card-small/node-entries-card-small.component.html +100 -0
- package/src/lib/node-entries/node-entries-card-small/node-entries-card-small.component.scss +46 -0
- package/src/lib/node-entries/node-entries-card-small/node-entries-card-small.component.ts +40 -0
- package/src/lib/node-entries/node-entries-global-options/node-entries-global-options.component.html +23 -0
- package/src/lib/node-entries/node-entries-global-options/node-entries-global-options.component.scss +58 -0
- package/src/lib/node-entries/node-entries-global-options/node-entries-global-options.component.ts +16 -0
- package/src/lib/node-entries/node-entries-global.service.ts +79 -0
- package/src/lib/node-entries/node-entries-table/column-chooser/column-chooser.component.html +25 -0
- package/src/lib/node-entries/node-entries-table/column-chooser/column-chooser.component.scss +32 -0
- package/src/lib/node-entries/node-entries-table/column-chooser/column-chooser.component.ts +31 -0
- package/src/lib/node-entries/node-entries-table/node-entries-table.component.html +270 -0
- package/src/lib/node-entries/node-entries-table/node-entries-table.component.scss +169 -0
- package/src/lib/node-entries/node-entries-table/node-entries-table.component.ts +333 -0
- package/src/lib/node-entries/node-entries-templates.service.ts +31 -0
- package/src/lib/node-entries/node-entries-wrapper.component.ts +363 -0
- package/src/lib/node-entries/node-entries.component.html +33 -0
- package/src/lib/node-entries/node-entries.component.scss +13 -0
- package/src/lib/node-entries/node-entries.component.ts +151 -0
- package/src/lib/node-entries/node-entries.module.ts +93 -0
- package/src/lib/node-entries/node-rating/node-rating.component.html +53 -0
- package/src/lib/node-entries/node-rating/node-rating.component.scss +31 -0
- package/src/lib/node-entries/node-rating/node-rating.component.ts +105 -0
- package/src/lib/node-entries/node-stats-badges/node-stats-badges.component.html +39 -0
- package/src/lib/node-entries/node-stats-badges/node-stats-badges.component.scss +44 -0
- package/src/lib/node-entries/node-stats-badges/node-stats-badges.component.ts +43 -0
- package/src/lib/node-entries/node-type-badge/node-type-badge.component.html +31 -0
- package/src/lib/node-entries/node-type-badge/node-type-badge.component.scss +5 -0
- package/src/lib/node-entries/node-type-badge/node-type-badge.component.ts +36 -0
- package/src/lib/node-entries/option-button/option-button.component.ts +42 -0
- package/src/lib/node-entries/preview-image/preview-image.component.html +19 -0
- package/src/lib/node-entries/preview-image/preview-image.component.scss +31 -0
- package/src/lib/node-entries/preview-image/preview-image.component.ts +47 -0
- package/src/lib/node-entries/sort-select-panel/sort-select-panel.component.html +27 -0
- package/src/lib/node-entries/sort-select-panel/sort-select-panel.component.scss +9 -0
- package/src/lib/node-entries/sort-select-panel/sort-select-panel.component.ts +26 -0
- package/src/lib/node-url/node-url.component.html +66 -0
- package/src/lib/node-url/node-url.component.scss +32 -0
- package/src/lib/node-url/node-url.component.ts +136 -0
- package/src/lib/pipes/file-size.pipe.ts +24 -0
- package/src/lib/pipes/format-date.pipe.ts +39 -0
- package/src/lib/pipes/node-icon.pipe.ts +11 -0
- package/src/lib/pipes/node-image-size.pipe.ts +18 -0
- package/src/lib/pipes/node-image.pipe.ts +71 -0
- package/src/lib/pipes/node-person-name.pipe.ts +41 -0
- package/src/lib/pipes/node-title.pipe.ts +12 -0
- package/src/lib/pipes/option-tooltip.pipe.ts +32 -0
- package/src/lib/pipes/replace-chars.pipe.ts +21 -0
- package/src/lib/pipes/vcard-name.pipe.ts +11 -0
- package/src/lib/services/abstract/app.service.ts +4 -0
- package/src/lib/services/abstract/keyboard-shortcuts.service.ts +10 -0
- package/src/lib/services/abstract/options-helper.service.ts +29 -0
- package/src/lib/services/abstract/toast.service.ts +5 -0
- package/src/lib/services/accessibility.service.ts +101 -0
- package/src/lib/services/local-events.service.ts +29 -0
- package/src/lib/services/node-entries.service.ts +172 -0
- package/src/lib/services/node-helper.service.ts +239 -0
- package/src/lib/services/nodes-drag-drop.service.ts +165 -0
- package/src/lib/services/options-helper-data.service.ts +186 -0
- package/src/lib/services/repo-url.service.ts +46 -0
- package/src/lib/services/temporary-storage.service.ts +58 -0
- package/src/lib/services/ui.service.ts +182 -0
- package/src/lib/sort-dropdown/sort-dropdown.component.html +22 -0
- package/src/lib/sort-dropdown/sort-dropdown.component.scss +47 -0
- package/src/lib/sort-dropdown/sort-dropdown.component.ts +42 -0
- package/src/lib/spinner/spinner.component.html +14 -0
- package/src/lib/spinner/spinner.component.scss +141 -0
- package/src/lib/spinner/spinner.component.ts +12 -0
- package/src/lib/translations/README.md +44 -0
- package/src/lib/translations/fallback-translation-handler.ts +7 -0
- package/src/lib/translations/languages.ts +6 -0
- package/src/lib/translations/translation-loader.spec.ts +352 -0
- package/src/lib/translations/translation-loader.ts +189 -0
- package/src/lib/translations/translation-source.ts +9 -0
- package/src/lib/translations/translations.module.ts +49 -0
- package/src/lib/translations/translations.service.spec.ts +152 -0
- package/src/lib/translations/translations.service.ts +188 -0
- package/src/lib/types/accessibillity.ts +15 -0
- package/src/lib/types/api-models.ts +4 -0
- package/src/lib/types/drag-drop.ts +22 -0
- package/src/lib/types/keyboard-shortcuts.ts +29 -0
- package/src/lib/types/list-item.ts +67 -0
- package/src/lib/types/option-item.ts +247 -0
- package/src/lib/types/workflow.ts +35 -0
- package/src/lib/util/DateHelper.spec.ts +112 -0
- package/src/lib/util/DateHelper.ts +197 -0
- package/src/lib/util/VCard.ts +277 -0
- package/src/lib/util/color-helper.ts +125 -0
- package/src/lib/util/duration-helper.spec.ts +35 -0
- package/src/lib/util/duration-helper.ts +98 -0
- package/src/lib/util/functions.ts +15 -0
- package/src/lib/util/helper.ts +60 -0
- package/src/lib/util/isNumeric.ts +13 -0
- package/src/lib/util/rest-helper.ts +28 -0
- package/src/lib/util/ui-animation.ts +154 -0
- package/src/lib/util/ui-constants.ts +20 -0
- package/src/module.ts +76 -0
- package/src/test.ts +28 -0
- package/tsconfig.lib.json +15 -0
- package/tsconfig.lib.prod.json +10 -0
- package/tsconfig.spec.json +17 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Sort, SortDirection } from '@angular/material/sort';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
|
|
4
|
+
export type ListItemType = 'NODE' | 'NODE_PROPOSAL' | 'COLLECTION' | 'ORG' | 'GROUP' | 'USER';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A list item info, which is basically a column
|
|
8
|
+
* Example:
|
|
9
|
+
this.columns.push(new ListItem(RestConstants.CM_NAME));
|
|
10
|
+
this.columns.push(new ListItem(RestConstants.CM_ARCHIVED_DATE));
|
|
11
|
+
*/
|
|
12
|
+
export class ListItem {
|
|
13
|
+
/**
|
|
14
|
+
* Should this item be shown by default
|
|
15
|
+
* @type {boolean}
|
|
16
|
+
*/
|
|
17
|
+
public visible = true;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Label to display, if set, should be preferred instead of automatic i18n
|
|
21
|
+
*/
|
|
22
|
+
public label: string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* custom format string for date fields, may be null
|
|
26
|
+
*/
|
|
27
|
+
public format: string;
|
|
28
|
+
constructor(
|
|
29
|
+
public type: ListItemType,
|
|
30
|
+
public name: string,
|
|
31
|
+
public config = {
|
|
32
|
+
showLabel: false,
|
|
33
|
+
},
|
|
34
|
+
) {}
|
|
35
|
+
|
|
36
|
+
static getCollectionDefaults() {
|
|
37
|
+
let columns = [];
|
|
38
|
+
columns.push(new ListItem('COLLECTION', 'title'));
|
|
39
|
+
columns.push(new ListItem('COLLECTION', 'info'));
|
|
40
|
+
columns.push(new ListItem('COLLECTION', 'scope'));
|
|
41
|
+
return columns;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export class ListItemSort extends ListItem {
|
|
45
|
+
constructor(
|
|
46
|
+
public type: ListItemType,
|
|
47
|
+
public name: string,
|
|
48
|
+
public mode: 'ascending' | 'descending' | null = null,
|
|
49
|
+
public config = {
|
|
50
|
+
showLabel: false,
|
|
51
|
+
},
|
|
52
|
+
) {
|
|
53
|
+
super(type, name, config);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export class SortEvent extends ListItemSort {
|
|
57
|
+
ascending: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* UI element that allows the user to choose sorting.
|
|
62
|
+
*/
|
|
63
|
+
export interface SortPanel {
|
|
64
|
+
active: string;
|
|
65
|
+
direction: SortDirection;
|
|
66
|
+
readonly sortChange: Observable<Sort>;
|
|
67
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A option from the actionbar+dropdown menu
|
|
3
|
+
* Example:
|
|
4
|
+
this.options.push(new OptionItem("RESTORE_SINGLE","undo", (node) => this.restoreSingle(node)));
|
|
5
|
+
this.options.push(new OptionItem("DELETE_SINGLE","archiveDelete", (node) => this.deleteSingle(node)));
|
|
6
|
+
|
|
7
|
+
*/
|
|
8
|
+
import { KeyboardShortcutCondition } from '../types/keyboard-shortcuts';
|
|
9
|
+
|
|
10
|
+
export enum NodesRightMode {
|
|
11
|
+
Local,
|
|
12
|
+
Original,
|
|
13
|
+
Both,
|
|
14
|
+
}
|
|
15
|
+
export class OptionItem {
|
|
16
|
+
/**
|
|
17
|
+
* If true, this option will be shown all the time in the node table
|
|
18
|
+
* @type {boolean}
|
|
19
|
+
*/
|
|
20
|
+
public showAlways = false;
|
|
21
|
+
/**
|
|
22
|
+
* If true, this option will be shown as an action (if room). If none of the items has showAsAction set, the first items will always be shown as action
|
|
23
|
+
* @type {boolean}
|
|
24
|
+
*/
|
|
25
|
+
public showAsAction = false;
|
|
26
|
+
/**
|
|
27
|
+
* If true, this option will be shown as a toggle on the right side (provide iconToggle as a toggle icon)
|
|
28
|
+
* @type {boolean}
|
|
29
|
+
*/
|
|
30
|
+
public isToggle = false;
|
|
31
|
+
/**
|
|
32
|
+
* If true, shows a line at the top.
|
|
33
|
+
*
|
|
34
|
+
* This feature is usually handled now by associating an entry to a `group`
|
|
35
|
+
* now. However `isSeparate` is kept as fallback for now.
|
|
36
|
+
*/
|
|
37
|
+
public isSeparate = false;
|
|
38
|
+
/**
|
|
39
|
+
* The item will be indicated with an accent color in the menu.
|
|
40
|
+
*
|
|
41
|
+
* Used by the dropdown variant of the main menu to indicate the currently
|
|
42
|
+
* active scope.
|
|
43
|
+
*/
|
|
44
|
+
public isSelected = false;
|
|
45
|
+
/**
|
|
46
|
+
* If true, only displayed on a mobile device (based on the navigator agent)
|
|
47
|
+
* @type {boolean}
|
|
48
|
+
*/
|
|
49
|
+
public onlyMobile = false;
|
|
50
|
+
/**
|
|
51
|
+
* If true, only displayed on a desktop device (based on the navigator agent)
|
|
52
|
+
* @type {boolean}
|
|
53
|
+
*/
|
|
54
|
+
public onlyDesktop = false;
|
|
55
|
+
/**
|
|
56
|
+
* You can set a media-query similar to CSS, see the MEDIA_QUERY constants in ui-constants
|
|
57
|
+
* Use in combination with mediaQueryValue
|
|
58
|
+
* @type {boolean}
|
|
59
|
+
*/
|
|
60
|
+
public mediaQueryType: string;
|
|
61
|
+
/**
|
|
62
|
+
* The value for the defined media query
|
|
63
|
+
*/
|
|
64
|
+
public mediaQueryValue: number;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Set to false if the action should be shown, but should not be clickable
|
|
68
|
+
* @type {boolean}
|
|
69
|
+
*/
|
|
70
|
+
public isEnabled = true;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Whether the option should be manually marked as primary action when always visible on an
|
|
74
|
+
* `actionbar`.
|
|
75
|
+
*/
|
|
76
|
+
public isPrimary: boolean;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* A function called with the node as param which should return true or false if the option should be shown for this node
|
|
80
|
+
* Is handled by optionsHelper and may not be used otherwise
|
|
81
|
+
* Please use @customShowCallback instead
|
|
82
|
+
*/
|
|
83
|
+
public showCallback: (node?: Node | any) => boolean;
|
|
84
|
+
/**
|
|
85
|
+
* A function called with the node as parm which should return true or false if the option should be shown for this node
|
|
86
|
+
* Will be called by the optionsHelper
|
|
87
|
+
*/
|
|
88
|
+
public customShowCallback: (nodes?: Node[] | any[]) => boolean;
|
|
89
|
+
/**
|
|
90
|
+
* A function called with the node as param which should return true or false if the option should be enabled or not
|
|
91
|
+
* Is handled by optionsHelper and may not be used otherwise
|
|
92
|
+
* Please use @customEnabledCallback instead
|
|
93
|
+
*/
|
|
94
|
+
public enabledCallback: (node?: Node | any) => boolean;
|
|
95
|
+
/**
|
|
96
|
+
* A function called with the node as param which should return true or false if the option should be enabled or not
|
|
97
|
+
* Will be called by the optionsHelper
|
|
98
|
+
*/
|
|
99
|
+
public customEnabledCallback: (nodes?: Node[] | any[]) => boolean;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Optional: A callback that is called when the user clicks on the option when it's currently disabled (greyed out)
|
|
103
|
+
*/
|
|
104
|
+
public disabledCallback: (node?: Node | any) => void;
|
|
105
|
+
/**
|
|
106
|
+
* Show the given name (if false, only icon will show)
|
|
107
|
+
*/
|
|
108
|
+
public showName = true;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* element with 0 has highest priority in it's group, higher values mean lower priority
|
|
112
|
+
*/
|
|
113
|
+
public priority: number;
|
|
114
|
+
/**
|
|
115
|
+
* the group this option belongs to
|
|
116
|
+
*/
|
|
117
|
+
public group: OptionGroup;
|
|
118
|
+
|
|
119
|
+
public keyboardShortcut: KeyboardShortcutCondition;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Or concat of supported element types for the action
|
|
123
|
+
*/
|
|
124
|
+
public elementType = [ElementType.Node];
|
|
125
|
+
public permissions: string[];
|
|
126
|
+
public constrains: Constrain[];
|
|
127
|
+
public permissionsMode = HideMode.Disable;
|
|
128
|
+
public permissionsRightMode = NodesRightMode.Local;
|
|
129
|
+
public toolpermissions: string[];
|
|
130
|
+
public toolpermissionsMode = HideMode.Disable;
|
|
131
|
+
public scopes: Scope[];
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
*
|
|
135
|
+
* @param name the option name, which is used for the translation
|
|
136
|
+
* @param icon A material icon name
|
|
137
|
+
* @param callback A function callback when this option is chosen. Will get the current node
|
|
138
|
+
* passed as an argument. If available, the relevant nodes are passed as second argument,
|
|
139
|
+
* i.e., the selection, if any, or the current node as single-item array otherwise.
|
|
140
|
+
*/
|
|
141
|
+
constructor(
|
|
142
|
+
public name: string,
|
|
143
|
+
public icon: string,
|
|
144
|
+
// TODO: Maybe switch to only providing the second parameter.
|
|
145
|
+
public callback: (object?: Node | any, objects?: (Node | any)[]) => void,
|
|
146
|
+
) {}
|
|
147
|
+
}
|
|
148
|
+
export class CustomOptions {
|
|
149
|
+
/**
|
|
150
|
+
* If true, all existing or available options for the object stay
|
|
151
|
+
* If false, no options will be set, only the options in "addOptions" are used
|
|
152
|
+
*/
|
|
153
|
+
public useDefaultOptions? = true;
|
|
154
|
+
/**
|
|
155
|
+
* List of ids of options to explicitly support
|
|
156
|
+
*/
|
|
157
|
+
public supportedOptions?: string[];
|
|
158
|
+
/**
|
|
159
|
+
* List of ids of options to explicitly remove
|
|
160
|
+
* Only supported if supportedOptions is empty
|
|
161
|
+
*/
|
|
162
|
+
public removeOptions?: string[];
|
|
163
|
+
/**
|
|
164
|
+
* Options to add/insert into the menu
|
|
165
|
+
*/
|
|
166
|
+
public addOptions?: OptionItem[];
|
|
167
|
+
}
|
|
168
|
+
export enum HideMode {
|
|
169
|
+
Disable,
|
|
170
|
+
Hide,
|
|
171
|
+
}
|
|
172
|
+
export enum Scope {
|
|
173
|
+
Render = 'Render',
|
|
174
|
+
Search = 'Search',
|
|
175
|
+
SearchCollections = 'SearchCollections',
|
|
176
|
+
SavedSearches = 'SavedSearches',
|
|
177
|
+
CollectionsReferences = 'CollectionsReferences',
|
|
178
|
+
CollectionsProposals = 'CollectionsProposals',
|
|
179
|
+
CollectionsCollection = 'CollectionsCollection',
|
|
180
|
+
WorkspaceList = 'WorkspaceList',
|
|
181
|
+
WorkspaceTree = 'WorkspaceTree',
|
|
182
|
+
Sharing = 'Sharing',
|
|
183
|
+
Oer = 'Oer',
|
|
184
|
+
UserManagement = 'UserManagement',
|
|
185
|
+
Stream = 'Stream',
|
|
186
|
+
CreateMenu = 'CreateMenu',
|
|
187
|
+
|
|
188
|
+
MediacenterNodesList = 'MediacenterNodesList',
|
|
189
|
+
Admin = 'Admin', // Admin Tools / Debugging
|
|
190
|
+
}
|
|
191
|
+
export enum ElementType {
|
|
192
|
+
Node,
|
|
193
|
+
NodeChild, // Child object
|
|
194
|
+
MapRef, // Map ref (link to another map)
|
|
195
|
+
NodePublishedCopy,
|
|
196
|
+
NodeBlockedImport, // node with property ccm:importblocked == true
|
|
197
|
+
NodeProposal, // node proposal for a collection
|
|
198
|
+
Person,
|
|
199
|
+
Group,
|
|
200
|
+
SavedSearch,
|
|
201
|
+
Unknown,
|
|
202
|
+
}
|
|
203
|
+
export class OptionGroup {
|
|
204
|
+
/**
|
|
205
|
+
* @param id The group identifier. Used to seperate elements based on the group
|
|
206
|
+
* @param priority Group with 0 has highest priority, higher values mean lower priority
|
|
207
|
+
*/
|
|
208
|
+
constructor(public id: string, public priority: number) {}
|
|
209
|
+
}
|
|
210
|
+
export class DefaultGroups {
|
|
211
|
+
static Primary = new OptionGroup('Primary', 10);
|
|
212
|
+
static Create = new OptionGroup('Create', 15);
|
|
213
|
+
static View = new OptionGroup('View', 20);
|
|
214
|
+
static CreateConnector = new OptionGroup('CreateConnector', 25);
|
|
215
|
+
static CreateLtiTools = new OptionGroup('CreateLtiTools', 28);
|
|
216
|
+
static Reuse = new OptionGroup('Reuse', 30);
|
|
217
|
+
static Edit = new OptionGroup('Edit', 40);
|
|
218
|
+
static FileOperations = new OptionGroup('FileOperations', 50);
|
|
219
|
+
static Delete = new OptionGroup('Delete', 60);
|
|
220
|
+
static Toggles = new OptionGroup('Toggles', 70);
|
|
221
|
+
}
|
|
222
|
+
export enum Constrain {
|
|
223
|
+
CollectionReference, // option is only visible for collection references
|
|
224
|
+
NoCollectionReference, // option is only visible for non-collection references
|
|
225
|
+
Directory, // only visible for directories (ccm:map)
|
|
226
|
+
Collections, // only visible for collections
|
|
227
|
+
Files, // only visible for files (ccm:io)
|
|
228
|
+
FilesAndDirectories, // only visible for files and directories (ccm:io / ccm:map) - no collections!
|
|
229
|
+
Admin, // only visible if user is admin or esDebug is enabled on window component
|
|
230
|
+
AdminOrDebug, // only visible if user is admin or esDebug is enabled on window component
|
|
231
|
+
NoBulk, // No support for bulk (multiple objects)
|
|
232
|
+
NoSelection, // Only visible when currently no element is selected
|
|
233
|
+
ClipboardContent, // Only visible when the clipboard has content
|
|
234
|
+
AddObjects, // Only visible when it is possible to add objects into the current list
|
|
235
|
+
HomeRepository, // Only visible when the nodes are from the local (home) repository
|
|
236
|
+
User, // Only visible when a user is present and logged in
|
|
237
|
+
NoScope, // Only visible when no current scope (i.e "safe" scope) is set
|
|
238
|
+
ReurlMode, // Only visible when a reurl is present (called to pick object from lms)
|
|
239
|
+
LTIMode, // Only visible when a lti session is present (called to pick object from lti platform)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export enum Target {
|
|
243
|
+
List, // Target is the ListTableComponent
|
|
244
|
+
ListDropdown,
|
|
245
|
+
Actionbar,
|
|
246
|
+
CreateMenu,
|
|
247
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface WorkflowDefinition {
|
|
2
|
+
id: string;
|
|
3
|
+
color: string;
|
|
4
|
+
hasReceiver: boolean;
|
|
5
|
+
next: string[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const WORKFLOW_STATUS_UNCHECKED: WorkflowDefinition = {
|
|
9
|
+
id: '100_unchecked',
|
|
10
|
+
color: '#539DD5',
|
|
11
|
+
hasReceiver: true,
|
|
12
|
+
next: null,
|
|
13
|
+
};
|
|
14
|
+
export const WORKFLOW_STATUS_TO_CHECK: WorkflowDefinition = {
|
|
15
|
+
id: '200_tocheck',
|
|
16
|
+
color: '#3CB0B0',
|
|
17
|
+
hasReceiver: true,
|
|
18
|
+
next: null,
|
|
19
|
+
};
|
|
20
|
+
export const WORKFLOW_STATUS_HASFLAWS: WorkflowDefinition = {
|
|
21
|
+
id: '300_hasflaws',
|
|
22
|
+
color: '#D58553',
|
|
23
|
+
hasReceiver: true,
|
|
24
|
+
next: null,
|
|
25
|
+
};
|
|
26
|
+
export const WORKFLOW_STATUS_CHECKED: WorkflowDefinition = {
|
|
27
|
+
id: '400_checked',
|
|
28
|
+
color: '#42A053',
|
|
29
|
+
hasReceiver: false,
|
|
30
|
+
next: null,
|
|
31
|
+
};
|
|
32
|
+
export type WorkflowDefinitionStatus = {
|
|
33
|
+
current: WorkflowDefinition;
|
|
34
|
+
initial: WorkflowDefinition;
|
|
35
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { DateHelper, FormatOptions, RelativeMode } from './DateHelper';
|
|
2
|
+
import { TranslateService } from '@ngx-translate/core/lib/translate.service';
|
|
3
|
+
|
|
4
|
+
const translateServiceMock = {
|
|
5
|
+
instant: (key: string, values?: any) => key + JSON.stringify(values),
|
|
6
|
+
} as TranslateService;
|
|
7
|
+
describe('testing relative dates', () => {
|
|
8
|
+
const date_now = new Date(new Date().getTime());
|
|
9
|
+
const date_10_mins_before = new Date(new Date().getTime() - 1000 - 10 * 60 * 1000);
|
|
10
|
+
const date_4_hours_before = new Date(new Date().getTime() - 1000 - 4 * 3600 * 1000);
|
|
11
|
+
const date_1_day_before = new Date(new Date().getTime() - 1000 - 24 * 3600 * 1000);
|
|
12
|
+
const date_2_days_before = new Date(new Date().getTime() - 1000 - 2 * 24 * 3600 * 1000);
|
|
13
|
+
const date_7_days_before = new Date(new Date().getTime() - 1000 - 7 * 24 * 3600 * 1000);
|
|
14
|
+
const date_2_months_before = new Date();
|
|
15
|
+
date_2_months_before.setMonth(date_2_months_before.getMonth() - 2);
|
|
16
|
+
const date_1_year_before = new Date();
|
|
17
|
+
date_1_year_before.setFullYear(date_1_year_before.getFullYear() - 1);
|
|
18
|
+
for (const mode of [
|
|
19
|
+
RelativeMode.short,
|
|
20
|
+
RelativeMode.medium,
|
|
21
|
+
RelativeMode.large,
|
|
22
|
+
RelativeMode.all,
|
|
23
|
+
]) {
|
|
24
|
+
it('testing relative mode ' + mode, () => {
|
|
25
|
+
const options: FormatOptions = {
|
|
26
|
+
relativeLabels: mode as any,
|
|
27
|
+
showAlwaysTime: false,
|
|
28
|
+
};
|
|
29
|
+
expect(DateHelper.formatDate(translateServiceMock, date_now, options)).toContain(
|
|
30
|
+
'JUST_NOW',
|
|
31
|
+
);
|
|
32
|
+
expect(
|
|
33
|
+
DateHelper.formatDate(translateServiceMock, date_4_hours_before, options),
|
|
34
|
+
).toContain('HOURS_AGO');
|
|
35
|
+
expect(
|
|
36
|
+
DateHelper.formatDate(translateServiceMock, date_4_hours_before, options),
|
|
37
|
+
).toContain('4');
|
|
38
|
+
expect(
|
|
39
|
+
DateHelper.formatDate(translateServiceMock, date_10_mins_before, options),
|
|
40
|
+
).toContain('MINUTES_AGO');
|
|
41
|
+
expect(
|
|
42
|
+
DateHelper.formatDate(translateServiceMock, date_10_mins_before, options),
|
|
43
|
+
).toContain('10');
|
|
44
|
+
if (mode === RelativeMode.short) {
|
|
45
|
+
expect(
|
|
46
|
+
DateHelper.formatDate(translateServiceMock, date_1_day_before, options),
|
|
47
|
+
).not.toContain('YESTERDAY');
|
|
48
|
+
expect(
|
|
49
|
+
DateHelper.formatDate(translateServiceMock, date_2_days_before, options),
|
|
50
|
+
).not.toBe('DAYS_AGO');
|
|
51
|
+
expect(
|
|
52
|
+
DateHelper.formatDate(translateServiceMock, date_7_days_before, options),
|
|
53
|
+
).not.toBe('DAYS_AGO');
|
|
54
|
+
} else {
|
|
55
|
+
expect(
|
|
56
|
+
DateHelper.formatDate(translateServiceMock, date_1_day_before, options),
|
|
57
|
+
).toContain('YESTERDAY');
|
|
58
|
+
expect(
|
|
59
|
+
DateHelper.formatDate(translateServiceMock, date_2_days_before, options),
|
|
60
|
+
).toContain('DAYS_AGO');
|
|
61
|
+
expect(
|
|
62
|
+
DateHelper.formatDate(translateServiceMock, date_2_days_before, options),
|
|
63
|
+
).toContain('2');
|
|
64
|
+
if (mode === RelativeMode.medium) {
|
|
65
|
+
expect(
|
|
66
|
+
DateHelper.formatDate(translateServiceMock, date_7_days_before, options),
|
|
67
|
+
).not.toContain('DAYS_AGO');
|
|
68
|
+
expect(
|
|
69
|
+
DateHelper.formatDate(translateServiceMock, date_2_months_before, options),
|
|
70
|
+
).not.toContain('MONTHS_AGO');
|
|
71
|
+
} else {
|
|
72
|
+
expect(
|
|
73
|
+
DateHelper.formatDate(translateServiceMock, date_7_days_before, options),
|
|
74
|
+
).toContain('DAYS_AGO');
|
|
75
|
+
expect(
|
|
76
|
+
DateHelper.formatDate(translateServiceMock, date_7_days_before, options),
|
|
77
|
+
).toContain('7');
|
|
78
|
+
expect(
|
|
79
|
+
DateHelper.formatDate(translateServiceMock, date_2_months_before, options),
|
|
80
|
+
).toContain('MONTHS_AGO');
|
|
81
|
+
expect(
|
|
82
|
+
DateHelper.formatDate(translateServiceMock, date_2_months_before, options),
|
|
83
|
+
).toContain('2');
|
|
84
|
+
if (mode == RelativeMode.large) {
|
|
85
|
+
expect(
|
|
86
|
+
DateHelper.formatDate(
|
|
87
|
+
translateServiceMock,
|
|
88
|
+
date_1_year_before,
|
|
89
|
+
options,
|
|
90
|
+
),
|
|
91
|
+
).not.toContain('YEARS_AGO');
|
|
92
|
+
} else {
|
|
93
|
+
expect(
|
|
94
|
+
DateHelper.formatDate(
|
|
95
|
+
translateServiceMock,
|
|
96
|
+
date_1_year_before,
|
|
97
|
+
options,
|
|
98
|
+
),
|
|
99
|
+
).toContain('YEARS_AGO');
|
|
100
|
+
expect(
|
|
101
|
+
DateHelper.formatDate(
|
|
102
|
+
translateServiceMock,
|
|
103
|
+
date_1_year_before,
|
|
104
|
+
options,
|
|
105
|
+
),
|
|
106
|
+
).toContain('1');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
});
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { TranslateService } from '@ngx-translate/core';
|
|
2
|
+
import { isNumeric } from './isNumeric';
|
|
3
|
+
export enum RelativeMode {
|
|
4
|
+
off,
|
|
5
|
+
short,
|
|
6
|
+
medium,
|
|
7
|
+
large,
|
|
8
|
+
all,
|
|
9
|
+
}
|
|
10
|
+
export class FormatOptions {
|
|
11
|
+
showDate? = true;
|
|
12
|
+
showAlwaysTime? = false;
|
|
13
|
+
showSeconds? = false;
|
|
14
|
+
// @Deprecated
|
|
15
|
+
// this will be mapped to relativeLabels = MEDIUM
|
|
16
|
+
// use relativeLabels instead
|
|
17
|
+
useRelativeLabels? = true;
|
|
18
|
+
relativeLabels?: RelativeMode;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class DateHelper {
|
|
22
|
+
/**
|
|
23
|
+
* Fill a date (day + month) string, e.g. 2 -> 02
|
|
24
|
+
* @param date
|
|
25
|
+
* @returns {string}
|
|
26
|
+
*/
|
|
27
|
+
private static fillDate(date: number): string {
|
|
28
|
+
if (date < 10) return '0' + date;
|
|
29
|
+
return date + '';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Convert date to a unix timestamp
|
|
34
|
+
* @param date
|
|
35
|
+
* @returns {number}
|
|
36
|
+
*/
|
|
37
|
+
public static convertDate(date: any) {
|
|
38
|
+
return new Date(date).getTime();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* format a date with a given, fixed string
|
|
43
|
+
* For consistency, we use the patterns from
|
|
44
|
+
* https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
|
|
45
|
+
* @param date
|
|
46
|
+
* @param {string} format
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
public static formatDateByPattern(date: number | any, format: string): string {
|
|
50
|
+
if (!isNumeric(date)) {
|
|
51
|
+
return date;
|
|
52
|
+
}
|
|
53
|
+
let dateObject = new Date((date as number) * 1);
|
|
54
|
+
format = format.replace('y', '' + dateObject.getFullYear());
|
|
55
|
+
format = format.replace('M', '' + DateHelper.fillDate(dateObject.getMonth() + 1));
|
|
56
|
+
format = format.replace('d', '' + DateHelper.fillDate(dateObject.getDate()));
|
|
57
|
+
return format;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Format a date for the current language
|
|
62
|
+
*/
|
|
63
|
+
public static formatDate(
|
|
64
|
+
translation: TranslateService,
|
|
65
|
+
date: number | any,
|
|
66
|
+
options: FormatOptions = new FormatOptions(),
|
|
67
|
+
): string {
|
|
68
|
+
try {
|
|
69
|
+
if (options.useRelativeLabels && !options.relativeLabels) {
|
|
70
|
+
options.relativeLabels = RelativeMode.medium;
|
|
71
|
+
}
|
|
72
|
+
if (date == null) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
if (!isNumeric(date)) {
|
|
76
|
+
date = Date.parse(date);
|
|
77
|
+
}
|
|
78
|
+
let dateObject = new Date((date as number) * 1);
|
|
79
|
+
let dateToday = new Date();
|
|
80
|
+
let dateYesterday = new Date();
|
|
81
|
+
dateYesterday.setDate(dateYesterday.getDate() - 1);
|
|
82
|
+
let isToday = dateObject.toDateString() == dateToday.toDateString();
|
|
83
|
+
let isYesterday = dateObject.toDateString() == dateYesterday.toDateString();
|
|
84
|
+
let prefix = '';
|
|
85
|
+
let timeDiff = (dateToday.getTime() - dateObject.getTime()) / 1000;
|
|
86
|
+
let diffDays = Math.floor(timeDiff / (3600 * 24));
|
|
87
|
+
let diffMonths = new Date(timeDiff * 1000).getMonth();
|
|
88
|
+
let diffYears = new Date(timeDiff * 1000).getFullYear() - 1970;
|
|
89
|
+
let addDate = true;
|
|
90
|
+
let timeFormat = 'HH:mm';
|
|
91
|
+
if (options.showSeconds) {
|
|
92
|
+
timeFormat += ':ss';
|
|
93
|
+
}
|
|
94
|
+
if (timeDiff < 3600 * 6 && options.relativeLabels >= RelativeMode.short) {
|
|
95
|
+
if (timeDiff < 90) {
|
|
96
|
+
prefix = translation.instant('JUST_NOW', { seconds: timeDiff });
|
|
97
|
+
} else if (timeDiff < 60 * 100) {
|
|
98
|
+
prefix = translation.instant('MINUTES_AGO', {
|
|
99
|
+
minutes: Math.round(timeDiff / 60),
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
prefix = translation.instant('HOURS_AGO', {
|
|
103
|
+
hours: Math.round(timeDiff / (60 * 60)),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
addDate = false;
|
|
107
|
+
timeFormat = '';
|
|
108
|
+
} else if (isToday && options.relativeLabels >= RelativeMode.short) {
|
|
109
|
+
prefix = translation.instant('TODAY');
|
|
110
|
+
addDate = false;
|
|
111
|
+
} else if (isYesterday && options.relativeLabels >= RelativeMode.medium) {
|
|
112
|
+
prefix = translation.instant('YESTERDAY');
|
|
113
|
+
addDate = false;
|
|
114
|
+
} else if (
|
|
115
|
+
(diffDays < 6 && options.relativeLabels >= RelativeMode.medium) ||
|
|
116
|
+
(diffDays < 45 && options.relativeLabels >= RelativeMode.large)
|
|
117
|
+
) {
|
|
118
|
+
prefix = translation.instant('DAYS_AGO', { days: diffDays });
|
|
119
|
+
addDate = false;
|
|
120
|
+
if (!options.showAlwaysTime) timeFormat = '';
|
|
121
|
+
} else if (
|
|
122
|
+
diffYears === 0 &&
|
|
123
|
+
diffMonths < 12 &&
|
|
124
|
+
options.relativeLabels >= RelativeMode.large
|
|
125
|
+
) {
|
|
126
|
+
prefix = translation.instant('MONTHS_AGO', { months: diffMonths });
|
|
127
|
+
addDate = false;
|
|
128
|
+
if (!options.showAlwaysTime) timeFormat = '';
|
|
129
|
+
} else if (options.relativeLabels === RelativeMode.all) {
|
|
130
|
+
prefix = translation.instant('YEARS_AGO', { years: diffYears });
|
|
131
|
+
addDate = false;
|
|
132
|
+
if (!options.showAlwaysTime) timeFormat = '';
|
|
133
|
+
} else {
|
|
134
|
+
if (!options.showAlwaysTime) timeFormat = '';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ng2's dateformatter is super slow, but it doesn't matter, we just iterate it once :)
|
|
138
|
+
//return dateFormat+time;
|
|
139
|
+
let str = prefix;
|
|
140
|
+
if (addDate) {
|
|
141
|
+
if (translation.currentLang === 'en') {
|
|
142
|
+
str +=
|
|
143
|
+
dateObject.getFullYear() +
|
|
144
|
+
'-' +
|
|
145
|
+
DateHelper.fillDate(dateObject.getMonth() + 1) +
|
|
146
|
+
'-' +
|
|
147
|
+
DateHelper.fillDate(dateObject.getDate());
|
|
148
|
+
} else {
|
|
149
|
+
str +=
|
|
150
|
+
DateHelper.fillDate(dateObject.getDate()) +
|
|
151
|
+
'.' +
|
|
152
|
+
DateHelper.fillDate(dateObject.getMonth() + 1) +
|
|
153
|
+
'.' +
|
|
154
|
+
dateObject.getFullYear();
|
|
155
|
+
}
|
|
156
|
+
//str += DateFormatter.format(dateObject, Translation.getLanguage(), dateFormat).trim();
|
|
157
|
+
}
|
|
158
|
+
if (options.showDate == false) {
|
|
159
|
+
str = '';
|
|
160
|
+
}
|
|
161
|
+
// ie fixes, timeFormat not working
|
|
162
|
+
if (timeFormat) {
|
|
163
|
+
if (str) str += ', ';
|
|
164
|
+
|
|
165
|
+
//let timeValue=dateObject.toLocaleTimeString(Translation.getLanguage());
|
|
166
|
+
//let times=timeValue.split(":");
|
|
167
|
+
str += timeFormat
|
|
168
|
+
.replace('HH', DateHelper.fillDate(dateObject.getHours()))
|
|
169
|
+
.replace('mm', DateHelper.fillDate(dateObject.getMinutes()))
|
|
170
|
+
.replace('ss', DateHelper.fillDate(dateObject.getSeconds()));
|
|
171
|
+
}
|
|
172
|
+
return str;
|
|
173
|
+
/*
|
|
174
|
+
let dateString=prefix+" ";
|
|
175
|
+
if(dateFormat!=""){
|
|
176
|
+
dateString+=dateObject.toLocaleDateString(Translation.getLanguage())+" ";
|
|
177
|
+
}
|
|
178
|
+
if(time!=""){
|
|
179
|
+
dateString+=dateObject.toLocaleTimeString(Translation.getLanguage());
|
|
180
|
+
}
|
|
181
|
+
return dateString;
|
|
182
|
+
*/
|
|
183
|
+
} catch (e) {
|
|
184
|
+
return date as any;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
static getDateFromDatepicker(date: Date) {
|
|
188
|
+
return new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
static getDateForNewFile() {
|
|
192
|
+
return DateHelper.formatDate(null, new Date().getTime(), {
|
|
193
|
+
showAlwaysTime: true,
|
|
194
|
+
useRelativeLabels: false,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|