@oneuptime/common 11.0.9 → 11.0.12

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 (125) hide show
  1. package/Models/DatabaseModels/CephCluster.ts +134 -0
  2. package/Models/DatabaseModels/CloudResource.ts +134 -0
  3. package/Models/DatabaseModels/DockerHost.ts +134 -0
  4. package/Models/DatabaseModels/DockerSwarmCluster.ts +134 -0
  5. package/Models/DatabaseModels/Host.ts +134 -0
  6. package/Models/DatabaseModels/KubernetesCluster.ts +134 -0
  7. package/Models/DatabaseModels/PodmanHost.ts +134 -0
  8. package/Models/DatabaseModels/ProxmoxCluster.ts +134 -0
  9. package/Models/DatabaseModels/RumApplication.ts +134 -0
  10. package/Models/DatabaseModels/ServerlessFunction.ts +134 -0
  11. package/Models/DatabaseModels/Service.ts +134 -0
  12. package/README.md +1 -1
  13. package/Scripts/generate-service-worker.js +46 -36
  14. package/Server/Infrastructure/Postgres/DataSourceOptions.ts +4 -2
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1782600000000-AddArchiveToResources.ts +331 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/Readme.md +3 -3
  18. package/Server/Services/AIAgentService.ts +9 -4
  19. package/Server/Services/AnalyticsDatabaseService.ts +89 -56
  20. package/Server/Services/CephClusterService.ts +6 -4
  21. package/Server/Services/CloudResourceService.ts +6 -4
  22. package/Server/Services/DatabaseService.ts +126 -0
  23. package/Server/Services/DockerHostService.ts +6 -4
  24. package/Server/Services/DockerSwarmClusterService.ts +6 -4
  25. package/Server/Services/HostService.ts +6 -4
  26. package/Server/Services/KubernetesClusterService.ts +6 -4
  27. package/Server/Services/PodmanHostService.ts +6 -4
  28. package/Server/Services/ProbeService.ts +10 -4
  29. package/Server/Services/ProxmoxClusterService.ts +6 -4
  30. package/Server/Services/RumApplicationService.ts +6 -4
  31. package/Server/Services/ServerlessFunctionService.ts +6 -4
  32. package/Server/Services/ServiceService.ts +17 -4
  33. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +1 -1
  34. package/Server/Utils/Monitor/MonitorResource.ts +24 -10
  35. package/Server/Utils/Telemetry/EntityRegistry.ts +10 -5
  36. package/Server/Utils/Workspace/Slack/app-manifest.json +86 -92
  37. package/Tests/Server/Services/UpdateColumnsByIdWithoutHooks.test.ts +154 -0
  38. package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +12 -9
  39. package/Tests/Types/DiskSize.test.ts +49 -0
  40. package/Types/Dashboard/DashboardComponents/DashboardTableComponent.ts +11 -0
  41. package/Types/Icon/IconProp.ts +1 -0
  42. package/Types/Monitor/MonitorType.ts +15 -31
  43. package/Types/Monitor/schema.json +32 -35
  44. package/UI/Components/BulkUpdate/BulkArchiveActions.tsx +150 -0
  45. package/UI/Components/Icon/Icon.tsx +42 -126
  46. package/UI/Components/Navbar/NavBarMenuModal.tsx +2 -5
  47. package/UI/esbuild-config.js +136 -110
  48. package/Utils/ClientAPI/README.md +1 -1
  49. package/build/dist/Models/DatabaseModels/CephCluster.js +136 -0
  50. package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
  51. package/build/dist/Models/DatabaseModels/CloudResource.js +136 -0
  52. package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
  53. package/build/dist/Models/DatabaseModels/DockerHost.js +136 -0
  54. package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
  55. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +136 -0
  56. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
  57. package/build/dist/Models/DatabaseModels/Host.js +136 -0
  58. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  59. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +136 -0
  60. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  61. package/build/dist/Models/DatabaseModels/PodmanHost.js +136 -0
  62. package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
  63. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +136 -0
  64. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
  65. package/build/dist/Models/DatabaseModels/RumApplication.js +136 -0
  66. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  67. package/build/dist/Models/DatabaseModels/ServerlessFunction.js +136 -0
  68. package/build/dist/Models/DatabaseModels/ServerlessFunction.js.map +1 -1
  69. package/build/dist/Models/DatabaseModels/Service.js +136 -0
  70. package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
  71. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +4 -2
  72. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
  73. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1782600000000-AddArchiveToResources.js +120 -0
  74. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1782600000000-AddArchiveToResources.js.map +1 -0
  75. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  76. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  77. package/build/dist/Server/Services/AIAgentService.js +9 -4
  78. package/build/dist/Server/Services/AIAgentService.js.map +1 -1
  79. package/build/dist/Server/Services/AnalyticsDatabaseService.js +52 -17
  80. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  81. package/build/dist/Server/Services/CephClusterService.js +6 -4
  82. package/build/dist/Server/Services/CephClusterService.js.map +1 -1
  83. package/build/dist/Server/Services/CloudResourceService.js +6 -4
  84. package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
  85. package/build/dist/Server/Services/DatabaseService.js +101 -0
  86. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  87. package/build/dist/Server/Services/DockerHostService.js +6 -4
  88. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  89. package/build/dist/Server/Services/DockerSwarmClusterService.js +6 -4
  90. package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
  91. package/build/dist/Server/Services/HostService.js +6 -4
  92. package/build/dist/Server/Services/HostService.js.map +1 -1
  93. package/build/dist/Server/Services/KubernetesClusterService.js +6 -4
  94. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  95. package/build/dist/Server/Services/PodmanHostService.js +6 -4
  96. package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
  97. package/build/dist/Server/Services/ProbeService.js +10 -4
  98. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  99. package/build/dist/Server/Services/ProxmoxClusterService.js +6 -4
  100. package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
  101. package/build/dist/Server/Services/RumApplicationService.js +6 -4
  102. package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
  103. package/build/dist/Server/Services/ServerlessFunctionService.js +6 -4
  104. package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
  105. package/build/dist/Server/Services/ServiceService.js +17 -4
  106. package/build/dist/Server/Services/ServiceService.js.map +1 -1
  107. package/build/dist/Server/Utils/Monitor/MonitorResource.js +24 -10
  108. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  109. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +10 -5
  110. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  111. package/build/dist/Server/Utils/Workspace/Slack/app-manifest.json +3 -9
  112. package/build/dist/Types/Dashboard/DashboardComponents/DashboardTableComponent.js.map +1 -1
  113. package/build/dist/Types/Icon/IconProp.js +1 -0
  114. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  115. package/build/dist/Types/Monitor/MonitorType.js +15 -31
  116. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  117. package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js +96 -0
  118. package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js.map +1 -0
  119. package/build/dist/UI/Components/Icon/Icon.js +17 -41
  120. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  121. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -3
  122. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  123. package/jest.config.json +47 -66
  124. package/package.json +1 -1
  125. package/tsconfig.json +109 -113
@@ -0,0 +1,49 @@
1
+ import BadDataException from "../../Types/Exception/BadDataException";
2
+ import DiskSize from "../../Types/DiskSize";
3
+
4
+ describe("DiskSize", () => {
5
+ describe("convertToDecimalPlaces", () => {
6
+ test("rounds to 2 decimal places by default", () => {
7
+ expect(DiskSize.convertToDecimalPlaces(3.14159)).toBe(3.14);
8
+ });
9
+
10
+ test("rounds to the requested number of decimal places", () => {
11
+ expect(DiskSize.convertToDecimalPlaces(3.14159, 3)).toBe(3.142);
12
+ });
13
+
14
+ test("returns the ceiling when decimalPlaces is 0", () => {
15
+ expect(DiskSize.convertToDecimalPlaces(4.2, 0)).toBe(5);
16
+ expect(DiskSize.convertToDecimalPlaces(4, 0)).toBe(4);
17
+ });
18
+
19
+ test("parses a string value before rounding", () => {
20
+ expect(
21
+ DiskSize.convertToDecimalPlaces("2.71828" as unknown as number),
22
+ ).toBe(2.72);
23
+ });
24
+
25
+ test("throws a BadDataException when decimalPlaces is negative", () => {
26
+ expect(() => {
27
+ return DiskSize.convertToDecimalPlaces(1.5, -1);
28
+ }).toThrow(BadDataException);
29
+ });
30
+ });
31
+
32
+ describe("byteSizeToGB", () => {
33
+ test("converts bytes to gigabytes", () => {
34
+ expect(DiskSize.byteSizeToGB(1024 * 1024 * 1024)).toBe(1);
35
+ });
36
+ });
37
+
38
+ describe("byteSizeToMB", () => {
39
+ test("converts bytes to megabytes", () => {
40
+ expect(DiskSize.byteSizeToMB(1024 * 1024)).toBe(1);
41
+ });
42
+ });
43
+
44
+ describe("byteSizeToKB", () => {
45
+ test("converts bytes to kilobytes", () => {
46
+ expect(DiskSize.byteSizeToKB(1024)).toBe(1);
47
+ });
48
+ });
49
+ });
@@ -2,6 +2,8 @@ import MetricFormulaConfigData from "../../Metrics/MetricFormulaConfigData";
2
2
  import MetricQueryConfigData from "../../Metrics/MetricQueryConfigData";
3
3
  import MetricsAggregationType from "../../Metrics/MetricsAggregationType";
4
4
  import ObjectID from "../../ObjectID";
5
+ import Dictionary from "../../Dictionary";
6
+ import { DictionaryEntryValue } from "../../../UI/Components/Dictionary/DictionaryFilterOperator";
5
7
  import DashboardComponentType from "../DashboardComponentType";
6
8
  import BaseComponent from "./DashboardBaseComponent";
7
9
 
@@ -76,6 +78,15 @@ export default interface DashboardTableComponent extends BaseComponent {
76
78
  maxRows?: number | undefined;
77
79
  reduce?: TableReduce | undefined;
78
80
  decimals?: number | undefined;
81
+ /*
82
+ * Widget-level attribute filter applied to EVERY metric column's query
83
+ * (e.g. deployment.environment = production, so the table only shows
84
+ * hosts/services in that environment). Stored in the same operator-aware
85
+ * shape the chart widget writes into filterData.attributes, so it flows
86
+ * straight through MetricUtil.fetchResults' sanitizeAttributeFilters with
87
+ * no backend changes. Empty/undefined = no filter (every series shown).
88
+ */
89
+ attributeFilters?: Dictionary<DictionaryEntryValue> | undefined;
79
90
  /*
80
91
  * Legacy widget shape from before the columns/groupByAttributes
81
92
  * redesign — read-only at render time, never written by the editor.
@@ -324,6 +324,7 @@ enum IconProp {
324
324
  XCircle = "XCircle",
325
325
  Kubernetes = "Kubernetes",
326
326
  Docker = "Docker",
327
+ DockerSwarm = "DockerSwarm",
327
328
  Podman = "Podman",
328
329
  Proxmox = "Proxmox",
329
330
  Ceph = "Ceph",
@@ -93,36 +93,20 @@ export class MonitorTypeHelper {
93
93
  monitorTypes: [MonitorType.IncomingRequest, MonitorType.IncomingEmail],
94
94
  },
95
95
  {
96
- label: "Infrastructure",
96
+ label: "Network",
97
97
  monitorTypes: [MonitorType.SNMP],
98
98
  },
99
99
  {
100
- label: "Kubernetes",
101
- monitorTypes: [MonitorType.Kubernetes],
102
- },
103
- {
104
- label: "Docker",
105
- monitorTypes: [MonitorType.Docker],
106
- },
107
- {
108
- label: "Host",
109
- monitorTypes: [MonitorType.Host],
110
- },
111
- {
112
- label: "Podman",
113
- monitorTypes: [MonitorType.Podman],
114
- },
115
- {
116
- label: "Docker Swarm",
117
- monitorTypes: [MonitorType.DockerSwarm],
118
- },
119
- {
120
- label: "Proxmox",
121
- monitorTypes: [MonitorType.Proxmox],
122
- },
123
- {
124
- label: "Ceph",
125
- monitorTypes: [MonitorType.Ceph],
100
+ label: "Infrastructure",
101
+ monitorTypes: [
102
+ MonitorType.Host,
103
+ MonitorType.Kubernetes,
104
+ MonitorType.Docker,
105
+ MonitorType.Podman,
106
+ MonitorType.DockerSwarm,
107
+ MonitorType.Proxmox,
108
+ MonitorType.Ceph,
109
+ ],
126
110
  },
127
111
  {
128
112
  label: "Telemetry",
@@ -225,28 +209,28 @@ export class MonitorTypeHelper {
225
209
  title: "Podman Container",
226
210
  description:
227
211
  "This monitor type lets you monitor Podman containers — CPU, memory, network, restarts, and lifecycle events.",
228
- icon: IconProp.Cube,
212
+ icon: IconProp.Podman,
229
213
  },
230
214
  {
231
215
  monitorType: MonitorType.DockerSwarm,
232
216
  title: "Docker Swarm",
233
217
  description:
234
218
  "This monitor type lets you monitor Docker Swarm clusters — per-task container CPU, memory, network, process count, and uptime across the cluster's services and nodes.",
235
- icon: IconProp.Cube,
219
+ icon: IconProp.DockerSwarm,
236
220
  },
237
221
  {
238
222
  monitorType: MonitorType.Proxmox,
239
223
  title: "Proxmox",
240
224
  description:
241
225
  "This monitor type lets you monitor Proxmox VE clusters — node availability, VM and container (guest) health, CPU, memory, storage, and HA state.",
242
- icon: IconProp.ServerStack,
226
+ icon: IconProp.Proxmox,
243
227
  },
244
228
  {
245
229
  monitorType: MonitorType.Ceph,
246
230
  title: "Ceph",
247
231
  description:
248
232
  "This monitor type lets you monitor Ceph storage clusters — cluster health, monitor quorum, OSD availability, pool capacity, and placement group states.",
249
- icon: IconProp.Database,
233
+ icon: IconProp.Ceph,
250
234
  },
251
235
  {
252
236
  monitorType: MonitorType.IP,
@@ -1,39 +1,36 @@
1
-
2
1
  {
3
- "_type": "MonitorSteps",
4
- "value": {
5
- "monitorStepsInstanceArray": [
6
- {
7
- "_type": "MonitorStep",
8
- "value": {
9
-
10
- "monitorDestination": {
11
- "_type": "URL",
12
- "value": "http://www.google.com"
13
- },
14
- "monitorCriteria": {
15
- "_type": "MonitorCriteria",
16
- "value": {
17
- "monitorCriteriaInstanceArray": [
18
- {
19
- "_type": "MonitorCriteriaInstance",
20
- "value": {
21
- "monitorCriteriaType": {
22
- "_type": "MonitorCriteriaType",
23
- "value": "HTTP_STATUS_CODE"
24
- },
25
- "monitorCriteriaValue": {
26
- "_type": "MonitorCriteriaValue",
27
- "value": "200"
28
- }
29
- }
30
- }
31
- ]
32
- }
33
- }
34
-
2
+ "_type": "MonitorSteps",
3
+ "value": {
4
+ "monitorStepsInstanceArray": [
5
+ {
6
+ "_type": "MonitorStep",
7
+ "value": {
8
+ "monitorDestination": {
9
+ "_type": "URL",
10
+ "value": "http://www.google.com"
11
+ },
12
+ "monitorCriteria": {
13
+ "_type": "MonitorCriteria",
14
+ "value": {
15
+ "monitorCriteriaInstanceArray": [
16
+ {
17
+ "_type": "MonitorCriteriaInstance",
18
+ "value": {
19
+ "monitorCriteriaType": {
20
+ "_type": "MonitorCriteriaType",
21
+ "value": "HTTP_STATUS_CODE"
22
+ },
23
+ "monitorCriteriaValue": {
24
+ "_type": "MonitorCriteriaValue",
25
+ "value": "200"
26
+ }
27
+ }
35
28
  }
29
+ ]
36
30
  }
37
- ]
38
- }
31
+ }
32
+ }
33
+ }
34
+ ]
35
+ }
39
36
  }
@@ -0,0 +1,150 @@
1
+ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
2
+ import BadDataException from "../../../Types/Exception/BadDataException";
3
+ import IconProp from "../../../Types/Icon/IconProp";
4
+ import ObjectID from "../../../Types/ObjectID";
5
+ import API from "../../Utils/API/API";
6
+ import ModelAPI from "../../Utils/ModelAPI/ModelAPI";
7
+ import { ButtonStyleType } from "../Button/Button";
8
+ import {
9
+ BulkActionButtonSchema,
10
+ BulkActionFailed,
11
+ BulkActionOnClickProps,
12
+ } from "./BulkUpdateForm";
13
+
14
+ export interface BulkArchiveActionsConfig<T extends BaseModel> {
15
+ modelType: { new (): T };
16
+ /**
17
+ * Singular/plural labels used in the confirmation copy, e.g. "service" /
18
+ * "services". Defaults to the model's own singular/plural names.
19
+ */
20
+ singularName?: string | undefined;
21
+ pluralName?: string | undefined;
22
+ }
23
+
24
+ export interface BulkArchiveActionsResult<T extends BaseModel> {
25
+ archiveBulkActions: Array<BulkActionButtonSchema<T>>;
26
+ unarchiveBulkActions: Array<BulkActionButtonSchema<T>>;
27
+ }
28
+
29
+ type ArchiveMode = "archive" | "unarchive";
30
+
31
+ /**
32
+ * Reusable hook that provides "Archive" and "Unarchive" bulk actions for any
33
+ * ModelTable whose model has an `isArchived` boolean column. Archiving is a
34
+ * pure visibility flag — telemetry keeps being ingested for archived resources.
35
+ *
36
+ * The client only ever sends `{ isArchived: true | false }`; the server stamps
37
+ * `archivedAt` / `archivedByUserId` (see DatabaseService.sanitizeCreateOrUpdate).
38
+ *
39
+ * No form modal is needed — these actions use the confirm flow built into
40
+ * BulkUpdateForm (confirmMessage / confirmTitle).
41
+ *
42
+ * Usage:
43
+ * const { archiveBulkActions } = useBulkArchiveActions({ modelType: Service });
44
+ * <ModelTable bulkActions={{ buttons: [...archiveBulkActions] }} />
45
+ */
46
+ function useBulkArchiveActions<T extends BaseModel>(
47
+ config: BulkArchiveActionsConfig<T>,
48
+ ): BulkArchiveActionsResult<T> {
49
+ const model: T = new config.modelType();
50
+ const singularName: string =
51
+ config.singularName || model.singularName || "resource";
52
+ const pluralName: string =
53
+ config.pluralName || model.pluralName || "resources";
54
+
55
+ const applyArchive: (
56
+ mode: ArchiveMode,
57
+ props: BulkActionOnClickProps<T>,
58
+ ) => Promise<void> = async (
59
+ mode: ArchiveMode,
60
+ props: BulkActionOnClickProps<T>,
61
+ ): Promise<void> => {
62
+ const { items, onProgressInfo, onBulkActionStart, onBulkActionEnd } = props;
63
+
64
+ onBulkActionStart();
65
+
66
+ const totalItems: Array<T> = [...items];
67
+ const inProgressItems: Array<T> = [...items];
68
+ const successItems: Array<T> = [];
69
+ const failedItems: Array<BulkActionFailed<T>> = [];
70
+
71
+ for (const item of totalItems) {
72
+ inProgressItems.splice(inProgressItems.indexOf(item), 1);
73
+
74
+ try {
75
+ if (!item.id) {
76
+ throw new BadDataException("Item ID not found");
77
+ }
78
+
79
+ await ModelAPI.updateById<T>({
80
+ id: item.id as ObjectID,
81
+ modelType: config.modelType,
82
+ data: {
83
+ isArchived: mode === "archive",
84
+ } as any,
85
+ });
86
+
87
+ successItems.push(item);
88
+ } catch (err) {
89
+ failedItems.push({
90
+ item: item,
91
+ failedMessage: API.getFriendlyMessage(err),
92
+ });
93
+ }
94
+
95
+ onProgressInfo({
96
+ totalItems: totalItems,
97
+ failed: failedItems,
98
+ successItems: successItems,
99
+ inProgressItems: inProgressItems,
100
+ });
101
+ }
102
+
103
+ onBulkActionEnd();
104
+ };
105
+
106
+ const archiveAction: BulkActionButtonSchema<T> = {
107
+ title: "Archive",
108
+ icon: IconProp.Archive,
109
+ buttonStyleType: ButtonStyleType.NORMAL,
110
+ confirmTitle: (items: Array<T>): string => {
111
+ return `Archive ${items.length} ${
112
+ items.length === 1 ? singularName : pluralName
113
+ }?`;
114
+ },
115
+ confirmMessage: (items: Array<T>): string => {
116
+ return `Are you sure you want to archive the selected ${
117
+ items.length === 1 ? singularName : pluralName
118
+ }? They will be hidden from the list but will keep collecting telemetry. You can unarchive them anytime from the Archived tab.`;
119
+ },
120
+ onClick: async (props: BulkActionOnClickProps<T>): Promise<void> => {
121
+ await applyArchive("archive", props);
122
+ },
123
+ };
124
+
125
+ const unarchiveAction: BulkActionButtonSchema<T> = {
126
+ title: "Unarchive",
127
+ icon: IconProp.Unarchive,
128
+ buttonStyleType: ButtonStyleType.NORMAL,
129
+ confirmTitle: (items: Array<T>): string => {
130
+ return `Unarchive ${items.length} ${
131
+ items.length === 1 ? singularName : pluralName
132
+ }?`;
133
+ },
134
+ confirmMessage: (items: Array<T>): string => {
135
+ return `Are you sure you want to unarchive the selected ${
136
+ items.length === 1 ? singularName : pluralName
137
+ }? They will reappear in the main list.`;
138
+ },
139
+ onClick: async (props: BulkActionOnClickProps<T>): Promise<void> => {
140
+ await applyArchive("unarchive", props);
141
+ },
142
+ };
143
+
144
+ return {
145
+ archiveBulkActions: [archiveAction],
146
+ unarchiveBulkActions: [unarchiveAction],
147
+ };
148
+ }
149
+
150
+ export default useBulkArchiveActions;
@@ -2894,146 +2894,62 @@ const Icon: FunctionComponent<ComponentProps> = ({
2894
2894
  />
2895
2895
  </>,
2896
2896
  );
2897
- } else if (icon === IconProp.Podman) {
2897
+ } else if (icon === IconProp.DockerSwarm) {
2898
2898
  /*
2899
- * Podman glyph — a pod (rounded enclosure) grouping containers, with a
2900
- * small seal-head nod to Podman's mascot. Intentionally a hand-drawn
2901
- * generic mark (not the official Podman seal logo / trademark), matching
2902
- * the generic-glyph convention used for Kubernetes/Docker above and
2903
- * deliberately distinct from the Docker whale.
2899
+ * Docker Swarm glyph — a honeycomb cluster of three hexagonal nodes, an
2900
+ * abstract "swarm of nodes" mark. Rendered as filled hexagons to sit with
2901
+ * the other resource brand logos (Podman / Proxmox / Ceph) and stay clearly
2902
+ * distinct from the single Docker whale. (Docker Swarm has no official
2903
+ * standalone logo, so this is a themed cluster mark rather than a real one.)
2904
2904
  */
2905
2905
  return getSvgWrapper(
2906
2906
  <>
2907
- {/* Pod enclosure */}
2908
- <rect
2909
- x="3"
2910
- y="8"
2911
- width="18"
2912
- height="11"
2913
- rx="2"
2914
- strokeLinecap="round"
2915
- strokeLinejoin="round"
2916
- />
2917
- {/* Grouped containers inside the pod */}
2918
- <rect
2919
- x="6"
2920
- y="12"
2921
- width="3.5"
2922
- height="4"
2923
- rx="0.4"
2924
- strokeLinecap="round"
2925
- strokeLinejoin="round"
2926
- />
2927
- <rect
2928
- x="10.25"
2929
- y="12"
2930
- width="3.5"
2931
- height="4"
2932
- rx="0.4"
2933
- strokeLinecap="round"
2934
- strokeLinejoin="round"
2907
+ {/* Top node */}
2908
+ <polygon
2909
+ fill="currentColor"
2910
+ stroke="none"
2911
+ points="12,3.2 15.55,5.25 15.55,9.35 12,11.4 8.45,9.35 8.45,5.25"
2935
2912
  />
2936
- <rect
2937
- x="14.5"
2938
- y="12"
2939
- width="3.5"
2940
- height="4"
2941
- rx="0.4"
2942
- strokeLinecap="round"
2943
- strokeLinejoin="round"
2913
+ {/* Bottom-left node */}
2914
+ <polygon
2915
+ fill="currentColor"
2916
+ stroke="none"
2917
+ points="7.7,11 11.25,13.05 11.25,17.15 7.7,19.2 4.15,17.15 4.15,13.05"
2944
2918
  />
2945
- {/* Seal head peeking over the pod */}
2946
- <circle cx="17" cy="5.5" r="2" />
2947
- <path
2948
- strokeLinecap="round"
2949
- strokeLinejoin="round"
2950
- d="M19 6.2c1 0.1 1.8-0.2 2.4-0.9"
2919
+ {/* Bottom-right node */}
2920
+ <polygon
2921
+ fill="currentColor"
2922
+ stroke="none"
2923
+ points="16.3,11 19.85,13.05 19.85,17.15 16.3,19.2 12.75,17.15 12.75,13.05"
2951
2924
  />
2952
2925
  </>,
2953
2926
  );
2927
+ } else if (icon === IconProp.Podman) {
2928
+ // Podman official logo mark (Simple Icons, CC0) — single filled path.
2929
+ return getSvgWrapper(
2930
+ <path
2931
+ fill="currentColor"
2932
+ stroke="none"
2933
+ d="M17.2.275L6.75.308a.259.259 0 0 0-.203.098L.056 8.602a.259.259 0 0 0-.05.219l2.356 10.194a.26.26 0 0 0 .14.174l9.43 4.511a.258.258 0 0 0 .224-.002l9.401-4.566a.259.259 0 0 0 .141-.175L23.993 8.75a.258.258 0 0 0-.051-.22L17.403.374A.259.259 0 0 0 17.2.275zm-.123.517l6.385 7.966-2.242 9.964-9.177 4.457-9.205-4.402L.54 8.827 6.875.824zM11.46 2.857c-.933 0-1.84.1-2.426.332h-.002c-1.554.569-2.725 2.105-3.074 3.952v.004c-.309 1.463-.392 2.703-.556 3.824-.07.481-.159.94-.283 1.387-.628.497-1.079 1.263-1.244 2.138v.004c-.116.547-.181 1.04-.237 1.5h-.644v.518h8.891c-.061.464-.122.996-.181 1.42H7.596v.517h7.939c-.242-.078-.486-.218-.756-.502h-.697l-.85.488-.232-.396.162-.092h-1.069c.113-.776.17-1.601.373-2.564v-.004c.22-1.164.96-2.112 1.895-2.453l.004-.002h.002c.318-.127.928-.205 1.543-.205.613 0 1.244.075 1.622.207.935.341 1.676 1.29 1.895 2.453v.004c.204.963.26 1.788.373 2.564h-.742l.162.092-.233.396-.85-.488h-.75c-.219.25-.474.412-.747.502h4.392v-.518h-.842c-.103-.743-.181-1.67-.382-2.623v-.002a4.14 4.14 0 0 0-.264-.863h1.863v-.517h-2.13a3.488 3.488 0 0 0-.8-.906h1.8v-.518H17.95a8.862 8.862 0 0 1-.193-.775h1.484v-.518h-1.576c-.013-.081-.027-.161-.039-.244-.164-1.12-.246-2.36-.555-3.824v-.004c-.348-1.848-1.52-3.383-3.075-3.952l-.002-.002h-.002c-.65-.227-1.596-.33-2.531-.33zm0 .386c.904 0 1.833.11 2.404.309h.002c1.4.514 2.5 1.934 2.826 3.666v.003c.303 1.436.385 2.66.552 3.805.076.515.173 1.013.315 1.505-.449-.135-1.05-.197-1.648-.197-.12 0-.236.003-.352.008l-1.863-1.865a2.17 2.17 0 0 0 .11-.246l2.13 1.23.13-.224-2.185-1.262c.016-.069.027-.14.036-.21l2.302.616.068-.248-2.354-.63c-.02-1.153-1.008-2.078-2.208-2.078-1.205 0-2.196.931-2.206 2.091l-2.303.617.066.25 2.252-.605c.01.076.024.151.041.224L7.436 11.24l.129.222 2.087-1.207c.034.089.074.176.12.258l-1.266 1.266a6.959 6.959 0 0 0-1.045-.075c-.603 0-1.186.064-1.578.22a2.668 2.668 0 0 0-.285.124c.076-.335.137-.675.187-1.021.168-1.144.248-2.37.551-3.805l.002-.001v-.002c.326-1.733 1.426-3.153 2.828-3.666h.002l.004-.002c.488-.194 1.381-.307 2.287-.307zM8.473 5.194a1.295 1.295 0 0 0-.965.502l-.117.153.306.236.12-.152a.923.923 0 0 1 .673-.352.92.92 0 0 1 .67.262l.139.134.271-.275-.136-.137a1.293 1.293 0 0 0-.961-.37zm6.39 0a1.289 1.289 0 0 0-.96.371l-.138.137.274.275.136-.134a.923.923 0 0 1 .672-.262.923.923 0 0 1 .674.352l.119.152.307-.236-.12-.153c-.23-.3-.587-.486-.964-.502zM8.53 6.708c-.642 0-1.164.538-1.164 1.19 0 .65.522 1.187 1.164 1.187.643 0 1.164-.536 1.164-1.188 0-.651-.521-1.19-1.164-1.19zm6.273 0c-.643 0-1.162.538-1.162 1.19 0 .65.52 1.187 1.162 1.187.643 0 1.164-.536 1.164-1.188 0-.651-.521-1.19-1.164-1.19zm-6.273.387c.428 0 .776.355.776.802 0 .447-.348.8-.776.8a.785.785 0 0 1-.775-.8c0-.035.002-.07.006-.103.07.191.248.318.445.318a.487.487 0 0 0 .477-.496.49.49 0 0 0-.383-.486.759.759 0 0 1 .23-.035zm6.273 0c.428 0 .777.355.777.802 0 .447-.349.8-.777.8a.785.785 0 0 1-.77-.9c.072.19.248.315.444.315a.486.486 0 0 0 .479-.496.491.491 0 0 0-.383-.484.755.755 0 0 1 .23-.037zm-3.08.716c1.012 0 1.819.775 1.819 1.723 0 .947-.807 1.722-1.819 1.722s-1.82-.775-1.82-1.722c0-.948.808-1.723 1.82-1.723zm-.002.528c-.142 0-.258.043-.355.076a.804.804 0 0 1-.232.054c-.107 0-.2.047-.268.127a.568.568 0 0 0-.104.207c-.04.134-.062.268-.08.315a.276.276 0 0 0 .032.25c.033.056.071.1.117.146.09.092.206.183.322.268.12.088.237.166.326.224l-.008.09c-.043.036-.14.102-.324.178a.533.533 0 0 1-.299.025.43.43 0 0 1-.236-.172c.015-.138.044-.293.068-.449l-.376-.095c-.05.238-.067.43-.094.64l.037.059c.143.224.318.344.506.392a.908.908 0 0 0 .52-.033 1.57 1.57 0 0 0 .444-.242c.088.067.244.174.446.242a.908.908 0 0 0 .52.033.868.868 0 0 0 .507-.392l.037-.059a6.292 6.292 0 0 0-.096-.637l-.377.092c.032.148.051.32.07.451a.434.434 0 0 1-.237.17.533.533 0 0 1-.3-.025c-.178-.068-.272-.14-.325-.178l-.006-.084c.09-.058.209-.137.336-.23.115-.085.231-.176.322-.268a.72.72 0 0 0 .117-.146.273.273 0 0 0 .031-.25c-.018-.047-.039-.181-.08-.315a.564.564 0 0 0-.103-.207.343.343 0 0 0-.268-.127.815.815 0 0 1-.234-.054c-.097-.033-.212-.076-.354-.076zm.002.386c.057 0 .134.024.23.057.09.03.208.07.337.076.04.102.06.237.09.338a.361.361 0 0 1-.041.045 2.66 2.66 0 0 1-.276.228c-.165.122-.271.188-.342.233a5.287 5.287 0 0 1-.34-.233 2.557 2.557 0 0 1-.275-.228.34.34 0 0 1-.04-.047c.035-.119.046-.234.089-.34.08.012.246-.042.336-.072a.837.837 0 0 1 .232-.057zm-3.234.61a.635.635 0 0 0-.611.517l1.084-.289a.614.614 0 0 0-.473-.228zm6.336 0a.61.61 0 0 0-.436.187c.352.096.69.184 1.033.275a.632.632 0 0 0-.597-.462zm-.623.607c-.007.035-.002.07-.002.103l.921.532a.648.648 0 0 0 .276-.313l-1.195-.322zm-5.086.05l-1.18.315c.078.15.207.264.362.316l.797-.46c.018-.059.015-.12.021-.17zm4.441.714l1.656 1.658a4.19 4.19 0 0 0-.826.146l-.95-1.647a2.51 2.51 0 0 0 .12-.157zm-3.646.03c.04.055.083.118.129.169l-.658 1.134a2.656 2.656 0 0 0-.276-.119l-.002-.002a3.3 3.3 0 0 0-.292-.082zm3.338.317l.892 1.547c-.623.251-1.149.725-1.523 1.33h-1.652c-.262-.75-.741-1.38-1.358-1.764l.623-1.082c.394.347.919.559 1.492.559a2.25 2.25 0 0 0 1.526-.59zM7.46 12.09c.574 0 1.167.073 1.518.195.867.319 1.555 1.203 1.76 2.285l.001.002v.002c.109.513.173.98.227 1.424H9.86a.386.386 0 0 0-.494 0H9.11a1.351 1.351 0 0 0-.078-.418.799.799 0 0 0 .569.238c.45 0 .814-.375.814-.828a.824.824 0 0 0-.814-.828.822.822 0 0 0-.791 1.016 1.495 1.495 0 0 0-1.18-.559c-.798 0-1.46.611-1.48 1.38h-.342a.386.386 0 0 0-.494 0H4.028c.054-.445.116-.912.224-1.425l.002-.002v-.002c.205-1.084.894-1.97 1.764-2.287h.002l.004-.002c.295-.117.863-.191 1.437-.19zm-1.91 1.105a.898.898 0 0 0-.67.348l-.119.154.307.237.119-.155a.525.525 0 0 1 .379-.197.52.52 0 0 1 .377.147l.138.136.272-.275-.137-.137a.895.895 0 0 0-.666-.258zm4.094 0a.9.9 0 0 0-.668.258l-.137.137.273.275.137-.136a.522.522 0 0 1 .377-.147.525.525 0 0 1 .379.197l.119.155.307-.237-.12-.154a.894.894 0 0 0-.667-.348zm4.222.735a.947.947 0 0 0-.707.365l-.117.154.306.237.12-.155a.568.568 0 0 1 .413-.213.571.571 0 0 1 .414.159l.14.136.27-.275-.138-.137a.942.942 0 0 0-.701-.271zm4.374 0a.942.942 0 0 0-.7.271l-.14.137.272.275.139-.136a.571.571 0 0 1 .414-.159.568.568 0 0 1 .414.213l.119.155.306-.237-.117-.154a.947.947 0 0 0-.707-.365zm-12.65.232a.824.824 0 0 0-.815.828c0 .453.365.828.814.828.45 0 .815-.375.815-.828a.824.824 0 0 0-.815-.828zm5.518.285h1.242a4.137 4.137 0 0 0-.263.864v.002c-.05.237-.092.464-.127.685h-.602a16.77 16.77 0 0 0-.236-1.5l-.002-.002c-.003-.016-.009-.032-.012-.049zm-5.519.102a.43.43 0 0 1 .426.441.43.43 0 0 1-.426.442c-.22 0-.4-.171-.422-.397a.298.298 0 0 0 .215.092.31.31 0 0 0 .305-.316.317.317 0 0 0-.129-.258c.01-.001.02-.004.031-.004zm4.014 0c.235 0 .427.193.427.441a.433.433 0 0 1-.427.442.427.427 0 0 1-.422-.405.3.3 0 0 0 .256.145.31.31 0 0 0 .304-.317.314.314 0 0 0-.207-.298c.023-.004.045-.008.069-.008zm4.304.414a.865.865 0 0 0-.856.87c0 .478.382.874.856.874a.868.868 0 0 0 .857-.873.867.867 0 0 0-.857-.871zm4.292 0a.867.867 0 0 0-.814 1.14 1.597 1.597 0 0 0-1.295-.652c-.846 0-1.546.65-1.568 1.463l-1.525.408.066.248 1.477-.394c.004.028.009.06.015.087l-1.418.817.131.222 1.367-.789c.235.552.801.94 1.455.94.66 0 1.233-.397 1.463-.957l1.398.806.13-.222-1.45-.836c.005-.025.008-.053.012-.078l1.511.404.067-.248-1.563-.418a1.438 1.438 0 0 0-.107-.5c.157.186.39.303.648.303a.867.867 0 0 0 .856-.873.865.865 0 0 0-.856-.871zm-10.567.043c.598 0 1.071.444 1.092.992h-.41c.007-.01.016-.02.023-.033a.24.24 0 0 0 .025-.22c-.005-.016-.021-.102-.05-.196a.416.416 0 0 0-.078-.156.282.282 0 0 0-.225-.108.499.499 0 0 1-.129-.031c-.062-.021-.142-.05-.248-.05-.106 0-.188.029-.25.05a.49.49 0 0 1-.127.031.29.29 0 0 0-.225.108.424.424 0 0 0-.08.156c-.029.094-.043.18-.048.195a.242.242 0 0 0 .023.22c.008.014.017.023.025.034h-.41c.02-.548.494-.992 1.092-.992zm6.275.344c.259 0 .47.211.47.484a.477.477 0 0 1-.47.486.472.472 0 0 1-.467-.453.322.322 0 0 0 .246.115c.18 0 .326-.15.326-.338a.34.34 0 0 0-.156-.289c.017-.002.033-.005.05-.005zm4.292 0c.26 0 .469.211.469.484 0 .272-.21.486-.469.486a.477.477 0 0 1-.47-.486c0-.016.002-.031.004-.047a.33.33 0 0 0 .312.24c.18 0 .326-.15.326-.338a.338.338 0 0 0-.256-.332.475.475 0 0 1 .084-.007zm-10.567.24c.021 0 .063.01.125.031.086.03.117.039.186.049.012.041.022.088.033.129a1.475 1.475 0 0 1-.168.138c-.038.028-.064.045-.088.061h-.176c-.024-.016-.052-.033-.09-.06a1.602 1.602 0 0 1-.168-.14l.034-.128c.107-.014.146-.04.185-.049a.504.504 0 0 1 .127-.031zm8.458.25c.661 0 1.184.502 1.184 1.113 0 .156-.035.304-.096.44l-.002-.024-.022-.156a2.443 2.443 0 0 0-.04-.24l-.377.093.044.274a.24.24 0 0 1-.115.074.299.299 0 0 1-.168-.014c-.087-.03-.132-.063-.18-.094.057-.037.13-.084.198-.134.08-.06.16-.123.226-.19a.542.542 0 0 0 .092-.111.245.245 0 0 0 .026-.225c-.008-.019-.022-.112-.053-.21a.444.444 0 0 0-.084-.163.286.286 0 0 0-.23-.107.566.566 0 0 1-.14-.037c-.065-.022-.152-.055-.263-.055-.11 0-.195.032-.262.055a.575.575 0 0 1-.14.037.294.294 0 0 0-.23.107.436.436 0 0 0-.083.162c-.03.1-.045.192-.052.211a.246.246 0 0 0 .025.225.534.534 0 0 0 .09.111c.066.067.146.13.226.19.068.05.138.095.194.132a.57.57 0 0 1-.18.096.305.305 0 0 1-.17.014.237.237 0 0 1-.111-.076c.008-.09.026-.177.04-.272l-.376-.094c-.032.146-.045.286-.063.409a1.052 1.052 0 0 1-.09-.428c0-.611.521-1.113 1.182-1.113zm0 .623c.026 0 .074.01.14.033.066.025.169.052.206.055l.035.156c-.04.04-.112.1-.184.152-.095.07-.14.095-.197.131-.056-.036-.1-.061-.195-.13a1.236 1.236 0 0 1-.184-.157l.035-.152a1.04 1.04 0 0 0 .206-.055.523.523 0 0 1 .138-.033zm-2.22.353a.43.43 0 0 0-.385.272l.656-.176a.416.416 0 0 0-.271-.096zm4.333 0a.414.414 0 0 0-.22.07l.603.16a.426.426 0 0 0-.383-.23zm-4.054.567l-.607.162a.436.436 0 0 0 .125.113zm3.925.002l.407.234a.443.443 0 0 0 .087-.102zm-1.986.234c.067.047.165.108.285.148a.68.68 0 0 0 .389.024.57.57 0 0 0 .232-.121 1.201 1.201 0 0 1-.904.394c-.356 0-.67-.145-.885-.375a.58.58 0 0 0 .207.102c.144.036.28.014.391-.024.12-.04.218-.1.285-.148zm-9.524 1.61v.517h6.214v-.518zm3.619 1.292v.517H15.3v-.517z"
2934
+ />,
2935
+ );
2954
2936
  } else if (icon === IconProp.Proxmox) {
2955
- /*
2956
- * Generic hypervisor glyph — VM tiles running on a server base.
2957
- * Intentionally NOT the official Proxmox logo (trademark of Proxmox
2958
- * Server Solutions GmbH); follows the hand-drawn-generic convention
2959
- * used for Kubernetes/Docker above.
2960
- */
2937
+ // Proxmox official logo mark (Simple Icons, CC0) — single filled path.
2961
2938
  return getSvgWrapper(
2962
- <>
2963
- {/* Virtual machine tiles */}
2964
- <rect
2965
- x="4"
2966
- y="4"
2967
- width="4.5"
2968
- height="4.5"
2969
- rx="0.5"
2970
- strokeLinecap="round"
2971
- strokeLinejoin="round"
2972
- />
2973
- <rect
2974
- x="9.75"
2975
- y="4"
2976
- width="4.5"
2977
- height="4.5"
2978
- rx="0.5"
2979
- strokeLinecap="round"
2980
- strokeLinejoin="round"
2981
- />
2982
- <rect
2983
- x="15.5"
2984
- y="4"
2985
- width="4.5"
2986
- height="4.5"
2987
- rx="0.5"
2988
- strokeLinecap="round"
2989
- strokeLinejoin="round"
2990
- />
2991
- {/* Connectors from VMs down to the hypervisor */}
2992
- <line x1="6.25" y1="8.5" x2="6.25" y2="14.5" strokeLinecap="round" />
2993
- <line x1="12" y1="8.5" x2="12" y2="14.5" strokeLinecap="round" />
2994
- <line x1="17.75" y1="8.5" x2="17.75" y2="14.5" strokeLinecap="round" />
2995
- {/* Hypervisor / server base */}
2996
- <rect
2997
- x="3"
2998
- y="14.5"
2999
- width="18"
3000
- height="5.5"
3001
- rx="1"
3002
- strokeLinecap="round"
3003
- strokeLinejoin="round"
3004
- />
3005
- <circle cx="6" cy="17.25" r="0.6" fill="currentColor" />
3006
- <line x1="9" y1="17.25" x2="18" y2="17.25" strokeLinecap="round" />
3007
- </>,
2939
+ <path
2940
+ fill="currentColor"
2941
+ stroke="none"
2942
+ d="M4.928 1.825c-1.09.553-1.09.64-.07 1.78 5.655 6.295 7.004 7.782 7.107 7.782.139.017 7.971-8.542 8.058-8.801.034-.07-.208-.312-.519-.536-.415-.312-.864-.433-1.712-.467-1.59-.104-2.144.242-4.115 2.455-.899 1.003-1.66 1.833-1.66 1.833-.017 0-.76-.813-1.642-1.798S8.473 2.1 8.127 1.91c-.796-.45-2.421-.484-3.2-.086zM1.297 4.367C.45 4.695 0 5.007 0 5.248c0 .121 1.331 1.678 2.94 3.459 1.625 1.78 2.939 3.268 2.939 3.302 0 .035-1.331 1.522-2.94 3.303C1.314 17.11.017 18.683.035 18.822c.086.467 1.504 1.055 2.541 1.055 1.678-.018 2.058-.312 5.603-4.202 1.78-1.954 3.233-3.614 3.233-3.666 0-.069-1.435-1.694-3.199-3.63-2.3-2.508-3.423-3.632-3.96-3.874-.812-.398-2.126-.467-2.956-.138zm18.467.12c-.502.26-1.764 1.505-3.943 3.891-1.763 1.937-3.199 3.562-3.199 3.631 0 .07 1.453 1.712 3.234 3.666 3.544 3.89 3.925 4.184 5.602 4.202 1.038 0 2.455-.588 2.542-1.055.017-.156-1.28-1.712-2.905-3.493-1.608-1.78-2.94-3.285-2.94-3.32 0-.034 1.332-1.539 2.94-3.32C22.72 6.91 24.017 5.352 24 5.214c-.087-.45-1.366-.968-2.473-1.038-.795-.034-1.21.035-1.763.312zM7.954 16.973c-2.144 2.369-3.908 4.374-3.943 4.46-.034.07.208.312.52.537.414.311.864.432 1.711.467 1.574.103 2.161-.26 4.15-2.508.864-.968 1.608-1.78 1.625-1.78s.761.812 1.643 1.798c2.023 2.248 2.559 2.576 4.132 2.49.848-.035 1.297-.156 1.712-.467.311-.225.553-.467.519-.536-.087-.26-7.92-8.819-8.058-8.801-.069 0-1.867 1.954-4.011 4.34z"
2943
+ />,
3008
2944
  );
3009
2945
  } else if (icon === IconProp.Ceph) {
3010
- /*
3011
- * Generic hexagon-cluster glyph — honeycomb of storage nodes.
3012
- * Intentionally NOT the official Ceph logo (trademark of the Ceph
3013
- * Foundation); follows the hand-drawn-generic convention used for
3014
- * Kubernetes/Docker above.
3015
- */
2946
+ // Ceph official logo mark (Simple Icons, CC0) — single filled path.
3016
2947
  return getSvgWrapper(
3017
- <>
3018
- <polygon
3019
- points="7.6,3.6 11.24,5.7 11.24,9.9 7.6,12 3.96,9.9 3.96,5.7"
3020
- strokeLinecap="round"
3021
- strokeLinejoin="round"
3022
- />
3023
- <polygon
3024
- points="16.4,3.6 20.04,5.7 20.04,9.9 16.4,12 12.76,9.9 12.76,5.7"
3025
- strokeLinecap="round"
3026
- strokeLinejoin="round"
3027
- />
3028
- <polygon
3029
- points="12,12 15.64,14.1 15.64,18.3 12,20.4 8.36,18.3 8.36,14.1"
3030
- strokeLinecap="round"
3031
- strokeLinejoin="round"
3032
- />
3033
- <circle cx="7.6" cy="7.8" r="0.8" fill="currentColor" />
3034
- <circle cx="16.4" cy="7.8" r="0.8" fill="currentColor" />
3035
- <circle cx="12" cy="16.2" r="0.8" fill="currentColor" />
3036
- </>,
2948
+ <path
2949
+ fill="currentColor"
2950
+ stroke="none"
2951
+ d="M11.959.257A11.912 11.912 0 003.503 3.76 11.92 11.92 0 000 12.217a11.934 11.934 0 001.207 5.243c.72 1.474 1.888 2.944 3.208 4.044.86-.47 1.35-.99 1.453-1.545.1-.533-.134-1.107-.737-1.805a9.031 9.031 0 01-2.219-5.937c0-4.988 4.058-9.047 9.047-9.047h.08c4.99 0 9.048 4.059 9.048 9.047a9.03 9.03 0 01-2.218 5.936c-.599.693-.84 1.292-.735 1.83.108.556.595 1.068 1.449 1.522 1.322-1.1 2.489-2.57 3.209-4.046A11.898 11.898 0 0024 12.217a11.929 11.929 0 00-3.503-8.457A11.923 11.923 0 0012.04.257h-.041zm-.005 4.837a7.072 7.072 0 00-3.76 1.075A7.202 7.202 0 006.15 8.093a7.164 7.164 0 00-1.161 2.65 7.188 7.188 0 00.04 3.125 7.14 7.14 0 001.22 2.607c.154.207.326.396.509.597l.185.202.005.006c.007.007.017.016.026.027.635.738.957 1.533.957 2.36a3.4 3.4 0 01-1.788 2.989 11.924 11.924 0 002.685 1.087c.14-.088.614-.441 1.077-1.083a4.899 4.899 0 00.94-2.99 6.595 6.595 0 00-.49-2.37 6.717 6.717 0 00-1.302-2.033l-.002-.004-.124-.142c-.21-.245-.428-.497-.602-.792a4.104 4.104 0 01-.462-1.135 4.258 4.258 0 01-.024-1.85 4.25 4.25 0 01.686-1.564 4.216 4.216 0 013.432-1.773H12.042a4.202 4.202 0 013.432 1.773c.33.466.568 1.007.686 1.565a4.27 4.27 0 01-.023 1.849c-.093.39-.249.772-.463 1.135-.173.295-.391.547-.602.792l-.123.142-.004.004a6.736 6.736 0 00-1.301 2.033 6.607 6.607 0 00-.49 2.37 4.897 4.897 0 00.94 2.99c.463.642.937.995 1.076 1.083a11.776 11.776 0 002.687-1.087 3.399 3.399 0 01-1.789-2.988c0-.817.313-1.59.956-2.359.009-.012.02-.022.027-.03l.006-.004.184-.204c.183-.2.355-.39.51-.596a7.14 7.14 0 001.22-2.608 7.21 7.21 0 00.04-3.124 7.185 7.185 0 00-1.16-2.65 7.203 7.203 0 00-2.044-1.924 7.074 7.074 0 00-3.762-1.075h-.09zM12 9.97a2.365 2.365 0 00-2.362 2.361A2.364 2.364 0 0012 14.691c1.301 0 2.36-1.059 2.36-2.36A2.364 2.364 0 0012 9.968z"
2952
+ />,
3037
2953
  );
3038
2954
  } else if (icon === IconProp.Gauge) {
3039
2955
  // Gauge/speedometer icon — semicircular meter with needle
@@ -183,17 +183,14 @@ const NavBarMenuModal: FunctionComponent<ComponentProps> = (
183
183
  return isApplePlatform ? "⌘K" : "Ctrl K";
184
184
  }, []);
185
185
 
186
- // Filter items by the search query (title + description + category).
186
+ // Filter items by the search query (title only).
187
187
  const filteredItems: MoreMenuItem[] = useMemo(() => {
188
188
  const normalizedQuery: string = query.trim().toLowerCase();
189
189
  if (!normalizedQuery) {
190
190
  return props.items;
191
191
  }
192
192
  return props.items.filter((item: MoreMenuItem) => {
193
- const haystack: string = `${item.title} ${item.description} ${
194
- item.category || ""
195
- }`.toLowerCase();
196
- return haystack.includes(normalizedQuery);
193
+ return item.title.toLowerCase().includes(normalizedQuery);
197
194
  });
198
195
  }, [props.items, query]);
199
196