@igstack/app-catalog-frontend-core 2.0.4 → 3.0.0-alpha-20260917212201

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 (26) hide show
  1. package/dist/esm/__tests__/modules/appCatalog/utils/areaGrouping.test.d.ts +1 -0
  2. package/dist/esm/__tests__/modules/pwa/PwaAutoUpdateController.test.d.ts +1 -0
  3. package/dist/esm/index.d.ts +2 -1
  4. package/dist/esm/index.js +2 -0
  5. package/dist/esm/index.js.map +1 -1
  6. package/dist/esm/modules/appCatalog/ui/catalog/AppCatalogGrid.d.ts +6 -3
  7. package/dist/esm/modules/appCatalog/ui/catalog/AppCatalogGrid.js +112 -32
  8. package/dist/esm/modules/appCatalog/ui/catalog/AppCatalogGrid.js.map +1 -1
  9. package/dist/esm/modules/appCatalog/ui/pages/AppCatalogPage.js +0 -5
  10. package/dist/esm/modules/appCatalog/ui/pages/AppCatalogPage.js.map +1 -1
  11. package/dist/esm/modules/appCatalog/utils/areaGrouping.d.ts +22 -0
  12. package/dist/esm/modules/appCatalog/utils/areaGrouping.js +46 -0
  13. package/dist/esm/modules/appCatalog/utils/areaGrouping.js.map +1 -0
  14. package/dist/esm/modules/pwa/PwaAutoUpdateController.d.ts +8 -0
  15. package/dist/esm/modules/pwa/PwaAutoUpdateController.js +15 -1
  16. package/dist/esm/modules/pwa/PwaAutoUpdateController.js.map +1 -1
  17. package/dist/esm/types/uiSettings.d.ts +28 -0
  18. package/package.json +4 -4
  19. package/src/__tests__/modules/appCatalog/utils/areaGrouping.test.ts +83 -0
  20. package/src/__tests__/modules/pwa/PwaAutoUpdateController.test.ts +61 -0
  21. package/src/index.tsx +2 -1
  22. package/src/modules/appCatalog/ui/catalog/AppCatalogGrid.tsx +159 -34
  23. package/src/modules/appCatalog/ui/pages/AppCatalogPage.tsx +0 -10
  24. package/src/modules/appCatalog/utils/areaGrouping.ts +85 -0
  25. package/src/modules/pwa/PwaAutoUpdateController.ts +19 -3
  26. package/src/types/uiSettings.ts +30 -0
@@ -0,0 +1,85 @@
1
+ import type {
2
+ GroupingTagDefinition,
3
+ Resource,
4
+ } from '@igstack/app-catalog-backend-core'
5
+
6
+ /**
7
+ * Grouping of the full resource list into areas.
8
+ *
9
+ * The vocabulary itself is NOT here: which `category:<value>` tags exist, what
10
+ * they are called and which of them belong on the day-to-day shelf is
11
+ * deployment-specific. Labels come from the catalog's own tag definitions and
12
+ * icons from `UiSettings.areas`, so the core only knows the mechanism.
13
+ */
14
+
15
+ const CATEGORY_PREFIX = 'category:'
16
+ const EVERYONE_TAG = 'universality:everyone'
17
+
18
+ /**
19
+ * Synthetic key for the merged first group. Underscored so it cannot collide
20
+ * with a real `category:<value>`.
21
+ */
22
+ export const DAY_TO_DAY_AREA_KEY = '__day-to-day__'
23
+
24
+ /** Fallback area for resources carrying no `category:` tag. */
25
+ export const OTHER_AREA_KEY = 'other'
26
+
27
+ export const categoryOf = (app: Resource): string =>
28
+ app.tags
29
+ ?.find((t) => t.startsWith(CATEGORY_PREFIX))
30
+ ?.slice(CATEGORY_PREFIX.length) ?? OTHER_AREA_KEY
31
+
32
+ const humanize = (key: string): string => {
33
+ const words = key.replace(/[-_]+/g, ' ').trim()
34
+ return words.charAt(0).toUpperCase() + words.slice(1)
35
+ }
36
+
37
+ /**
38
+ * Day-to-day tools first, then one area per category, biggest area first.
39
+ * Input order is preserved inside each group.
40
+ *
41
+ * `dayToDayCategories` are categories that fold into the day-to-day group
42
+ * instead of getting an area of their own (perks, office services, …).
43
+ */
44
+ export function groupByArea(
45
+ apps: Resource[],
46
+ dayToDayCategories: readonly string[] = [],
47
+ ): [string, Resource[]][] {
48
+ const folded = new Set(dayToDayCategories)
49
+ const dayToDay: Resource[] = []
50
+ const byCategory = new Map<string, Resource[]>()
51
+
52
+ for (const app of apps) {
53
+ const key = categoryOf(app)
54
+ if (app.tags?.includes(EVERYONE_TAG) || folded.has(key)) {
55
+ dayToDay.push(app)
56
+ continue
57
+ }
58
+ const list = byCategory.get(key)
59
+ if (list) list.push(app)
60
+ else byCategory.set(key, [app])
61
+ }
62
+
63
+ const areas = [...byCategory.entries()].sort(
64
+ (a, b) => b[1].length - a[1].length,
65
+ )
66
+ return dayToDay.length
67
+ ? [[DAY_TO_DAY_AREA_KEY, dayToDay] as [string, Resource[]], ...areas]
68
+ : areas
69
+ }
70
+
71
+ /**
72
+ * Title for an area. The catalog's `category` tag definition supplies the
73
+ * display names; an unknown value still gets a readable humanized slug.
74
+ */
75
+ export function areaLabel(
76
+ key: string,
77
+ tagsDefinitions: readonly GroupingTagDefinition[] = [],
78
+ dayToDayLabel = 'Day-to-day tools',
79
+ ): string {
80
+ if (key === DAY_TO_DAY_AREA_KEY) return dayToDayLabel
81
+ const defined = tagsDefinitions
82
+ .find((d) => d.prefix === 'category')
83
+ ?.values.find((v) => v.value === key)?.displayName
84
+ return defined || humanize(key)
85
+ }
@@ -1,6 +1,6 @@
1
1
  import type { PwaAutoUpdateOptions, PwaUpdateHandle } from './types'
2
2
 
3
- const DEFAULT_IDLE_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes
3
+ const DEFAULT_IDLE_TIMEOUT_MS = 60 * 1000 // 1 minute
4
4
  const DEFAULT_MIN_CHECK_INTERVAL_MS = 30 * 1000 // 30 seconds
5
5
  const VISIBILITY_DEBOUNCE_MS = 1000
6
6
  const ERROR_UPDATE_WAIT_MS = 3000
@@ -96,6 +96,8 @@ export class PwaAutoUpdateController {
96
96
  } catch {
97
97
  this.log('registration.update() failed, reloading anyway')
98
98
  }
99
+
100
+ this.activateWaitingWorker(registration)
99
101
  }
100
102
 
101
103
  // Wait briefly for a new SW to activate, then reload
@@ -158,8 +160,22 @@ export class PwaAutoUpdateController {
158
160
  } catch (error) {
159
161
  this.log('registration.update() failed:', error)
160
162
  }
161
- // With autoUpdate registerType, vite-plugin-pwa handles
162
- // skipWaiting + clientsClaim + calling updateSW() automatically
163
+
164
+ this.activateWaitingWorker(registration)
165
+ }
166
+
167
+ /**
168
+ * A freshly installed worker stays in `waiting` for as long as this page is
169
+ * controlled by the old one — a reload does not release it, only closing
170
+ * every tab on the origin does. Ask it to take over now; the generated
171
+ * worker answers this message with `skipWaiting()`, and the registration's
172
+ * own `activated` listener reloads the page onto the new build.
173
+ */
174
+ private activateWaitingWorker(registration: ServiceWorkerRegistration): void {
175
+ if (!registration.waiting) return
176
+
177
+ this.log('New worker is waiting, sending SKIP_WAITING')
178
+ registration.waiting.postMessage({ type: 'SKIP_WAITING' })
163
179
  }
164
180
 
165
181
  private reload(): void {
@@ -1,5 +1,33 @@
1
+ import type { ComponentType } from 'react'
1
2
  import type { PwaAutoUpdateOptions } from '~/modules/pwa/types'
2
3
 
4
+ /** Icon component for an area header. Lucide icon components satisfy this. */
5
+ export type AreaIcon = ComponentType<{
6
+ size?: number
7
+ strokeWidth?: number
8
+ className?: string
9
+ }>
10
+
11
+ /**
12
+ * Presentation of the area sections on the home view. The taxonomy is
13
+ * deployment-specific, so the core ships none of it: labels come from the
14
+ * catalog's own `category` tag definition and everything below is optional.
15
+ */
16
+ export interface AreasSettings {
17
+ /**
18
+ * Icon per `category:<value>`; the key `DAY_TO_DAY_AREA_KEY` targets the
19
+ * merged first group. Areas without an icon render title-only.
20
+ */
21
+ icons?: Record<string, AreaIcon>
22
+ /**
23
+ * Category values that fold into the day-to-day group instead of getting an
24
+ * area of their own (e.g. perks, office services).
25
+ */
26
+ dayToDayCategories?: string[]
27
+ /** Title of the merged first group. Defaults to "Day-to-day tools". */
28
+ dayToDayLabel?: string
29
+ }
30
+
3
31
  /**
4
32
  * UI settings passed from the app entry point.
5
33
  */
@@ -11,6 +39,8 @@ export interface UiSettings {
11
39
  }
12
40
  /** Frontend build identifier baked at build time (e.g., pipeline ID via VITE env var) */
13
41
  frontendBuildId?: string
42
+ /** Area sections on the home view: icons and the day-to-day fold. */
43
+ areas?: AreasSettings
14
44
  /** PWA auto-update configuration (idle timeout, check interval, debug) */
15
45
  pwaAutoUpdate?: PwaAutoUpdateOptions
16
46
  /**