@drodil/backstage-plugin-qeta-react 3.59.6 → 3.59.7

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.
@@ -3,7 +3,7 @@ import { Autocomplete } from '@material-ui/lab';
3
3
  import { getEntityTitle, getEntityDescription } from '../../utils/utils.esm.js';
4
4
  import { stringifyEntityRef } from '@backstage/catalog-model';
5
5
  import { Box, TextField, CircularProgress, Tooltip, Typography, Chip } from '@material-ui/core';
6
- import { forwardRef, useState, useMemo, useCallback } from 'react';
6
+ import { forwardRef, useState, useRef, useMemo, useEffect, useCallback } from 'react';
7
7
  import { useApi, configApiRef } from '@backstage/core-plugin-api';
8
8
  import { catalogApiRef } from '@backstage/plugin-catalog-react';
9
9
  import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
@@ -24,6 +24,142 @@ const CATALOG_FIELDS = [
24
24
  "spec.profile.displayName",
25
25
  "spec.profile.email"
26
26
  ];
27
+ const CATALOG_SEARCH_FIELDS = [
28
+ "metadata.name",
29
+ "metadata.title",
30
+ "spec.profile.displayName",
31
+ "spec.profile.email"
32
+ ];
33
+ const CATALOG_DEFAULT_ORDER_FIELDS = [
34
+ {
35
+ field: "metadata.name",
36
+ order: "asc"
37
+ }
38
+ ];
39
+ const ENTITY_SEARCH_LIMIT = 25;
40
+ const ENTITY_KIND_KEY_SEPARATOR = "\0";
41
+ const getEntityKindsKey = (entityKinds) => [...entityKinds].sort((left, right) => left.localeCompare(right)).join(ENTITY_KIND_KEY_SEPARATOR);
42
+ const getEntityKindsFromKey = (entityKindsKey) => entityKindsKey ? entityKindsKey.split(ENTITY_KIND_KEY_SEPARATOR) : [];
43
+ const getEntitySearchQuery = (entityKinds) => {
44
+ if (entityKinds.length === 0) {
45
+ return void 0;
46
+ }
47
+ if (entityKinds.length === 1) {
48
+ return { kind: entityKinds[0] };
49
+ }
50
+ return {
51
+ kind: {
52
+ $in: entityKinds
53
+ }
54
+ };
55
+ };
56
+ const getEntitySearchCacheScope = (term, useOnlyUsedEntities, hasExplicitKinds) => {
57
+ if (!term) {
58
+ return hasExplicitKinds ? "catalog-defaults" : "used-defaults";
59
+ }
60
+ if (useOnlyUsedEntities) {
61
+ return "used";
62
+ }
63
+ return "catalog";
64
+ };
65
+ const getUsedEntitiesRequest = (term) => ({
66
+ limit: ENTITY_SEARCH_LIMIT,
67
+ orderBy: "postsCount",
68
+ order: "desc",
69
+ ...term ? { searchQuery: term } : {}
70
+ });
71
+ const loadUsedEntities = async (params) => {
72
+ const { catalogQuery, getEntities, getEntitiesByRefs, term } = params;
73
+ const qetaEntities = await getEntities(getUsedEntitiesRequest(term));
74
+ const refs = qetaEntities.entities.map((entity) => entity.entityRef);
75
+ if (refs.length === 0) {
76
+ return [];
77
+ }
78
+ const catalogData = await getEntitiesByRefs({
79
+ entityRefs: refs,
80
+ fields: CATALOG_FIELDS,
81
+ ...catalogQuery ? { query: catalogQuery } : {}
82
+ });
83
+ return compact(catalogData.items);
84
+ };
85
+ const loadCatalogEntities = async (params) => {
86
+ const { catalogQuery, queryEntities, term } = params;
87
+ const request = {
88
+ query: catalogQuery,
89
+ limit: ENTITY_SEARCH_LIMIT,
90
+ fields: CATALOG_FIELDS,
91
+ orderFields: CATALOG_DEFAULT_ORDER_FIELDS
92
+ };
93
+ if (term) {
94
+ request.fullTextFilter = {
95
+ term,
96
+ fields: CATALOG_SEARCH_FIELDS
97
+ };
98
+ }
99
+ const entities = await queryEntities(request);
100
+ return compact(entities.items);
101
+ };
102
+ const mergeEntities = (...groups) => {
103
+ const seen = /* @__PURE__ */ new Set();
104
+ const merged = [];
105
+ for (const entity of groups.flat()) {
106
+ if (!entity) {
107
+ continue;
108
+ }
109
+ const entityRef = stringifyEntityRef(entity);
110
+ if (!seen.has(entityRef)) {
111
+ seen.add(entityRef);
112
+ merged.push(entity);
113
+ }
114
+ }
115
+ return merged;
116
+ };
117
+ const getCurrentValueEntities = (value) => [value ?? []].flat();
118
+ const handleEntitySelectionChange = ({
119
+ max,
120
+ multiple,
121
+ newValue,
122
+ onChange
123
+ }) => {
124
+ if (multiple) {
125
+ if (!newValue) {
126
+ onChange([]);
127
+ return;
128
+ }
129
+ const values = Array.isArray(newValue) ? newValue : [newValue];
130
+ if (max === null || values.length <= max) {
131
+ onChange(values.filter((v) => typeof v !== "string"));
132
+ }
133
+ return;
134
+ }
135
+ if (newValue) {
136
+ onChange(newValue);
137
+ }
138
+ };
139
+ const handleAutocompleteInputChange = ({
140
+ nextValue,
141
+ reason,
142
+ setInputValue
143
+ }) => {
144
+ if (reason === "reset") {
145
+ setInputValue("");
146
+ return;
147
+ }
148
+ setInputValue(nextValue);
149
+ };
150
+ const appendSuggestedEntity = ({
151
+ entity,
152
+ max,
153
+ values
154
+ }) => {
155
+ if (values.includes(entity)) {
156
+ return void 0;
157
+ }
158
+ if (max !== null && values.length >= max) {
159
+ return void 0;
160
+ }
161
+ return [...values, entity];
162
+ };
27
163
  const EntitiesInput = forwardRef(
28
164
  (props, _ref) => {
29
165
  const {
@@ -50,71 +186,177 @@ const EntitiesInput = forwardRef(
50
186
  const configApi = useApi(configApiRef);
51
187
  const catalogApi = useApi(catalogApiRef);
52
188
  const qetaApi = useApi(qetaApiRef);
53
- const [availableEntities, setAvailableEntities] = useState(
54
- []
55
- );
189
+ const [availableEntities, setAvailableEntities] = useState([]);
56
190
  const [loading, setLoading] = useState(false);
57
191
  const [open, setOpen] = useState(false);
58
192
  const { t } = useTranslationRef(qetaTranslationRef);
59
193
  const [suggestedEntities, setSuggestedEntities] = useState([]);
60
- const [, setLoadingSuggestions] = useState(false);
194
+ const [loadingSuggestions, setLoadingSuggestions] = useState(false);
195
+ const [inputValue, setInputValue] = useState("");
196
+ const searchCache = useRef(/* @__PURE__ */ new Map());
197
+ const activeRequest = useRef(0);
198
+ const explicitEntityKindsKey = useMemo(
199
+ () => getEntityKindsKey(kind ?? []),
200
+ [kind]
201
+ );
61
202
  const entityKinds = useMemo(() => {
62
- if (kind) {
63
- return kind;
203
+ if (explicitEntityKindsKey) {
204
+ return getEntityKindsFromKey(explicitEntityKindsKey);
64
205
  }
65
206
  return getSupportedEntityKinds(configApi);
66
- }, [configApi, kind]);
207
+ }, [configApi, explicitEntityKindsKey]);
67
208
  const max = useMemo(() => {
68
209
  if (maximum) {
69
210
  return maximum;
70
211
  }
71
212
  return configApi.getOptionalNumber("qeta.entities.max") ?? 3;
72
213
  }, [configApi, maximum]);
73
- const handleOpen = useCallback(() => {
74
- setOpen(true);
75
- (async () => {
76
- setLoading(true);
77
- if (singleValue) {
78
- const entity = await catalogApi.getEntityByRef(singleValue);
79
- setLoading(false);
80
- setAvailableEntities(entity ? [entity] : null);
81
- return;
82
- }
83
- if (useOnlyUsedEntities) {
84
- const qetaEntities = await qetaApi.getEntities();
85
- const refs = qetaEntities.entities.map((r) => r.entityRef);
86
- const catalogData = await catalogApi.getEntitiesByRefs({
87
- entityRefs: refs,
88
- fields: CATALOG_FIELDS
89
- });
90
- setLoading(false);
91
- setAvailableEntities(
92
- catalogData ? compact(catalogData.items).sort(
93
- (a, b) => getEntityTitle(a).localeCompare(getEntityTitle(b))
94
- ) : null
95
- );
96
- return;
97
- }
98
- if (entityKinds && entityKinds.length > 0) {
99
- const entities = await catalogApi.getEntities({
100
- filter: { kind: entityKinds },
101
- fields: CATALOG_FIELDS,
102
- order: { field: "kind", order: "asc" }
103
- });
104
- setLoading(false);
105
- setAvailableEntities(entities ? entities.items : null);
106
- return;
107
- }
108
- setLoading(false);
109
- setAvailableEntities(null);
110
- })();
111
- }, [singleValue, useOnlyUsedEntities, entityKinds, catalogApi, qetaApi]);
214
+ const entityKindsKey = useMemo(
215
+ () => getEntityKindsKey(entityKinds),
216
+ [entityKinds]
217
+ );
218
+ const hasExplicitKinds = explicitEntityKindsKey.length > 0;
219
+ const valueEntities = useMemo(
220
+ () => getCurrentValueEntities(value),
221
+ [value]
222
+ );
223
+ const helperText = useMemo(
224
+ () => hideHelpText ? "" : error?.message ?? t("entitiesInput.helperText", {
225
+ max: max?.toString() ?? ""
226
+ }),
227
+ [error?.message, hideHelpText, max, t]
228
+ );
112
229
  const usedValue = useMemo(() => {
113
230
  if (!value) {
114
231
  return multiple ? [] : null;
115
232
  }
116
233
  return value;
117
234
  }, [value, multiple]);
235
+ const selectedEntities = useMemo(
236
+ () => mergeEntities(Array.isArray(usedValue) ? usedValue : [usedValue]),
237
+ [usedValue]
238
+ );
239
+ const options = useMemo(
240
+ () => mergeEntities(selectedEntities, availableEntities),
241
+ [availableEntities, selectedEntities]
242
+ );
243
+ const displayedInputValue = useMemo(() => {
244
+ if (!multiple && !open && usedValue && !Array.isArray(usedValue)) {
245
+ return getEntityTitle(usedValue);
246
+ }
247
+ return inputValue;
248
+ }, [inputValue, multiple, open, usedValue]);
249
+ useEffect(() => {
250
+ searchCache.current.clear();
251
+ activeRequest.current += 1;
252
+ setAvailableEntities([]);
253
+ setInputValue("");
254
+ setLoading(false);
255
+ }, [entityKindsKey, singleValue, useOnlyUsedEntities]);
256
+ useEffect(() => {
257
+ if (!singleValue) {
258
+ return void 0;
259
+ }
260
+ if (selectedEntities.some(
261
+ (entity) => stringifyEntityRef(entity) === singleValue
262
+ )) {
263
+ return void 0;
264
+ }
265
+ let active = true;
266
+ catalogApi.getEntityByRef(singleValue).then((entity) => {
267
+ if (!active || !entity) {
268
+ return;
269
+ }
270
+ setAvailableEntities((prev) => mergeEntities([entity], prev));
271
+ }).catch(() => {
272
+ });
273
+ return () => {
274
+ active = false;
275
+ };
276
+ }, [catalogApi, selectedEntities, singleValue]);
277
+ const searchEntities = useCallback(
278
+ async (term) => {
279
+ const trimmed = term.trim();
280
+ const currentEntityKinds = getEntityKindsFromKey(entityKindsKey);
281
+ const catalogQuery = getEntitySearchQuery(currentEntityKinds);
282
+ const shouldLoadCatalogDefaults = !trimmed && hasExplicitKinds;
283
+ const shouldLoadUsedEntities = useOnlyUsedEntities || !trimmed && !hasExplicitKinds;
284
+ const cacheKey = [
285
+ getEntitySearchCacheScope(
286
+ trimmed,
287
+ useOnlyUsedEntities,
288
+ hasExplicitKinds
289
+ ),
290
+ entityKindsKey,
291
+ trimmed.toLocaleLowerCase()
292
+ ].join(":");
293
+ const cached = searchCache.current.get(cacheKey);
294
+ if (cached) {
295
+ setLoading(false);
296
+ setAvailableEntities((prev) => mergeEntities(prev, cached));
297
+ return;
298
+ }
299
+ const requestId = activeRequest.current + 1;
300
+ activeRequest.current = requestId;
301
+ setLoading(true);
302
+ try {
303
+ let nextEntities = [];
304
+ if (shouldLoadCatalogDefaults && catalogQuery) {
305
+ nextEntities = await loadCatalogEntities({
306
+ catalogQuery,
307
+ queryEntities: (request) => catalogApi.queryEntities(request),
308
+ term: ""
309
+ });
310
+ } else if (shouldLoadUsedEntities) {
311
+ nextEntities = await loadUsedEntities({
312
+ catalogQuery,
313
+ getEntities: (entityOptions) => qetaApi.getEntities(entityOptions),
314
+ getEntitiesByRefs: (request) => catalogApi.getEntitiesByRefs(request),
315
+ term: trimmed
316
+ });
317
+ } else if (catalogQuery) {
318
+ nextEntities = await loadCatalogEntities({
319
+ catalogQuery,
320
+ queryEntities: (request) => catalogApi.queryEntities(request),
321
+ term: trimmed
322
+ });
323
+ }
324
+ if (activeRequest.current !== requestId) {
325
+ return;
326
+ }
327
+ searchCache.current.set(cacheKey, nextEntities);
328
+ setAvailableEntities((prev) => mergeEntities(prev, nextEntities));
329
+ } catch {
330
+ } finally {
331
+ if (activeRequest.current === requestId) {
332
+ setLoading(false);
333
+ }
334
+ }
335
+ },
336
+ [
337
+ catalogApi,
338
+ entityKindsKey,
339
+ hasExplicitKinds,
340
+ qetaApi,
341
+ useOnlyUsedEntities
342
+ ]
343
+ );
344
+ const handleOpen = useCallback(() => {
345
+ setInputValue("");
346
+ setOpen(true);
347
+ }, []);
348
+ useEffect(() => {
349
+ searchEntities("");
350
+ }, [searchEntities]);
351
+ useDebounce(
352
+ () => {
353
+ if (open) {
354
+ searchEntities(inputValue);
355
+ }
356
+ },
357
+ 300,
358
+ [inputValue, open, searchEntities]
359
+ );
118
360
  useDebounce(
119
361
  () => {
120
362
  if (title && content) {
@@ -123,7 +365,7 @@ const EntitiesInput = forwardRef(
123
365
  title,
124
366
  content,
125
367
  tags,
126
- entities: [value ?? []].flat().map(stringifyEntityRef),
368
+ entities: valueEntities.map(stringifyEntityRef),
127
369
  limit: 5
128
370
  }).then((response) => {
129
371
  setSuggestedEntities(response.entities);
@@ -134,17 +376,18 @@ const EntitiesInput = forwardRef(
134
376
  }
135
377
  },
136
378
  2e3,
137
- [title, content, qetaApi]
379
+ [content, qetaApi, tags, title, valueEntities]
138
380
  );
139
381
  const handleSuggestedEntityClick = (entity) => {
140
- const values = [value ?? []].flat();
141
- if (values && values.length < max && !values.includes(entity)) {
142
- onChange([...values, entity]);
382
+ const nextValues = appendSuggestedEntity({
383
+ entity,
384
+ max,
385
+ values: valueEntities
386
+ });
387
+ if (nextValues) {
388
+ onChange(nextValues);
143
389
  }
144
390
  };
145
- if (!availableEntities) {
146
- return null;
147
- }
148
391
  return /* @__PURE__ */ jsxs(Box, { children: [
149
392
  /* @__PURE__ */ jsx(
150
393
  Autocomplete,
@@ -156,35 +399,40 @@ const EntitiesInput = forwardRef(
156
399
  value: usedValue,
157
400
  disabled,
158
401
  loading,
402
+ limitTags: max,
159
403
  loadingText: t("common.loading"),
160
404
  groupBy: entityKinds.length > 1 ? (option) => option.kind : void 0,
161
405
  renderGroup,
162
406
  handleHomeEndKeys: true,
163
407
  open,
164
408
  onOpen: handleOpen,
165
- onClose: () => setOpen(false),
166
- options: availableEntities,
409
+ onClose: () => {
410
+ activeRequest.current += 1;
411
+ setLoading(false);
412
+ setInputValue("");
413
+ setOpen(false);
414
+ },
415
+ options,
167
416
  getOptionLabel: getEntityTitle,
417
+ inputValue: displayedInputValue,
418
+ onInputChange: (_event, nextValue, reason) => {
419
+ handleAutocompleteInputChange({
420
+ nextValue,
421
+ reason,
422
+ setInputValue
423
+ });
424
+ },
168
425
  ListboxComponent: AutocompleteListboxComponent,
169
426
  disableListWrap: true,
170
427
  style,
171
428
  getOptionSelected: (o, v) => stringifyEntityRef(o) === stringifyEntityRef(v),
172
429
  onChange: (_e, newValue) => {
173
- if (multiple) {
174
- if (!newValue) {
175
- onChange([]);
176
- return;
177
- }
178
- const val = Array.isArray(newValue) ? newValue : [newValue];
179
- if (max === null || val.length <= max) {
180
- onChange(val.filter((v) => typeof v !== "string"));
181
- }
182
- } else {
183
- if (!newValue) {
184
- return;
185
- }
186
- onChange(newValue);
187
- }
430
+ handleEntitySelectionChange({
431
+ max,
432
+ multiple,
433
+ newValue,
434
+ onChange
435
+ });
188
436
  },
189
437
  renderOption: (option) => {
190
438
  const stringified = stringifyEntityRef(option);
@@ -202,16 +450,6 @@ const EntitiesInput = forwardRef(
202
450
  ) }, stringified);
203
451
  },
204
452
  renderInput: (params) => {
205
- let helperText = "";
206
- if (!hideHelpText) {
207
- if (error && error.message) {
208
- helperText = error.message;
209
- } else {
210
- helperText = t("entitiesInput.helperText", {
211
- max: max.toString()
212
- });
213
- }
214
- }
215
453
  return /* @__PURE__ */ jsx(
216
454
  TextField,
217
455
  {
@@ -249,7 +487,7 @@ const EntitiesInput = forwardRef(
249
487
  size: "small",
250
488
  onClick: () => handleSuggestedEntityClick(entity),
251
489
  style: { margin: "0 4px 4px 0" },
252
- disabled: [value ?? []].flat().map(stringifyEntityRef).includes(stringifyEntityRef(entity)) || [value ?? []].flat().length >= max
490
+ disabled: valueEntities.map(stringifyEntityRef).includes(stringifyEntityRef(entity)) || max !== null && valueEntities.length >= max || loadingSuggestions
253
491
  },
254
492
  stringifyEntityRef(entity)
255
493
  )) })
@@ -1 +1 @@
1
- {"version":3,"file":"EntitiesInput.esm.js","sources":["../../../src/components/PostForm/EntitiesInput.tsx"],"sourcesContent":["import { Autocomplete } from '@material-ui/lab';\nimport { getEntityDescription, getEntityTitle } from '../../utils/utils';\nimport { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport {\n Box,\n Chip,\n CircularProgress,\n TextField,\n Tooltip,\n Typography,\n} from '@material-ui/core';\nimport {\n ComponentType,\n CSSProperties,\n forwardRef,\n HTMLAttributes,\n useCallback,\n useMemo,\n useState,\n} from 'react';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { qetaTranslationRef } from '../../translation.ts';\nimport { qetaApiRef } from '../../api';\nimport { compact } from 'lodash';\nimport {\n AutocompleteListboxComponent,\n renderGroup,\n} from './AutocompleteListComponent';\nimport { AutocompleteProps } from '@material-ui/lab/Autocomplete/Autocomplete';\nimport { FieldError } from 'react-hook-form';\nimport { getSupportedEntityKinds } from '@drodil/backstage-plugin-qeta-common';\nimport { useDebounce } from 'react-use';\n\ntype CommonEntitiesInputProps = {\n singleValue?: string;\n required?: boolean;\n useOnlyUsedEntities?: boolean;\n hideHelpText?: boolean;\n style?: CSSProperties;\n disabled?: boolean;\n kind?: string[];\n maximum?: number | null;\n error?: FieldError;\n label?: string;\n name?: string;\n placeholder?: string;\n autocompleteProps?: AutocompleteProps<any, any, any, any>;\n onChange: (value: any) => void;\n title?: string;\n content?: string;\n tags?: string[];\n};\ntype SingleEntitiesInputValue = CommonEntitiesInputProps & {\n multiple: false;\n value?: Entity | null;\n onChange: (value: Entity) => void;\n};\n\ntype MultipleEntitiesInputValue = CommonEntitiesInputProps & {\n multiple?: true;\n value?: Entity[];\n onChange: (value: Entity[]) => void;\n};\n\nexport type EntitiesInputProps =\n | SingleEntitiesInputValue\n | MultipleEntitiesInputValue;\n\nconst CATALOG_FIELDS = [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n 'metadata.description',\n 'spec.type',\n 'spec.profile.displayName',\n 'spec.profile.email',\n];\n\nexport const EntitiesInput = forwardRef<any, EntitiesInputProps>(\n (props, _ref) => {\n const {\n value,\n singleValue,\n onChange,\n multiple = true,\n required = false,\n useOnlyUsedEntities = false,\n hideHelpText = false,\n style,\n disabled,\n kind,\n error,\n maximum,\n label,\n name = 'entities',\n placeholder,\n autocompleteProps,\n title,\n content,\n tags,\n } = props;\n\n const configApi = useApi(configApiRef);\n const catalogApi = useApi(catalogApiRef);\n const qetaApi = useApi(qetaApiRef);\n const [availableEntities, setAvailableEntities] = useState<Entity[] | null>(\n [],\n );\n const [loading, setLoading] = useState(false);\n const [open, setOpen] = useState(false);\n const { t } = useTranslationRef(qetaTranslationRef);\n const [suggestedEntities, setSuggestedEntities] = useState<Entity[]>([]);\n const [, setLoadingSuggestions] = useState(false);\n\n const entityKinds: string[] = useMemo(() => {\n if (kind) {\n return kind;\n }\n return getSupportedEntityKinds(configApi);\n }, [configApi, kind]);\n const max = useMemo(() => {\n if (maximum) {\n return maximum;\n }\n return configApi.getOptionalNumber('qeta.entities.max') ?? 3;\n }, [configApi, maximum]);\n\n const handleOpen = useCallback(() => {\n setOpen(true);\n (async () => {\n setLoading(true);\n if (singleValue) {\n const entity = await catalogApi.getEntityByRef(singleValue);\n setLoading(false);\n setAvailableEntities(entity ? [entity] : null);\n return;\n }\n\n if (useOnlyUsedEntities) {\n const qetaEntities = await qetaApi.getEntities();\n const refs = qetaEntities.entities.map(r => r.entityRef);\n const catalogData = await catalogApi.getEntitiesByRefs({\n entityRefs: refs,\n fields: CATALOG_FIELDS,\n });\n setLoading(false);\n setAvailableEntities(\n catalogData\n ? compact(catalogData.items).sort((a, b) =>\n getEntityTitle(a).localeCompare(getEntityTitle(b)),\n )\n : null,\n );\n return;\n }\n\n if (entityKinds && entityKinds.length > 0) {\n const entities = await catalogApi.getEntities({\n filter: { kind: entityKinds },\n fields: CATALOG_FIELDS,\n order: { field: 'kind', order: 'asc' },\n });\n setLoading(false);\n setAvailableEntities(entities ? entities.items : null);\n return;\n }\n setLoading(false);\n setAvailableEntities(null);\n })();\n }, [singleValue, useOnlyUsedEntities, entityKinds, catalogApi, qetaApi]);\n\n const usedValue = useMemo(() => {\n if (!value) {\n return multiple ? [] : null;\n }\n return value;\n }, [value, multiple]);\n\n useDebounce(\n () => {\n if (title && content) {\n setLoadingSuggestions(true);\n qetaApi\n .getEntitySuggestions({\n title,\n content,\n tags,\n entities: [value ?? []].flat().map(stringifyEntityRef),\n limit: 5,\n })\n .then(response => {\n setSuggestedEntities(response.entities);\n })\n .catch(() => {\n // Ignore errors\n })\n .finally(() => {\n setLoadingSuggestions(false);\n });\n }\n },\n 2000,\n [title, content, qetaApi],\n );\n\n const handleSuggestedEntityClick = (entity: Entity) => {\n const values = [value ?? []].flat();\n if (values && values.length < max && !values.includes(entity)) {\n onChange([...values, entity]);\n }\n };\n\n if (!availableEntities) {\n return null;\n }\n\n return (\n <Box>\n <Autocomplete\n multiple={multiple}\n autoHighlight\n autoComplete\n className=\"qetaEntitiesInput\"\n value={usedValue}\n disabled={disabled}\n loading={loading}\n loadingText={t('common.loading')}\n groupBy={entityKinds.length > 1 ? option => option.kind : undefined}\n renderGroup={renderGroup}\n handleHomeEndKeys\n open={open}\n onOpen={handleOpen}\n onClose={() => setOpen(false)}\n options={availableEntities}\n getOptionLabel={getEntityTitle}\n ListboxComponent={\n AutocompleteListboxComponent as ComponentType<\n HTMLAttributes<HTMLElement>\n >\n }\n disableListWrap\n style={style}\n getOptionSelected={(o, v) =>\n stringifyEntityRef(o) === stringifyEntityRef(v)\n }\n onChange={(_e, newValue) => {\n if (multiple) {\n if (!newValue) {\n onChange([]);\n return;\n }\n const val = Array.isArray(newValue) ? newValue : [newValue];\n if (max === null || val.length <= max) {\n onChange(val.filter(v => typeof v !== 'string'));\n }\n } else {\n if (!newValue) {\n return;\n }\n onChange(newValue as Entity);\n }\n }}\n renderOption={(option: Entity) => {\n const stringified = stringifyEntityRef(option);\n return (\n <span key={stringified}>\n <Tooltip\n arrow\n placement=\"right\"\n title={\n <>\n <Typography>{getEntityTitle(option)}</Typography>\n <Typography variant=\"caption\">\n {getEntityDescription(option)}\n </Typography>\n </>\n }\n >\n <span>{getEntityTitle(option, { withType: false })}</span>\n </Tooltip>\n </span>\n );\n }}\n renderInput={params => {\n let helperText = '';\n if (!hideHelpText) {\n if (error && error.message) {\n helperText = error.message;\n } else {\n helperText = t('entitiesInput.helperText', {\n max: max.toString(),\n });\n }\n }\n\n return (\n <TextField\n {...params}\n variant=\"outlined\"\n margin=\"normal\"\n required={required}\n label={label || t('entitiesInput.label')}\n placeholder={placeholder || t('entitiesInput.placeholder')}\n helperText={helperText}\n name={name}\n FormHelperTextProps={{\n style: { marginLeft: '0.2em' },\n }}\n InputProps={{\n ...params.InputProps,\n endAdornment: (\n <>\n {loading ? (\n <CircularProgress color=\"inherit\" size={20} />\n ) : null}\n {params.InputProps.endAdornment}\n </>\n ),\n }}\n error={error !== undefined}\n />\n );\n }}\n {...autocompleteProps}\n />\n {suggestedEntities?.length > 0 && (\n <Box style={{ marginLeft: '4px' }}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {t('entitiesInput.suggestedEntities')}\n </Typography>\n <Box mt={0.5}>\n {suggestedEntities.map(entity => (\n <Chip\n key={stringifyEntityRef(entity)}\n label={getEntityTitle(entity)}\n size=\"small\"\n onClick={() => handleSuggestedEntityClick(entity)}\n style={{ margin: '0 4px 4px 0' }}\n disabled={\n [value ?? []]\n .flat()\n .map(stringifyEntityRef)\n .includes(stringifyEntityRef(entity)) ||\n [value ?? []].flat().length >= max\n }\n />\n ))}\n </Box>\n </Box>\n )}{' '}\n </Box>\n );\n },\n);\n\nEntitiesInput.displayName = 'EntitiesInput';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EntitiesInput.esm.js","sources":["../../../src/components/PostForm/EntitiesInput.tsx"],"sourcesContent":["import { Autocomplete } from '@material-ui/lab';\nimport { getEntityDescription, getEntityTitle } from '../../utils/utils';\nimport { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport {\n Box,\n Chip,\n CircularProgress,\n TextField,\n Tooltip,\n Typography,\n} from '@material-ui/core';\nimport {\n ComponentType,\n CSSProperties,\n forwardRef,\n HTMLAttributes,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { qetaTranslationRef } from '../../translation.ts';\nimport { qetaApiRef } from '../../api';\nimport { compact } from 'lodash';\nimport {\n AutocompleteListboxComponent,\n renderGroup,\n} from './AutocompleteListComponent';\nimport { AutocompleteProps } from '@material-ui/lab/Autocomplete/Autocomplete';\nimport { FieldError } from 'react-hook-form';\nimport type { CatalogApi } from '@backstage/catalog-client';\nimport type {\n EntitiesQuery,\n QetaApi,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { getSupportedEntityKinds } from '@drodil/backstage-plugin-qeta-common';\nimport { useDebounce } from 'react-use';\n\ntype CommonEntitiesInputProps = {\n singleValue?: string;\n required?: boolean;\n useOnlyUsedEntities?: boolean;\n hideHelpText?: boolean;\n style?: CSSProperties;\n disabled?: boolean;\n kind?: string[];\n maximum?: number | null;\n error?: FieldError;\n label?: string;\n name?: string;\n placeholder?: string;\n autocompleteProps?: AutocompleteProps<any, any, any, any>;\n onChange: (value: any) => void;\n title?: string;\n content?: string;\n tags?: string[];\n};\ntype SingleEntitiesInputValue = CommonEntitiesInputProps & {\n multiple: false;\n value?: Entity | null;\n onChange: (value: Entity) => void;\n};\n\ntype MultipleEntitiesInputValue = CommonEntitiesInputProps & {\n multiple?: true;\n value?: Entity[];\n onChange: (value: Entity[]) => void;\n};\n\nexport type EntitiesInputProps =\n | SingleEntitiesInputValue\n | MultipleEntitiesInputValue;\n\nconst CATALOG_FIELDS = [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n 'metadata.description',\n 'spec.type',\n 'spec.profile.displayName',\n 'spec.profile.email',\n];\n\nconst CATALOG_SEARCH_FIELDS = [\n 'metadata.name',\n 'metadata.title',\n 'spec.profile.displayName',\n 'spec.profile.email',\n];\n\nconst CATALOG_DEFAULT_ORDER_FIELDS = [\n {\n field: 'metadata.name',\n order: 'asc' as const,\n },\n];\n\nconst ENTITY_SEARCH_LIMIT = 25;\nconst ENTITY_KIND_KEY_SEPARATOR = '\\u0000';\n\nconst getEntityKindsKey = (entityKinds: string[]) =>\n [...entityKinds]\n .sort((left, right) => left.localeCompare(right))\n .join(ENTITY_KIND_KEY_SEPARATOR);\n\nconst getEntityKindsFromKey = (entityKindsKey: string) =>\n entityKindsKey ? entityKindsKey.split(ENTITY_KIND_KEY_SEPARATOR) : [];\n\ntype EntitySearchQuery = {\n kind: string | { $in: string[] };\n};\n\nconst getEntitySearchQuery = (\n entityKinds: string[],\n): EntitySearchQuery | undefined => {\n if (entityKinds.length === 0) {\n return undefined;\n }\n\n if (entityKinds.length === 1) {\n return { kind: entityKinds[0] };\n }\n\n return {\n kind: {\n $in: entityKinds,\n },\n };\n};\n\nconst getEntitySearchCacheScope = (\n term: string,\n useOnlyUsedEntities: boolean,\n hasExplicitKinds: boolean,\n) => {\n if (!term) {\n return hasExplicitKinds ? 'catalog-defaults' : 'used-defaults';\n }\n\n if (useOnlyUsedEntities) {\n return 'used';\n }\n\n return 'catalog';\n};\n\nconst getUsedEntitiesRequest = (term: string): EntitiesQuery => ({\n limit: ENTITY_SEARCH_LIMIT,\n orderBy: 'postsCount',\n order: 'desc',\n ...(term ? { searchQuery: term } : {}),\n});\n\nconst loadUsedEntities = async (params: {\n catalogQuery?: EntitySearchQuery;\n getEntities: QetaApi['getEntities'];\n getEntitiesByRefs: CatalogApi['getEntitiesByRefs'];\n term: string;\n}) => {\n const { catalogQuery, getEntities, getEntitiesByRefs, term } = params;\n const qetaEntities = await getEntities(getUsedEntitiesRequest(term));\n const refs = qetaEntities.entities.map(entity => entity.entityRef);\n\n if (refs.length === 0) {\n return [];\n }\n\n const catalogData = await getEntitiesByRefs({\n entityRefs: refs,\n fields: CATALOG_FIELDS,\n ...(catalogQuery ? { query: catalogQuery } : {}),\n });\n\n return compact(catalogData.items);\n};\n\nconst loadCatalogEntities = async (params: {\n catalogQuery: EntitySearchQuery;\n queryEntities: CatalogApi['queryEntities'];\n term: string;\n}) => {\n const { catalogQuery, queryEntities, term } = params;\n const request: NonNullable<Parameters<CatalogApi['queryEntities']>[0]> = {\n query: catalogQuery,\n limit: ENTITY_SEARCH_LIMIT,\n fields: CATALOG_FIELDS,\n orderFields: CATALOG_DEFAULT_ORDER_FIELDS,\n };\n\n if (term) {\n request.fullTextFilter = {\n term,\n fields: CATALOG_SEARCH_FIELDS,\n };\n }\n\n const entities = await queryEntities(request);\n\n return compact(entities.items);\n};\n\nconst mergeEntities = (...groups: Array<Array<Entity | null | undefined>>) => {\n const seen = new Set<string>();\n const merged: Entity[] = [];\n\n for (const entity of groups.flat()) {\n if (!entity) {\n continue;\n }\n\n const entityRef = stringifyEntityRef(entity);\n if (!seen.has(entityRef)) {\n seen.add(entityRef);\n merged.push(entity);\n }\n }\n\n return merged;\n};\n\nconst getCurrentValueEntities = (value: Entity | Entity[] | null | undefined) =>\n [value ?? []].flat() as Entity[];\n\nconst handleEntitySelectionChange = ({\n max,\n multiple,\n newValue,\n onChange,\n}: {\n max: number | null;\n multiple: boolean;\n newValue: Entity | string | Array<Entity | string> | null;\n onChange: (value: any) => void;\n}) => {\n if (multiple) {\n if (!newValue) {\n onChange([]);\n return;\n }\n\n const values = Array.isArray(newValue) ? newValue : [newValue];\n if (max === null || values.length <= max) {\n onChange(values.filter(v => typeof v !== 'string'));\n }\n return;\n }\n\n if (newValue) {\n onChange(newValue);\n }\n};\n\nconst handleAutocompleteInputChange = ({\n nextValue,\n reason,\n setInputValue,\n}: {\n nextValue: string;\n reason: string;\n setInputValue: (value: string) => void;\n}) => {\n if (reason === 'reset') {\n setInputValue('');\n return;\n }\n\n setInputValue(nextValue);\n};\n\nconst appendSuggestedEntity = ({\n entity,\n max,\n values,\n}: {\n entity: Entity;\n max: number | null;\n values: Entity[];\n}) => {\n if (values.includes(entity)) {\n return undefined;\n }\n\n if (max !== null && values.length >= max) {\n return undefined;\n }\n\n return [...values, entity];\n};\n\nexport const EntitiesInput = forwardRef<any, EntitiesInputProps>(\n (props, _ref) => {\n const {\n value,\n singleValue,\n onChange,\n multiple = true,\n required = false,\n useOnlyUsedEntities = false,\n hideHelpText = false,\n style,\n disabled,\n kind,\n error,\n maximum,\n label,\n name = 'entities',\n placeholder,\n autocompleteProps,\n title,\n content,\n tags,\n } = props;\n\n const configApi = useApi(configApiRef);\n const catalogApi = useApi(catalogApiRef);\n const qetaApi = useApi(qetaApiRef);\n const [availableEntities, setAvailableEntities] = useState<Entity[]>([]);\n const [loading, setLoading] = useState(false);\n const [open, setOpen] = useState(false);\n const { t } = useTranslationRef(qetaTranslationRef);\n const [suggestedEntities, setSuggestedEntities] = useState<Entity[]>([]);\n const [loadingSuggestions, setLoadingSuggestions] = useState(false);\n const [inputValue, setInputValue] = useState('');\n const searchCache = useRef<Map<string, Entity[]>>(new Map());\n const activeRequest = useRef(0);\n\n const explicitEntityKindsKey = useMemo(\n () => getEntityKindsKey(kind ?? []),\n [kind],\n );\n\n const entityKinds: string[] = useMemo(() => {\n if (explicitEntityKindsKey) {\n return getEntityKindsFromKey(explicitEntityKindsKey);\n }\n return getSupportedEntityKinds(configApi);\n }, [configApi, explicitEntityKindsKey]);\n const max = useMemo(() => {\n if (maximum) {\n return maximum;\n }\n return configApi.getOptionalNumber('qeta.entities.max') ?? 3;\n }, [configApi, maximum]);\n const entityKindsKey = useMemo(\n () => getEntityKindsKey(entityKinds),\n [entityKinds],\n );\n const hasExplicitKinds = explicitEntityKindsKey.length > 0;\n\n const valueEntities = useMemo(\n () => getCurrentValueEntities(value),\n [value],\n );\n\n const helperText = useMemo(\n () =>\n hideHelpText\n ? ''\n : (error?.message ??\n t('entitiesInput.helperText', {\n max: max?.toString() ?? '',\n })),\n [error?.message, hideHelpText, max, t],\n );\n\n const usedValue = useMemo(() => {\n if (!value) {\n return multiple ? [] : null;\n }\n return value;\n }, [value, multiple]);\n\n const selectedEntities = useMemo(\n () => mergeEntities(Array.isArray(usedValue) ? usedValue : [usedValue]),\n [usedValue],\n );\n\n const options = useMemo(\n () => mergeEntities(selectedEntities, availableEntities),\n [availableEntities, selectedEntities],\n );\n\n const displayedInputValue = useMemo(() => {\n if (!multiple && !open && usedValue && !Array.isArray(usedValue)) {\n return getEntityTitle(usedValue);\n }\n\n return inputValue;\n }, [inputValue, multiple, open, usedValue]);\n\n useEffect(() => {\n searchCache.current.clear();\n activeRequest.current += 1;\n setAvailableEntities([]);\n setInputValue('');\n setLoading(false);\n }, [entityKindsKey, singleValue, useOnlyUsedEntities]);\n\n useEffect(() => {\n if (!singleValue) {\n return undefined;\n }\n\n if (\n selectedEntities.some(\n entity => stringifyEntityRef(entity) === singleValue,\n )\n ) {\n return undefined;\n }\n\n let active = true;\n catalogApi\n .getEntityByRef(singleValue)\n .then(entity => {\n if (!active || !entity) {\n return;\n }\n setAvailableEntities(prev => mergeEntities([entity], prev));\n })\n .catch(() => {\n // Ignore errors\n });\n\n return () => {\n active = false;\n };\n }, [catalogApi, selectedEntities, singleValue]);\n\n const searchEntities = useCallback(\n async (term: string) => {\n const trimmed = term.trim();\n const currentEntityKinds = getEntityKindsFromKey(entityKindsKey);\n const catalogQuery = getEntitySearchQuery(currentEntityKinds);\n const shouldLoadCatalogDefaults = !trimmed && hasExplicitKinds;\n const shouldLoadUsedEntities =\n useOnlyUsedEntities || (!trimmed && !hasExplicitKinds);\n\n const cacheKey = [\n getEntitySearchCacheScope(\n trimmed,\n useOnlyUsedEntities,\n hasExplicitKinds,\n ),\n entityKindsKey,\n trimmed.toLocaleLowerCase(),\n ].join(':');\n const cached = searchCache.current.get(cacheKey);\n\n if (cached) {\n setLoading(false);\n setAvailableEntities(prev => mergeEntities(prev, cached));\n return;\n }\n\n const requestId = activeRequest.current + 1;\n activeRequest.current = requestId;\n setLoading(true);\n\n try {\n let nextEntities: Entity[] = [];\n\n if (shouldLoadCatalogDefaults && catalogQuery) {\n nextEntities = await loadCatalogEntities({\n catalogQuery,\n queryEntities: request => catalogApi.queryEntities(request),\n term: '',\n });\n } else if (shouldLoadUsedEntities) {\n nextEntities = await loadUsedEntities({\n catalogQuery,\n getEntities: entityOptions => qetaApi.getEntities(entityOptions),\n getEntitiesByRefs: request =>\n catalogApi.getEntitiesByRefs(request),\n term: trimmed,\n });\n } else if (catalogQuery) {\n nextEntities = await loadCatalogEntities({\n catalogQuery,\n queryEntities: request => catalogApi.queryEntities(request),\n term: trimmed,\n });\n }\n\n if (activeRequest.current !== requestId) {\n return;\n }\n\n searchCache.current.set(cacheKey, nextEntities);\n setAvailableEntities(prev => mergeEntities(prev, nextEntities));\n } catch {\n // Keep already fetched entities visible on request failures.\n } finally {\n if (activeRequest.current === requestId) {\n setLoading(false);\n }\n }\n },\n [\n catalogApi,\n entityKindsKey,\n hasExplicitKinds,\n qetaApi,\n useOnlyUsedEntities,\n ],\n );\n\n const handleOpen = useCallback(() => {\n setInputValue('');\n setOpen(true);\n }, []);\n\n useEffect(() => {\n searchEntities('');\n }, [searchEntities]);\n\n useDebounce(\n () => {\n if (open) {\n searchEntities(inputValue);\n }\n },\n 300,\n [inputValue, open, searchEntities],\n );\n\n useDebounce(\n () => {\n if (title && content) {\n setLoadingSuggestions(true);\n qetaApi\n .getEntitySuggestions({\n title,\n content,\n tags,\n entities: valueEntities.map(stringifyEntityRef),\n limit: 5,\n })\n .then(response => {\n setSuggestedEntities(response.entities);\n })\n .catch(() => {\n // Ignore errors\n })\n .finally(() => {\n setLoadingSuggestions(false);\n });\n }\n },\n 2000,\n [content, qetaApi, tags, title, valueEntities],\n );\n\n const handleSuggestedEntityClick = (entity: Entity) => {\n const nextValues = appendSuggestedEntity({\n entity,\n max,\n values: valueEntities,\n });\n\n if (nextValues) {\n onChange(nextValues);\n }\n };\n\n return (\n <Box>\n <Autocomplete\n multiple={multiple}\n autoHighlight\n autoComplete\n className=\"qetaEntitiesInput\"\n value={usedValue}\n disabled={disabled}\n loading={loading}\n limitTags={max}\n loadingText={t('common.loading')}\n groupBy={entityKinds.length > 1 ? option => option.kind : undefined}\n renderGroup={renderGroup}\n handleHomeEndKeys\n open={open}\n onOpen={handleOpen}\n onClose={() => {\n activeRequest.current += 1;\n setLoading(false);\n setInputValue('');\n setOpen(false);\n }}\n options={options}\n getOptionLabel={getEntityTitle}\n inputValue={displayedInputValue}\n onInputChange={(_event, nextValue, reason) => {\n handleAutocompleteInputChange({\n nextValue,\n reason,\n setInputValue,\n });\n }}\n ListboxComponent={\n AutocompleteListboxComponent as ComponentType<\n HTMLAttributes<HTMLElement>\n >\n }\n disableListWrap\n style={style}\n getOptionSelected={(o, v) =>\n stringifyEntityRef(o) === stringifyEntityRef(v)\n }\n onChange={(_e, newValue) => {\n handleEntitySelectionChange({\n max,\n multiple,\n newValue,\n onChange,\n });\n }}\n renderOption={(option: Entity) => {\n const stringified = stringifyEntityRef(option);\n return (\n <span key={stringified}>\n <Tooltip\n arrow\n placement=\"right\"\n title={\n <>\n <Typography>{getEntityTitle(option)}</Typography>\n <Typography variant=\"caption\">\n {getEntityDescription(option)}\n </Typography>\n </>\n }\n >\n <span>{getEntityTitle(option, { withType: false })}</span>\n </Tooltip>\n </span>\n );\n }}\n renderInput={params => {\n return (\n <TextField\n {...params}\n variant=\"outlined\"\n margin=\"normal\"\n required={required}\n label={label || t('entitiesInput.label')}\n placeholder={placeholder || t('entitiesInput.placeholder')}\n helperText={helperText}\n name={name}\n FormHelperTextProps={{\n style: { marginLeft: '0.2em' },\n }}\n InputProps={{\n ...params.InputProps,\n endAdornment: (\n <>\n {loading ? (\n <CircularProgress color=\"inherit\" size={20} />\n ) : null}\n {params.InputProps.endAdornment}\n </>\n ),\n }}\n error={error !== undefined}\n />\n );\n }}\n {...autocompleteProps}\n />\n {suggestedEntities?.length > 0 && (\n <Box style={{ marginLeft: '4px' }}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {t('entitiesInput.suggestedEntities')}\n </Typography>\n <Box mt={0.5}>\n {suggestedEntities.map(entity => (\n <Chip\n key={stringifyEntityRef(entity)}\n label={getEntityTitle(entity)}\n size=\"small\"\n onClick={() => handleSuggestedEntityClick(entity)}\n style={{ margin: '0 4px 4px 0' }}\n disabled={\n valueEntities\n .map(stringifyEntityRef)\n .includes(stringifyEntityRef(entity)) ||\n (max !== null && valueEntities.length >= max) ||\n loadingSuggestions\n }\n />\n ))}\n </Box>\n </Box>\n )}{' '}\n </Box>\n );\n },\n);\n\nEntitiesInput.displayName = 'EntitiesInput';\n"],"names":[],"mappings":"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"}