@equinor/roma-framework 3.0.0 → 4.0.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 (46) hide show
  1. package/cypress.mjs +3 -112
  2. package/dev-portal/lib/api/ms-graph/api/group/find-group.d.ts +2 -0
  3. package/dev-portal/lib/api/ms-graph/api/group/get-groups-by-ids.d.ts +2 -0
  4. package/dev-portal/lib/api/ms-graph/api/user/get-user-by-id.d.ts +9 -0
  5. package/dev-portal/lib/api/ms-graph/api/user/search.d.ts +4 -0
  6. package/dev-portal/lib/api/ms-graph/index.d.ts +4 -0
  7. package/dev-portal/lib/api/roma/api/app-controller/app-controller.d.ts +10 -10
  8. package/dev-portal/lib/api/roma/api/category-controller/category-controller.d.ts +8 -8
  9. package/dev-portal/lib/api/roma/api/environment-controller/environment-controller.d.ts +2 -2
  10. package/dev-portal/lib/api/roma/api/feedback-controller/feedback-controller.d.ts +4 -4
  11. package/dev-portal/lib/api/roma/api/roma-configuration-controller/roma-configuration-controller.d.ts +14 -14
  12. package/dev-portal/lib/api/roma/api/server-side-event-controller/server-side-event-controller.d.ts +2 -2
  13. package/dev-portal/lib/api/roma/api/service-controller/service-controller.d.ts +8 -8
  14. package/dev-portal/lib/api/roma/api/setting-controller/setting-controller.d.ts +20 -20
  15. package/dev-portal/lib/app-provider.d.ts +7 -1
  16. package/dev-portal/lib/dev-portal/ErrorViewer.d.ts +2 -2
  17. package/dev-portal/lib/dev-portal/PortalStyles.d.ts +291 -15
  18. package/dev-portal/lib/dev-portal/config/AppClient.d.ts +62 -2
  19. package/dev-portal/lib/eds-event-provider.d.ts +2 -1
  20. package/dev-portal/lib/make-component.d.ts +1 -1
  21. package/dev-portal/lib/test-utils/roma-cypress-wrapper.d.ts +2 -2
  22. package/dev-portal/package.json +1 -1
  23. package/dev-portal/roma-framework.umd.js +4066 -3749
  24. package/lib/api/ms-graph/api/group/find-group.d.ts +2 -0
  25. package/lib/api/ms-graph/api/group/get-groups-by-ids.d.ts +2 -0
  26. package/lib/api/ms-graph/api/user/get-user-by-id.d.ts +9 -0
  27. package/lib/api/ms-graph/api/user/search.d.ts +4 -0
  28. package/lib/api/ms-graph/index.d.ts +4 -0
  29. package/lib/api/roma/api/app-controller/app-controller.d.ts +10 -10
  30. package/lib/api/roma/api/category-controller/category-controller.d.ts +8 -8
  31. package/lib/api/roma/api/environment-controller/environment-controller.d.ts +2 -2
  32. package/lib/api/roma/api/feedback-controller/feedback-controller.d.ts +4 -4
  33. package/lib/api/roma/api/roma-configuration-controller/roma-configuration-controller.d.ts +14 -14
  34. package/lib/api/roma/api/server-side-event-controller/server-side-event-controller.d.ts +2 -2
  35. package/lib/api/roma/api/service-controller/service-controller.d.ts +8 -8
  36. package/lib/api/roma/api/setting-controller/setting-controller.d.ts +20 -20
  37. package/lib/app-provider.d.ts +7 -1
  38. package/lib/dev-portal/ErrorViewer.d.ts +2 -2
  39. package/lib/dev-portal/PortalStyles.d.ts +291 -15
  40. package/lib/dev-portal/config/AppClient.d.ts +62 -2
  41. package/lib/eds-event-provider.d.ts +2 -1
  42. package/lib/make-component.d.ts +1 -1
  43. package/lib/test-utils/roma-cypress-wrapper.d.ts +2 -2
  44. package/package.json +1 -1
  45. package/roma-framework.mjs +338 -20
  46. package/{router-DDzmmkip.mjs → router-JkkLp8wN.mjs} +3 -3
@@ -5,6 +5,7 @@ import { FetchRequest } from '@equinor/fusion-framework-module-http/client';
5
5
  export declare class CustomAppClient implements IAppClient {
6
6
  #private;
7
7
  private client;
8
+ private graphClient;
8
9
  getAppConfig({}: {
9
10
  appKey: string;
10
11
  tag?: string;
@@ -12,8 +13,67 @@ export declare class CustomAppClient implements IAppClient {
12
13
  getAppManifest({ appKey }: {
13
14
  appKey: string;
14
15
  }): Observable<AppManifest>;
15
- getAppManifests(): Observable<never[] | AppManifest[]>;
16
+ getAppManifests(): Observable<never[] | {
17
+ hasAccess: boolean | undefined;
18
+ key: string;
19
+ appKey: string;
20
+ name: string;
21
+ displayName: string;
22
+ description: string;
23
+ type: "template" | "standalone" | "report" | "launcher";
24
+ isPinned?: boolean | null | undefined;
25
+ templateSource?: string | null | undefined;
26
+ category?: ({
27
+ id: string;
28
+ name: string;
29
+ displayName: string;
30
+ color: string;
31
+ defaultIcon: string;
32
+ sortOrder: number;
33
+ } & import('../../api/roma').CategoryDto) | undefined;
34
+ visualization?: {
35
+ color?: string | null | undefined;
36
+ icon?: string | null | undefined;
37
+ sortOrder: number;
38
+ } | null | undefined;
39
+ keywords?: string[] | null | undefined;
40
+ admins?: {
41
+ id: string;
42
+ azureUniqueId: string;
43
+ displayName: string;
44
+ mail?: string | null | undefined;
45
+ upn?: string | null | undefined;
46
+ accountType: string;
47
+ accountClassification?: string | null | undefined;
48
+ isExpired?: boolean | null | undefined;
49
+ }[] | null | undefined;
50
+ owners?: {
51
+ id: string;
52
+ azureUniqueId: string;
53
+ displayName: string;
54
+ mail?: string | null | undefined;
55
+ upn?: string | null | undefined;
56
+ accountType: string;
57
+ accountClassification?: string | null | undefined;
58
+ isExpired?: boolean | null | undefined;
59
+ }[] | null | undefined;
60
+ build?: import('@equinor/fusion-framework-module-app').AppBuildManifest | null | undefined;
61
+ accentColor?: string;
62
+ categoryId: string;
63
+ entry: string;
64
+ hide?: boolean;
65
+ icon?: string;
66
+ order?: number;
67
+ publishedDate?: string;
68
+ shortName: string;
69
+ tags?: string[];
70
+ version: import('../../api/roma').VersionDto;
71
+ config?: {
72
+ groups: Array<string>;
73
+ };
74
+ }[]>;
16
75
  getAppSettings(): Observable<{}>;
17
76
  updateAppSettings(): Observable<{}>;
18
- constructor(client: IHttpClient<FetchRequest, Response>);
77
+ constructor(client: IHttpClient<FetchRequest, Response>, graphClient: IHttpClient<FetchRequest, Response>);
78
+ [Symbol.dispose](): void;
19
79
  }
@@ -1,6 +1,7 @@
1
1
  import { IEventModuleProvider } from '@equinor/fusion-framework-module-event';
2
2
  import { ReactNode } from 'react';
3
- export declare const EdsEventProvider: ({ event, children }: {
3
+ export declare const EdsEventProvider: ({ event, children, portalContainer, }: {
4
4
  event: IEventModuleProvider;
5
5
  children: ReactNode;
6
+ portalContainer: string;
6
7
  }) => import("react/jsx-runtime").JSX.Element;
@@ -8,5 +8,5 @@ export type RomaComponentRenderArgs = FusionComponentRenderArgs & {
8
8
  query?: QueryClient;
9
9
  };
10
10
  export type RomaAppModuleInitiator<TModules extends Array<AnyModule> | unknown = unknown, TRef extends Fusion = Fusion, TEnv = AppEnv> = AppModuleInitiator<TModules, TRef, TEnv>;
11
- export declare const makeComponent: <TModules extends Array<AnyModule>, TRef extends Fusion = Fusion<unknown>, TEnv extends AppEnv = AppEnv>(Component: React.ReactNode, args: RomaComponentRenderArgs, configure?: RomaAppModuleInitiator<TModules, TRef, TEnv>) => React.LazyExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
11
+ export declare const makeComponent: <TModules extends Array<AnyModule>, TRef extends Fusion = Fusion, TEnv extends AppEnv = AppEnv>(Component: React.ReactNode, args: RomaComponentRenderArgs, configure?: RomaAppModuleInitiator<TModules, TRef, TEnv>) => React.LazyExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
12
12
  export declare const withStyleIsolation: (children: ReactNode, args: RomaComponentRenderArgs) => React.LazyExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
@@ -1,10 +1,10 @@
1
1
  import { ReactNode } from 'react';
2
- import { MountOptions } from 'cypress/react18';
2
+ import { MountOptions } from 'cypress/react';
3
3
  import { ServerSentEvent } from '../../../../modules/sse/src/index.ts';
4
4
  type RomaMountOptions = MountOptions & {
5
5
  moduleConfig?: {
6
6
  events?: Array<ServerSentEvent>;
7
7
  };
8
8
  };
9
- export declare const mount: (component: ReactNode, options?: RomaMountOptions) => Cypress.Chainable<import('cypress/react18').MountReturn>;
9
+ export declare const mount: (component: ReactNode, options?: RomaMountOptions) => Cypress.Chainable<import('cypress/react').MountReturn>;
10
10
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/roma-framework",
3
- "version": "3.0.0",
3
+ "version": "4.0.0",
4
4
  "repository": "https://github.com/equinor/tops-roma",
5
5
  "types": "./index.d.ts",
6
6
  "private": false,
@@ -13,18 +13,18 @@ import * as React from "react";
13
13
  import { useState, useEffect, lazy, useRef, createContext, useContext, useMemo } from "react";
14
14
  import { ModuleProvider } from "@equinor/fusion-framework-react-module";
15
15
  import styled, { StyleSheetManager, keyframes } from "styled-components";
16
- import { EdsProvider, StarProgress, Typography, Card, Button, TopBar, SideSheet, Menu, Tooltip, Icon } from "@equinor/eds-core-react";
17
- import { E as EmptyError, o as operate, c as createOperatorSubscriber, i as innerFrom, a as identity, b as isFunction, I as IntlProvider, d as invariant, j as joinPaths, g as getPathContributingMatches, r as resolveTo, w as warning, s as stripBasename, e as createPath, B as BehaviorSubject, f as firstValueFrom, h as getDefaultExportFromCjs, k as of, l as from } from "./router-DDzmmkip.mjs";
16
+ import { EdsProvider, StarProgress, Typography, Card, Button, TopBar, Chip, SideSheet, Menu, Tooltip, Icon, List } from "@equinor/eds-core-react";
17
+ import { E as EmptyError, o as operate, c as createOperatorSubscriber, i as innerFrom, a as identity, b as isFunction, I as IntlProvider, d as invariant, j as joinPaths, g as getPathContributingMatches, r as resolveTo, w as warning, s as stripBasename, e as createPath, B as BehaviorSubject, f as firstValueFrom, h as getDefaultExportFromCjs, k as of, l as from } from "./router-JkkLp8wN.mjs";
18
18
  import { QueryClient, QueryClientProvider, useQueryClient, useQuery, useMutation } from "@tanstack/react-query";
19
19
  import { useCurrentApp, useApps as useApps$1 } from "@equinor/fusion-framework-react/app";
20
20
  import { App } from "@equinor/fusion-framework-module-app/app";
21
+ import { tokens } from "@equinor/eds-tokens";
21
22
  import { comment_more, accessible, account_circle, help_outline } from "@equinor/eds-icons";
22
23
  import { enableAppModule } from "@equinor/fusion-framework-module-app";
23
24
  import { enableContext } from "@equinor/fusion-framework-module-context";
24
25
  import { enableNavigation } from "@equinor/fusion-framework-module-navigation";
25
26
  import { ModuleConfigBuilder } from "@equinor/fusion-framework-module";
26
27
  import { enableServiceDiscovery } from "@equinor/fusion-framework-module-service-discovery";
27
- import { tokens } from "@equinor/eds-tokens";
28
28
  import { useHttpClient } from "@equinor/fusion-framework-react-module-http";
29
29
  const createExtraScopePlugin = (scope) => {
30
30
  const plugin = (element, index, childEls) => {
@@ -162,18 +162,38 @@ function tap(observerOrNext, error, complete) {
162
162
  }));
163
163
  }) : identity;
164
164
  }
165
- const EdsEventProvider = ({ event, children }) => {
165
+ const EdsEventProvider = ({
166
+ event,
167
+ children,
168
+ portalContainer
169
+ }) => {
166
170
  const [density, setDensity] = useState(
167
171
  localStorage.getItem("roma__density") ?? "comfortable"
168
172
  );
169
173
  const evModule = useFramework().modules.event;
174
+ const [root, setRoot] = useState(null);
170
175
  useEffect(() => {
171
176
  const sub = evModule.event$.pipe(filter((e) => e.type === "onDensityChanged")).subscribe((e) => {
172
177
  setDensity(e.detail);
173
178
  });
174
179
  return () => sub.unsubscribe();
175
180
  }, [event]);
176
- return /* @__PURE__ */ jsx(EdsProvider, { density, children });
181
+ useEffect(() => {
182
+ if (root) return;
183
+ const interval = setInterval(() => {
184
+ setRoot(document.querySelector(`#${portalContainer}`));
185
+ }, 250);
186
+ if (root) clearInterval(interval);
187
+ return () => clearInterval(interval);
188
+ }, [root, portalContainer]);
189
+ return /* @__PURE__ */ jsx(
190
+ EdsProvider,
191
+ {
192
+ density,
193
+ rootElement: document.querySelector(`#${portalContainer}`),
194
+ children
195
+ }
196
+ );
177
197
  };
178
198
  const makeComponent = (Component, args, configure2) => lazy(async () => {
179
199
  const init = configureModules(configure2);
@@ -187,7 +207,14 @@ const makeComponent = (Component, args, configure2) => lazy(async () => {
187
207
  });
188
208
  const queryClient = args.query ?? new QueryClient();
189
209
  return {
190
- default: () => /* @__PURE__ */ jsx(FrameworkProvider, { value: fusion, children: /* @__PURE__ */ jsx(IntlProvider, { locale: navigator.language, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(StyleProvider, { scope: `roma-${appKey}`, children: /* @__PURE__ */ jsx(EdsEventProvider, { event: modules.event, children: /* @__PURE__ */ jsx(ModuleProvider, { value: modules, children: Component }) }) }) }) }) })
210
+ default: () => /* @__PURE__ */ jsx(FrameworkProvider, { value: fusion, children: /* @__PURE__ */ jsx(IntlProvider, { locale: navigator.language, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(StyleProvider, { scope: `roma-${appKey}`, children: /* @__PURE__ */ jsx(
211
+ EdsEventProvider,
212
+ {
213
+ portalContainer: `roma-${appKey}`,
214
+ event: modules.event,
215
+ children: /* @__PURE__ */ jsx(ModuleProvider, { value: modules, children: Component })
216
+ }
217
+ ) }) }) }) })
191
218
  };
192
219
  });
193
220
  const withStyleIsolation = (children, args) => lazy(async () => {
@@ -1111,6 +1138,12 @@ const Styled = {
1111
1138
  margin-left: 1.5rem;
1112
1139
  `
1113
1140
  };
1141
+ const EnvChip = styled(Chip)`
1142
+ background-color: ${tokens.colors.interactive.primary__resting.rgba};
1143
+ color: ${tokens.colors.text.static_icons__primary_white.hex};
1144
+ margin-left: 16px;
1145
+ padding: 0 32px;
1146
+ `;
1114
1147
  const StyledSideSheet = styled(SideSheet)`
1115
1148
  position: fixed;
1116
1149
  right: 0;
@@ -1283,7 +1316,18 @@ const HeaderMenu = ({ menuState }) => {
1283
1316
  ) })
1284
1317
  ] });
1285
1318
  };
1319
+ const getEnvironment = async () => {
1320
+ const request = await fetch("/_discovery/environments/current");
1321
+ const environment = await request.json();
1322
+ const isProd = environment.type === "Production";
1323
+ return {
1324
+ name: environment.type,
1325
+ environmentName: environment.environmentName,
1326
+ isProd
1327
+ };
1328
+ };
1286
1329
  const Header = () => {
1330
+ var _a;
1287
1331
  const [a11yOpen, setA11yOpen] = useState(false);
1288
1332
  const [userMenuOpen, setUserMenuOpen] = useState(false);
1289
1333
  const [activityLogOpen, setActivityLogOpen] = useState(false);
@@ -1296,15 +1340,31 @@ const Header = () => {
1296
1340
  activityLogOpen,
1297
1341
  setActivityLogOpen
1298
1342
  };
1343
+ const [env, setEnv] = useState(null);
1344
+ useEffect(() => {
1345
+ getEnvironment().then((info) => {
1346
+ setEnv(info);
1347
+ });
1348
+ }, []);
1299
1349
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1300
- /* @__PURE__ */ jsxs(TopBarFadeIn, { id: "cli-top-bar", children: [
1301
- /* @__PURE__ */ jsx(TopBar.Header, { children: /* @__PURE__ */ jsxs(Styled.Title, { children: [
1302
- /* @__PURE__ */ jsx(Icon, { color: "#eb0037", data: logoIcon, viewBox: "0 0 42 48" }),
1303
- /* @__PURE__ */ jsx("span", { children: "Roma" })
1304
- ] }) }),
1305
- /* @__PURE__ */ jsx(TopBar.CustomContent, {}),
1306
- /* @__PURE__ */ jsx(TopBar.Actions, { children: /* @__PURE__ */ jsx(HeaderMenu, { menuState: headerMenuState }) })
1307
- ] }),
1350
+ /* @__PURE__ */ jsxs(
1351
+ TopBarFadeIn,
1352
+ {
1353
+ id: "cli-top-bar",
1354
+ style: !(env == null ? void 0 : env.isProd) ? {
1355
+ backgroundColor: tokens.colors.interactive.warning__highlight.rgba
1356
+ } : void 0,
1357
+ children: [
1358
+ /* @__PURE__ */ jsx(TopBar.Header, { children: /* @__PURE__ */ jsxs(Styled.Title, { children: [
1359
+ /* @__PURE__ */ jsx(Icon, { color: "#eb0037", data: logoIcon, viewBox: "0 0 42 48" }),
1360
+ /* @__PURE__ */ jsx("span", { children: "Roma" }),
1361
+ env && !(env == null ? void 0 : env.isProd) && /* @__PURE__ */ jsx(EnvChip, { children: (_a = env == null ? void 0 : env.environmentName) == null ? void 0 : _a.split(" ")[0].toUpperCase() })
1362
+ ] }) }),
1363
+ /* @__PURE__ */ jsx(TopBar.CustomContent, {}),
1364
+ /* @__PURE__ */ jsx(TopBar.Actions, { children: /* @__PURE__ */ jsx(HeaderMenu, { menuState: headerMenuState }) })
1365
+ ]
1366
+ }
1367
+ ),
1308
1368
  /* @__PURE__ */ jsx(SideSheets, { apps: allApps, menuState: headerMenuState })
1309
1369
  ] });
1310
1370
  };
@@ -3863,9 +3923,10 @@ const rootSchema = create$3({
3863
3923
  })
3864
3924
  });
3865
3925
  class CustomAppClient {
3866
- constructor(client) {
3926
+ constructor(client, graphClient) {
3867
3927
  __privateAdd(this, _manifests, []);
3868
3928
  this.client = client;
3929
+ this.graphClient = graphClient;
3869
3930
  }
3870
3931
  // eslint-disable-next-line no-empty-pattern
3871
3932
  getAppConfig({}) {
@@ -3884,7 +3945,75 @@ class CustomAppClient {
3884
3945
  getAppManifests() {
3885
3946
  return this.client.fetch$(`/api/apps`).pipe(
3886
3947
  switchMap(
3887
- (r) => from(r.json())
3948
+ (r) => from(r.json()).pipe(
3949
+ catchError(() => {
3950
+ let message = "Error fetching app manifests: ";
3951
+ if (r.status === 403 || r.status === 401) {
3952
+ message = /* @__PURE__ */ jsxs("div", { children: [
3953
+ /* @__PURE__ */ jsx(Typography, { children: "You are not authorized to view this page." }),
3954
+ /* @__PURE__ */ jsx("br", {}),
3955
+ " ",
3956
+ /* @__PURE__ */ jsx(Typography, { variant: "body_short", children: "Please apply for the relevant roles in Access IT:" }),
3957
+ /* @__PURE__ */ jsx("br", {}),
3958
+ /* @__PURE__ */ jsxs(List, { children: [
3959
+ /* @__PURE__ */ jsx(List.Item, { children: /* @__PURE__ */ jsx(
3960
+ Tooltip,
3961
+ {
3962
+ title: "Will also grant access to Roma Workbench",
3963
+ children: /* @__PURE__ */ jsx(
3964
+ Typography,
3965
+ {
3966
+ variant: "body_short_link",
3967
+ as: "a",
3968
+ href: "https://accessit.equinor.com/Search/Search?term=COMMERCIAL+OPERATOR+LIQUIDS+ACCESS+CONTROL",
3969
+ children: "Cargo Operations - Commercial Operator"
3970
+ }
3971
+ )
3972
+ }
3973
+ ) }),
3974
+ /* @__PURE__ */ jsx(List.Item, { children: /* @__PURE__ */ jsx(
3975
+ Tooltip,
3976
+ {
3977
+ title: "Apply for the access & sales office relevant for your role",
3978
+ children: /* @__PURE__ */ jsx(
3979
+ Typography,
3980
+ {
3981
+ variant: "body_short_link",
3982
+ as: "a",
3983
+ href: "https://accessit.equinor.com/Search/Search?term=LIQUIDS+ACCESS+CONTROL",
3984
+ children: "Trading systems"
3985
+ }
3986
+ )
3987
+ }
3988
+ ) }),
3989
+ /* @__PURE__ */ jsx(List.Item, { children: /* @__PURE__ */ jsx(
3990
+ Tooltip,
3991
+ {
3992
+ title: "Autogranted via cargo / trading roles",
3993
+ children: /* @__PURE__ */ jsx(
3994
+ Typography,
3995
+ {
3996
+ variant: "body_short_link",
3997
+ as: "a",
3998
+ href: "https://accessit.equinor.com/Search/Search?term=User+%28TOPS+ROMA%29",
3999
+ children: "Roma Workbench - TOPS ROMA User"
4000
+ }
4001
+ )
4002
+ }
4003
+ ) })
4004
+ ] })
4005
+ ] });
4006
+ } else {
4007
+ message = `${message} ${r.statusText}`;
4008
+ }
4009
+ window.Fusion.modules.event.dispatchEvent("workbenchInitError", {
4010
+ detail: {
4011
+ message
4012
+ }
4013
+ });
4014
+ return of([]);
4015
+ })
4016
+ )
3888
4017
  ),
3889
4018
  map(
3890
4019
  (v) => v.map((vv) => {
@@ -3898,6 +4027,7 @@ class CustomAppClient {
3898
4027
  return {
3899
4028
  ...vv,
3900
4029
  entry: pathname,
4030
+ config: vv.config ?? { groups: null, admins: null, roles: null },
3901
4031
  keywords: vv.keywords ?? vv.tags,
3902
4032
  appKey: vv.appKey ?? vv.key,
3903
4033
  name: vv.displayName ?? vv.name,
@@ -3913,6 +4043,20 @@ class CustomAppClient {
3913
4043
  };
3914
4044
  })
3915
4045
  ),
4046
+ switchMap((apps) => {
4047
+ return this.graphClient.fetch(`v1.0/me/memberOf?$select=id`).then((r) => r.json()).then((res) => {
4048
+ const list = res.value.map(
4049
+ (v) => v.id
4050
+ );
4051
+ return apps.map((app) => {
4052
+ var _a, _b;
4053
+ return {
4054
+ ...app,
4055
+ hasAccess: (((_a = app.config) == null ? void 0 : _a.groups) ?? []).length === 0 || ((_b = app.config) == null ? void 0 : _b.groups.some((g) => list.includes(g)))
4056
+ };
4057
+ });
4058
+ });
4059
+ }),
3916
4060
  tap((v) => __privateSet(this, _manifests, v)),
3917
4061
  catchError((err) => {
3918
4062
  console.error("Error fetching app manifests", err);
@@ -3928,6 +4072,8 @@ class CustomAppClient {
3928
4072
  console.log("updateAppSettings");
3929
4073
  return of({});
3930
4074
  }
4075
+ [Symbol.dispose]() {
4076
+ }
3931
4077
  }
3932
4078
  _manifests = new WeakMap();
3933
4079
  class ServiceDiscoveryClient {
@@ -3956,14 +4102,19 @@ class ServiceDiscoveryClient {
3956
4102
  }
3957
4103
  }
3958
4104
  const configure = async (config) => {
3959
- var _a;
4105
+ var _a, _b;
3960
4106
  const request = await fetch("/_discovery/environments/current");
3961
4107
  const environment = await request.json();
3962
4108
  const services = environment.services;
3963
4109
  if (!services) {
3964
4110
  throw new Error(`ServiceDiscoveryMissingError: No services found`);
3965
4111
  }
3966
- const portalService = (_a = environment.services) == null ? void 0 : _a.find((v) => v.key === "portal");
4112
+ const portalService = (_a = environment.services) == null ? void 0 : _a.find(
4113
+ (v) => v.key === "portal"
4114
+ );
4115
+ const graphService = (_b = environment.services) == null ? void 0 : _b.find(
4116
+ (v) => v.key === "graph"
4117
+ );
3967
4118
  if (!portalService || !environment.frontendClientId) {
3968
4119
  const error = [];
3969
4120
  if (!portalService) error.push(`Missing service: "portal"`);
@@ -3988,8 +4139,15 @@ ${error.join("\n")}`);
3988
4139
  builder.setAssetUri(`/`);
3989
4140
  builder.setClient(async (client) => {
3990
4141
  const http = await client.requireInstance("http");
3991
- const httpClient = http.createClient(portalService);
3992
- return new CustomAppClient(httpClient);
4142
+ const httpClient = http.createClient({
4143
+ ...portalService,
4144
+ baseUri: portalService.uri ?? portalService.baseUri
4145
+ });
4146
+ const graphHttpClient = http.createClient({
4147
+ ...graphService,
4148
+ baseUri: (graphService == null ? void 0 : graphService.uri) ?? (graphService == null ? void 0 : graphService.baseUri)
4149
+ });
4150
+ return new CustomAppClient(httpClient, graphHttpClient);
3993
4151
  });
3994
4152
  });
3995
4153
  enableNavigation(config);
@@ -5028,6 +5186,70 @@ const useFindGroupMembers = (groupId, query) => {
5028
5186
  queryFn: () => findGroupMembers(client, groupId, query)
5029
5187
  });
5030
5188
  };
5189
+ const findGroup$1 = async (client, query) => {
5190
+ const headers = {
5191
+ ConsistencyLevel: "eventual"
5192
+ // Required to search by name
5193
+ };
5194
+ const params = new URLSearchParams();
5195
+ params.set("$count", "true");
5196
+ params.set("$orderby", "displayName");
5197
+ params.set("$select", "displayName,id");
5198
+ if (query) {
5199
+ params.set("$search", `"displayName:${query}"`);
5200
+ }
5201
+ const req = await client.fetch(`v1.0/groups?${params.toString()}`, {
5202
+ headers
5203
+ });
5204
+ if (req.status === 504) {
5205
+ throw new Error(`Application took to long to respond`);
5206
+ }
5207
+ const res = await req.json();
5208
+ if (req.status >= 400) {
5209
+ throw new Error(res.error.message);
5210
+ } else {
5211
+ return res;
5212
+ }
5213
+ };
5214
+ const useFindGroup = (query) => {
5215
+ const client = useHttpClient("graph");
5216
+ return useQuery({
5217
+ queryKey: ["graph", "group", "members", query],
5218
+ queryFn: () => findGroup$1(client, query),
5219
+ enabled: query.length > 2
5220
+ });
5221
+ };
5222
+ const findGroup = async (client, ids) => {
5223
+ const headers = {
5224
+ ConsistencyLevel: "eventual"
5225
+ // Required to search by name
5226
+ };
5227
+ const params = new URLSearchParams();
5228
+ params.set("$count", "true");
5229
+ params.set("$orderby", "displayName");
5230
+ params.set("$select", "displayName,id");
5231
+ params.set("$filter", `id in ('${ids.join("', '")}')`);
5232
+ const req = await client.fetch(`v1.0/groups?${params.toString()}`, {
5233
+ headers
5234
+ });
5235
+ if (req.status === 504) {
5236
+ throw new Error(`Application took to long to respond`);
5237
+ }
5238
+ const res = await req.json();
5239
+ if (req.status >= 400) {
5240
+ throw new Error(res.error.message);
5241
+ } else {
5242
+ return res;
5243
+ }
5244
+ };
5245
+ const useFindGroupById = (ids) => {
5246
+ const client = useHttpClient("graph");
5247
+ return useQuery({
5248
+ queryKey: ["graph", "group", "members", ids],
5249
+ queryFn: () => findGroup(client, ids),
5250
+ enabled: ids.length > 0
5251
+ });
5252
+ };
5031
5253
  const findUsersByMail = async (client, email, fields) => {
5032
5254
  const headers = {
5033
5255
  ConsistencyLevel: "eventual"
@@ -5068,6 +5290,97 @@ const useFindUsersByShortname = (shortnames, fields = ["displayName", "mail", "g
5068
5290
  const emails = (shortnames ?? []).map((name) => `${name}@equinor.com`);
5069
5291
  return useFindUsersByMail(emails, fields);
5070
5292
  };
5293
+ const searchUser = async (client, query) => {
5294
+ const headers = {
5295
+ ConsistencyLevel: "eventual"
5296
+ // Required to search by name
5297
+ };
5298
+ const params = new URLSearchParams();
5299
+ params.set("$orderby", "displayName");
5300
+ if (query) {
5301
+ params.set("$search", `"displayName:${query}" OR "mail:${query}"`);
5302
+ }
5303
+ const req = await client.fetch(`/v1.0/users?${params.toString()}`, {
5304
+ headers
5305
+ });
5306
+ if (req.status === 504) {
5307
+ throw new Error(`Application took to long to respond`);
5308
+ }
5309
+ const res = await req.json();
5310
+ if (req.status >= 400) {
5311
+ throw new Error(res.error.message);
5312
+ } else {
5313
+ return res;
5314
+ }
5315
+ };
5316
+ const searchServicePrincipal = async (client, query) => {
5317
+ const headers = {
5318
+ ConsistencyLevel: "eventual"
5319
+ // Required to search by name
5320
+ };
5321
+ const params = new URLSearchParams();
5322
+ params.set("$orderby", "displayName");
5323
+ params.set("$select", "id,appId,displayName");
5324
+ if (query) {
5325
+ params.set("$search", `"displayName:${query}"`);
5326
+ }
5327
+ const req = await client.fetch(
5328
+ `/v1.0/servicePrincipals?${params.toString()}`,
5329
+ {
5330
+ headers
5331
+ }
5332
+ );
5333
+ if (req.status === 504) {
5334
+ throw new Error(`Application took to long to respond`);
5335
+ }
5336
+ const res = await req.json();
5337
+ if (req.status >= 400) {
5338
+ throw new Error(res.error.message);
5339
+ } else {
5340
+ return res;
5341
+ }
5342
+ };
5343
+ const useFindUser = (query) => {
5344
+ const client = useHttpClient("graph");
5345
+ return useQuery({
5346
+ queryKey: ["graph", "group", "members", query],
5347
+ queryFn: async () => {
5348
+ const users = await searchUser(client, query);
5349
+ const servicePrincipals = await searchServicePrincipal(client, query);
5350
+ return {
5351
+ value: [...users.value ?? [], ...servicePrincipals.value ?? []]
5352
+ };
5353
+ },
5354
+ select: (data) => data ? data.value : [],
5355
+ enabled: query.length > 2
5356
+ });
5357
+ };
5358
+ const findUserById = async (client, id, fields) => {
5359
+ const headers = {
5360
+ ConsistencyLevel: "eventual"
5361
+ // Required to search by name
5362
+ };
5363
+ const req = await client.fetch(`v1.0/users/${id}`, {
5364
+ headers
5365
+ });
5366
+ if (req.status === 504) {
5367
+ throw new Error(`Application took to long to respond`);
5368
+ }
5369
+ const res = await req.json();
5370
+ if (req.status >= 400) {
5371
+ throw new Error(res.error.message);
5372
+ } else {
5373
+ return res;
5374
+ }
5375
+ };
5376
+ const useFindUserById = (id, fields = ["displayName", "mail", "givenName"]) => {
5377
+ const client = useHttpClient("graph");
5378
+ return useQuery({
5379
+ queryKey: ["graph", "user", "id", id],
5380
+ queryFn: () => findUserById(client, id),
5381
+ enabled: !!id
5382
+ });
5383
+ };
5071
5384
  const checkRomaApi = (queryKey) => {
5072
5385
  const first = (queryKey ?? []).at(0);
5073
5386
  if (typeof first === "string") {
@@ -5437,6 +5750,7 @@ export {
5437
5750
  StyleProvider,
5438
5751
  configure,
5439
5752
  createIDBPersister,
5753
+ findUserById,
5440
5754
  findUsersByMail,
5441
5755
  getGetAllAppsQueryKey,
5442
5756
  getGetAllCategoriesQueryKey,
@@ -5499,7 +5813,11 @@ export {
5499
5813
  useDeleteServiceByKey,
5500
5814
  useDeleteServiceByKeyHook,
5501
5815
  useDeleteServiceByKeyMutationOptions,
5816
+ useFindGroup,
5817
+ useFindGroupById,
5502
5818
  useFindGroupMembers,
5819
+ useFindUser,
5820
+ useFindUserById,
5503
5821
  useFindUsersByMail,
5504
5822
  useFindUsersByShortname,
5505
5823
  useGetAllApps,
@@ -68,8 +68,8 @@ function __generator(thisArg, body) {
68
68
  var _ = { label: 0, sent: function() {
69
69
  if (t[0] & 1) throw t[1];
70
70
  return t[1];
71
- }, trys: [], ops: [] }, f, y, t, g;
72
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
71
+ }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
72
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
73
73
  return this;
74
74
  }), g;
75
75
  function verb(n) {
@@ -176,7 +176,7 @@ function __await(v) {
176
176
  function __asyncGenerator(thisArg, _arguments, generator) {
177
177
  if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
178
178
  var g = generator.apply(thisArg, _arguments || []), i, q = [];
179
- return i = {}, verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function() {
179
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function() {
180
180
  return this;
181
181
  }, i;
182
182
  function awaitReturn(f) {