mirror of https://github.com/halo-dev/halo
Refactor thumbnail size handling to use new enum
parent
d24d6d5c07
commit
57602d60a2
|
@ -6679,12 +6679,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "The size of the thumbnail,available values are s,m,l,xl",
|
"description": "The size of the thumbnail",
|
||||||
"in": "query",
|
"in": "query",
|
||||||
"name": "size",
|
"name": "size",
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"S",
|
||||||
|
"M",
|
||||||
|
"L",
|
||||||
|
"XL"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -20587,12 +20593,12 @@
|
||||||
},
|
},
|
||||||
"visible": {
|
"visible": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "PUBLIC",
|
|
||||||
"enum": [
|
"enum": [
|
||||||
"PUBLIC",
|
"PUBLIC",
|
||||||
"INTERNAL",
|
"INTERNAL",
|
||||||
"PRIVATE"
|
"PRIVATE"
|
||||||
]
|
],
|
||||||
|
"default": "PUBLIC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -22363,12 +22369,12 @@
|
||||||
},
|
},
|
||||||
"visible": {
|
"visible": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "PUBLIC",
|
|
||||||
"enum": [
|
"enum": [
|
||||||
"PUBLIC",
|
"PUBLIC",
|
||||||
"INTERNAL",
|
"INTERNAL",
|
||||||
"PRIVATE"
|
"PRIVATE"
|
||||||
]
|
],
|
||||||
|
"default": "PUBLIC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -5475,12 +5475,12 @@
|
||||||
},
|
},
|
||||||
"visible": {
|
"visible": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "PUBLIC",
|
|
||||||
"enum": [
|
"enum": [
|
||||||
"PUBLIC",
|
"PUBLIC",
|
||||||
"INTERNAL",
|
"INTERNAL",
|
||||||
"PRIVATE"
|
"PRIVATE"
|
||||||
]
|
],
|
||||||
|
"default": "PUBLIC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -6015,12 +6015,12 @@
|
||||||
},
|
},
|
||||||
"visible": {
|
"visible": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "PUBLIC",
|
|
||||||
"enum": [
|
"enum": [
|
||||||
"PUBLIC",
|
"PUBLIC",
|
||||||
"INTERNAL",
|
"INTERNAL",
|
||||||
"PRIVATE"
|
"PRIVATE"
|
||||||
]
|
],
|
||||||
|
"default": "PUBLIC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -12903,12 +12903,12 @@
|
||||||
},
|
},
|
||||||
"visible": {
|
"visible": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "PUBLIC",
|
|
||||||
"enum": [
|
"enum": [
|
||||||
"PUBLIC",
|
"PUBLIC",
|
||||||
"INTERNAL",
|
"INTERNAL",
|
||||||
"PRIVATE"
|
"PRIVATE"
|
||||||
]
|
],
|
||||||
|
"default": "PUBLIC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -14281,12 +14281,12 @@
|
||||||
},
|
},
|
||||||
"visible": {
|
"visible": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "PUBLIC",
|
|
||||||
"enum": [
|
"enum": [
|
||||||
"PUBLIC",
|
"PUBLIC",
|
||||||
"INTERNAL",
|
"INTERNAL",
|
||||||
"PRIVATE"
|
"PRIVATE"
|
||||||
]
|
],
|
||||||
|
"default": "PUBLIC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1159,12 +1159,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "The size of the thumbnail,available values are s,m,l,xl",
|
"description": "The size of the thumbnail",
|
||||||
"in": "query",
|
"in": "query",
|
||||||
"name": "size",
|
"name": "size",
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"S",
|
||||||
|
"M",
|
||||||
|
"L",
|
||||||
|
"XL"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -2613,12 +2619,12 @@
|
||||||
},
|
},
|
||||||
"visible": {
|
"visible": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "PUBLIC",
|
|
||||||
"enum": [
|
"enum": [
|
||||||
"PUBLIC",
|
"PUBLIC",
|
||||||
"INTERNAL",
|
"INTERNAL",
|
||||||
"PRIVATE"
|
"PRIVATE"
|
||||||
]
|
],
|
||||||
|
"default": "PUBLIC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3191,12 +3197,12 @@
|
||||||
},
|
},
|
||||||
"visible": {
|
"visible": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "PUBLIC",
|
|
||||||
"enum": [
|
"enum": [
|
||||||
"PUBLIC",
|
"PUBLIC",
|
||||||
"INTERNAL",
|
"INTERNAL",
|
||||||
"PRIVATE"
|
"PRIVATE"
|
||||||
]
|
],
|
||||||
|
"default": "PUBLIC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -2470,12 +2470,12 @@
|
||||||
},
|
},
|
||||||
"visible": {
|
"visible": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "PUBLIC",
|
|
||||||
"enum": [
|
"enum": [
|
||||||
"PUBLIC",
|
"PUBLIC",
|
||||||
"INTERNAL",
|
"INTERNAL",
|
||||||
"PRIVATE"
|
"PRIVATE"
|
||||||
]
|
],
|
||||||
|
"default": "PUBLIC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,87 +1,39 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {
|
import { SIZE_MAP } from "../composables/use-thumbnail-detail";
|
||||||
LocalThumbnailStatusPhaseEnum,
|
|
||||||
type LocalThumbnail,
|
|
||||||
} from "@halo-dev/api-client";
|
|
||||||
import { VButton } from "@halo-dev/components";
|
|
||||||
import { toRefs } from "vue";
|
|
||||||
import { useThumbnailControl } from "../composables/use-thumbnail-control";
|
|
||||||
import {
|
|
||||||
SIZE_MAP,
|
|
||||||
useThumbnailDetail,
|
|
||||||
} from "../composables/use-thumbnail-detail";
|
|
||||||
|
|
||||||
const props = withDefaults(
|
const { size, permalink } = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
thumbnail: LocalThumbnail;
|
size: string;
|
||||||
|
permalink: string;
|
||||||
}>(),
|
}>(),
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
const { thumbnail } = toRefs(props);
|
|
||||||
|
|
||||||
const { phase } = useThumbnailDetail(thumbnail);
|
|
||||||
const { handleRetry } = useThumbnailControl(thumbnail);
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
class="flex w-full cursor-pointer items-center justify-between space-x-3 rounded border p-3 hover:border-primary"
|
class="flex w-full cursor-pointer items-center justify-between space-x-3 rounded border p-3 hover:border-primary"
|
||||||
>
|
>
|
||||||
<a
|
<a :href="permalink" target="_blank" class="block flex-none">
|
||||||
:href="thumbnail.spec.thumbnailUri"
|
|
||||||
target="_blank"
|
|
||||||
class="block flex-none"
|
|
||||||
>
|
|
||||||
<img
|
<img
|
||||||
v-if="
|
:src="permalink"
|
||||||
thumbnail.status.phase === LocalThumbnailStatusPhaseEnum.Succeeded
|
|
||||||
"
|
|
||||||
:src="thumbnail.spec.thumbnailUri"
|
|
||||||
alt=""
|
alt=""
|
||||||
class="h-10 w-10 rounded-md object-cover"
|
class="h-10 w-10 rounded-md object-cover"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
<div
|
|
||||||
v-else
|
|
||||||
class="flex h-10 w-10 items-center justify-center rounded-md border"
|
|
||||||
>
|
|
||||||
<component
|
|
||||||
:is="phase.icon"
|
|
||||||
class="h-4.5 w-4.5"
|
|
||||||
:class="phase.color"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
<div class="flex min-w-0 flex-1 flex-col space-y-2 text-xs text-gray-900">
|
<div class="flex min-w-0 flex-1 flex-col space-y-2 text-xs text-gray-900">
|
||||||
<span class="font-semibold">
|
<span class="font-semibold">
|
||||||
{{ SIZE_MAP[thumbnail.spec.size] }}
|
{{ SIZE_MAP[size] }}
|
||||||
</span>
|
</span>
|
||||||
<a
|
<a
|
||||||
:href="thumbnail.spec.thumbnailUri"
|
:href="permalink"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="line-clamp-1 hover:text-gray-600"
|
class="line-clamp-1 hover:text-gray-600"
|
||||||
>
|
>
|
||||||
{{ thumbnail.spec.thumbnailUri }}
|
{{ permalink }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-none items-center gap-2">
|
|
||||||
<component
|
|
||||||
:is="phase.icon"
|
|
||||||
v-tooltip="$t(phase.label)"
|
|
||||||
class="h-4.5 w-4.5"
|
|
||||||
:class="phase.color"
|
|
||||||
/>
|
|
||||||
<VButton
|
|
||||||
v-if="
|
|
||||||
thumbnail.status.phase !== LocalThumbnailStatusPhaseEnum.Succeeded
|
|
||||||
"
|
|
||||||
size="sm"
|
|
||||||
@click="handleRetry"
|
|
||||||
>
|
|
||||||
{{ $t("core.common.buttons.retry") }}
|
|
||||||
</VButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { storageAnnotations } from "@/constants/annotations";
|
|
||||||
import {
|
import {
|
||||||
coreApiClient,
|
GetThumbnailByUriSizeEnum,
|
||||||
LocalThumbnailSpecSizeEnum,
|
|
||||||
LocalThumbnailStatusPhaseEnum,
|
|
||||||
type Attachment,
|
type Attachment,
|
||||||
} from "@halo-dev/api-client";
|
} from "@halo-dev/api-client";
|
||||||
import { VLoading } from "@halo-dev/components";
|
|
||||||
import { useQuery } from "@tanstack/vue-query";
|
|
||||||
import sha256 from "crypto-js/sha256";
|
|
||||||
import { computed, toRefs } from "vue";
|
import { computed, toRefs } from "vue";
|
||||||
import AttachmentSingleThumbnailItem from "./AttachmentSingleThumbnailItem.vue";
|
import AttachmentSingleThumbnailItem from "./AttachmentSingleThumbnailItem.vue";
|
||||||
|
|
||||||
|
@ -23,53 +17,33 @@ const props = withDefaults(
|
||||||
|
|
||||||
const { attachment } = toRefs(props);
|
const { attachment } = toRefs(props);
|
||||||
|
|
||||||
const imageSignature = computed(() => {
|
const sizeOrder: Record<GetThumbnailByUriSizeEnum, number> = {
|
||||||
const uri = attachment.value?.metadata.annotations?.[storageAnnotations.URI];
|
|
||||||
if (!uri) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return sha256(uri);
|
|
||||||
});
|
|
||||||
|
|
||||||
const sizeOrder: Record<LocalThumbnailSpecSizeEnum, number> = {
|
|
||||||
XL: 4,
|
XL: 4,
|
||||||
L: 3,
|
L: 3,
|
||||||
M: 2,
|
M: 2,
|
||||||
S: 1,
|
S: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data: thumbnails, isLoading } = useQuery({
|
const thumbnails = computed(() => {
|
||||||
queryKey: ["core:attachments:thumbnails", attachment, imageSignature],
|
return Object.entries(attachment.value?.status?.thumbnails || {})
|
||||||
queryFn: async () => {
|
.sort(
|
||||||
const { data } =
|
([sizeA], [sizeB]) =>
|
||||||
await coreApiClient.storage.localThumbnail.listLocalThumbnail({
|
(sizeOrder[sizeB as GetThumbnailByUriSizeEnum] || 0) -
|
||||||
fieldSelector: [`spec.imageSignature=${imageSignature.value}`],
|
(sizeOrder[sizeA as GetThumbnailByUriSizeEnum] || 0)
|
||||||
});
|
)
|
||||||
|
.map(([size, permalink]) => ({
|
||||||
return data.items.sort((a, b) => {
|
size: size as GetThumbnailByUriSizeEnum,
|
||||||
const aSize = a.spec.size as keyof typeof sizeOrder;
|
permalink,
|
||||||
const bSize = b.spec.size as keyof typeof sizeOrder;
|
}));
|
||||||
return (sizeOrder[bSize] || 0) - (sizeOrder[aSize] || 0);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
enabled: computed(() => !!imageSignature.value),
|
|
||||||
refetchInterval: (data) => {
|
|
||||||
const hasAbnormalData = data?.some(
|
|
||||||
(thumbnail) =>
|
|
||||||
thumbnail.status.phase !== LocalThumbnailStatusPhaseEnum.Succeeded
|
|
||||||
);
|
|
||||||
|
|
||||||
return hasAbnormalData ? 1000 : false;
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VLoading v-if="isLoading" />
|
<ul class="flex flex-col space-y-2">
|
||||||
<ul v-else class="flex flex-col space-y-2">
|
|
||||||
<AttachmentSingleThumbnailItem
|
<AttachmentSingleThumbnailItem
|
||||||
v-for="thumbnail in thumbnails"
|
v-for="thumbnail in thumbnails"
|
||||||
:key="thumbnail.metadata.name"
|
:key="thumbnail.size"
|
||||||
:thumbnail="thumbnail"
|
:size="thumbnail.size"
|
||||||
|
:permalink="thumbnail.permalink"
|
||||||
/>
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {
|
import {
|
||||||
LocalThumbnailSpecSizeEnum,
|
GetThumbnailByUriSizeEnum,
|
||||||
LocalThumbnailStatusPhaseEnum,
|
LocalThumbnailStatusPhaseEnum,
|
||||||
type LocalThumbnail,
|
type LocalThumbnail,
|
||||||
} from "@halo-dev/api-client";
|
} from "@halo-dev/api-client";
|
||||||
|
@ -7,7 +7,7 @@ import { IconCheckboxCircle, IconErrorWarning } from "@halo-dev/components";
|
||||||
import { computed, type Component, type Ref } from "vue";
|
import { computed, type Component, type Ref } from "vue";
|
||||||
import RiTimeLine from "~icons/ri/time-line";
|
import RiTimeLine from "~icons/ri/time-line";
|
||||||
|
|
||||||
export const SIZE_MAP: Record<LocalThumbnailSpecSizeEnum, string> = {
|
export const SIZE_MAP: Record<GetThumbnailByUriSizeEnum, string> = {
|
||||||
XL: "1600w",
|
XL: "1600w",
|
||||||
L: "1200w",
|
L: "1200w",
|
||||||
M: "800w",
|
M: "800w",
|
||||||
|
|
|
@ -30,11 +30,11 @@ export const ThumbnailV1alpha1PublicApiAxiosParamCreator = function (configurati
|
||||||
/**
|
/**
|
||||||
* Get thumbnail by URI
|
* Get thumbnail by URI
|
||||||
* @param {string} uri The URI of the image
|
* @param {string} uri The URI of the image
|
||||||
* @param {string} size The size of the thumbnail,available values are s,m,l,xl
|
* @param {GetThumbnailByUriSizeEnum} size The size of the thumbnail
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
getThumbnailByUri: async (uri: string, size: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
|
getThumbnailByUri: async (uri: string, size: GetThumbnailByUriSizeEnum, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
// verify required parameter 'uri' is not null or undefined
|
// verify required parameter 'uri' is not null or undefined
|
||||||
assertParamExists('getThumbnailByUri', 'uri', uri)
|
assertParamExists('getThumbnailByUri', 'uri', uri)
|
||||||
// verify required parameter 'size' is not null or undefined
|
// verify required parameter 'size' is not null or undefined
|
||||||
|
@ -91,11 +91,11 @@ export const ThumbnailV1alpha1PublicApiFp = function(configuration?: Configurati
|
||||||
/**
|
/**
|
||||||
* Get thumbnail by URI
|
* Get thumbnail by URI
|
||||||
* @param {string} uri The URI of the image
|
* @param {string} uri The URI of the image
|
||||||
* @param {string} size The size of the thumbnail,available values are s,m,l,xl
|
* @param {GetThumbnailByUriSizeEnum} size The size of the thumbnail
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
async getThumbnailByUri(uri: string, size: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<File>> {
|
async getThumbnailByUri(uri: string, size: GetThumbnailByUriSizeEnum, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<File>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getThumbnailByUri(uri, size, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.getThumbnailByUri(uri, size, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['ThumbnailV1alpha1PublicApi.getThumbnailByUri']?.[localVarOperationServerIndex]?.url;
|
const localVarOperationServerBasePath = operationServerMap['ThumbnailV1alpha1PublicApi.getThumbnailByUri']?.[localVarOperationServerIndex]?.url;
|
||||||
|
@ -137,11 +137,11 @@ export interface ThumbnailV1alpha1PublicApiGetThumbnailByUriRequest {
|
||||||
readonly uri: string
|
readonly uri: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size of the thumbnail,available values are s,m,l,xl
|
* The size of the thumbnail
|
||||||
* @type {string}
|
* @type {'S' | 'M' | 'L' | 'XL'}
|
||||||
* @memberof ThumbnailV1alpha1PublicApiGetThumbnailByUri
|
* @memberof ThumbnailV1alpha1PublicApiGetThumbnailByUri
|
||||||
*/
|
*/
|
||||||
readonly size: string
|
readonly size: GetThumbnailByUriSizeEnum
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,3 +163,13 @@ export class ThumbnailV1alpha1PublicApi extends BaseAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @export
|
||||||
|
*/
|
||||||
|
export const GetThumbnailByUriSizeEnum = {
|
||||||
|
S: 'S',
|
||||||
|
M: 'M',
|
||||||
|
L: 'L',
|
||||||
|
Xl: 'XL'
|
||||||
|
} as const;
|
||||||
|
export type GetThumbnailByUriSizeEnum = typeof GetThumbnailByUriSizeEnum[keyof typeof GetThumbnailByUriSizeEnum];
|
||||||
|
|
Loading…
Reference in New Issue