mirror of https://github.com/halo-dev/halo
refactor: optimize auth provider sorting with drag-and-drop support (#5914)
#### What type of PR is this? /kind feature /area core /area ui /milestone 2.16.x #### What this PR does / why we need it: 优化认证方式的排序并支持拖动 #### Which issue(s) this PR fixes: Fixes #5813 #### Does this PR introduce a user-facing change? ```release-note 优化认证方式的排序并支持拖动 ```pull/5953/head^2
parent
94d625fbb0
commit
c22b4e9ef4
|
@ -13221,6 +13221,10 @@
|
|||
"logo": {
|
||||
"type": "string"
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"settingRef": {
|
||||
"$ref": "#/components/schemas/SettingRef"
|
||||
},
|
||||
|
|
|
@ -52,6 +52,8 @@ public class AuthProvider extends AbstractExtension {
|
|||
|
||||
private String unbindUrl;
|
||||
|
||||
private int priority;
|
||||
|
||||
@Schema(requiredMode = NOT_REQUIRED)
|
||||
private SettingRef settingRef;
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ public class AuthProviderServiceImpl implements AuthProviderService {
|
|||
public Mono<List<ListedAuthProvider>> listAll() {
|
||||
return client.list(AuthProvider.class, provider ->
|
||||
provider.getMetadata().getDeletionTimestamp() == null,
|
||||
Comparator.comparing(item -> item.getMetadata().getCreationTimestamp())
|
||||
defaultComparator()
|
||||
)
|
||||
.map(this::convertTo)
|
||||
.collectList()
|
||||
|
@ -105,6 +105,12 @@ public class AuthProviderServiceImpl implements AuthProviderService {
|
|||
);
|
||||
}
|
||||
|
||||
private static Comparator<AuthProvider> defaultComparator() {
|
||||
return Comparator.comparing((AuthProvider item) -> item.getSpec().getPriority())
|
||||
.thenComparing(item -> item.getMetadata().getName())
|
||||
.thenComparing(item -> item.getMetadata().getCreationTimestamp());
|
||||
}
|
||||
|
||||
private Mono<ConfigMap> updateAuthProviderEnabled(Consumer<Set<String>> consumer) {
|
||||
return client.fetch(ConfigMap.class, SystemSetting.SYSTEM_CONFIG)
|
||||
.switchIfEmpty(Mono.defer(() -> {
|
||||
|
|
|
@ -7,22 +7,22 @@ import {
|
|||
} from "@halo-dev/components";
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { apiClient } from "@/utils/api-client";
|
||||
import type { ListedAuthProvider } from "@halo-dev/api-client";
|
||||
import type { AuthProvider, ListedAuthProvider } from "@halo-dev/api-client";
|
||||
import AuthProviderListItem from "./components/AuthProviderListItem.vue";
|
||||
import { computed, ref } from "vue";
|
||||
import Fuse from "fuse.js";
|
||||
import { VueDraggable } from "vue-draggable-plus";
|
||||
|
||||
const {
|
||||
data: authProviders,
|
||||
isLoading,
|
||||
refetch,
|
||||
} = useQuery<ListedAuthProvider[]>({
|
||||
const authProviders = ref<ListedAuthProvider[]>([]);
|
||||
|
||||
const { isLoading, refetch } = useQuery<ListedAuthProvider[]>({
|
||||
queryKey: ["auth-providers"],
|
||||
queryFn: async () => {
|
||||
const { data } = await apiClient.authProvider.listAuthProviders();
|
||||
return data;
|
||||
},
|
||||
onSuccess(data) {
|
||||
authProviders.value = data;
|
||||
fuse = new Fuse(data, {
|
||||
keys: ["name", "displayName"],
|
||||
useExtendedSearch: true,
|
||||
|
@ -41,6 +41,44 @@ const searchResults = computed(() => {
|
|||
|
||||
return fuse?.search(keyword.value).map((item) => item.item);
|
||||
});
|
||||
|
||||
// Drag and drop
|
||||
const updating = ref(false);
|
||||
|
||||
async function onSortUpdate() {
|
||||
try {
|
||||
updating.value = true;
|
||||
|
||||
const { data: rawAuthProviders } =
|
||||
await apiClient.extension.authProvider.listauthHaloRunV1alpha1AuthProvider();
|
||||
|
||||
const authProviderNames = authProviders.value.map((item) => item.name);
|
||||
|
||||
const sortedAuthProviders = authProviderNames
|
||||
.map((name) => {
|
||||
const authProvider = rawAuthProviders.items.find(
|
||||
(item) => item.metadata.name === name
|
||||
);
|
||||
if (authProvider) {
|
||||
authProvider.spec.priority = authProviderNames.indexOf(name);
|
||||
}
|
||||
return authProvider;
|
||||
})
|
||||
.filter(Boolean) as AuthProvider[];
|
||||
|
||||
for (const authProvider of sortedAuthProviders) {
|
||||
await apiClient.extension.authProvider.updateauthHaloRunV1alpha1AuthProvider(
|
||||
{
|
||||
name: authProvider.metadata.name,
|
||||
authProvider: authProvider,
|
||||
}
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
await refetch();
|
||||
updating.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -69,9 +107,18 @@ const searchResults = computed(() => {
|
|||
</template>
|
||||
<VLoading v-if="isLoading" />
|
||||
<Transition v-else appear name="fade">
|
||||
<ul
|
||||
<VueDraggable
|
||||
v-model="authProviders"
|
||||
ghost-class="opacity-50"
|
||||
handle=".drag-element"
|
||||
class="box-border h-full w-full divide-y divide-gray-100"
|
||||
:class="{
|
||||
'cursor-progress opacity-60': updating,
|
||||
}"
|
||||
role="list"
|
||||
tag="ul"
|
||||
:disabled="updating"
|
||||
@update="onSortUpdate"
|
||||
>
|
||||
<li v-for="(authProvider, index) in searchResults" :key="index">
|
||||
<AuthProviderListItem
|
||||
|
@ -79,7 +126,7 @@ const searchResults = computed(() => {
|
|||
@reload="refetch"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</VueDraggable>
|
||||
</Transition>
|
||||
</VCard>
|
||||
</div>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { apiClient } from "@/utils/api-client";
|
|||
import type { ListedAuthProvider } from "@halo-dev/api-client";
|
||||
import {
|
||||
Dialog,
|
||||
IconList,
|
||||
IconSettings,
|
||||
Toast,
|
||||
VAvatar,
|
||||
|
@ -55,6 +56,13 @@ const handleChangeStatus = async () => {
|
|||
|
||||
<template>
|
||||
<VEntity>
|
||||
<template #prepend>
|
||||
<div
|
||||
class="drag-element absolute inset-y-0 left-0 hidden w-3.5 cursor-move items-center bg-gray-100 transition-all hover:bg-gray-200 group-hover:flex"
|
||||
>
|
||||
<IconList class="h-3.5 w-3.5" />
|
||||
</div>
|
||||
</template>
|
||||
<template #start>
|
||||
<VEntityField>
|
||||
<template #description>
|
||||
|
|
|
@ -97,6 +97,7 @@
|
|||
"transliteration": "^2.3.5",
|
||||
"vue": "^3.4.19",
|
||||
"vue-demi": "^0.14.7",
|
||||
"vue-draggable-plus": "^0.4.1",
|
||||
"vue-grid-layout": "3.0.0-beta1",
|
||||
"vue-i18n": "^9.9.1",
|
||||
"vue-router": "^4.2.5",
|
||||
|
|
|
@ -68,6 +68,12 @@ export interface AuthProviderSpec {
|
|||
* @memberof AuthProviderSpec
|
||||
*/
|
||||
'logo'?: string;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AuthProviderSpec
|
||||
*/
|
||||
'priority'?: number;
|
||||
/**
|
||||
*
|
||||
* @type {SettingRef}
|
||||
|
|
|
@ -185,6 +185,9 @@ importers:
|
|||
vue-demi:
|
||||
specifier: ^0.14.7
|
||||
version: 0.14.7(vue@3.4.19)
|
||||
vue-draggable-plus:
|
||||
specifier: ^0.4.1
|
||||
version: 0.4.1(@types/sortablejs@1.15.8)
|
||||
vue-grid-layout:
|
||||
specifier: 3.0.0-beta1
|
||||
version: 3.0.0-beta1(@interactjs/core@1.10.17)(@interactjs/utils@1.10.17)
|
||||
|
@ -8101,6 +8104,10 @@ packages:
|
|||
resolution: {integrity: sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==}
|
||||
dev: true
|
||||
|
||||
/@types/sortablejs@1.15.8:
|
||||
resolution: {integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==}
|
||||
dev: false
|
||||
|
||||
/@types/tough-cookie@4.0.2:
|
||||
resolution: {integrity: sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==}
|
||||
dev: true
|
||||
|
@ -20089,6 +20096,18 @@ packages:
|
|||
vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.4.19)
|
||||
dev: true
|
||||
|
||||
/vue-draggable-plus@0.4.1(@types/sortablejs@1.15.8):
|
||||
resolution: {integrity: sha512-KNi+c482OQUZTZ2kXIGc41fEwknkNF+LlngjBr5TVtBLNvpX2dmwRJJ3J7dy5dGcijXb7V1j+mhqce4iHOoi6Q==}
|
||||
peerDependencies:
|
||||
'@types/sortablejs': ^1.15.0
|
||||
'@vue/composition-api': '*'
|
||||
peerDependenciesMeta:
|
||||
'@vue/composition-api':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@types/sortablejs': 1.15.8
|
||||
dev: false
|
||||
|
||||
/vue-eslint-parser@9.3.0(eslint@8.43.0):
|
||||
resolution: {integrity: sha512-48IxT9d0+wArT1+3wNIy0tascRoywqSUe2E1YalIC1L8jsUGe5aJQItWfRok7DVFGz3UYvzEI7n5wiTXsCMAcQ==}
|
||||
engines: {node: ^14.17.0 || >=16.0.0}
|
||||
|
|
Loading…
Reference in New Issue