@geogirafe/lib-geoportal 1.2.0-dev.2873796427 → 1.2.0-dev.2889467567
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/api/apicontext.d.ts +12 -1
- package/api/apicontext.js +19 -111
- package/api/apisessionmanager.d.ts +1 -1
- package/api/apisessionmanager.js +1 -1
- package/base/GirafeSingleton.d.ts +1 -1
- package/base/GirafeSingleton.js +1 -1
- package/components/navigation/component.d.ts +2 -2
- package/components/navigation/component.js +6 -6
- package/components/news/news-button/component.d.ts +0 -1
- package/components/news/news-button/component.js +0 -6
- package/components/news/news-panel/component.d.ts +2 -2
- package/components/news/news-panel/component.js +5 -5
- package/components/search-filter/component.d.ts +2 -0
- package/components/search-filter/component.js +6 -3
- package/components/search-filter/style.css +4 -0
- package/components/themes/component.d.ts +1 -1
- package/components/themes/component.js +4 -4
- package/components/userpreferences/component.d.ts +1 -1
- package/components/userpreferences/component.js +7 -7
- package/package.json +1 -1
- package/templates/public/about.json +1 -1
- package/tools/app/lifecyclemanager.d.ts +1 -1
- package/tools/app/lifecyclemanager.js +1 -1
- package/tools/auth/abstractconnectmanager.js +2 -2
- package/tools/auth/authmanager.d.ts +1 -1
- package/tools/auth/authmanager.js +1 -1
- package/tools/auth/pluginmanager.d.ts +1 -1
- package/tools/auth/pluginmanager.js +1 -1
- package/tools/configuration/configmanager.d.ts +3 -2
- package/tools/configuration/configmanager.js +9 -5
- package/tools/configuration/girafeconfig.d.ts +7 -5
- package/tools/configuration/girafeconfig.js +4 -0
- package/tools/context/context.d.ts +1 -0
- package/tools/context/context.js +4 -112
- package/tools/context/contexthelper.d.ts +6 -0
- package/tools/context/contexthelper.js +102 -0
- package/tools/error/errormanager.d.ts +1 -1
- package/tools/error/errormanager.js +1 -1
- package/tools/feedback/feedbackmanager.d.ts +1 -2
- package/tools/feedback/feedbackmanager.js +6 -8
- package/tools/i18n/i18nmanager.d.ts +1 -1
- package/tools/i18n/i18nmanager.js +22 -20
- package/tools/layers/layermanager.d.ts +1 -1
- package/tools/layers/layermanager.js +1 -1
- package/tools/layers/snapmanager.d.ts +1 -1
- package/tools/layers/snapmanager.js +1 -1
- package/tools/localfile/localfilemanager.d.ts +1 -1
- package/tools/localfile/localfilemanager.js +1 -1
- package/tools/logging/defaultconsole.d.ts +8 -0
- package/tools/logging/defaultconsole.js +9 -0
- package/tools/logging/logmanager.d.ts +1 -7
- package/tools/logging/logmanager.js +8 -13
- package/tools/main.d.ts +3 -1
- package/tools/main.js +2 -0
- package/tools/offline/offlinemanager.d.ts +3 -3
- package/tools/offline/offlinemanager.js +6 -6
- package/tools/ogcapi/ogcapifeaturesmanager.d.ts +1 -1
- package/tools/ogcapi/ogcapifeaturesmanager.js +1 -1
- package/tools/onboarding/onboardingmanager.js +4 -4
- package/tools/ordering/orderingmanager.d.ts +1 -1
- package/tools/ordering/orderingmanager.js +1 -1
- package/tools/search/abstractsearchclient.d.ts +1 -1
- package/tools/search/abstractsearchclient.js +2 -2
- package/tools/search/searchmanager.d.ts +1 -1
- package/tools/search/searchmanager.js +2 -2
- package/tools/selection/selectionmanager.d.ts +1 -1
- package/tools/selection/selectionmanager.js +1 -1
- package/tools/share/sessionmanager.d.ts +1 -1
- package/tools/share/sessionmanager.js +1 -1
- package/tools/share/sharemanager.d.ts +1 -1
- package/tools/share/sharemanager.js +1 -1
- package/tools/share/stateserializer.d.ts +1 -1
- package/tools/share/stateserializer.js +1 -1
- package/tools/state/statemanager.d.ts +1 -1
- package/tools/state/statemanager.js +1 -1
- package/tools/tests/mockconfig.d.ts +2 -3
- package/tools/tests/mockconfig.js +0 -1
- package/tools/tests/mockcontext.d.ts +13 -1
- package/tools/tests/mockcontext.js +27 -112
- package/tools/tests/mockhelper.d.ts +2 -2
- package/tools/tests/mockhelper.js +4 -5
- package/tools/themes/customthemesmanager.d.ts +3 -3
- package/tools/themes/customthemesmanager.js +9 -9
- package/tools/themes/themefavoritesmanager.d.ts +5 -5
- package/tools/themes/themefavoritesmanager.js +16 -16
- package/tools/themes/themeshelper.d.ts +1 -1
- package/tools/themes/themeshelper.js +1 -1
- package/tools/themes/themesmanager.d.ts +1 -1
- package/tools/themes/themesmanager.js +2 -2
- package/tools/url/permalinkmanager.d.ts +1 -1
- package/tools/url/permalinkmanager.js +1 -1
- package/tools/userdata/userdatamanager.d.ts +18 -39
- package/tools/userdata/userdatamanager.js +111 -75
- package/tools/wfs/wfsmanager.d.ts +1 -1
- package/tools/wfs/wfsmanager.js +1 -1
- package/tools/wms/wmsmanager.d.ts +1 -1
- package/tools/wms/wmsmanager.js +1 -1
package/api/apicontext.d.ts
CHANGED
|
@@ -46,8 +46,8 @@ export default class GirafeApiContext implements IGirafeContext {
|
|
|
46
46
|
readonly themesManager: ThemesManager;
|
|
47
47
|
readonly themesHelper: ThemesHelper;
|
|
48
48
|
readonly permalinkManager: PermalinkManager;
|
|
49
|
-
readonly urlManager: UrlManager;
|
|
50
49
|
readonly dragManager: DragManager;
|
|
50
|
+
readonly urlManager: UrlManager;
|
|
51
51
|
readonly layerManager: LayerManager;
|
|
52
52
|
readonly sessionManager: ApiSessionManager;
|
|
53
53
|
readonly stateSerializer: StateSerializer;
|
|
@@ -72,6 +72,17 @@ export default class GirafeApiContext implements IGirafeContext {
|
|
|
72
72
|
readonly themeFavoritesManager: ThemeFavoritesManager;
|
|
73
73
|
readonly searchManager: SearchManager;
|
|
74
74
|
readonly feedbackManager: FeedbackManager;
|
|
75
|
+
private readonly contextHelper;
|
|
75
76
|
constructor();
|
|
76
77
|
initialize(): Promise<void>;
|
|
78
|
+
/** The context can contains hook methods that will be called after each manager initialization.
|
|
79
|
+
* The hook method must be named with the property name + the "Hook" suffix.
|
|
80
|
+
* The hook method must be async and will be awaited
|
|
81
|
+
* For example, the methods themesManagerHook() will be called immediately after
|
|
82
|
+
* the call of themesManager.initializeSingleton().
|
|
83
|
+
* This allows specific initialization methods when defining custom contexts
|
|
84
|
+
* (for example for the apiContext, the mockContext, or any customContext)
|
|
85
|
+
*/
|
|
86
|
+
protected configManagerHook(): Promise<void>;
|
|
87
|
+
protected stateManagerHook(): Promise<void>;
|
|
77
88
|
}
|
package/api/apicontext.js
CHANGED
|
@@ -1,41 +1,6 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
import ApplicationLifeCycleManager from '../tools/app/lifecyclemanager.js';
|
|
3
|
-
import AuthManager from '../tools/auth/authmanager.js';
|
|
4
|
-
import DragManager from '../components/treeview/tools/dragmanager.js';
|
|
5
|
-
import PluginManager from '../tools/auth/pluginmanager.js';
|
|
6
|
-
import ConfigManager from '../tools/configuration/configmanager.js';
|
|
7
|
-
import ErrorManager from '../tools/error/errormanager.js';
|
|
8
|
-
import I18nManager from '../tools/i18n/i18nmanager.js';
|
|
9
|
-
import LayerManager from '../tools/layers/layermanager.js';
|
|
10
|
-
import SnapManager from '../tools/layers/snapmanager.js';
|
|
11
|
-
import LocalFileManager from '../tools/localfile/localfilemanager.js';
|
|
12
|
-
import LogManager from '../tools/logging/logmanager.js';
|
|
13
|
-
import OfflineManager from '../tools/offline/offlinemanager.js';
|
|
14
|
-
import OgcApiFeaturesManager from '../tools/ogcapi/ogcapifeaturesmanager.js';
|
|
15
|
-
import OrderingManager from '../tools/ordering/orderingmanager.js';
|
|
16
|
-
import ShareManager from '../tools/share/sharemanager.js';
|
|
17
|
-
import StateSerializer from '../tools/share/stateserializer.js';
|
|
18
|
-
import ComponentManager from '../tools/state/componentManager.js';
|
|
19
|
-
import MapManager from '../tools/state/mapManager.js';
|
|
20
|
-
import StateManager from '../tools/state/statemanager.js';
|
|
21
|
-
import UserInteractionManager from '../tools/state/userInteractionManager.js';
|
|
22
|
-
import CustomThemesManager from '../tools/themes/customthemesmanager.js';
|
|
23
|
-
import ThemesHelper from '../tools/themes/themeshelper.js';
|
|
24
|
-
import ThemesManager from '../tools/themes/themesmanager.js';
|
|
25
|
-
import UserLayerManager from '../tools/themes/userlayermanager.js';
|
|
26
|
-
import PermalinkManager from '../tools/url/permalinkmanager.js';
|
|
27
|
-
import UrlManager from '../tools/url/urlmanager.js';
|
|
28
|
-
import UserDataManager from '../tools/userdata/userdatamanager.js';
|
|
29
|
-
import WfsManager from '../tools/wfs/wfsmanager.js';
|
|
30
|
-
import WmsManager from '../tools/wms/wmsmanager.js';
|
|
31
|
-
import WmtsManager from '../tools/wmts/wmtsmanager.js';
|
|
32
|
-
import SelectionManager from '../tools/selection/selectionmanager.js';
|
|
33
1
|
import ApiSessionManager from './apisessionmanager.js';
|
|
34
|
-
import OnBoardingManager from '../tools/onboarding/onboardingmanager.js';
|
|
35
|
-
import ThemeFavoritesManager from '../tools/themes/themefavoritesmanager.js';
|
|
36
|
-
import SearchManager from '../tools/search/searchmanager.js';
|
|
37
|
-
import FeedbackManager from '../tools/feedback/feedbackmanager.js';
|
|
38
2
|
import { updateConfigPaths } from './apiutils.js';
|
|
3
|
+
import ContextInitializationHelper from '../tools/context/contexthelper.js';
|
|
39
4
|
export default class GirafeApiContext {
|
|
40
5
|
userDataManager;
|
|
41
6
|
configManager;
|
|
@@ -47,8 +12,8 @@ export default class GirafeApiContext {
|
|
|
47
12
|
themesManager;
|
|
48
13
|
themesHelper;
|
|
49
14
|
permalinkManager;
|
|
50
|
-
urlManager;
|
|
51
15
|
dragManager;
|
|
16
|
+
urlManager;
|
|
52
17
|
layerManager;
|
|
53
18
|
sessionManager;
|
|
54
19
|
stateSerializer;
|
|
@@ -73,87 +38,30 @@ export default class GirafeApiContext {
|
|
|
73
38
|
themeFavoritesManager;
|
|
74
39
|
searchManager;
|
|
75
40
|
feedbackManager;
|
|
41
|
+
contextHelper = new ContextInitializationHelper();
|
|
76
42
|
constructor() {
|
|
77
|
-
this.
|
|
78
|
-
this.userDataManager = new UserDataManager(this);
|
|
79
|
-
this.configManager = new ConfigManager(this);
|
|
80
|
-
this.logManager = new LogManager(this);
|
|
81
|
-
this.stateManager = new StateManager(this);
|
|
82
|
-
this.orderingManager = new OrderingManager(this);
|
|
83
|
-
this.applicationLifeCycleManager = new ApplicationLifeCycleManager(this);
|
|
84
|
-
this.mapManager = new MapManager(this);
|
|
85
|
-
this.offlineManager = new OfflineManager(this);
|
|
86
|
-
this.snapManager = new SnapManager(this);
|
|
87
|
-
this.authManager = new AuthManager(this);
|
|
88
|
-
this.pluginManager = new PluginManager(this);
|
|
89
|
-
this.i18nManager = new I18nManager(this);
|
|
90
|
-
this.userInteractionManager = new UserInteractionManager(this);
|
|
91
|
-
this.dragManager = new DragManager(this);
|
|
92
|
-
this.urlManager = new UrlManager(this);
|
|
93
|
-
this.permalinkManager = new PermalinkManager(this);
|
|
94
|
-
this.layerManager = new LayerManager(this);
|
|
95
|
-
this.userLayerManager = new UserLayerManager(this);
|
|
96
|
-
this.themesHelper = new ThemesHelper(this);
|
|
97
|
-
this.stateSerializer = new StateSerializer(this);
|
|
43
|
+
this.contextHelper.constructContext(this, ['sessionManager']);
|
|
98
44
|
this.sessionManager = new ApiSessionManager(this);
|
|
99
|
-
this.shareManager = new ShareManager(this);
|
|
100
|
-
this.wfsManager = new WfsManager(this);
|
|
101
|
-
this.errorManager = new ErrorManager(this);
|
|
102
|
-
this.customThemesManager = new CustomThemesManager(this);
|
|
103
|
-
this.themesManager = new ThemesManager(this);
|
|
104
|
-
this.wmsManager = new WmsManager(this);
|
|
105
|
-
this.wmtsManager = new WmtsManager(this);
|
|
106
|
-
this.selectionManager = new SelectionManager(this);
|
|
107
|
-
this.localFileManager = new LocalFileManager(this);
|
|
108
|
-
this.ogcApiFeaturesManager = new OgcApiFeaturesManager(this);
|
|
109
|
-
this.onBoardingManager = new OnBoardingManager(this);
|
|
110
|
-
this.themeFavoritesManager = new ThemeFavoritesManager(this);
|
|
111
|
-
this.searchManager = new SearchManager(this);
|
|
112
|
-
this.feedbackManager = new FeedbackManager(this);
|
|
113
45
|
}
|
|
114
46
|
async initialize() {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
47
|
+
await this.contextHelper.initializeContext(this);
|
|
48
|
+
}
|
|
49
|
+
/** The context can contains hook methods that will be called after each manager initialization.
|
|
50
|
+
* The hook method must be named with the property name + the "Hook" suffix.
|
|
51
|
+
* The hook method must be async and will be awaited
|
|
52
|
+
* For example, the methods themesManagerHook() will be called immediately after
|
|
53
|
+
* the call of themesManager.initializeSingleton().
|
|
54
|
+
* This allows specific initialization methods when defining custom contexts
|
|
55
|
+
* (for example for the apiContext, the mockContext, or any customContext)
|
|
56
|
+
*/
|
|
57
|
+
async configManagerHook() {
|
|
58
|
+
await this.configManager.initializeSingleton();
|
|
120
59
|
// For the API context, some configuraton options in the config file can be relative.
|
|
121
60
|
// We have to convert them to absolute paths.
|
|
122
61
|
updateConfigPaths(this.configManager.Config);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
this.stateManager.initializeSingleton();
|
|
62
|
+
}
|
|
63
|
+
async stateManagerHook() {
|
|
64
|
+
await this.stateManager.initializeSingleton();
|
|
126
65
|
this.stateManager.state.interface.isApi = true;
|
|
127
|
-
this.orderingManager.initializeSingleton();
|
|
128
|
-
this.applicationLifeCycleManager.initializeSingleton();
|
|
129
|
-
this.mapManager.initializeSingleton();
|
|
130
|
-
this.offlineManager.initializeSingleton();
|
|
131
|
-
this.snapManager.initializeSingleton();
|
|
132
|
-
this.authManager.initializeSingleton();
|
|
133
|
-
this.pluginManager.initializeSingleton();
|
|
134
|
-
this.i18nManager.initializeSingleton();
|
|
135
|
-
this.userInteractionManager.initializeSingleton();
|
|
136
|
-
this.dragManager.initializeSingleton();
|
|
137
|
-
this.urlManager.initializeSingleton();
|
|
138
|
-
this.permalinkManager.initializeSingleton();
|
|
139
|
-
this.layerManager.initializeSingleton();
|
|
140
|
-
this.userLayerManager.initializeSingleton();
|
|
141
|
-
this.themesHelper.initializeSingleton();
|
|
142
|
-
this.stateSerializer.initializeSingleton();
|
|
143
|
-
this.sessionManager.initializeSingleton();
|
|
144
|
-
this.shareManager.initializeSingleton();
|
|
145
|
-
this.wfsManager.initializeSingleton();
|
|
146
|
-
this.errorManager.initializeSingleton();
|
|
147
|
-
this.customThemesManager.initializeSingleton();
|
|
148
|
-
this.themesManager.initializeSingleton();
|
|
149
|
-
this.wmsManager.initializeSingleton();
|
|
150
|
-
this.wmtsManager.initializeSingleton();
|
|
151
|
-
this.localFileManager.initializeSingleton();
|
|
152
|
-
this.selectionManager.initializeSingleton();
|
|
153
|
-
this.ogcApiFeaturesManager.initializeSingleton();
|
|
154
|
-
this.onBoardingManager.initializeSingleton();
|
|
155
|
-
this.themeFavoritesManager.initializeSingleton();
|
|
156
|
-
this.searchManager.initializeSingleton();
|
|
157
|
-
this.feedbackManager.initializeSingleton();
|
|
158
66
|
}
|
|
159
67
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import GirafeSingleton from '../base/GirafeSingleton.js';
|
|
2
2
|
import ISessionManager from '../tools/share/isessionmanager.js';
|
|
3
3
|
declare class ApiSessionManager extends GirafeSingleton implements ISessionManager {
|
|
4
|
-
initializeSingleton(): void
|
|
4
|
+
initializeSingleton(): Promise<void>;
|
|
5
5
|
beginSession(): void;
|
|
6
6
|
saveStateToSession(): void;
|
|
7
7
|
hasState(): boolean;
|
package/api/apisessionmanager.js
CHANGED
|
@@ -2,7 +2,7 @@ import IGirafeContext from '../tools/context/icontext.js';
|
|
|
2
2
|
declare class GirafeSingleton {
|
|
3
3
|
protected readonly context: IGirafeContext;
|
|
4
4
|
constructor(context: IGirafeContext);
|
|
5
|
-
initializeSingleton(): void
|
|
5
|
+
initializeSingleton(): Promise<void>;
|
|
6
6
|
protected isNullOrUndefinedOrBlank(val: unknown): val is "" | null | undefined;
|
|
7
7
|
}
|
|
8
8
|
export default GirafeSingleton;
|
package/base/GirafeSingleton.js
CHANGED
|
@@ -4,7 +4,7 @@ class GirafeSingleton {
|
|
|
4
4
|
constructor(context) {
|
|
5
5
|
this.context = context;
|
|
6
6
|
}
|
|
7
|
-
initializeSingleton() {
|
|
7
|
+
async initializeSingleton() {
|
|
8
8
|
/*
|
|
9
9
|
* This method does nothing by default, but will be called by the context when creating the singleton
|
|
10
10
|
* (This prevent overriding the constructor in every songleton and creating a strong dependency to the context object)
|
|
@@ -15,8 +15,8 @@ declare class NavigationComponent extends GirafeHTMLElement {
|
|
|
15
15
|
render(): void;
|
|
16
16
|
addBookmark(): Promise<void>;
|
|
17
17
|
removeBookmark(bookmark: Bookmark): Promise<void>;
|
|
18
|
-
saveBookmarks
|
|
19
|
-
loadBookmarks
|
|
18
|
+
private saveBookmarks;
|
|
19
|
+
private loadBookmarks;
|
|
20
20
|
registerEvents(): void;
|
|
21
21
|
onPositionChanged(position: MapPosition): void;
|
|
22
22
|
navigateBack(): void;
|
|
@@ -36,7 +36,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
36
36
|
if (name) {
|
|
37
37
|
const bookmark = new Bookmark(name, this.state.position);
|
|
38
38
|
this.bookmarks.push(bookmark);
|
|
39
|
-
this.saveBookmarks();
|
|
39
|
+
await this.saveBookmarks();
|
|
40
40
|
super.render();
|
|
41
41
|
super.girafeTranslate();
|
|
42
42
|
}
|
|
@@ -48,17 +48,17 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
48
48
|
if (index >= 0) {
|
|
49
49
|
this.bookmarks.splice(index, 1);
|
|
50
50
|
}
|
|
51
|
-
this.saveBookmarks();
|
|
51
|
+
await this.saveBookmarks();
|
|
52
52
|
super.render();
|
|
53
53
|
super.girafeTranslate();
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
saveBookmarks() {
|
|
57
|
-
this.context.userDataManager.saveUserData(this.storagePath, this.bookmarks);
|
|
56
|
+
async saveBookmarks() {
|
|
57
|
+
await this.context.userDataManager.saveUserData(this.storagePath, this.bookmarks);
|
|
58
58
|
}
|
|
59
|
-
loadBookmarks() {
|
|
59
|
+
async loadBookmarks() {
|
|
60
60
|
this.bookmarks = [];
|
|
61
|
-
const storedBookmarks = this.context.userDataManager.getUserData(this.storagePath);
|
|
61
|
+
const storedBookmarks = (await this.context.userDataManager.getUserData(this.storagePath));
|
|
62
62
|
if (storedBookmarks) {
|
|
63
63
|
for (const bookmark of storedBookmarks) {
|
|
64
64
|
try {
|
|
@@ -26,12 +26,6 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
26
26
|
}
|
|
27
27
|
super.render();
|
|
28
28
|
}
|
|
29
|
-
loadLastViewDate() {
|
|
30
|
-
const lastViewDate = this.context.userDataManager.getUserData('lastViewDate');
|
|
31
|
-
if (lastViewDate) {
|
|
32
|
-
this.context.stateManager.state.news.lastViewDate = lastViewDate;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
29
|
getIcon() {
|
|
36
30
|
const icon = this.warn ? 'icons/bell-warn.svg' : 'icons/bell.svg';
|
|
37
31
|
return icon;
|
|
@@ -10,8 +10,8 @@ declare class NewsPanelComponent extends GirafeHTMLElement implements IGirafePan
|
|
|
10
10
|
panelTogglePath: string;
|
|
11
11
|
entries: FeedEntry[];
|
|
12
12
|
constructor();
|
|
13
|
-
saveLastViewDate(): void
|
|
14
|
-
loadLastViewDate
|
|
13
|
+
saveLastViewDate(): Promise<void>;
|
|
14
|
+
private loadLastViewDate;
|
|
15
15
|
togglePanel(visible: boolean): void;
|
|
16
16
|
render(): void;
|
|
17
17
|
private initializeNewsState;
|
|
@@ -22,13 +22,13 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
22
22
|
constructor() {
|
|
23
23
|
super('news-panel');
|
|
24
24
|
}
|
|
25
|
-
saveLastViewDate() {
|
|
25
|
+
async saveLastViewDate() {
|
|
26
26
|
const currentTimestamp = Date.now();
|
|
27
|
-
this.context.userDataManager.saveUserData('lastViewDate', currentTimestamp);
|
|
27
|
+
await this.context.userDataManager.saveUserData('lastViewDate', currentTimestamp);
|
|
28
28
|
this.context.stateManager.state.news.lastViewDate = currentTimestamp;
|
|
29
29
|
}
|
|
30
|
-
loadLastViewDate() {
|
|
31
|
-
const raw = this.context.userDataManager.getUserData('lastViewDate');
|
|
30
|
+
async loadLastViewDate() {
|
|
31
|
+
const raw = await this.context.userDataManager.getUserData('lastViewDate');
|
|
32
32
|
const lastViewDate = Number(raw);
|
|
33
33
|
this.context.stateManager.state.news.lastViewDate = Number.isFinite(lastViewDate) ? lastViewDate : 0;
|
|
34
34
|
}
|
|
@@ -52,7 +52,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
52
52
|
if (!this.context.configManager.Config.news) {
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
|
-
this.loadLastViewDate();
|
|
55
|
+
await this.loadLastViewDate();
|
|
56
56
|
const urls = this.context.configManager.Config.news.urls;
|
|
57
57
|
this.entries = await loadFeeds(urls);
|
|
58
58
|
// Update state manager
|
|
@@ -8,6 +8,7 @@ interface CategoryEntry {
|
|
|
8
8
|
provider: string;
|
|
9
9
|
category: string;
|
|
10
10
|
label: string;
|
|
11
|
+
example?: string;
|
|
11
12
|
}
|
|
12
13
|
declare class SearchFilterComponent extends GirafeHTMLElement {
|
|
13
14
|
protected templateUrl: string | null;
|
|
@@ -19,6 +20,7 @@ declare class SearchFilterComponent extends GirafeHTMLElement {
|
|
|
19
20
|
private categories;
|
|
20
21
|
private availableShortcuts;
|
|
21
22
|
private selectedCategories;
|
|
23
|
+
private filterExamples;
|
|
22
24
|
private fsmState;
|
|
23
25
|
private focusedShortcutIndex;
|
|
24
26
|
private readonly numberOfChipsToShow;
|
|
@@ -15,10 +15,10 @@ class SearchFilterComponent extends GirafeHTMLElement {
|
|
|
15
15
|
return uHtml `<style>
|
|
16
16
|
.hidden{display:none!important}.gg-rotate90{transform:rotate(90deg)}.gg-rotate180{transform:rotate(180deg)}.gg-rotate270{transform:rotate(270deg)}img{filter:var(--svg-filter)}img.legend-image{filter:var(--svg-map-filter);background:var(--svg-legend-bkg)}div{scrollbar-width:thin}a,a:visited{color:var(--link-color)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spin-wait{0%{transform:rotate(0)}7%{transform:rotate(360deg)}to{transform:rotate(360deg)}}.gg-spin{animation-name:spin;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}.gg-spin-wait{animation-name:spin-wait;animation-duration:10s;animation-timing-function:linear;animation-iteration-count:infinite}::-webkit-scrollbar{width:5px}::-webkit-scrollbar-thumb{background:#999}button,input,select,textarea{font:inherit}.gg-button,.gg-select,.gg-input,.gg-textarea{background-color:var(--bkg-color);color:var(--text-color);border:var(--app-standard-border);box-sizing:border-box;cursor:pointer;border-radius:3px;outline:0;margin:0;padding:0 0 0 .5rem;display:inline-block}.gg-label{background-color:var(--bkg-color);color:var(--text-color);border:none;align-items:center;margin:0;padding:0;display:flex}.gg-button,.gg-select,.gg-input,.gg-label{min-height:calc(var(--app-standard-height) / 1.5)}.gg-textarea{max-height:initial;resize:vertical;height:6rem;padding:.5rem;line-height:1.3rem}.gg-input{cursor:text}.gg-checkbox{accent-color:var(--text-color);cursor:pointer;width:1.2rem}.gg-range{accent-color:var(--text-color)}.gg-button{padding:0 .5rem}.gg-button.active{border:solid 1px var(--text-color-grad1);background-color:var(--bkg-color-grad2)}.gg-button:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed;border:none}.gg-button:disabled img{filter:opacity(.6)}.gg-input:disabled,.gg-select:disabled,.gg-textarea:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed}.gg-button>img{vertical-align:middle}.gg-icon-button{color:var(--text-color);cursor:pointer;background-color:#0000;border:none;flex-direction:column;justify-content:center;align-items:center;padding:0;display:flex}.gg-icon{justify-content:center;align-items:center;display:flex}.gg-big,.gg-big-withtext{min-width:var(--app-standard-height);min-height:var(--app-standard-height);max-height:var(--app-standard-height)}.gg-big img,.gg-big-withtext img{width:calc(var(--app-standard-height) - 1.5rem);margin:0}.gg-big-withtext span{font-variant:small-caps;padding:0 1rem;font-size:.9rem}.gg-medium,.gg-medium-withtext{min-width:calc(var(--app-standard-height) / 1.2);min-height:calc(var(--app-standard-height) / 1.2);max-height:calc(var(--app-standard-height) / 1.2);flex-direction:row}.gg-medium img{width:calc(var(--app-standard-height) / 2.4);margin:0}.gg-medium-withtext img{width:calc(var(--app-standard-height) / 2.4);margin-left:.5rem}.gg-medium-withtext span{padding:0 1rem 0 .5rem;font-size:.9rem}.gg-small,.gg-small-withtext{min-width:calc(var(--app-standard-height) / 2);min-height:calc(var(--app-standard-height) / 2);max-height:calc(var(--app-standard-height) / 2);flex-direction:row}.gg-small img{width:calc(var(--app-standard-height) / 3);margin:0}.gg-small-withtext img{width:calc(var(--app-standard-height) / 3);margin-left:.5rem}.gg-small-withtext span{padding:0 .5rem 0 .3rem;font-size:.9rem}.gg-button:hover:not(:disabled),.gg-select:hover:not(:disabled),.gg-input:hover:not(:disabled),.gg-textarea:hover:not(:disabled),.gg-icon-button:hover:not(:disabled){background-color:var(--bkg-color-grad1)}.gg-opacity{opacity:.5}.gg-opacity:hover{opacity:1;background-color:#0000}.gg-tabs{cursor:pointer;grid-auto-flow:column;padding-bottom:1rem;font-size:1rem;display:grid}.gg-tab{border:none;border-bottom:var(--app-standard-border);cursor:pointer;color:var(--text-color);background:0 0;padding:.5rem}.gg-tab.active{border-bottom:solid 1px var(--text-color)}.girafe-button-big,.girafe-button-large,.girafe-button-small,.girafe-button-tiny{color:var(--text-color);background-color:#0000;border:none;flex-direction:column;display:flex}.girafe-button-big:hover,.girafe-button-large:hover,.girafe-button-small:hover,.girafe-button-tiny:hover{background-color:var(--bkg-color-grad1);cursor:pointer}.girafe-button-big.dark,.girafe-button-large.dark,.girafe-button-small.dark,.girafe-button-tiny.dark{background-color:var(--bkg-color);filter:invert()}.girafe-button-big{width:var(--app-standard-height);height:var(--app-standard-height);align-items:center;padding:1rem}.girafe-button-big img{overflow:hidden}.girafe-button-large{flex-direction:row}.girafe-button-large img{height:2rem;margin:.3rem}.girafe-button-large span{height:2rem;margin:.3rem;line-height:2rem}.girafe-button-small{min-width:calc(var(--app-standard-height) / 2);height:calc(var(--app-standard-height) / 2);align-items:center;padding:.5rem}.girafe-button-small img{overflow:hidden}.girafe-button-small span{text-align:left;text-overflow:ellipsis;width:100%;overflow:hidden}.girafe-button-tiny{align-items:center;width:1rem;height:1rem;padding:0}.girafe-button-tiny img{overflow:hidden}.girafe-onboarding-theme{background-color:var(--bkg-color)!important;color:var(--text-color)!important}.girafe-onboarding-theme button{background-color:var(--bkg-color)!important;color:var(--text-color)!important;text-shadow:none!important}.girafe-onboarding-theme button.driver-popover-close-btn{z-index:10000}.tippy-box{background-color:var(--bkg-color)!important;border:var(--app-standard-border)!important}.tippy-content{color:var(--text-color)!important}.tippy-arrow{color:var(--bkg-color)!important}.tippy-box[data-theme~=error]{background-color:var(--error-color);white-space:pre-line}div.tippy-box[data-theme=image-popup]{border:var(--app-standard-border)!important;& div.tippy-content{background-color:var(--bkg-color)!important;& img{max-width:20rem;max-height:20rem}}& div.tippy-arrow{color:var(--bkg-color)!important}}
|
|
17
17
|
</style><style>
|
|
18
|
-
#search-filter-root{--active-color:#2563eb;--chip-text-color:#102e91;--chip-bg-color:#dbeafe;--chip-width:7rem;width:max-content;max-width:100%;color:var(--text-color);align-items:center;gap:.4rem;display:inline-flex;position:relative}#search-filter-button{background:var(--bkg-color);cursor:pointer;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;min-width:2.25rem;height:2.25rem;display:inline-flex;position:relative}#search-filter-button.active{border-color:var(--active-color);background:var(--bkg-color);box-shadow:inset 0 0 0 2px #2563eb33}#search-filter-button.active .filter-icon{filter:invert(35%)sepia()saturate(400%)hue-rotate(190deg)}.filter-icon{width:20px;height:20px}.badge{background:var(--active-color);color:#fff;text-align:center;border-radius:5rem;min-width:1rem;height:1rem;padding:0 .15rem;font-size:.7rem;line-height:1rem;position:absolute;top:-.25rem;right:-.5rem}#search-filter-chips{align-items:center;gap:.35rem;min-width:0;display:flex}.chip{background:var(--chip-bg-color);color:var(--chip-text-color);border:1px solid var(--chip-text-color);max-width:var(--chip-width);cursor:pointer;border-radius:5rem;flex:none;align-items:center;height:1.1rem;padding:.1rem .5rem;font-size:.8rem;display:inline-flex}.chip-label{color:inherit;cursor:pointer;background:0 0;border:none;outline:none;width:100%;min-width:0;padding:0}.chip-remove{color:var(--chip-text-color);cursor:pointer;background:0 0;border:none;width:1rem;height:1rem;padding:0;font-size:1rem;line-height:1}#search-filter-menu{width:100%;min-width:28rem;max-width:min(36rem,50vw);color:var(--text-color);background:var(--bkg-color);border:var(--app-standard-border);z-index:1001;border-radius:4px;flex-direction:column;min-height:0;max-height:min(31rem,60vh);display:flex;position:absolute;top:3.15rem;left:0;overflow:hidden}.menu-header{background:var(--bkg-color);border-bottom:var(--app-standard-border);z-index:1002;padding:1rem 1rem .5rem;position:sticky;top:0}.category-title{padding-bottom:.75rem;font-size:1rem;font-weight:700}.menu-actions{gap:.35rem;display:flex}.menu-action{border:var(--app-standard-border);background:var(--bkg-color);cursor:pointer;border-radius:4px;padding:.15rem .5rem}.shortcut-title{align-self:center;margin:0 .5rem 0 auto;font-size:.85rem}.menu-list{scrollbar-width:thin;flex-direction:column;padding:.5rem;display:flex;overflow:auto}.category-row{cursor:pointer;border-radius:4px;align-items:center;gap:.4rem;padding:.25rem;display:flex}.category-row:hover{background-color:var(--bkg-color-grad1)}.category-label{min-width:0;margin-right:auto}.shortcut{color:var(--text-color-grad1);font-family:monospace;font-size:.85rem}.shortcut-header{padding:.5rem;font-style:italic}.shortcut-row{background:var(--bkg-color);color:var(--text-color);cursor:pointer;text-align:left;border:0 solid #0000;border-radius:4px;align-items:center;padding:.5rem;display:flex}.shortcut-row:hover,.shortcut-row:focus,.shortcut-row.active{background-color:var(--bkg-color-grad1);outline:none}.shortcut-row>.shortcut{min-width:4rem}.text-ellipsis{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}
|
|
18
|
+
#search-filter-root{--active-color:#2563eb;--chip-text-color:#102e91;--chip-bg-color:#dbeafe;--chip-width:7rem;width:max-content;max-width:100%;color:var(--text-color);align-items:center;gap:.4rem;display:inline-flex;position:relative}#search-filter-button{background:var(--bkg-color);cursor:pointer;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;min-width:2.25rem;height:2.25rem;display:inline-flex;position:relative}#search-filter-button.active{border-color:var(--active-color);background:var(--bkg-color);box-shadow:inset 0 0 0 2px #2563eb33}#search-filter-button.active .filter-icon{filter:invert(35%)sepia()saturate(400%)hue-rotate(190deg)}.filter-icon{width:20px;height:20px}.badge{background:var(--active-color);color:#fff;text-align:center;border-radius:5rem;min-width:1rem;height:1rem;padding:0 .15rem;font-size:.7rem;line-height:1rem;position:absolute;top:-.25rem;right:-.5rem}#search-filter-chips{align-items:center;gap:.35rem;min-width:0;display:flex}.chip{background:var(--chip-bg-color);color:var(--chip-text-color);border:1px solid var(--chip-text-color);max-width:var(--chip-width);cursor:pointer;border-radius:5rem;flex:none;align-items:center;height:1.1rem;padding:.1rem .5rem;font-size:.8rem;display:inline-flex}.chip-label{color:inherit;cursor:pointer;background:0 0;border:none;outline:none;width:100%;min-width:0;padding:0}.chip-remove{color:var(--chip-text-color);cursor:pointer;background:0 0;border:none;width:1rem;height:1rem;padding:0;font-size:1rem;line-height:1}#search-filter-menu{width:100%;min-width:28rem;max-width:min(36rem,50vw);color:var(--text-color);background:var(--bkg-color);border:var(--app-standard-border);z-index:1001;border-radius:4px;flex-direction:column;min-height:0;max-height:min(31rem,60vh);display:flex;position:absolute;top:3.15rem;left:0;overflow:hidden}.menu-header{background:var(--bkg-color);border-bottom:var(--app-standard-border);z-index:1002;padding:1rem 1rem .5rem;position:sticky;top:0}.category-title{padding-bottom:.75rem;font-size:1rem;font-weight:700}.menu-actions{gap:.35rem;display:flex}.menu-action{border:var(--app-standard-border);background:var(--bkg-color);cursor:pointer;border-radius:4px;padding:.15rem .5rem}.shortcut-title{align-self:center;margin:0 .5rem 0 auto;font-size:.85rem}.menu-list{scrollbar-width:thin;flex-direction:column;padding:.5rem;display:flex;overflow:auto}.category-row{cursor:pointer;border-radius:4px;align-items:center;gap:.4rem;padding:.25rem;display:flex}.category-row:hover{background-color:var(--bkg-color-grad1)}.category-label{min-width:0;margin-right:auto}.category-example{font-size:.8em}.shortcut{color:var(--text-color-grad1);font-family:monospace;font-size:.85rem}.shortcut-header{padding:.5rem;font-style:italic}.shortcut-row{background:var(--bkg-color);color:var(--text-color);cursor:pointer;text-align:left;border:0 solid #0000;border-radius:4px;align-items:center;padding:.5rem;display:flex}.shortcut-row:hover,.shortcut-row:focus,.shortcut-row.active{background-color:var(--bkg-color-grad1);outline:none}.shortcut-row>.shortcut{min-width:4rem}.text-ellipsis{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}
|
|
19
19
|
</style>
|
|
20
20
|
<style>${this.customStyle}</style>
|
|
21
|
-
<div id="search-filter-root" class="${this.enabled ? '' : 'hidden'}"><button id="search-filter-button" class="${this.isFilterActive() ? 'active' : ''}" type="button" title="Filter categories" aria-label="Filter categories" aria-expanded="${this.isMenuOpen()}" aria-haspopup="dialog" onclick="${(e) => this.onFilterButtonClick(e)}"><img class="filter-icon" alt="filter icon" src="icons/filter.svg"> <span class="${this.getSelectionCount() > 0 ? 'badge' : 'hidden'}">${this.getSelectionCount()}</span></button><div id="search-filter-chips" class="${this.getSelectedCategoryEntries().length > 0 ? '' : 'hidden'}">${this.getSelectedCategoryEntries(true).map((entry) => uHtml `<div class="chip"><button class="chip-label text-ellipsis" i18n="${entry.label}" onclick="${(e) => this.onChipClick(e)}">${entry.label}</button> <button class="chip-remove" type="button" title="Remove category" aria-label="Remove category" onclick="${(e) => this.onRemoveChip(entry, e)}">×</button></div>`)} ${this.getNumberOfOverflowChips() ? uHtml `<div class="chip"><button class="chip-label text-ellipsis" onclick="${(e) => this.onChipClick(e)}">${this.getNumberOfOverflowChipsAsLabel()}</button></div>` : ''}</div>${this.isMenuOpen() ? uHtml `<div id="search-filter-menu">${this.isCategoriesOpen() ? uHtml `<div class="menu-header"><div i18n="Filter categories" class="category-title">Search categories</div><div class="menu-actions"><button class="gg-button gg-medium menu-action" type="button" i18n="Select all" onclick="${(e) => this.onSelectAll(e)}">Select all</button> <button class="gg-button gg-medium menu-action" type="button" i18n="Reset" onclick="${(e) => this.onClearSelection(e)}">Reset</button><div class="${this.hasShortcutsConfigured() ? 'shortcut-title' : 'hidden'}"><span i18n="Shortcut">Shortcut</span></div></div></div><div class="menu-list">${this.getAllCategoriesFlattened().map((entry) => uHtml ` <label class="category-row"><input type="checkbox" value="${entry.key}" class="gg-checkbox" .checked="${this.isCategorySelected(entry)}" onchange="${(e) => this.onCategoryToggle(entry, e)}"> <span class="category-label text-ellipsis" i18n="${entry.label}">${entry.label}</span> <span class="shortcut">${this.getShortcutForCategory(entry)}</span></label> `)}</div>` : ''} ${this.isShortcutsOpen() ? uHtml `<div class="menu-header shortcut-header" i18n="Type or select a shortcut from the list to quickly filter search results.">Type or select a shortcut from the list to quickly filter search results.</div><div id="shortcut-list" class="menu-list">${this.getShortcutEntries().map((shEntry) => uHtml ` <button type="button" class="shortcut-row" data-shortcut="${shEntry.shortcut}" onkeydown="${(e) => this.onShortcutListDown(e)}" onclick="${() => this.onShortcutClick(shEntry.shortcut)}"><span class="shortcut">${this.currentPrefixSymbol}${shEntry.shortcut}</span> <span class="text-ellipsis">${shEntry.categoriesList}</span></button> `)} ` : ''}</div></div>` : ''}</div>
|
|
21
|
+
<div id="search-filter-root" class="${this.enabled ? '' : 'hidden'}"><button id="search-filter-button" class="${this.isFilterActive() ? 'active' : ''}" type="button" title="Filter categories" aria-label="Filter categories" aria-expanded="${this.isMenuOpen()}" aria-haspopup="dialog" onclick="${(e) => this.onFilterButtonClick(e)}"><img class="filter-icon" alt="filter icon" src="icons/filter.svg"> <span class="${this.getSelectionCount() > 0 ? 'badge' : 'hidden'}">${this.getSelectionCount()}</span></button><div id="search-filter-chips" class="${this.getSelectedCategoryEntries().length > 0 ? '' : 'hidden'}">${this.getSelectedCategoryEntries(true).map((entry) => uHtml `<div class="chip"><button class="chip-label text-ellipsis" i18n="${entry.label}" onclick="${(e) => this.onChipClick(e)}">${entry.label}</button> <button class="chip-remove" type="button" title="Remove category" aria-label="Remove category" onclick="${(e) => this.onRemoveChip(entry, e)}">×</button></div>`)} ${this.getNumberOfOverflowChips() ? uHtml `<div class="chip"><button class="chip-label text-ellipsis" onclick="${(e) => this.onChipClick(e)}">${this.getNumberOfOverflowChipsAsLabel()}</button></div>` : ''}</div>${this.isMenuOpen() ? uHtml `<div id="search-filter-menu">${this.isCategoriesOpen() ? uHtml `<div class="menu-header"><div i18n="Filter categories" class="category-title">Search categories</div><div class="menu-actions"><button class="gg-button gg-medium menu-action" type="button" i18n="Select all" onclick="${(e) => this.onSelectAll(e)}">Select all</button> <button class="gg-button gg-medium menu-action" type="button" i18n="Reset" onclick="${(e) => this.onClearSelection(e)}">Reset</button><div class="${this.hasShortcutsConfigured() ? 'shortcut-title' : 'hidden'}"><span i18n="Shortcut">Shortcut</span></div></div></div><div class="menu-list">${this.getAllCategoriesFlattened().map((entry) => uHtml ` <label class="category-row"><input type="checkbox" value="${entry.key}" class="gg-checkbox" .checked="${this.isCategorySelected(entry)}" onchange="${(e) => this.onCategoryToggle(entry, e)}"> <span class="category-label text-ellipsis" title="${entry.example ? `${entry.label} (${entry.example})` : entry.label}"><span i18n="${entry.label}">${entry.label}</span> ${entry.example ? uHtml ` <span class="category-example">(<span i18n="${entry.example}">${entry.example}</span>)</span> ` : ''} </span><span class="shortcut">${this.getShortcutForCategory(entry)}</span></label> `)}</div>` : ''} ${this.isShortcutsOpen() ? uHtml `<div class="menu-header shortcut-header" i18n="Type or select a shortcut from the list to quickly filter search results.">Type or select a shortcut from the list to quickly filter search results.</div><div id="shortcut-list" class="menu-list">${this.getShortcutEntries().map((shEntry) => uHtml ` <button type="button" class="shortcut-row" data-shortcut="${shEntry.shortcut}" onkeydown="${(e) => this.onShortcutListDown(e)}" onclick="${() => this.onShortcutClick(shEntry.shortcut)}"><span class="shortcut">${this.currentPrefixSymbol}${shEntry.shortcut}</span> <span class="text-ellipsis">${shEntry.categoriesList}</span></button> `)} ` : ''}</div></div>` : ''}</div>
|
|
22
22
|
${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
23
23
|
};
|
|
24
24
|
enabled = false;
|
|
@@ -27,6 +27,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
27
27
|
categories = {};
|
|
28
28
|
availableShortcuts = {};
|
|
29
29
|
selectedCategories = new Map();
|
|
30
|
+
filterExamples = {};
|
|
30
31
|
fsmState = 'Idle';
|
|
31
32
|
focusedShortcutIndex = -1;
|
|
32
33
|
numberOfChipsToShow = 1;
|
|
@@ -54,6 +55,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
54
55
|
this.prefixSymbols = searchConfig?.filterShortcutPrefix ?? ['#'];
|
|
55
56
|
this.currentPrefixSymbol = this.prefixSymbols[0];
|
|
56
57
|
this.availableShortcuts = searchConfig?.filterShortcuts ?? {};
|
|
58
|
+
this.filterExamples = searchConfig?.filterExamples ?? {};
|
|
57
59
|
this.sanitizeShortcuts();
|
|
58
60
|
this.refreshRender();
|
|
59
61
|
}
|
|
@@ -192,7 +194,8 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
192
194
|
key: `${provider}-${category}`,
|
|
193
195
|
provider,
|
|
194
196
|
category: category,
|
|
195
|
-
label: this.context.searchManager.getI18nKeyForCategory(provider, category)
|
|
197
|
+
label: this.context.searchManager.getI18nKeyForCategory(provider, category),
|
|
198
|
+
example: this.filterExamples[category]
|
|
196
199
|
};
|
|
197
200
|
}
|
|
198
201
|
categoryEntriesToSearchCategories() {
|
|
@@ -25,7 +25,7 @@ declare class ThemeComponent extends GirafeHTMLElement {
|
|
|
25
25
|
onThemeChanged(theme: ThemeLayer | CustomTheme): void;
|
|
26
26
|
isThemeActive(theme: ThemeLayer | CustomTheme): boolean;
|
|
27
27
|
isThemeFavorite(theme: ThemeLayer | CustomTheme): boolean;
|
|
28
|
-
onThemeFavoriteChanged(theme: ThemeLayer | CustomTheme, e: Event): void
|
|
28
|
+
onThemeFavoriteChanged(theme: ThemeLayer | CustomTheme, e: Event): Promise<void>;
|
|
29
29
|
isThemeTypeActive(themeType: ThemeType): boolean;
|
|
30
30
|
isCustomTheme(theme: ThemeLayer | CustomTheme): theme is CustomTheme;
|
|
31
31
|
onCustomThemeChanged(customTheme: CustomTheme): void;
|
|
@@ -117,10 +117,10 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
117
117
|
isThemeFavorite(theme) {
|
|
118
118
|
return this.context.themeFavoritesManager.isThemeInFavorites(theme);
|
|
119
119
|
}
|
|
120
|
-
onThemeFavoriteChanged(theme, e) {
|
|
120
|
+
async onThemeFavoriteChanged(theme, e) {
|
|
121
121
|
e.preventDefault();
|
|
122
122
|
e.stopPropagation();
|
|
123
|
-
this.context.themeFavoritesManager.addOrRemoveThemeFromFavorites(theme);
|
|
123
|
+
await this.context.themeFavoritesManager.addOrRemoveThemeFromFavorites(theme);
|
|
124
124
|
this.render();
|
|
125
125
|
}
|
|
126
126
|
isThemeTypeActive(themeType) {
|
|
@@ -136,7 +136,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
136
136
|
async onAddCustomTheme() {
|
|
137
137
|
const themeName = await window.gPrompt('Enter a name for your custom theme', 'Create custom theme', 'Enter a name...');
|
|
138
138
|
if (themeName !== false && themeName.trim().length > 0) {
|
|
139
|
-
this.context.customThemesManager.addTheme(themeName, this.state.layers.layersList);
|
|
139
|
+
await this.context.customThemesManager.addTheme(themeName, this.state.layers.layersList);
|
|
140
140
|
this.render();
|
|
141
141
|
}
|
|
142
142
|
}
|
|
@@ -144,7 +144,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
144
144
|
e.stopPropagation();
|
|
145
145
|
const confirm = await window.gConfirm('Do you want to delete this theme?', 'Delete Theme');
|
|
146
146
|
if (confirm) {
|
|
147
|
-
this.context.customThemesManager.deleteTheme(customTheme);
|
|
147
|
+
await this.context.customThemesManager.deleteTheme(customTheme);
|
|
148
148
|
this.render();
|
|
149
149
|
}
|
|
150
150
|
}
|
|
@@ -59,7 +59,7 @@ export default class UserPreferencesComponent extends GirafeHTMLElement implemen
|
|
|
59
59
|
/**
|
|
60
60
|
Update state and local storage with new value
|
|
61
61
|
*/
|
|
62
|
-
changePreference(preferenceKey: string, newValue: unknown): void
|
|
62
|
+
changePreference(preferenceKey: string, newValue: unknown): Promise<void>;
|
|
63
63
|
/**
|
|
64
64
|
Update the config object with the new value
|
|
65
65
|
*/
|
|
@@ -272,12 +272,12 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
272
272
|
/**
|
|
273
273
|
Update state and local storage with new value
|
|
274
274
|
*/
|
|
275
|
-
changePreference(preferenceKey, newValue) {
|
|
275
|
+
async changePreference(preferenceKey, newValue) {
|
|
276
276
|
if (this.preferences[preferenceKey]) {
|
|
277
277
|
this.preferences[preferenceKey].currentValue = newValue;
|
|
278
278
|
this.updatePreferenceInConfig(preferenceKey);
|
|
279
279
|
this.updatePreferenceInState(preferenceKey);
|
|
280
|
-
this.updatePreferenceInStorage(preferenceKey);
|
|
280
|
+
await this.updatePreferenceInStorage(preferenceKey);
|
|
281
281
|
this.refreshRender();
|
|
282
282
|
}
|
|
283
283
|
}
|
|
@@ -300,10 +300,10 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
300
300
|
/**
|
|
301
301
|
Save the user preference as a config override in user data storage
|
|
302
302
|
*/
|
|
303
|
-
updatePreferenceInStorage(preferenceKey) {
|
|
303
|
+
async updatePreferenceInStorage(preferenceKey) {
|
|
304
304
|
const preference = this.preferences[preferenceKey];
|
|
305
305
|
// Values are saved under 'configOverrides' in the same structure as in the config
|
|
306
|
-
this.context.userDataManager.saveUserData(`${this.storagePath}.${preference.configPath}`, preference.currentValue);
|
|
306
|
+
await this.context.userDataManager.saveUserData(`${this.storagePath}.${preference.configPath}`, preference.currentValue);
|
|
307
307
|
}
|
|
308
308
|
/**
|
|
309
309
|
* Reset user preferences back to defaults. This will delete the configOverrides object in storage and set the
|
|
@@ -312,11 +312,11 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
|
|
|
312
312
|
async onResetAll() {
|
|
313
313
|
const confirm = await window.gConfirm('Reset user preferences back to default values?', 'Reset preferences');
|
|
314
314
|
if (confirm) {
|
|
315
|
-
this.resetAll();
|
|
315
|
+
await this.resetAll();
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
|
-
resetAll() {
|
|
319
|
-
this.context.userDataManager.deleteUserData(this.storagePath);
|
|
318
|
+
async resetAll() {
|
|
319
|
+
await this.context.userDataManager.deleteUserData(this.storagePath);
|
|
320
320
|
for (const preferenceKey in this.preferences) {
|
|
321
321
|
this.preferences[preferenceKey].currentValue = this.context.configManager.getDefaultConfigValue(this.preferences[preferenceKey].configPath);
|
|
322
322
|
this.updatePreferenceInState(preferenceKey);
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.2.0-dev.
|
|
1
|
+
{"version":"1.2.0-dev.2889467567", "build":"2889467567", "date":"28/09/2026"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import GirafeSingleton from '../../base/GirafeSingleton.js';
|
|
2
2
|
export default class ApplicationLifeCycleManager extends GirafeSingleton {
|
|
3
3
|
private get state();
|
|
4
|
-
initializeSingleton(): void
|
|
4
|
+
initializeSingleton(): Promise<void>;
|
|
5
5
|
private log;
|
|
6
6
|
/**
|
|
7
7
|
* For the application to be ready to load the themes and to deserialize the shared state or the session,
|
|
@@ -4,7 +4,7 @@ export default class ApplicationLifeCycleManager extends GirafeSingleton {
|
|
|
4
4
|
get state() {
|
|
5
5
|
return this.context.stateManager.state;
|
|
6
6
|
}
|
|
7
|
-
initializeSingleton() {
|
|
7
|
+
async initializeSingleton() {
|
|
8
8
|
this.context.stateManager.subscribe('themes.isLoaded', (_, isThemesLoaded) => {
|
|
9
9
|
this.log(isThemesLoaded, 'Themes are loaded');
|
|
10
10
|
this.checkApplicationReady();
|
|
@@ -60,10 +60,10 @@ export default class AbstractConnectManager {
|
|
|
60
60
|
return url.toString();
|
|
61
61
|
}
|
|
62
62
|
loadFromLocalStorage(path) {
|
|
63
|
-
return this.context.userDataManager.
|
|
63
|
+
return this.context.userDataManager.getFromLocalStorage(`${this.storagePath}.${path}`) ?? '';
|
|
64
64
|
}
|
|
65
65
|
saveToLocalStorage(path, value) {
|
|
66
|
-
|
|
66
|
+
this.context.userDataManager.saveToLocalStorage(`${this.storagePath}.${path}`, value);
|
|
67
67
|
}
|
|
68
68
|
resetUrl() {
|
|
69
69
|
const url = new URL(this.context.urlManager.getBaseUrlPath());
|
|
@@ -6,7 +6,7 @@ export default class AuthManager extends GirafeSingleton {
|
|
|
6
6
|
private readonly gmfManager;
|
|
7
7
|
private get state();
|
|
8
8
|
constructor(context: IGirafeContext);
|
|
9
|
-
initializeSingleton(): void
|
|
9
|
+
initializeSingleton(): Promise<void>;
|
|
10
10
|
initialize(sw: ServiceWorker | null): Promise<void>;
|
|
11
11
|
private initializeOAuth;
|
|
12
12
|
private initializeGmfAuth;
|
|
@@ -15,7 +15,7 @@ export default class AuthManager extends GirafeSingleton {
|
|
|
15
15
|
super(context);
|
|
16
16
|
this.gmfManager = new GMFManager(this.context);
|
|
17
17
|
}
|
|
18
|
-
initializeSingleton() {
|
|
18
|
+
async initializeSingleton() {
|
|
19
19
|
this.context.stateManager.subscribe('oauth.status', () => this.loginStateChanged());
|
|
20
20
|
this.context.stateManager.subscribe('oauth.tokens', () => this.tokensChanged());
|
|
21
21
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import GirafeSingleton from '../../base/GirafeSingleton.js';
|
|
2
2
|
declare class PluginManager extends GirafeSingleton {
|
|
3
|
-
initializeSingleton(): void
|
|
3
|
+
initializeSingleton(): Promise<void>;
|
|
4
4
|
filterPlugins(dom: DocumentFragment | Document): void;
|
|
5
5
|
private filterPluginFromConfig;
|
|
6
6
|
private filterPlugin;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
import GirafeSingleton from '../../base/GirafeSingleton.js';
|
|
3
3
|
class PluginManager extends GirafeSingleton {
|
|
4
|
-
initializeSingleton() {
|
|
4
|
+
async initializeSingleton() {
|
|
5
5
|
this.context.stateManager.subscribe('oauth.userInfo', () => this.filterPlugins(document));
|
|
6
6
|
this.filterPlugins(document);
|
|
7
7
|
}
|