diff --git a/docs/framework/public/components/progressbar.png b/docs/framework/public/components/progressbar.png new file mode 100644 index 000000000..872528352 Binary files /dev/null and b/docs/framework/public/components/progressbar.png differ diff --git a/src/ui/src/components/core/base/BaseInputWrapper.vue b/src/ui/src/components/core/base/BaseInputWrapper.vue index 1cb3b391b..ed3b64273 100644 --- a/src/ui/src/components/core/base/BaseInputWrapper.vue +++ b/src/ui/src/components/core/base/BaseInputWrapper.vue @@ -4,16 +4,16 @@ class="BaseInputWrapper" :class="{ horizontal: isHorizontal }" > - + diff --git a/src/ui/src/composables/useFieldValue.ts b/src/ui/src/composables/useFieldValue.ts new file mode 100644 index 000000000..595f1f93a --- /dev/null +++ b/src/ui/src/composables/useFieldValue.ts @@ -0,0 +1,10 @@ +import { ComputedRef, computed } from "vue"; + +type Fields = Record>; + +export function useFieldValueAsYesNo( + fields: Fields, + key: string, +): ComputedRef { + return computed(() => fields[key].value === "yes"); +} diff --git a/src/ui/src/composables/useFormatter.ts b/src/ui/src/composables/useFormatter.ts new file mode 100644 index 000000000..da47c5912 --- /dev/null +++ b/src/ui/src/composables/useFormatter.ts @@ -0,0 +1,18 @@ +import { computed, ComputedRef } from "vue"; + +export function usePercentageFormatter( + number: ComputedRef, + options: Pick< + Intl.NumberFormatOptions, + "minimumFractionDigits" | "maximumFractionDigits" + > = { + minimumFractionDigits: 0, + maximumFractionDigits: 1, + }, +) { + const formatter = new Intl.NumberFormat(undefined, { + style: "percent", + ...options, + }); + return computed(() => formatter.format(number.value)); +} diff --git a/src/ui/src/core/templateMap.ts b/src/ui/src/core/templateMap.ts index c3031ccbd..ec4b344f2 100644 --- a/src/ui/src/core/templateMap.ts +++ b/src/ui/src/core/templateMap.ts @@ -17,6 +17,7 @@ import CoreTags from "../components/core/content/CoreTags.vue"; import CoreAvatar from "../components/core/content/CoreAvatar.vue"; import CoreAnnotatedText from "../components/core/content/CoreAnnotatedText.vue"; import CoreJsonViewer from "../components/core/content/CoreJsonViewer.vue"; +import CoreProgressBar from "../components/core/content/CoreProgressBar.vue"; // input import CoreCheckboxInput from "../components/core/input/CoreCheckboxInput.vue"; @@ -136,6 +137,7 @@ const templateMap: TemplateMap = { jsonviewer: CoreJsonViewer, workflows_root: WorkflowsRoot, workflows_workflow: WorkflowsWorkflow, + progressbar: CoreProgressBar, }; const abstractTemplateMap: Record = {}; diff --git a/src/ui/src/renderer/syntheticEvents.ts b/src/ui/src/renderer/syntheticEvents.ts index df7bab08c..5fcf3b229 100644 --- a/src/ui/src/renderer/syntheticEvents.ts +++ b/src/ui/src/renderer/syntheticEvents.ts @@ -1,4 +1,7 @@ -export function getClick(ev: MouseEvent): CustomEvent { +/** + * @param ev event from a mouse click, or a keyboard click (using tab navigation, then click with `Enter`) + */ +export function getClick(ev: MouseEvent | KeyboardEvent): CustomEvent { const payload = { ctrlKey: ev.ctrlKey, shiftKey: ev.shiftKey,