@oneuptime/common 10.0.69 → 10.0.71
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/Models/DatabaseModels/KubernetesCluster.ts +7 -0
- package/Models/DatabaseModels/Project.ts +5 -5
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776865086264-MigrationName.ts +11 -8
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776881254913-DedupeKubernetesClustersAndAddUniqueIndex.ts +137 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Services/AIBillingService.ts +2 -2
- package/Server/Services/BillingService.ts +116 -48
- package/Server/Services/DatabaseService.ts +10 -27
- package/Server/Services/KubernetesResourceService.ts +33 -10
- package/Server/Services/NotificationService.ts +2 -2
- package/Server/Types/Database/QueryHelper.ts +127 -0
- package/Server/Types/Database/QueryUtil.ts +250 -0
- package/Server/Utils/Monitor/MonitorAlert.ts +79 -0
- package/Server/Utils/Monitor/MonitorIncident.ts +79 -0
- package/Types/BaseDatabase/EndsWith.ts +41 -0
- package/Types/BaseDatabase/IncludesAll.ts +45 -0
- package/Types/BaseDatabase/IncludesNone.ts +45 -0
- package/Types/BaseDatabase/NotContains.ts +41 -0
- package/Types/BaseDatabase/StartsWith.ts +41 -0
- package/Types/Email.ts +50 -0
- package/Types/JSON.ts +20 -0
- package/Types/SerializableObjectDictionary.ts +10 -0
- package/UI/Components/Filters/BooleanFilter.tsx +1 -0
- package/UI/Components/Filters/DateFilter.tsx +220 -25
- package/UI/Components/Filters/DropdownFilter.tsx +1 -0
- package/UI/Components/Filters/EntityFilter.tsx +229 -41
- package/UI/Components/Filters/FilterViewer.tsx +231 -147
- package/UI/Components/Filters/FilterViewerItem.tsx +1 -11
- package/UI/Components/Filters/FiltersForm.tsx +146 -97
- package/UI/Components/Filters/NumberFilter.tsx +220 -34
- package/UI/Components/Filters/OperatorSelector.tsx +91 -0
- package/UI/Components/Filters/TextFilter.tsx +183 -71
- package/UI/Components/Filters/Types/FilterOperator.ts +73 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +10 -0
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +9 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +5 -5
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776865086264-MigrationName.js +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776865086264-MigrationName.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776881254913-DedupeKubernetesClustersAndAddUniqueIndex.js +125 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776881254913-DedupeKubernetesClustersAndAddUniqueIndex.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIBillingService.js +2 -2
- package/build/dist/Server/Services/AIBillingService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +99 -39
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +9 -6
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesResourceService.js +4 -2
- package/build/dist/Server/Services/KubernetesResourceService.js.map +1 -1
- package/build/dist/Server/Services/NotificationService.js +2 -2
- package/build/dist/Server/Services/NotificationService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +110 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryUtil.js +186 -0
- package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +68 -0
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +68 -0
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Types/BaseDatabase/EndsWith.js +31 -0
- package/build/dist/Types/BaseDatabase/EndsWith.js.map +1 -0
- package/build/dist/Types/BaseDatabase/IncludesAll.js +34 -0
- package/build/dist/Types/BaseDatabase/IncludesAll.js.map +1 -0
- package/build/dist/Types/BaseDatabase/IncludesNone.js +34 -0
- package/build/dist/Types/BaseDatabase/IncludesNone.js.map +1 -0
- package/build/dist/Types/BaseDatabase/NotContains.js +31 -0
- package/build/dist/Types/BaseDatabase/NotContains.js.map +1 -0
- package/build/dist/Types/BaseDatabase/StartsWith.js +31 -0
- package/build/dist/Types/BaseDatabase/StartsWith.js.map +1 -0
- package/build/dist/Types/Email.js +42 -0
- package/build/dist/Types/Email.js.map +1 -1
- package/build/dist/Types/JSON.js +5 -0
- package/build/dist/Types/JSON.js.map +1 -1
- package/build/dist/Types/SerializableObjectDictionary.js +10 -0
- package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
- package/build/dist/UI/Components/Filters/BooleanFilter.js +1 -1
- package/build/dist/UI/Components/Filters/BooleanFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/DateFilter.js +155 -14
- package/build/dist/UI/Components/Filters/DateFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/DropdownFilter.js +1 -1
- package/build/dist/UI/Components/Filters/DropdownFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/EntityFilter.js +181 -30
- package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/FilterViewer.js +188 -98
- package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
- package/build/dist/UI/Components/Filters/FilterViewerItem.js +1 -6
- package/build/dist/UI/Components/Filters/FilterViewerItem.js.map +1 -1
- package/build/dist/UI/Components/Filters/FiltersForm.js +46 -38
- package/build/dist/UI/Components/Filters/FiltersForm.js.map +1 -1
- package/build/dist/UI/Components/Filters/NumberFilter.js +164 -23
- package/build/dist/UI/Components/Filters/NumberFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/OperatorSelector.js +41 -0
- package/build/dist/UI/Components/Filters/OperatorSelector.js.map +1 -0
- package/build/dist/UI/Components/Filters/TextFilter.js +131 -53
- package/build/dist/UI/Components/Filters/TextFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/Types/FilterOperator.js +63 -0
- package/build/dist/UI/Components/Filters/Types/FilterOperator.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +9 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,21 @@
|
|
|
1
|
+
import Icon, { SizeProp } from "../Icon/Icon";
|
|
1
2
|
import Includes from "../../../Types/BaseDatabase/Includes";
|
|
3
|
+
import IncludesAll from "../../../Types/BaseDatabase/IncludesAll";
|
|
4
|
+
import IncludesNone from "../../../Types/BaseDatabase/IncludesNone";
|
|
5
|
+
import StartsWith from "../../../Types/BaseDatabase/StartsWith";
|
|
6
|
+
import EndsWith from "../../../Types/BaseDatabase/EndsWith";
|
|
7
|
+
import NotContains from "../../../Types/BaseDatabase/NotContains";
|
|
8
|
+
import EqualTo from "../../../Types/BaseDatabase/EqualTo";
|
|
9
|
+
import NotEqual from "../../../Types/BaseDatabase/NotEqual";
|
|
10
|
+
import GreaterThan from "../../../Types/BaseDatabase/GreaterThan";
|
|
11
|
+
import LessThan from "../../../Types/BaseDatabase/LessThan";
|
|
12
|
+
import GreaterThanOrEqual from "../../../Types/BaseDatabase/GreaterThanOrEqual";
|
|
13
|
+
import LessThanOrEqual from "../../../Types/BaseDatabase/LessThanOrEqual";
|
|
14
|
+
import IsNull from "../../../Types/BaseDatabase/IsNull";
|
|
15
|
+
import NotNull from "../../../Types/BaseDatabase/NotNull";
|
|
2
16
|
import Button, { ButtonStyleType } from "../Button/Button";
|
|
3
17
|
import { DropdownOption } from "../Dropdown/Dropdown";
|
|
4
18
|
import ErrorMessage from "../ErrorMessage/ErrorMessage";
|
|
5
|
-
import { SizeProp } from "../Icon/Icon";
|
|
6
19
|
import Modal, { ModalWidth } from "../Modal/Modal";
|
|
7
20
|
import FieldType from "../Types/FieldType";
|
|
8
21
|
import FilterViewerItem from "./FilterViewerItem";
|
|
@@ -151,13 +164,12 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
151
164
|
|
|
152
165
|
if (data.filter.type === FieldType.Boolean) {
|
|
153
166
|
filterText = (
|
|
154
|
-
<
|
|
155
|
-
{" "}
|
|
167
|
+
<span>
|
|
156
168
|
<span className="font-medium">{data.filter.title}</span> is{" "}
|
|
157
169
|
<span className="font-medium">
|
|
158
170
|
{data.filterData[data.filter.key] ? "Yes" : "No"}
|
|
159
|
-
</span>
|
|
160
|
-
</
|
|
171
|
+
</span>
|
|
172
|
+
</span>
|
|
161
173
|
);
|
|
162
174
|
return filterText;
|
|
163
175
|
}
|
|
@@ -168,34 +180,83 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
168
180
|
data.filter.type === FieldType.Email ||
|
|
169
181
|
data.filter.type === FieldType.Phone ||
|
|
170
182
|
data.filter.type === FieldType.URL ||
|
|
171
|
-
data.filter.type === FieldType.Hostname
|
|
183
|
+
data.filter.type === FieldType.Hostname ||
|
|
184
|
+
data.filter.type === FieldType.LongText ||
|
|
185
|
+
data.filter.type === FieldType.Name ||
|
|
186
|
+
data.filter.type === FieldType.Port ||
|
|
187
|
+
data.filter.type === FieldType.ObjectID
|
|
172
188
|
) {
|
|
173
189
|
const key: keyof T = data.filter.key;
|
|
190
|
+
const value: unknown = data.filterData[key];
|
|
174
191
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
<span className="font-medium">
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
</div>
|
|
192
|
+
type RenderFunction = (verb: string, display: string) => ReactElement;
|
|
193
|
+
const render: RenderFunction = (
|
|
194
|
+
verb: string,
|
|
195
|
+
display: string,
|
|
196
|
+
): ReactElement => {
|
|
197
|
+
return (
|
|
198
|
+
<span>
|
|
199
|
+
<span className="font-medium">{data.filter.title}</span> {verb}{" "}
|
|
200
|
+
<span className="font-medium">{display}</span>
|
|
201
|
+
</span>
|
|
186
202
|
);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
<span className="font-medium">
|
|
193
|
-
|
|
194
|
-
</span>{" "}
|
|
195
|
-
</div>
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
if (value instanceof IsNull) {
|
|
206
|
+
return (
|
|
207
|
+
<span>
|
|
208
|
+
<span className="font-medium">{data.filter.title}</span> is empty
|
|
209
|
+
</span>
|
|
196
210
|
);
|
|
197
211
|
}
|
|
198
|
-
|
|
212
|
+
if (value instanceof NotNull) {
|
|
213
|
+
return (
|
|
214
|
+
<span>
|
|
215
|
+
<span className="font-medium">{data.filter.title}</span> is not
|
|
216
|
+
empty
|
|
217
|
+
</span>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
if (value instanceof Search) {
|
|
221
|
+
return render("contains", value.toString());
|
|
222
|
+
}
|
|
223
|
+
if (value instanceof NotContains) {
|
|
224
|
+
return render("does not contain", value.toString());
|
|
225
|
+
}
|
|
226
|
+
if (value instanceof StartsWith) {
|
|
227
|
+
return render("starts with", value.toString());
|
|
228
|
+
}
|
|
229
|
+
if (value instanceof EndsWith) {
|
|
230
|
+
return render("ends with", value.toString());
|
|
231
|
+
}
|
|
232
|
+
if (value instanceof InBetween) {
|
|
233
|
+
return render(
|
|
234
|
+
"is between",
|
|
235
|
+
`${value.startValue} and ${value.endValue}`,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
if (value instanceof GreaterThanOrEqual) {
|
|
239
|
+
return render("is ≥", value.toString());
|
|
240
|
+
}
|
|
241
|
+
if (value instanceof LessThanOrEqual) {
|
|
242
|
+
return render("is ≤", value.toString());
|
|
243
|
+
}
|
|
244
|
+
if (value instanceof GreaterThan) {
|
|
245
|
+
return render("is greater than", value.toString());
|
|
246
|
+
}
|
|
247
|
+
if (value instanceof LessThan) {
|
|
248
|
+
return render("is less than", value.toString());
|
|
249
|
+
}
|
|
250
|
+
if (value instanceof NotEqual) {
|
|
251
|
+
return render("does not equal", value.toString());
|
|
252
|
+
}
|
|
253
|
+
if (value instanceof EqualTo) {
|
|
254
|
+
return render("equals", value.toString());
|
|
255
|
+
}
|
|
256
|
+
if (value !== undefined && value !== null && value !== "") {
|
|
257
|
+
return render("is", (value as any).toString());
|
|
258
|
+
}
|
|
259
|
+
return null;
|
|
199
260
|
}
|
|
200
261
|
|
|
201
262
|
if (
|
|
@@ -203,62 +264,67 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
203
264
|
data.filter.type === FieldType.DateTime
|
|
204
265
|
) {
|
|
205
266
|
const key: keyof T = data.filter.key;
|
|
206
|
-
|
|
207
|
-
const startAndEndDates: InBetween<Date> = data.filterData[
|
|
208
|
-
key
|
|
209
|
-
] as InBetween<Date>;
|
|
267
|
+
const value: unknown = data.filterData[key];
|
|
210
268
|
|
|
211
269
|
const shouldOnlyShowDate: boolean = data.filter.type === FieldType.Date;
|
|
212
270
|
const shouldShowSeconds: boolean =
|
|
213
271
|
data.filter.type === FieldType.DateTime;
|
|
214
272
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
273
|
+
type FormatFunction = (d: Date) => string;
|
|
274
|
+
const format: FormatFunction = (d: Date): string => {
|
|
275
|
+
return OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
|
|
276
|
+
d,
|
|
218
277
|
shouldOnlyShowDate,
|
|
219
278
|
shouldShowSeconds,
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
279
|
+
);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
type RenderFunction = (verb: string, display: string) => ReactElement;
|
|
283
|
+
const render: RenderFunction = (
|
|
284
|
+
verb: string,
|
|
285
|
+
display: string,
|
|
286
|
+
): ReactElement => {
|
|
227
287
|
return (
|
|
228
|
-
<
|
|
229
|
-
{" "}
|
|
230
|
-
<span className="font-medium">{
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
288
|
+
<span>
|
|
289
|
+
<span className="font-medium">{data.filter.title}</span> {verb}{" "}
|
|
290
|
+
<span className="font-medium">{display}</span>
|
|
291
|
+
</span>
|
|
292
|
+
);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
if (value instanceof IsNull) {
|
|
296
|
+
return (
|
|
297
|
+
<span>
|
|
298
|
+
<span className="font-medium">{data.filter.title}</span> is empty
|
|
299
|
+
</span>
|
|
239
300
|
);
|
|
240
301
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
302
|
+
if (value instanceof NotNull) {
|
|
303
|
+
return (
|
|
304
|
+
<span>
|
|
305
|
+
<span className="font-medium">{data.filter.title}</span> is not
|
|
306
|
+
empty
|
|
307
|
+
</span>
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
if (value instanceof InBetween) {
|
|
311
|
+
const start: Date = value.startValue as unknown as Date;
|
|
312
|
+
const end: Date = value.endValue as unknown as Date;
|
|
313
|
+
if (format(start) === format(end)) {
|
|
314
|
+
return render("is", format(start));
|
|
315
|
+
}
|
|
316
|
+
return render("is between", `${format(start)} and ${format(end)}`);
|
|
317
|
+
}
|
|
318
|
+
if (value instanceof GreaterThan) {
|
|
319
|
+
return render("is after", format(value.value as unknown as Date));
|
|
320
|
+
}
|
|
321
|
+
if (value instanceof LessThan) {
|
|
322
|
+
return render("is before", format(value.value as unknown as Date));
|
|
323
|
+
}
|
|
324
|
+
if (value instanceof EqualTo) {
|
|
325
|
+
return render("is", format(value.value as unknown as Date));
|
|
326
|
+
}
|
|
327
|
+
return null;
|
|
262
328
|
}
|
|
263
329
|
|
|
264
330
|
if (data.filter.type === FieldType.JSON) {
|
|
@@ -277,14 +343,11 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
277
343
|
const isPlural: boolean = Object.keys(json).length > 1;
|
|
278
344
|
|
|
279
345
|
return (
|
|
280
|
-
<
|
|
281
|
-
|
|
282
|
-
<
|
|
283
|
-
<
|
|
284
|
-
|
|
285
|
-
</div>
|
|
286
|
-
<div className="font-medium">{formatJson(json)}</div>{" "}
|
|
287
|
-
</div>
|
|
346
|
+
<span className="inline-flex items-center space-x-1">
|
|
347
|
+
<span className="font-medium">{data.filter.title}</span>
|
|
348
|
+
<span>{isPlural ? "are" : "is"}</span>
|
|
349
|
+
<span className="font-medium">{formatJson(json)}</span>
|
|
350
|
+
</span>
|
|
288
351
|
);
|
|
289
352
|
}
|
|
290
353
|
|
|
@@ -295,56 +358,83 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
295
358
|
data.filter.type === FieldType.EntityArray
|
|
296
359
|
) {
|
|
297
360
|
const key: keyof T = data.filter.key;
|
|
361
|
+
const rawValue: unknown = data.filterData[key];
|
|
298
362
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
363
|
+
if (rawValue instanceof IsNull) {
|
|
364
|
+
return (
|
|
365
|
+
<span>
|
|
366
|
+
<span className="font-medium">{data.filter.title}</span> is empty
|
|
367
|
+
</span>
|
|
368
|
+
);
|
|
303
369
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
370
|
+
if (rawValue instanceof NotNull) {
|
|
371
|
+
return (
|
|
372
|
+
<span>
|
|
373
|
+
<span className="font-medium">{data.filter.title}</span> is not
|
|
374
|
+
empty
|
|
375
|
+
</span>
|
|
376
|
+
);
|
|
307
377
|
}
|
|
308
378
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
return null;
|
|
328
|
-
})
|
|
329
|
-
.filter((item: string | null) => {
|
|
330
|
-
return item !== null;
|
|
331
|
-
})
|
|
332
|
-
.join(", ");
|
|
379
|
+
let items: Array<string> = [];
|
|
380
|
+
type MatchMode = "any" | "all" | "none";
|
|
381
|
+
let matchMode: MatchMode = "any";
|
|
382
|
+
|
|
383
|
+
if (rawValue instanceof IncludesAll) {
|
|
384
|
+
items = rawValue.values as Array<string>;
|
|
385
|
+
matchMode = "all";
|
|
386
|
+
} else if (rawValue instanceof IncludesNone) {
|
|
387
|
+
items = rawValue.values as Array<string>;
|
|
388
|
+
matchMode = "none";
|
|
389
|
+
} else if (rawValue instanceof Includes) {
|
|
390
|
+
items = rawValue.values as Array<string>;
|
|
391
|
+
} else if (Array.isArray(rawValue)) {
|
|
392
|
+
items = rawValue as Array<string>;
|
|
393
|
+
} else if (typeof rawValue === "string") {
|
|
394
|
+
items = [rawValue];
|
|
395
|
+
}
|
|
333
396
|
|
|
334
|
-
|
|
397
|
+
const entityNames: string = items
|
|
398
|
+
.map((item: string) => {
|
|
399
|
+
const entity: DropdownOption | undefined =
|
|
400
|
+
data.filter.filterDropdownOptions?.find(
|
|
401
|
+
(e: DropdownOption | undefined) => {
|
|
402
|
+
return e?.value.toString() === item.toString();
|
|
403
|
+
},
|
|
404
|
+
);
|
|
405
|
+
if (entity) {
|
|
406
|
+
return entity.label.toString();
|
|
407
|
+
}
|
|
335
408
|
return null;
|
|
336
|
-
}
|
|
409
|
+
})
|
|
410
|
+
.filter((name: string | null) => {
|
|
411
|
+
return name !== null;
|
|
412
|
+
})
|
|
413
|
+
.join(", ");
|
|
337
414
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
<span className="font-medium">{data.filter.title}</span>
|
|
341
|
-
{isMoreItems ? " is any of these values: " : " is "}
|
|
342
|
-
<span className="font-medium">{entityNames}</span>
|
|
343
|
-
</div>
|
|
344
|
-
);
|
|
415
|
+
if (!entityNames) {
|
|
416
|
+
return null;
|
|
345
417
|
}
|
|
346
418
|
|
|
347
|
-
|
|
419
|
+
const isMoreItems: boolean = items.length > 1;
|
|
420
|
+
let joiner: string;
|
|
421
|
+
if (matchMode === "all") {
|
|
422
|
+
joiner = " has all of: ";
|
|
423
|
+
} else if (matchMode === "none") {
|
|
424
|
+
joiner = " has none of: ";
|
|
425
|
+
} else if (isMoreItems) {
|
|
426
|
+
joiner = " is any of: ";
|
|
427
|
+
} else {
|
|
428
|
+
joiner = " is ";
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return (
|
|
432
|
+
<span>
|
|
433
|
+
<span className="font-medium">{data.filter.title}</span>
|
|
434
|
+
{joiner}
|
|
435
|
+
<span className="font-medium">{entityNames}</span>
|
|
436
|
+
</span>
|
|
437
|
+
);
|
|
348
438
|
}
|
|
349
439
|
|
|
350
440
|
return filterText;
|
|
@@ -365,36 +455,30 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
365
455
|
<div>
|
|
366
456
|
{showViewer && (
|
|
367
457
|
<div>
|
|
368
|
-
<div className="mt-
|
|
369
|
-
<div className="flex
|
|
370
|
-
<div className="flex-
|
|
458
|
+
<div className="mt-4 mb-4 bg-gray-50 rounded-xl p-4 border border-gray-200">
|
|
459
|
+
<div className="flex items-center justify-between mb-3">
|
|
460
|
+
<div className="flex items-center gap-2 text-sm text-gray-700">
|
|
461
|
+
<Icon icon={IconProp.Filter} size={SizeProp.Smaller} />
|
|
371
462
|
<span className="font-semibold">
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
</span>{" "}
|
|
463
|
+
Showing {props.pluralLabel || "results"} that match
|
|
464
|
+
</span>
|
|
375
465
|
</div>
|
|
376
466
|
</div>
|
|
377
467
|
|
|
378
|
-
<
|
|
468
|
+
<div className="flex flex-wrap gap-2">
|
|
379
469
|
{filterTexts.map((filterText: ReactElement, index: number) => {
|
|
380
|
-
const isLastItem: boolean = index === filterTexts.length - 1;
|
|
381
470
|
return (
|
|
382
|
-
<
|
|
383
|
-
{
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
<div className="relative flex h-6 w-6 flex-none items-center justify-center bg-gray-50">
|
|
389
|
-
<div className="h-1.5 w-1.5 rounded-full bg-gray-100 ring-1 ring-gray-300"></div>
|
|
390
|
-
</div>
|
|
391
|
-
<FilterViewerItem key={index} text={filterText} />{" "}
|
|
392
|
-
</li>
|
|
471
|
+
<div
|
|
472
|
+
key={index}
|
|
473
|
+
className="inline-flex items-center rounded-full bg-white border border-gray-200 px-3 py-1 text-sm text-gray-700 shadow-sm whitespace-nowrap"
|
|
474
|
+
>
|
|
475
|
+
<FilterViewerItem key={index} text={filterText} />
|
|
476
|
+
</div>
|
|
393
477
|
);
|
|
394
478
|
})}
|
|
395
|
-
</
|
|
479
|
+
</div>
|
|
396
480
|
|
|
397
|
-
<div className="flex -ml-3 mt-3 -mb-
|
|
481
|
+
<div className="flex -ml-3 mt-3 -mb-1">
|
|
398
482
|
{/** Edit Filter Button */}
|
|
399
483
|
<Button
|
|
400
484
|
className="font-medium text-gray-900"
|
|
@@ -425,10 +509,10 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
425
509
|
<Modal
|
|
426
510
|
modalWidth={ModalWidth.Large}
|
|
427
511
|
isLoading={props.isModalLoading}
|
|
428
|
-
title={
|
|
429
|
-
description={`
|
|
430
|
-
props.pluralLabel || ""
|
|
431
|
-
} by
|
|
512
|
+
title={`Filter ${props.pluralLabel || props.singularLabel || "results"}`}
|
|
513
|
+
description={`Narrow down ${
|
|
514
|
+
props.pluralLabel || "results"
|
|
515
|
+
} by one or more criteria below.`}
|
|
432
516
|
submitButtonText={`Apply Filters`}
|
|
433
517
|
onClose={() => {
|
|
434
518
|
props.onFilterModalClose?.();
|
|
@@ -11,17 +11,7 @@ type FilterViewerItemComponentFunction = (
|
|
|
11
11
|
const FilterViewerItem: FilterViewerItemComponentFunction = (
|
|
12
12
|
props: ComponentProps,
|
|
13
13
|
): ReactElement => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<div className="flex w-full -ml-3">
|
|
18
|
-
<div className="flex">
|
|
19
|
-
<div className="ml-1 flex-auto py-0.5 text-sm leading-5 text-gray-500">
|
|
20
|
-
<span className="text-gray-900">{text}</span>{" "}
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
24
|
-
);
|
|
14
|
+
return <span className="text-gray-800 leading-5">{props.text}</span>;
|
|
25
15
|
};
|
|
26
16
|
|
|
27
17
|
export default FilterViewerItem;
|