diff --git a/packages/ui/src/components/base/Combobox.vue b/packages/ui/src/components/base/Combobox.vue index 750238a9e1..eddd74c20c 100644 --- a/packages/ui/src/components/base/Combobox.vue +++ b/packages/ui/src/components/base/Combobox.vue @@ -478,7 +478,7 @@ function setInitialFocus() { function determineOpenDirection( triggerRect: DOMRect, - dropdownRect: DOMRect, + dropdownRect: { width: number; height: number }, viewport: ViewportRect, ): 'up' | 'down' { if (props.forceDirection) { @@ -499,7 +499,7 @@ function determineOpenDirection( function calculateVerticalPosition( triggerRect: DOMRect, - dropdownRect: DOMRect, + dropdownRect: { width: number; height: number }, direction: 'up' | 'down', viewport: ViewportRect, ): number { @@ -513,7 +513,7 @@ function calculateVerticalPosition( function calculateHorizontalPosition( triggerRect: DOMRect, - dropdownRect: DOMRect, + dropdownRect: { width: number; height: number }, viewport: ViewportRect, ): number { const minLeft = viewport.offsetLeft + DROPDOWN_VIEWPORT_MARGIN @@ -556,7 +556,7 @@ async function updateDropdownPosition() { await nextTick() const triggerRect = effectiveTriggerEl.value.getBoundingClientRect() - const width = resolveDropdownWidth(triggerRect.width) + const width = resolveDropdownWidth(effectiveTriggerEl.value.offsetWidth) const minWidth = resolveCssSize(props.dropdownMinWidth) ?? '0px' dropdownStyle.value = { @@ -567,7 +567,10 @@ async function updateDropdownPosition() { await nextTick() - const dropdownRect = dropdownRef.value.getBoundingClientRect() + const dropdownRect = { + width: dropdownRef.value.offsetWidth, + height: dropdownRef.value.offsetHeight, + } const viewport = getViewportRect() const direction = determineOpenDirection(triggerRect, dropdownRect, viewport) diff --git a/packages/ui/src/components/base/buttons/ButtonLink.vue b/packages/ui/src/components/base/buttons/ButtonLink.vue index cb11c7c6c6..08d59351cf 100644 --- a/packages/ui/src/components/base/buttons/ButtonLink.vue +++ b/packages/ui/src/components/base/buttons/ButtonLink.vue @@ -38,6 +38,11 @@ const resolvedRel = computed(() => { return props.target === '_blank' ? 'noopener noreferrer' : undefined }) +// https://github.com/vuejs/vue-router/issues/2005 moment +const linkAttrs = computed(() => + usesRouter.value ? { to: props.to } : !props.disabled ? { href: props.href } : {}, +) + function handleClick(event: MouseEvent) { if (!props.disabled) return event.preventDefault() @@ -52,8 +57,7 @@ function handleClick(event: MouseEvent) { :color="props.color" :size="props.size" :interaction="props.interaction" - :to="usesRouter ? props.to : undefined" - :href="!usesRouter && !props.disabled ? props.href : undefined" + v-bind="linkAttrs" :target="props.target" :rel="resolvedRel" :download="!props.disabled ? props.download : undefined" diff --git a/packages/ui/src/layouts/shared/content-tab/components/managed-content-modal/index.vue b/packages/ui/src/layouts/shared/content-tab/components/managed-content-modal/index.vue index ccce906bd7..8932684043 100644 --- a/packages/ui/src/layouts/shared/content-tab/components/managed-content-modal/index.vue +++ b/packages/ui/src/layouts/shared/content-tab/components/managed-content-modal/index.vue @@ -3,6 +3,7 @@ import { ArrowLeftRightIcon, BoxIcon, ExternalIcon, + FileIcon, GlassesIcon, PaintbrushIcon, SearchIcon, @@ -104,6 +105,10 @@ const messages = defineMessages({ id: 'instances.managed-content-modal.open-in-slicer', defaultMessage: 'Open in Slicer', }, + downloadFile: { + id: 'instances.managed-content-modal.download-file', + defaultMessage: 'Download File', + }, }) export interface ManagedContentModalState { @@ -314,6 +319,15 @@ const externalSlicerUrls = computed(() => { } return urls }) +const externalUrls = computed(() => { + const urls: Record = {} + for (const item of items.value) { + if (item.external && item.external_url) { + urls[item.id] = item.external_url + } + } + return urls +}) const hasExternalSlicerUrls = computed(() => Object.keys(externalSlicerUrls.value).length > 0) const showTableActions = computed(() => props.enableToggle || hasExternalSlicerUrls.value) @@ -598,6 +612,18 @@ defineExpose({ show, showLoading, hide, getState, restore, updateItem, setItems > + + + diff --git a/packages/ui/src/locales/en-US/index.json b/packages/ui/src/locales/en-US/index.json index 70e6094b35..e45eaec0ce 100644 --- a/packages/ui/src/locales/en-US/index.json +++ b/packages/ui/src/locales/en-US/index.json @@ -2252,6 +2252,9 @@ "instances.content-install.show-unavailable": { "defaultMessage": "Show unavailable" }, + "instances.managed-content-modal.download-file": { + "defaultMessage": "Download File" + }, "instances.managed-content-modal.empty-description": { "defaultMessage": "This source does not include any managed content." },