@backstage/plugin-scaffolder-react 1.2.0 → 1.3.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @backstage/plugin-scaffolder-react
2
2
 
3
+ ## 1.3.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 259d3407b9b: Move `CategoryPicker` from `scaffolder` into `scaffolder-react`
8
+ Move `ContextMenu` into `scaffolder-react` and rename it to `ScaffolderPageContextMenu`
9
+ - 2cfd03d7376: To offer better customization options, `ScaffolderPageContextMenu` takes callbacks as props instead of booleans
10
+ - 48da4c46e45: `scaffolder/next`: Export the `TemplateGroupFilter` and `TemplateGroups` and make an extensible component
11
+
12
+ ### Patch Changes
13
+
14
+ - e27ddc36dad: Added a possibility to cancel the running task (executing of a scaffolder template)
15
+ - 7a6b16cc506: `scaffolder/next`: Bump `@rjsf/*` deps to 5.3.1
16
+ - f84fc7fd040: Updated dependency `@rjsf/validator-ajv8` to `5.3.0`.
17
+ - 8e00acb28db: Small tweaks to remove warnings in the console during development (mainly focusing on techdocs)
18
+ - Updated dependencies
19
+ - @backstage/plugin-scaffolder-common@1.2.7-next.0
20
+ - @backstage/core-components@0.12.6-next.0
21
+ - @backstage/plugin-catalog-react@1.4.1-next.0
22
+ - @backstage/core-plugin-api@1.5.0
23
+ - @backstage/catalog-client@1.4.0
24
+ - @backstage/catalog-model@1.2.1
25
+ - @backstage/errors@1.1.5
26
+ - @backstage/theme@0.2.18
27
+ - @backstage/types@1.0.2
28
+ - @backstage/version-bridge@1.0.3
29
+
3
30
  ## 1.2.0
4
31
 
5
32
  ### Minor Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder-react",
3
- "version": "1.2.0",
3
+ "version": "1.3.0-next.0",
4
4
  "main": "../dist/alpha.esm.js",
5
5
  "module": "../dist/alpha.esm.js",
6
6
  "types": "../dist/alpha.d.ts"
package/dist/alpha.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /// <reference types="react" />
2
2
  import { JsonObject, JsonValue } from '@backstage/types';
3
- import * as react from 'react';
4
- import react__default, { PropsWithChildren, ReactNode } from 'react';
3
+ import * as React from 'react';
4
+ import React__default, { PropsWithChildren, ReactNode } from 'react';
5
5
  import { ApiHolder, Extension, IconComponent } from '@backstage/core-plugin-api';
6
6
  import * as _rjsf_utils from '@rjsf/utils';
7
7
  import { FieldProps, UiSchema, UIOptionsType, FieldValidation } from '@rjsf/utils';
@@ -156,9 +156,9 @@ interface TemplateGroupProps {
156
156
  }[];
157
157
  }[];
158
158
  onSelected: (template: TemplateEntityV1beta3) => void;
159
- title: react__default.ReactNode;
159
+ title: React__default.ReactNode;
160
160
  components?: {
161
- CardComponent?: react__default.ComponentType<TemplateCardProps>;
161
+ CardComponent?: React__default.ComponentType<TemplateCardProps>;
162
162
  };
163
163
  }
164
164
  /**
@@ -167,6 +167,34 @@ interface TemplateGroupProps {
167
167
  */
168
168
  declare const TemplateGroup: (props: TemplateGroupProps) => JSX.Element;
169
169
 
170
+ /**
171
+ * @alpha
172
+ */
173
+ declare type TemplateGroupFilter = {
174
+ title?: React__default.ReactNode;
175
+ filter: (entity: TemplateEntityV1beta3) => boolean;
176
+ };
177
+ /**
178
+ * @alpha
179
+ */
180
+ interface TemplateGroupsProps {
181
+ groups: TemplateGroupFilter[];
182
+ templateFilter?: (entity: TemplateEntityV1beta3) => boolean;
183
+ TemplateCardComponent?: React__default.ComponentType<{
184
+ template: TemplateEntityV1beta3;
185
+ }>;
186
+ onTemplateSelected?: (template: TemplateEntityV1beta3) => void;
187
+ additionalLinksForEntity?: (template: TemplateEntityV1beta3) => {
188
+ icon: IconComponent;
189
+ text: string;
190
+ url: string;
191
+ }[];
192
+ }
193
+ /**
194
+ * @alpha
195
+ */
196
+ declare const TemplateGroups: (props: TemplateGroupsProps) => JSX.Element | null;
197
+
170
198
  /**
171
199
  * @alpha
172
200
  */
@@ -196,7 +224,7 @@ declare const DefaultTemplateOutputs: (props: {
196
224
  }) => JSX.Element | null;
197
225
 
198
226
  /** @alpha */
199
- declare const Form: react.ComponentType<_rjsf_core_v5.FormProps<any, _rjsf_utils.RJSFSchema, any>>;
227
+ declare const Form: React.ComponentType<_rjsf_core_v5.FormProps<any, _rjsf_utils.RJSFSchema, any>>;
200
228
 
201
229
  /**
202
230
  * Props for the TaskSteps component
@@ -227,6 +255,26 @@ declare const TaskLogStream: (props: {
227
255
  };
228
256
  }) => JSX.Element;
229
257
 
258
+ /**
259
+ * The Category Picker that is rendered on the left side for picking
260
+ * categories and filtering the template list.
261
+ * @alpha
262
+ */
263
+ declare const TemplateCategoryPicker: () => JSX.Element | null;
264
+
265
+ /**
266
+ * @alpha
267
+ */
268
+ declare type ScaffolderPageContextMenuProps = {
269
+ onEditorClicked?: () => void;
270
+ onActionsClicked?: () => void;
271
+ onTasksClicked?: () => void;
272
+ };
273
+ /**
274
+ * @alpha
275
+ */
276
+ declare function ScaffolderPageContextMenu(props: ScaffolderPageContextMenuProps): JSX.Element | null;
277
+
230
278
  /**
231
279
  * Takes a step from a Backstage Template Manifest and converts it to a JSON Schema and UI Schema for rjsf
232
280
  * @alpha
@@ -245,7 +293,7 @@ declare const createFieldValidation: () => FieldValidation;
245
293
  * This hook is used to get the formData from the query string.
246
294
  * @alpha
247
295
  */
248
- declare const useFormDataFromQuery: (initialState?: Record<string, JsonValue>) => [Record<string, any>, react.Dispatch<react.SetStateAction<Record<string, any>>>];
296
+ declare const useFormDataFromQuery: (initialState?: Record<string, JsonValue>) => [Record<string, any>, React.Dispatch<React.SetStateAction<Record<string, any>>>];
249
297
 
250
298
  /**
251
299
  * @alpha
@@ -256,4 +304,4 @@ declare const useTemplateParameterSchema: (templateRef: string) => {
256
304
  error: Error | undefined;
257
305
  };
258
306
 
259
- export { DefaultTemplateOutputs, EmbeddableWorkflow, Form, FormProps, NextCustomFieldValidator, NextFieldExtensionComponentProps, NextFieldExtensionOptions, NextFieldExtensionUiSchema, ParsedTemplateSchema, ReviewState, ReviewStateProps, Stepper, StepperProps, TaskLogStream, TaskSteps, TaskStepsProps, TemplateCard, TemplateCardProps, TemplateGroup, TemplateGroupProps, Workflow, WorkflowProps, createFieldValidation, createNextScaffolderFieldExtension, extractSchemaFromStep, useFormDataFromQuery, useTemplateParameterSchema, useTemplateSchema };
307
+ export { DefaultTemplateOutputs, EmbeddableWorkflow, Form, FormProps, NextCustomFieldValidator, NextFieldExtensionComponentProps, NextFieldExtensionOptions, NextFieldExtensionUiSchema, ParsedTemplateSchema, ReviewState, ReviewStateProps, ScaffolderPageContextMenu, ScaffolderPageContextMenuProps, Stepper, StepperProps, TaskLogStream, TaskSteps, TaskStepsProps, TemplateCard, TemplateCardProps, TemplateCategoryPicker, TemplateGroup, TemplateGroupFilter, TemplateGroupProps, TemplateGroups, TemplateGroupsProps, Workflow, WorkflowProps, createFieldValidation, createNextScaffolderFieldExtension, extractSchemaFromStep, useFormDataFromQuery, useTemplateParameterSchema, useTemplateSchema };
package/dist/alpha.esm.js CHANGED
@@ -1,5 +1,5 @@
1
- import { useApi, featureFlagsApiRef, createApiRef, useAnalytics, useApiHolder, useApp, errorApiRef, useRouteRef, attachComponentData } from '@backstage/core-plugin-api';
2
- import { makeStyles, Stepper as Stepper$1, Step, StepLabel, Button, useTheme, Card, CardContent, Grid, Box, Divider, Chip, CardActions, Typography, Paper, CircularProgress, LinearProgress, StepButton } from '@material-ui/core';
1
+ import { useApi, featureFlagsApiRef, createApiRef, useAnalytics, useApiHolder, useApp, errorApiRef, useRouteRef, alertApiRef, attachComponentData } from '@backstage/core-plugin-api';
2
+ import { makeStyles, Stepper as Stepper$1, Step, StepLabel, Button, useTheme, Card, CardContent, Grid, Box, Divider, Chip, CardActions, Typography, Paper, CircularProgress, LinearProgress, StepButton, FormControlLabel, Checkbox, TextField } from '@material-ui/core';
3
3
  import React, { useState, useMemo, useCallback, useEffect } from 'react';
4
4
  import { Draft07 } from 'json-schema-library';
5
5
  import { StructuredMetadataTable, MarkdownContent, ItemCardHeader, Link, UserIcon, Content, ItemCardGrid, ContentHeader, Progress, InfoCard, LogViewer } from '@backstage/core-components';
@@ -9,8 +9,10 @@ import useAsync from 'react-use/lib/useAsync';
9
9
  import { getOrCreateGlobalSingleton, createVersionedContext, createVersionedValueMap } from '@backstage/version-bridge';
10
10
  import { withTheme } from '@rjsf/core-v5';
11
11
  import { RELATION_OWNED_BY, stringifyEntityRef, parseEntityRef } from '@backstage/catalog-model';
12
- import { FavoriteEntity, getEntityRelations, EntityRefLinks, entityRouteRef } from '@backstage/plugin-catalog-react';
12
+ import { FavoriteEntity, getEntityRelations, EntityRefLinks, useEntityList, entityRouteRef, useEntityTypeFilter } from '@backstage/plugin-catalog-react';
13
13
  import LanguageIcon from '@material-ui/icons/Language';
14
+ import { isTemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
15
+ import { TemplateGroup as TemplateGroup$1 } from '@backstage/plugin-scaffolder-react/alpha';
14
16
  import WebIcon from '@material-ui/icons/Web';
15
17
  import RemoveCircleOutline from '@material-ui/icons/RemoveCircleOutline';
16
18
  import PanoramaFishEyeIcon from '@material-ui/icons/PanoramaFishEye';
@@ -22,6 +24,21 @@ import { DateTime, Interval } from 'luxon';
22
24
  import humanizeDuration from 'humanize-duration';
23
25
  import { useMountEffect } from '@react-hookz/web';
24
26
  import { makeStyles as makeStyles$1 } from '@material-ui/core/styles';
27
+ import capitalize from 'lodash/capitalize';
28
+ import CheckBoxIcon from '@material-ui/icons/CheckBox';
29
+ import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
30
+ import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
31
+ import { Autocomplete } from '@material-ui/lab';
32
+ import IconButton from '@material-ui/core/IconButton';
33
+ import ListItemIcon from '@material-ui/core/ListItemIcon';
34
+ import ListItemText from '@material-ui/core/ListItemText';
35
+ import MenuItem from '@material-ui/core/MenuItem';
36
+ import MenuList from '@material-ui/core/MenuList';
37
+ import Popover from '@material-ui/core/Popover';
38
+ import Description from '@material-ui/icons/Description';
39
+ import Edit from '@material-ui/icons/Edit';
40
+ import List from '@material-ui/icons/List';
41
+ import MoreVert from '@material-ui/icons/MoreVert';
25
42
 
26
43
  function isObject$1(value) {
27
44
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -328,7 +345,7 @@ var FieldOverrides = /*#__PURE__*/Object.freeze({
328
345
 
329
346
  const Form = withTheme(require("@rjsf/material-ui-v5").Theme);
330
347
 
331
- const useStyles$7 = makeStyles((theme) => ({
348
+ const useStyles$8 = makeStyles((theme) => ({
332
349
  backButton: {
333
350
  marginRight: theme.spacing(1)
334
351
  },
@@ -355,7 +372,7 @@ const Stepper = (stepperProps) => {
355
372
  const [activeStep, setActiveStep] = useState(0);
356
373
  const [formState, setFormState] = useFormDataFromQuery(props.initialState);
357
374
  const [errors, setErrors] = useState();
358
- const styles = useStyles$7();
375
+ const styles = useStyles$8();
359
376
  const extensions = useMemo(() => {
360
377
  return Object.fromEntries(
361
378
  props.extensions.map(({ name, component }) => [name, component])
@@ -447,7 +464,7 @@ const Stepper = (stepperProps) => {
447
464
  )))));
448
465
  };
449
466
 
450
- const useStyles$6 = makeStyles(() => ({
467
+ const useStyles$7 = makeStyles(() => ({
451
468
  header: {
452
469
  backgroundImage: ({ cardBackgroundImage }) => cardBackgroundImage,
453
470
  color: ({ cardFontColor }) => cardFontColor
@@ -466,7 +483,7 @@ const CardHeader = (props) => {
466
483
  } = props;
467
484
  const { getPageTheme } = useTheme();
468
485
  const themeForType = getPageTheme({ themeId: type });
469
- const styles = useStyles$6({
486
+ const styles = useStyles$7({
470
487
  cardFontColor: themeForType.fontColor,
471
488
  cardBackgroundImage: themeForType.backgroundImage
472
489
  });
@@ -481,18 +498,18 @@ const CardHeader = (props) => {
481
498
  );
482
499
  };
483
500
 
484
- const useStyles$5 = makeStyles(() => ({
501
+ const useStyles$6 = makeStyles(() => ({
485
502
  linkText: {
486
503
  display: "inline-flex",
487
504
  alignItems: "center"
488
505
  }
489
506
  }));
490
507
  const CardLink = ({ icon: Icon, text, url }) => {
491
- const styles = useStyles$5();
508
+ const styles = useStyles$6();
492
509
  return /* @__PURE__ */ React.createElement("div", { className: styles.linkText }, /* @__PURE__ */ React.createElement(Icon, { fontSize: "small" }), /* @__PURE__ */ React.createElement(Link, { style: { marginLeft: "8px" }, to: url }, text || url));
493
510
  };
494
511
 
495
- const useStyles$4 = makeStyles((theme) => ({
512
+ const useStyles$5 = makeStyles((theme) => ({
496
513
  box: {
497
514
  overflow: "hidden",
498
515
  textOverflow: "ellipsis",
@@ -530,7 +547,7 @@ const useStyles$4 = makeStyles((theme) => ({
530
547
  const TemplateCard = (props) => {
531
548
  var _a, _b, _c, _d, _e, _f, _g;
532
549
  const { template } = props;
533
- const styles = useStyles$4();
550
+ const styles = useStyles$5();
534
551
  const ownedByRelations = getEntityRelations(template, RELATION_OWNED_BY);
535
552
  const app = useApp();
536
553
  const iconResolver = (key) => {
@@ -551,14 +568,16 @@ const TemplateCard = (props) => {
551
568
  label: tag,
552
569
  key: tag
553
570
  }
554
- )))))), (props.additionalLinks || ((_e = template.metadata.links) == null ? void 0 : _e.length)) && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Divider, null)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2 }, (_f = props.additionalLinks) == null ? void 0 : _f.map(({ icon, text, url }) => /* @__PURE__ */ React.createElement(Grid, { className: styles.linkText, item: true, xs: 6 }, /* @__PURE__ */ React.createElement(CardLink, { icon, text, url }))), (_g = template.metadata.links) == null ? void 0 : _g.map(({ url, icon, title }) => /* @__PURE__ */ React.createElement(Grid, { className: styles.linkText, item: true, xs: 6 }, /* @__PURE__ */ React.createElement(
555
- CardLink,
556
- {
557
- icon: iconResolver(icon),
558
- text: title || url,
559
- url
560
- }
561
- )))))))), /* @__PURE__ */ React.createElement(CardActions, { style: { padding: "16px", flex: 1, alignItems: "flex-end" } }, /* @__PURE__ */ React.createElement("div", { className: styles.footer }, /* @__PURE__ */ React.createElement("div", { className: styles.ownedBy }, ownedByRelations.length > 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(UserIcon, { fontSize: "small" }), /* @__PURE__ */ React.createElement(
571
+ )))))), (props.additionalLinks || ((_e = template.metadata.links) == null ? void 0 : _e.length)) && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Divider, null)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2 }, (_f = props.additionalLinks) == null ? void 0 : _f.map(({ icon, text, url }, index) => /* @__PURE__ */ React.createElement(Grid, { className: styles.linkText, item: true, xs: 6, key: index }, /* @__PURE__ */ React.createElement(CardLink, { icon, text, url }))), (_g = template.metadata.links) == null ? void 0 : _g.map(
572
+ ({ url, icon, title }, index) => /* @__PURE__ */ React.createElement(Grid, { className: styles.linkText, item: true, xs: 6, key: index }, /* @__PURE__ */ React.createElement(
573
+ CardLink,
574
+ {
575
+ icon: iconResolver(icon),
576
+ text: title || url,
577
+ url
578
+ }
579
+ ))
580
+ )))))), /* @__PURE__ */ React.createElement(CardActions, { style: { padding: "16px", flex: 1, alignItems: "flex-end" } }, /* @__PURE__ */ React.createElement("div", { className: styles.footer }, /* @__PURE__ */ React.createElement("div", { className: styles.ownedBy }, ownedByRelations.length > 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(UserIcon, { fontSize: "small" }), /* @__PURE__ */ React.createElement(
562
581
  EntityRefLinks,
563
582
  {
564
583
  style: { marginLeft: "8px" },
@@ -603,6 +622,48 @@ const TemplateGroup = (props) => {
603
622
  ))));
604
623
  };
605
624
 
625
+ const TemplateGroups = (props) => {
626
+ const { loading, error, entities } = useEntityList();
627
+ const { groups, templateFilter, TemplateCardComponent, onTemplateSelected } = props;
628
+ const errorApi = useApi(errorApiRef);
629
+ const onSelected = useCallback(
630
+ (template) => {
631
+ onTemplateSelected == null ? void 0 : onTemplateSelected(template);
632
+ },
633
+ [onTemplateSelected]
634
+ );
635
+ if (loading) {
636
+ return /* @__PURE__ */ React.createElement(Progress, null);
637
+ }
638
+ if (error) {
639
+ errorApi.post(error);
640
+ return null;
641
+ }
642
+ if (!entities || !entities.length) {
643
+ return /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, "No templates found that match your filter. Learn more about", " ", /* @__PURE__ */ React.createElement(Link, { to: "https://backstage.io/docs/features/software-templates/adding-templates" }, "adding templates"), ".");
644
+ }
645
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, groups.map(({ title, filter }, index) => {
646
+ const templates = entities.filter(isTemplateEntityV1beta3).filter((e) => templateFilter ? !templateFilter(e) : true).filter(filter).map((template) => {
647
+ var _a, _b;
648
+ const additionalLinks = (_b = (_a = props.additionalLinksForEntity) == null ? void 0 : _a.call(props, template)) != null ? _b : [];
649
+ return {
650
+ template,
651
+ additionalLinks
652
+ };
653
+ });
654
+ return /* @__PURE__ */ React.createElement(
655
+ TemplateGroup$1,
656
+ {
657
+ key: index,
658
+ templates,
659
+ title,
660
+ components: { CardComponent: TemplateCardComponent },
661
+ onSelected
662
+ }
663
+ );
664
+ }));
665
+ };
666
+
606
667
  const SecretsContext = createVersionedContext("secrets-context");
607
668
  const SecretsContextProvider = (props) => {
608
669
  const [secrets, setSecrets] = useState({});
@@ -615,7 +676,7 @@ const SecretsContextProvider = (props) => {
615
676
  );
616
677
  };
617
678
 
618
- const useStyles$3 = makeStyles(() => ({
679
+ const useStyles$4 = makeStyles(() => ({
619
680
  markdown: {
620
681
  /** to make the styles for React Markdown not leak into the description */
621
682
  "& :first-child": {
@@ -629,7 +690,7 @@ const useStyles$3 = makeStyles(() => ({
629
690
  const Workflow = (workflowProps) => {
630
691
  var _a;
631
692
  const { title, description, namespace, templateName, ...props } = workflowProps;
632
- const styles = useStyles$3();
693
+ const styles = useStyles$4();
633
694
  const templateRef = stringifyEntityRef({
634
695
  kind: "Template",
635
696
  namespace,
@@ -664,7 +725,7 @@ const Workflow = (workflowProps) => {
664
725
  };
665
726
  const EmbeddableWorkflow = (props) => /* @__PURE__ */ React.createElement(SecretsContextProvider, null, /* @__PURE__ */ React.createElement(Workflow, { ...props }));
666
727
 
667
- const useStyles$2 = makeStyles({
728
+ const useStyles$3 = makeStyles({
668
729
  root: {
669
730
  "&:hover": {
670
731
  textDecoration: "none"
@@ -673,7 +734,7 @@ const useStyles$2 = makeStyles({
673
734
  });
674
735
  const LinkOutputs = (props) => {
675
736
  const { links = [] } = props.output;
676
- const classes = useStyles$2();
737
+ const classes = useStyles$3();
677
738
  const app = useApp();
678
739
  const entityRoute = useRouteRef(entityRouteRef);
679
740
  const iconResolver = (key) => {
@@ -760,7 +821,7 @@ const StepTime = (props) => {
760
821
  return /* @__PURE__ */ React.createElement(Typography, { variant: "caption" }, time);
761
822
  };
762
823
 
763
- const useStyles$1 = makeStyles((theme) => ({
824
+ const useStyles$2 = makeStyles((theme) => ({
764
825
  failed: {
765
826
  backgroundColor: theme.palette.error.main
766
827
  },
@@ -769,7 +830,7 @@ const useStyles$1 = makeStyles((theme) => ({
769
830
  }
770
831
  }));
771
832
  const TaskBorder = (props) => {
772
- const styles = useStyles$1();
833
+ const styles = useStyles$2();
773
834
  if (!props.isComplete) {
774
835
  return /* @__PURE__ */ React.createElement(LinearProgress, { variant: "indeterminate" });
775
836
  }
@@ -823,7 +884,7 @@ const TaskSteps = (props) => {
823
884
  )));
824
885
  };
825
886
 
826
- const useStyles = makeStyles$1({
887
+ const useStyles$1 = makeStyles$1({
827
888
  root: {
828
889
  width: "100%",
829
890
  height: "100%",
@@ -831,7 +892,7 @@ const useStyles = makeStyles$1({
831
892
  }
832
893
  });
833
894
  const TaskLogStream = (props) => {
834
- const styles = useStyles();
895
+ const styles = useStyles$1();
835
896
  return /* @__PURE__ */ React.createElement("div", { className: styles.root }, /* @__PURE__ */ React.createElement(
836
897
  LogViewer,
837
898
  {
@@ -840,6 +901,94 @@ const TaskLogStream = (props) => {
840
901
  ));
841
902
  };
842
903
 
904
+ const icon = /* @__PURE__ */ React.createElement(CheckBoxOutlineBlankIcon, { fontSize: "small" });
905
+ const checkedIcon = /* @__PURE__ */ React.createElement(CheckBoxIcon, { fontSize: "small" });
906
+ const TemplateCategoryPicker = () => {
907
+ const alertApi = useApi(alertApiRef);
908
+ const { error, loading, availableTypes, selectedTypes, setSelectedTypes } = useEntityTypeFilter();
909
+ if (loading)
910
+ return /* @__PURE__ */ React.createElement(Progress, null);
911
+ if (error) {
912
+ alertApi.post({
913
+ message: `Failed to load entity types with error: ${error}`,
914
+ severity: "error"
915
+ });
916
+ return null;
917
+ }
918
+ if (!availableTypes)
919
+ return null;
920
+ return /* @__PURE__ */ React.createElement(Box, { pb: 1, pt: 1 }, /* @__PURE__ */ React.createElement(Typography, { variant: "button" }, "Categories"), /* @__PURE__ */ React.createElement(
921
+ Autocomplete,
922
+ {
923
+ multiple: true,
924
+ "aria-label": "Categories",
925
+ options: availableTypes,
926
+ value: selectedTypes,
927
+ onChange: (_, value) => setSelectedTypes(value),
928
+ renderOption: (option, { selected }) => /* @__PURE__ */ React.createElement(
929
+ FormControlLabel,
930
+ {
931
+ control: /* @__PURE__ */ React.createElement(
932
+ Checkbox,
933
+ {
934
+ icon,
935
+ checkedIcon,
936
+ checked: selected
937
+ }
938
+ ),
939
+ label: capitalize(option)
940
+ }
941
+ ),
942
+ size: "small",
943
+ popupIcon: /* @__PURE__ */ React.createElement(ExpandMoreIcon, null),
944
+ renderInput: (params) => /* @__PURE__ */ React.createElement(TextField, { ...params, variant: "outlined" })
945
+ }
946
+ ));
947
+ };
948
+
949
+ const useStyles = makeStyles$1((theme) => ({
950
+ button: {
951
+ color: theme.page.fontColor
952
+ }
953
+ }));
954
+ function ScaffolderPageContextMenu(props) {
955
+ const { onEditorClicked, onActionsClicked, onTasksClicked } = props;
956
+ const classes = useStyles();
957
+ const [anchorEl, setAnchorEl] = useState();
958
+ if (!onEditorClicked && !onActionsClicked) {
959
+ return null;
960
+ }
961
+ const onOpen = (event) => {
962
+ setAnchorEl(event.currentTarget);
963
+ };
964
+ const onClose = () => {
965
+ setAnchorEl(void 0);
966
+ };
967
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
968
+ IconButton,
969
+ {
970
+ "aria-label": "more",
971
+ "aria-controls": "long-menu",
972
+ "aria-haspopup": "true",
973
+ onClick: onOpen,
974
+ "data-testid": "menu-button",
975
+ color: "inherit",
976
+ className: classes.button
977
+ },
978
+ /* @__PURE__ */ React.createElement(MoreVert, null)
979
+ ), /* @__PURE__ */ React.createElement(
980
+ Popover,
981
+ {
982
+ open: Boolean(anchorEl),
983
+ onClose,
984
+ anchorEl,
985
+ anchorOrigin: { vertical: "bottom", horizontal: "right" },
986
+ transformOrigin: { vertical: "top", horizontal: "right" }
987
+ },
988
+ /* @__PURE__ */ React.createElement(MenuList, null, onEditorClicked && /* @__PURE__ */ React.createElement(MenuItem, { onClick: onEditorClicked }, /* @__PURE__ */ React.createElement(ListItemIcon, null, /* @__PURE__ */ React.createElement(Edit, { fontSize: "small" })), /* @__PURE__ */ React.createElement(ListItemText, { primary: "Template Editor" })), onActionsClicked && /* @__PURE__ */ React.createElement(MenuItem, { onClick: onActionsClicked }, /* @__PURE__ */ React.createElement(ListItemIcon, null, /* @__PURE__ */ React.createElement(Description, { fontSize: "small" })), /* @__PURE__ */ React.createElement(ListItemText, { primary: "Installed Actions" })), onTasksClicked && /* @__PURE__ */ React.createElement(MenuItem, { onClick: onTasksClicked }, /* @__PURE__ */ React.createElement(ListItemIcon, null, /* @__PURE__ */ React.createElement(List, { fontSize: "small" })), /* @__PURE__ */ React.createElement(ListItemText, { primary: "Task List" })))
989
+ ));
990
+ }
991
+
843
992
  const FIELD_EXTENSION_KEY = "scaffolder.extensions.field.v1";
844
993
 
845
994
  function createNextScaffolderFieldExtension(options) {
@@ -856,5 +1005,5 @@ function createNextScaffolderFieldExtension(options) {
856
1005
  };
857
1006
  }
858
1007
 
859
- export { DefaultTemplateOutputs, EmbeddableWorkflow, Form, ReviewState, Stepper, TaskLogStream, TaskSteps, TemplateCard, TemplateGroup, Workflow, createFieldValidation, createNextScaffolderFieldExtension, extractSchemaFromStep, useFormDataFromQuery, useTemplateParameterSchema, useTemplateSchema };
1008
+ export { DefaultTemplateOutputs, EmbeddableWorkflow, Form, ReviewState, ScaffolderPageContextMenu, Stepper, TaskLogStream, TaskSteps, TemplateCard, TemplateCategoryPicker, TemplateGroup, TemplateGroups, Workflow, createFieldValidation, createNextScaffolderFieldExtension, extractSchemaFromStep, useFormDataFromQuery, useTemplateParameterSchema, useTemplateSchema };
860
1009
  //# sourceMappingURL=alpha.esm.js.map