@drodil/backstage-plugin-qeta-react 3.58.2 → 3.58.3

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.
@@ -67,36 +67,51 @@ const QetaProvider = (props) => {
67
67
  subscription.unsubscribe();
68
68
  };
69
69
  }, [storageApi]);
70
+ function cleanSettingsRecord(obj) {
71
+ const cleaned = {};
72
+ Object.entries(obj).forEach(([key, val]) => {
73
+ if (val !== void 0) {
74
+ cleaned[key] = val;
75
+ }
76
+ });
77
+ return cleaned;
78
+ }
70
79
  const updateSettings = useCallback(
71
- async (updates) => {
80
+ async (updates, replace = false) => {
72
81
  const bucket = storageApi.forBucket(BUCKET_KEY);
73
82
  const snapshot = bucket.snapshot(STORAGE_KEY);
74
83
  const storedSettings = snapshot.value;
75
84
  const currentSettings = storedSettings ? merge({}, DEFAULT_SETTINGS, storedSettings) : settingsRef.current;
76
- const newSettings = { ...currentSettings };
77
- Object.keys(updates).forEach((key) => {
78
- const k = key;
79
- const value = updates[k];
80
- if (Object.hasOwn(updates, k)) {
81
- if (k === "viewType" || k === "filterPanelExpanded") {
82
- const currentValue = currentSettings[k] || {};
83
- const updateValue = value || {};
84
- const merged = { ...currentValue };
85
- Object.keys(updateValue).forEach((subKey) => {
86
- if (updateValue[subKey] === void 0) {
87
- delete merged[subKey];
88
- } else {
89
- merged[subKey] = updateValue[subKey];
90
- }
85
+ let newSettings;
86
+ if (replace) {
87
+ newSettings = { ...updates };
88
+ } else {
89
+ const processedUpdates = {};
90
+ Object.keys(updates).forEach((key) => {
91
+ const value = updates[key];
92
+ if (value === void 0) {
93
+ return;
94
+ }
95
+ if (key === "viewType") {
96
+ const current = currentSettings.viewType || {};
97
+ const update = value;
98
+ processedUpdates.viewType = cleanSettingsRecord({
99
+ ...current,
100
+ ...update
91
101
  });
92
- newSettings[k] = merged;
93
- } else if (value !== void 0 && value && typeof value === "object" && !Array.isArray(value)) {
94
- newSettings[k] = merge({}, currentSettings[k], value);
95
- } else if (value !== void 0) {
96
- newSettings[k] = value;
102
+ } else if (key === "filterPanelExpanded") {
103
+ const current = currentSettings.filterPanelExpanded || {};
104
+ const update = value;
105
+ processedUpdates.filterPanelExpanded = cleanSettingsRecord({
106
+ ...current,
107
+ ...update
108
+ });
109
+ } else {
110
+ processedUpdates[key] = value;
97
111
  }
98
- }
99
- });
112
+ });
113
+ newSettings = { ...currentSettings, ...processedUpdates };
114
+ }
100
115
  settingsRef.current = newSettings;
101
116
  setSettings(newSettings);
102
117
  isUpdatingRef.current = true;
@@ -122,7 +137,7 @@ const QetaProvider = (props) => {
122
137
  [updateSettings]
123
138
  );
124
139
  const resetSettings = useCallback(async () => {
125
- await updateSettings(DEFAULT_SETTINGS);
140
+ await updateSettings(DEFAULT_SETTINGS, true);
126
141
  }, [updateSettings]);
127
142
  const contextValue = useMemo(
128
143
  () => ({
@@ -1 +1 @@
1
- {"version":3,"file":"QetaContext.esm.js","sources":["../../../src/components/QetaContext/QetaContext.tsx"],"sourcesContent":["import {\n createContext,\n Dispatch,\n PropsWithChildren,\n SetStateAction,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { PluggableList } from 'unified';\nimport { storageApiRef, useApi } from '@backstage/core-plugin-api';\nimport { merge } from 'lodash';\nimport { ViewType } from '../ViewToggle/ViewToggle';\n\nexport type UserSettings = {\n autoSaveEnabled: boolean;\n anonymousPosting: boolean;\n filterPanelExpanded: Record<string, boolean>;\n viewType: Record<string, ViewType>;\n aiAnswerExpanded: boolean;\n usePagination: boolean;\n};\n\nconst DEFAULT_SETTINGS: UserSettings = {\n autoSaveEnabled: false,\n anonymousPosting: false,\n filterPanelExpanded: {},\n viewType: {},\n aiAnswerExpanded: false,\n usePagination: false,\n};\n\nconst BUCKET_KEY = 'qeta';\nconst STORAGE_KEY = 'qeta-user-settings';\n\nexport type QetaContextProps = {\n remarkPlugins?: PluggableList;\n rehypePlugins?: PluggableList;\n draftQuestion?: {\n title: string;\n content: string;\n tags?: string[];\n entities?: string[];\n };\n setDraftQuestion?: Dispatch<\n SetStateAction<\n | {\n title: string;\n content: string;\n tags?: string[];\n entities?: string[];\n }\n | undefined\n >\n >;\n settings?: UserSettings;\n updateSettings?: (updates: Partial<UserSettings>) => Promise<void>;\n getSetting?: <K extends keyof UserSettings>(key: K) => UserSettings[K];\n setSetting?: <K extends keyof UserSettings>(\n key: K,\n value: UserSettings[K],\n ) => Promise<void>;\n resetSettings?: () => Promise<void>;\n isSettingsLoaded?: boolean;\n};\n\nexport const QetaContext = createContext<QetaContextProps>({\n remarkPlugins: [],\n rehypePlugins: [],\n settings: DEFAULT_SETTINGS,\n updateSettings: async () => {},\n getSetting: <K extends keyof UserSettings>(key: K): UserSettings[K] =>\n DEFAULT_SETTINGS[key],\n setSetting: async () => {},\n resetSettings: async () => {},\n isSettingsLoaded: false,\n});\n\nexport const QetaProvider = (props: PropsWithChildren<QetaContextProps>) => {\n const storageApi = useApi(storageApiRef);\n const [settings, setSettings] = useState<UserSettings>(DEFAULT_SETTINGS);\n const [isSettingsLoaded, setIsSettingsLoaded] = useState(false);\n const settingsRef = useRef<UserSettings>(DEFAULT_SETTINGS);\n const isUpdatingRef = useRef(false);\n\n const [draftQuestion, setDraftQuestion] = useState<\n | {\n title: string;\n content: string;\n tags?: string[];\n entities?: string[];\n }\n | undefined\n >(undefined);\n\n useEffect(() => {\n settingsRef.current = settings;\n }, [settings]);\n\n useEffect(() => {\n const bucket = storageApi.forBucket(BUCKET_KEY);\n\n isUpdatingRef.current = false;\n\n const snapshot = bucket.snapshot(STORAGE_KEY);\n const stored = snapshot.value as UserSettings | undefined;\n\n if (stored) {\n const merged = merge({}, DEFAULT_SETTINGS, stored);\n setSettings(merged);\n settingsRef.current = merged;\n } else {\n setSettings(DEFAULT_SETTINGS);\n settingsRef.current = DEFAULT_SETTINGS;\n }\n\n setIsSettingsLoaded(true);\n\n const subscription = bucket.observe$<UserSettings>(STORAGE_KEY).subscribe({\n next: newSnapshot => {\n if (isUpdatingRef.current) {\n return;\n }\n\n const value = newSnapshot.value;\n if (value) {\n const merged = merge({}, DEFAULT_SETTINGS, value);\n setSettings(merged);\n settingsRef.current = merged;\n }\n },\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [storageApi]);\n\n const updateSettings = useCallback(\n async (updates: Partial<UserSettings>) => {\n const bucket = storageApi.forBucket(BUCKET_KEY);\n\n const snapshot = bucket.snapshot(STORAGE_KEY);\n const storedSettings = snapshot.value as UserSettings | undefined;\n const currentSettings = storedSettings\n ? merge({}, DEFAULT_SETTINGS, storedSettings)\n : settingsRef.current;\n\n const newSettings = { ...currentSettings };\n Object.keys(updates).forEach(key => {\n const k = key as keyof UserSettings;\n const value = updates[k];\n if (Object.hasOwn(updates, k)) {\n if (k === 'viewType' || k === 'filterPanelExpanded') {\n const currentValue = currentSettings[k] || {};\n const updateValue = (value || {}) as Record<string, any>;\n const merged = { ...currentValue };\n\n Object.keys(updateValue).forEach(subKey => {\n if (updateValue[subKey] === undefined) {\n delete merged[subKey];\n } else {\n merged[subKey] = updateValue[subKey];\n }\n });\n\n newSettings[k] = merged as any;\n } else if (\n value !== undefined &&\n value &&\n typeof value === 'object' &&\n !Array.isArray(value)\n ) {\n newSettings[k] = merge({}, currentSettings[k], value);\n } else if (value !== undefined) {\n newSettings[k] = value as any;\n }\n }\n });\n\n settingsRef.current = newSettings;\n setSettings(newSettings);\n\n isUpdatingRef.current = true;\n try {\n await bucket.set(STORAGE_KEY, newSettings);\n } finally {\n await Promise.resolve();\n isUpdatingRef.current = false;\n }\n },\n [storageApi],\n );\n\n const getSetting = useCallback(\n <K extends keyof UserSettings>(key: K): UserSettings[K] => {\n return settingsRef.current[key] ?? DEFAULT_SETTINGS[key];\n },\n [],\n );\n\n const setSetting = useCallback(\n async <K extends keyof UserSettings>(\n key: K,\n value: UserSettings[K],\n ): Promise<void> => {\n await updateSettings({ [key]: value } as Partial<UserSettings>);\n },\n [updateSettings],\n );\n\n const resetSettings = useCallback(async () => {\n await updateSettings(DEFAULT_SETTINGS);\n }, [updateSettings]);\n\n const contextValue = useMemo(\n () => ({\n ...props,\n draftQuestion,\n setDraftQuestion,\n settings,\n updateSettings,\n getSetting,\n setSetting,\n resetSettings,\n isSettingsLoaded,\n }),\n [\n props,\n draftQuestion,\n setDraftQuestion,\n settings,\n updateSettings,\n getSetting,\n setSetting,\n resetSettings,\n isSettingsLoaded,\n ],\n );\n\n return (\n <QetaContext.Provider value={contextValue}>\n {props.children}\n </QetaContext.Provider>\n );\n};\n\nexport function useQetaContext(): QetaContextProps {\n const context = useContext(QetaContext);\n\n if (!context) {\n return {\n remarkPlugins: [],\n rehypePlugins: [],\n draftQuestion: undefined,\n setDraftQuestion: undefined,\n settings: DEFAULT_SETTINGS,\n updateSettings: async () => {},\n getSetting: <K extends keyof UserSettings>(key: K): UserSettings[K] =>\n DEFAULT_SETTINGS[key],\n setSetting: async () => {},\n resetSettings: async () => {},\n isSettingsLoaded: false,\n };\n }\n\n return context;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"QetaContext.esm.js","sources":["../../../src/components/QetaContext/QetaContext.tsx"],"sourcesContent":["import {\n createContext,\n Dispatch,\n PropsWithChildren,\n SetStateAction,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { PluggableList } from 'unified';\nimport { storageApiRef, useApi } from '@backstage/core-plugin-api';\nimport { merge } from 'lodash';\nimport { ViewType } from '../ViewToggle/ViewToggle';\n\nexport type UserSettings = {\n autoSaveEnabled: boolean;\n anonymousPosting: boolean;\n filterPanelExpanded: Record<string, boolean>;\n viewType: Record<string, ViewType>;\n aiAnswerExpanded: boolean;\n usePagination: boolean;\n};\n\nconst DEFAULT_SETTINGS: UserSettings = {\n autoSaveEnabled: false,\n anonymousPosting: false,\n filterPanelExpanded: {},\n viewType: {},\n aiAnswerExpanded: false,\n usePagination: false,\n};\n\nconst BUCKET_KEY = 'qeta';\nconst STORAGE_KEY = 'qeta-user-settings';\n\nexport type QetaContextProps = {\n remarkPlugins?: PluggableList;\n rehypePlugins?: PluggableList;\n draftQuestion?: {\n title: string;\n content: string;\n tags?: string[];\n entities?: string[];\n };\n setDraftQuestion?: Dispatch<\n SetStateAction<\n | {\n title: string;\n content: string;\n tags?: string[];\n entities?: string[];\n }\n | undefined\n >\n >;\n settings?: UserSettings;\n updateSettings?: (updates: Partial<UserSettings>) => Promise<void>;\n getSetting?: <K extends keyof UserSettings>(key: K) => UserSettings[K];\n setSetting?: <K extends keyof UserSettings>(\n key: K,\n value: UserSettings[K],\n ) => Promise<void>;\n resetSettings?: () => Promise<void>;\n isSettingsLoaded?: boolean;\n};\n\nexport const QetaContext = createContext<QetaContextProps>({\n remarkPlugins: [],\n rehypePlugins: [],\n settings: DEFAULT_SETTINGS,\n updateSettings: async () => {},\n getSetting: <K extends keyof UserSettings>(key: K): UserSettings[K] =>\n DEFAULT_SETTINGS[key],\n setSetting: async () => {},\n resetSettings: async () => {},\n isSettingsLoaded: false,\n});\n\nexport const QetaProvider = (props: PropsWithChildren<QetaContextProps>) => {\n const storageApi = useApi(storageApiRef);\n const [settings, setSettings] = useState<UserSettings>(DEFAULT_SETTINGS);\n const [isSettingsLoaded, setIsSettingsLoaded] = useState(false);\n const settingsRef = useRef<UserSettings>(DEFAULT_SETTINGS);\n const isUpdatingRef = useRef(false);\n\n const [draftQuestion, setDraftQuestion] = useState<\n | {\n title: string;\n content: string;\n tags?: string[];\n entities?: string[];\n }\n | undefined\n >(undefined);\n\n useEffect(() => {\n settingsRef.current = settings;\n }, [settings]);\n\n useEffect(() => {\n const bucket = storageApi.forBucket(BUCKET_KEY);\n\n isUpdatingRef.current = false;\n\n const snapshot = bucket.snapshot(STORAGE_KEY);\n const stored = snapshot.value as UserSettings | undefined;\n\n if (stored) {\n const merged = merge({}, DEFAULT_SETTINGS, stored);\n setSettings(merged);\n settingsRef.current = merged;\n } else {\n setSettings(DEFAULT_SETTINGS);\n settingsRef.current = DEFAULT_SETTINGS;\n }\n\n setIsSettingsLoaded(true);\n\n const subscription = bucket.observe$<UserSettings>(STORAGE_KEY).subscribe({\n next: newSnapshot => {\n if (isUpdatingRef.current) {\n return;\n }\n\n const value = newSnapshot.value;\n if (value) {\n const merged = merge({}, DEFAULT_SETTINGS, value);\n setSettings(merged);\n settingsRef.current = merged;\n }\n },\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [storageApi]);\n\n function cleanSettingsRecord<T>(obj: Record<string, T>): Record<string, T> {\n const cleaned: Record<string, T> = {};\n Object.entries(obj).forEach(([key, val]) => {\n if (val !== undefined) {\n cleaned[key] = val;\n }\n });\n return cleaned;\n }\n\n const updateSettings = useCallback(\n async (updates: Partial<UserSettings>, replace = false) => {\n const bucket = storageApi.forBucket(BUCKET_KEY);\n\n const snapshot = bucket.snapshot(STORAGE_KEY);\n const storedSettings = snapshot.value as UserSettings | undefined;\n const currentSettings = storedSettings\n ? merge({}, DEFAULT_SETTINGS, storedSettings)\n : settingsRef.current;\n\n let newSettings: UserSettings;\n\n if (replace) {\n newSettings = { ...updates } as UserSettings;\n } else {\n const processedUpdates: Partial<UserSettings> = {};\n (Object.keys(updates) as Array<keyof UserSettings>).forEach(key => {\n const value = updates[key];\n if (value === undefined) {\n return;\n }\n\n if (key === 'viewType') {\n const current = currentSettings.viewType || {};\n const update = value as Record<string, ViewType>;\n processedUpdates.viewType = cleanSettingsRecord({\n ...current,\n ...update,\n });\n } else if (key === 'filterPanelExpanded') {\n const current = currentSettings.filterPanelExpanded || {};\n const update = value as Record<string, boolean>;\n processedUpdates.filterPanelExpanded = cleanSettingsRecord({\n ...current,\n ...update,\n });\n } else {\n processedUpdates[key] =\n value as (typeof processedUpdates)[typeof key];\n }\n });\n\n newSettings = { ...currentSettings, ...processedUpdates };\n }\n\n settingsRef.current = newSettings;\n setSettings(newSettings);\n\n isUpdatingRef.current = true;\n try {\n await bucket.set(STORAGE_KEY, newSettings);\n } finally {\n await Promise.resolve();\n isUpdatingRef.current = false;\n }\n },\n [storageApi],\n );\n\n const getSetting = useCallback(\n <K extends keyof UserSettings>(key: K): UserSettings[K] => {\n return settingsRef.current[key] ?? DEFAULT_SETTINGS[key];\n },\n [],\n );\n\n const setSetting = useCallback(\n async <K extends keyof UserSettings>(\n key: K,\n value: UserSettings[K],\n ): Promise<void> => {\n await updateSettings({ [key]: value } as Partial<UserSettings>);\n },\n [updateSettings],\n );\n\n const resetSettings = useCallback(async () => {\n await updateSettings(DEFAULT_SETTINGS, true);\n }, [updateSettings]);\n\n const contextValue = useMemo(\n () => ({\n ...props,\n draftQuestion,\n setDraftQuestion,\n settings,\n updateSettings,\n getSetting,\n setSetting,\n resetSettings,\n isSettingsLoaded,\n }),\n [\n props,\n draftQuestion,\n setDraftQuestion,\n settings,\n updateSettings,\n getSetting,\n setSetting,\n resetSettings,\n isSettingsLoaded,\n ],\n );\n\n return (\n <QetaContext.Provider value={contextValue}>\n {props.children}\n </QetaContext.Provider>\n );\n};\n\nexport function useQetaContext(): QetaContextProps {\n const context = useContext(QetaContext);\n\n if (!context) {\n return {\n remarkPlugins: [],\n rehypePlugins: [],\n draftQuestion: undefined,\n setDraftQuestion: undefined,\n settings: DEFAULT_SETTINGS,\n updateSettings: async () => {},\n getSetting: <K extends keyof UserSettings>(key: K): UserSettings[K] =>\n DEFAULT_SETTINGS[key],\n setSetting: async () => {},\n resetSettings: async () => {},\n isSettingsLoaded: false,\n };\n }\n\n return context;\n}\n"],"names":[],"mappings":";;;;;AA0BA,MAAM,gBAAiC,GAAA;AAAA,EACrC,eAAiB,EAAA,KAAA;AAAA,EACjB,gBAAkB,EAAA,KAAA;AAAA,EAClB,qBAAqB,EAAC;AAAA,EACtB,UAAU,EAAC;AAAA,EACX,gBAAkB,EAAA,KAAA;AAAA,EAClB,aAAe,EAAA;AACjB,CAAA;AAEA,MAAM,UAAa,GAAA,MAAA;AACnB,MAAM,WAAc,GAAA,oBAAA;AAiCb,MAAM,cAAc,aAAgC,CAAA;AAAA,EACzD,eAAe,EAAC;AAAA,EAChB,eAAe,EAAC;AAAA,EAChB,QAAU,EAAA,gBAAA;AAAA,EACV,gBAAgB,YAAY;AAAA,GAAC;AAAA,EAC7B,UAAY,EAAA,CAA+B,GACzC,KAAA,gBAAA,CAAiB,GAAG,CAAA;AAAA,EACtB,YAAY,YAAY;AAAA,GAAC;AAAA,EACzB,eAAe,YAAY;AAAA,GAAC;AAAA,EAC5B,gBAAkB,EAAA;AACpB,CAAC;AAEY,MAAA,YAAA,GAAe,CAAC,KAA+C,KAAA;AAC1E,EAAM,MAAA,UAAA,GAAa,OAAO,aAAa,CAAA;AACvC,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAuB,gBAAgB,CAAA;AACvE,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,SAAS,KAAK,CAAA;AAC9D,EAAM,MAAA,WAAA,GAAc,OAAqB,gBAAgB,CAAA;AACzD,EAAM,MAAA,aAAA,GAAgB,OAAO,KAAK,CAAA;AAElC,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAQxC,KAAS,CAAA,CAAA;AAEX,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,WAAA,CAAY,OAAU,GAAA,QAAA;AAAA,GACxB,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,SAAA,CAAU,MAAM;AACd,IAAM,MAAA,MAAA,GAAS,UAAW,CAAA,SAAA,CAAU,UAAU,CAAA;AAE9C,IAAA,aAAA,CAAc,OAAU,GAAA,KAAA;AAExB,IAAM,MAAA,QAAA,GAAW,MAAO,CAAA,QAAA,CAAS,WAAW,CAAA;AAC5C,IAAA,MAAM,SAAS,QAAS,CAAA,KAAA;AAExB,IAAA,IAAI,MAAQ,EAAA;AACV,MAAA,MAAM,MAAS,GAAA,KAAA,CAAM,EAAC,EAAG,kBAAkB,MAAM,CAAA;AACjD,MAAA,WAAA,CAAY,MAAM,CAAA;AAClB,MAAA,WAAA,CAAY,OAAU,GAAA,MAAA;AAAA,KACjB,MAAA;AACL,MAAA,WAAA,CAAY,gBAAgB,CAAA;AAC5B,MAAA,WAAA,CAAY,OAAU,GAAA,gBAAA;AAAA;AAGxB,IAAA,mBAAA,CAAoB,IAAI,CAAA;AAExB,IAAA,MAAM,YAAe,GAAA,MAAA,CAAO,QAAuB,CAAA,WAAW,EAAE,SAAU,CAAA;AAAA,MACxE,MAAM,CAAe,WAAA,KAAA;AACnB,QAAA,IAAI,cAAc,OAAS,EAAA;AACzB,UAAA;AAAA;AAGF,QAAA,MAAM,QAAQ,WAAY,CAAA,KAAA;AAC1B,QAAA,IAAI,KAAO,EAAA;AACT,UAAA,MAAM,MAAS,GAAA,KAAA,CAAM,EAAC,EAAG,kBAAkB,KAAK,CAAA;AAChD,UAAA,WAAA,CAAY,MAAM,CAAA;AAClB,UAAA,WAAA,CAAY,OAAU,GAAA,MAAA;AAAA;AACxB;AACF,KACD,CAAA;AAED,IAAA,OAAO,MAAM;AACX,MAAA,YAAA,CAAa,WAAY,EAAA;AAAA,KAC3B;AAAA,GACF,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAA,SAAS,oBAAuB,GAA2C,EAAA;AACzE,IAAA,MAAM,UAA6B,EAAC;AACpC,IAAO,MAAA,CAAA,OAAA,CAAQ,GAAG,CAAE,CAAA,OAAA,CAAQ,CAAC,CAAC,GAAA,EAAK,GAAG,CAAM,KAAA;AAC1C,MAAA,IAAI,QAAQ,KAAW,CAAA,EAAA;AACrB,QAAA,OAAA,CAAQ,GAAG,CAAI,GAAA,GAAA;AAAA;AACjB,KACD,CAAA;AACD,IAAO,OAAA,OAAA;AAAA;AAGT,EAAA,MAAM,cAAiB,GAAA,WAAA;AAAA,IACrB,OAAO,OAAgC,EAAA,OAAA,GAAU,KAAU,KAAA;AACzD,MAAM,MAAA,MAAA,GAAS,UAAW,CAAA,SAAA,CAAU,UAAU,CAAA;AAE9C,MAAM,MAAA,QAAA,GAAW,MAAO,CAAA,QAAA,CAAS,WAAW,CAAA;AAC5C,MAAA,MAAM,iBAAiB,QAAS,CAAA,KAAA;AAChC,MAAM,MAAA,eAAA,GAAkB,iBACpB,KAAM,CAAA,IAAI,gBAAkB,EAAA,cAAc,IAC1C,WAAY,CAAA,OAAA;AAEhB,MAAI,IAAA,WAAA;AAEJ,MAAA,IAAI,OAAS,EAAA;AACX,QAAc,WAAA,GAAA,EAAE,GAAG,OAAQ,EAAA;AAAA,OACtB,MAAA;AACL,QAAA,MAAM,mBAA0C,EAAC;AACjD,QAAC,MAAO,CAAA,IAAA,CAAK,OAAO,CAAA,CAAgC,QAAQ,CAAO,GAAA,KAAA;AACjE,UAAM,MAAA,KAAA,GAAQ,QAAQ,GAAG,CAAA;AACzB,UAAA,IAAI,UAAU,KAAW,CAAA,EAAA;AACvB,YAAA;AAAA;AAGF,UAAA,IAAI,QAAQ,UAAY,EAAA;AACtB,YAAM,MAAA,OAAA,GAAU,eAAgB,CAAA,QAAA,IAAY,EAAC;AAC7C,YAAA,MAAM,MAAS,GAAA,KAAA;AACf,YAAA,gBAAA,CAAiB,WAAW,mBAAoB,CAAA;AAAA,cAC9C,GAAG,OAAA;AAAA,cACH,GAAG;AAAA,aACJ,CAAA;AAAA,WACH,MAAA,IAAW,QAAQ,qBAAuB,EAAA;AACxC,YAAM,MAAA,OAAA,GAAU,eAAgB,CAAA,mBAAA,IAAuB,EAAC;AACxD,YAAA,MAAM,MAAS,GAAA,KAAA;AACf,YAAA,gBAAA,CAAiB,sBAAsB,mBAAoB,CAAA;AAAA,cACzD,GAAG,OAAA;AAAA,cACH,GAAG;AAAA,aACJ,CAAA;AAAA,WACI,MAAA;AACL,YAAA,gBAAA,CAAiB,GAAG,CAClB,GAAA,KAAA;AAAA;AACJ,SACD,CAAA;AAED,QAAA,WAAA,GAAc,EAAE,GAAG,eAAiB,EAAA,GAAG,gBAAiB,EAAA;AAAA;AAG1D,MAAA,WAAA,CAAY,OAAU,GAAA,WAAA;AACtB,MAAA,WAAA,CAAY,WAAW,CAAA;AAEvB,MAAA,aAAA,CAAc,OAAU,GAAA,IAAA;AACxB,MAAI,IAAA;AACF,QAAM,MAAA,MAAA,CAAO,GAAI,CAAA,WAAA,EAAa,WAAW,CAAA;AAAA,OACzC,SAAA;AACA,QAAA,MAAM,QAAQ,OAAQ,EAAA;AACtB,QAAA,aAAA,CAAc,OAAU,GAAA,KAAA;AAAA;AAC1B,KACF;AAAA,IACA,CAAC,UAAU;AAAA,GACb;AAEA,EAAA,MAAM,UAAa,GAAA,WAAA;AAAA,IACjB,CAA+B,GAA4B,KAAA;AACzD,MAAA,OAAO,WAAY,CAAA,OAAA,CAAQ,GAAG,CAAA,IAAK,iBAAiB,GAAG,CAAA;AAAA,KACzD;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,UAAa,GAAA,WAAA;AAAA,IACjB,OACE,KACA,KACkB,KAAA;AAClB,MAAA,MAAM,eAAe,EAAE,CAAC,GAAG,GAAG,OAAgC,CAAA;AAAA,KAChE;AAAA,IACA,CAAC,cAAc;AAAA,GACjB;AAEA,EAAM,MAAA,aAAA,GAAgB,YAAY,YAAY;AAC5C,IAAM,MAAA,cAAA,CAAe,kBAAkB,IAAI,CAAA;AAAA,GAC7C,EAAG,CAAC,cAAc,CAAC,CAAA;AAEnB,EAAA,MAAM,YAAe,GAAA,OAAA;AAAA,IACnB,OAAO;AAAA,MACL,GAAG,KAAA;AAAA,MACH,aAAA;AAAA,MACA,gBAAA;AAAA,MACA,QAAA;AAAA,MACA,cAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,IACA;AAAA,MACE,KAAA;AAAA,MACA,aAAA;AAAA,MACA,gBAAA;AAAA,MACA,QAAA;AAAA,MACA,cAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAA;AAAA,MACA;AAAA;AACF,GACF;AAEA,EAAA,2BACG,WAAY,CAAA,QAAA,EAAZ,EAAqB,KAAO,EAAA,YAAA,EAC1B,gBAAM,QACT,EAAA,CAAA;AAEJ;AAEO,SAAS,cAAmC,GAAA;AACjD,EAAM,MAAA,OAAA,GAAU,WAAW,WAAW,CAAA;AAEtC,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAO,OAAA;AAAA,MACL,eAAe,EAAC;AAAA,MAChB,eAAe,EAAC;AAAA,MAChB,aAAe,EAAA,KAAA,CAAA;AAAA,MACf,gBAAkB,EAAA,KAAA,CAAA;AAAA,MAClB,QAAU,EAAA,gBAAA;AAAA,MACV,gBAAgB,YAAY;AAAA,OAAC;AAAA,MAC7B,UAAY,EAAA,CAA+B,GACzC,KAAA,gBAAA,CAAiB,GAAG,CAAA;AAAA,MACtB,YAAY,YAAY;AAAA,OAAC;AAAA,MACzB,eAAe,YAAY;AAAA,OAAC;AAAA,MAC5B,gBAAkB,EAAA;AAAA,KACpB;AAAA;AAGF,EAAO,OAAA,OAAA;AACT;;;;"}
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "frontend",
8
8
  "backstage.io"
9
9
  ],
10
- "version": "3.58.2",
10
+ "version": "3.58.3",
11
11
  "main": "dist/index.esm.js",
12
12
  "types": "dist/index.d.ts",
13
13
  "prepublishOnly": "yarn tsc && yarn build",
@@ -57,7 +57,7 @@
57
57
  "@backstage/plugin-permission-common": "^0.9.4",
58
58
  "@backstage/plugin-permission-react": "^0.4.39",
59
59
  "@backstage/plugin-signals-react": "^0.0.18",
60
- "@drodil/backstage-plugin-qeta-common": "^3.58.2",
60
+ "@drodil/backstage-plugin-qeta-common": "^3.58.3",
61
61
  "@jsdevtools/rehype-toc": "^3.0.2",
62
62
  "@material-ui/core": "^4.12.2",
63
63
  "@material-ui/icons": "^4.11.3",