mirror of https://github.com/halo-dev/halo
parent
878129d072
commit
16cf4d70a1
|
@ -35,6 +35,7 @@
|
|||
"@halo-dev/admin-shared": "workspace:*",
|
||||
"@halo-dev/api-client": "^0.0.0",
|
||||
"@halo-dev/components": "workspace:*",
|
||||
"@vueuse/components": "^8.9.2",
|
||||
"@vueuse/core": "^8.9.2",
|
||||
"axios": "^0.27.2",
|
||||
"filepond": "^4.30.4",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { useOffsetPagination } from "@vueuse/core";
|
||||
import { UseOffsetPagination } from "@vueuse/components";
|
||||
import { IconArrowLeft, IconArrowRight } from "../../icons/icons";
|
||||
import { defineProps } from "vue";
|
||||
import { defineProps, ref, toRefs, watch } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
page: {
|
||||
|
@ -18,6 +18,10 @@ const props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const { page, size, total } = toRefs(props);
|
||||
|
||||
const key = ref(Math.random());
|
||||
|
||||
const emit = defineEmits(["update:page", "update:size", "change"]);
|
||||
|
||||
const onPageChange = ({
|
||||
|
@ -27,73 +31,81 @@ const onPageChange = ({
|
|||
currentPage: number;
|
||||
currentPageSize: number;
|
||||
}) => {
|
||||
emit("update:size", props.size);
|
||||
emit("update:page", props.page);
|
||||
emit("change", {
|
||||
page: currentPage,
|
||||
size: currentPageSize,
|
||||
});
|
||||
};
|
||||
|
||||
const { currentPage, pageCount, prev, next } = useOffsetPagination({
|
||||
total: props.total,
|
||||
page: props.page,
|
||||
pageSize: props.size,
|
||||
onPageChange: onPageChange,
|
||||
onPageSizeChange: onPageChange,
|
||||
});
|
||||
watch(
|
||||
() => total?.value,
|
||||
() => {
|
||||
key.value = Math.random();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<template>
|
||||
<div class="bg-white flex items-center justify-between">
|
||||
<div class="flex-1 flex justify-between sm:hidden items-center">
|
||||
<span
|
||||
class="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 cursor-pointer"
|
||||
@click="prev"
|
||||
>
|
||||
<IconArrowLeft />
|
||||
</span>
|
||||
<span class="text-sm text-gray-500">
|
||||
{{ currentPage }} / {{ pageCount }}
|
||||
</span>
|
||||
<span
|
||||
class="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 cursor-pointer"
|
||||
@click="next"
|
||||
>
|
||||
<IconArrowRight />
|
||||
</span>
|
||||
</div>
|
||||
<div class="hidden sm:flex-1 sm:flex sm:items-center">
|
||||
<nav
|
||||
aria-label="Pagination"
|
||||
class="relative z-0 inline-flex rounded-base shadow-sm -space-x-px"
|
||||
>
|
||||
<UseOffsetPagination
|
||||
:key="key"
|
||||
v-slot="{ currentPage, next, prev, pageCount }"
|
||||
:page="page"
|
||||
:pageSize="size"
|
||||
:total="total"
|
||||
@page-change="onPageChange"
|
||||
@page-size-change="onPageChange"
|
||||
>
|
||||
<div class="bg-white flex items-center justify-between">
|
||||
<div class="flex-1 flex justify-between sm:hidden items-center">
|
||||
<span
|
||||
class="relative inline-flex items-center px-2 py-2 rounded-l-[4px] border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 cursor-pointer"
|
||||
class="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 cursor-pointer"
|
||||
@click="prev"
|
||||
>
|
||||
<IconArrowLeft />
|
||||
</span>
|
||||
<span
|
||||
v-for="i in pageCount"
|
||||
:key="i"
|
||||
:class="{
|
||||
'z-10 bg-primary/1 border-primary text-primary': i === currentPage,
|
||||
'bg-white border-gray-300 text-gray-500 hover:bg-gray-50':
|
||||
i !== currentPage,
|
||||
}"
|
||||
aria-current="page"
|
||||
class="relative inline-flex items-center px-4 py-2 border text-sm font-medium cursor-pointer select-none"
|
||||
@click="currentPage = i"
|
||||
>
|
||||
{{ i }}
|
||||
<span class="text-sm text-gray-500">
|
||||
{{ currentPage }} / {{ pageCount }}
|
||||
</span>
|
||||
<span
|
||||
class="relative inline-flex items-center px-2 py-2 rounded-r-[4px] border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 cursor-pointer"
|
||||
class="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 cursor-pointer"
|
||||
@click="next"
|
||||
>
|
||||
<IconArrowRight />
|
||||
</span>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="hidden sm:flex-1 sm:flex sm:items-center">
|
||||
<nav
|
||||
aria-label="Pagination"
|
||||
class="relative z-0 inline-flex rounded-base shadow-sm -space-x-px"
|
||||
>
|
||||
<span
|
||||
class="relative inline-flex items-center px-2 py-2 rounded-l-[4px] border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 cursor-pointer"
|
||||
@click="prev"
|
||||
>
|
||||
<IconArrowLeft />
|
||||
</span>
|
||||
<span
|
||||
v-for="i in pageCount"
|
||||
:key="i"
|
||||
:class="{
|
||||
'z-10 bg-primary/1 border-primary text-primary':
|
||||
i === currentPage,
|
||||
'bg-white border-gray-300 text-gray-500 hover:bg-gray-50':
|
||||
i !== currentPage,
|
||||
}"
|
||||
aria-current="page"
|
||||
class="relative inline-flex items-center px-4 py-2 border text-sm font-medium cursor-pointer select-none"
|
||||
@click="currentPage.value = i"
|
||||
>
|
||||
{{ i }}
|
||||
</span>
|
||||
<span
|
||||
class="relative inline-flex items-center px-2 py-2 rounded-r-[4px] border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 cursor-pointer"
|
||||
@click="next"
|
||||
>
|
||||
<IconArrowRight />
|
||||
</span>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</UseOffsetPagination>
|
||||
</template>
|
||||
|
|
|
@ -30,6 +30,7 @@ importers:
|
|||
'@vue/eslint-config-typescript': ^11.0.0
|
||||
'@vue/test-utils': ^2.0.2
|
||||
'@vue/tsconfig': ^0.1.3
|
||||
'@vueuse/components': ^8.9.2
|
||||
'@vueuse/core': ^8.9.2
|
||||
autoprefixer: ^10.4.7
|
||||
axios: ^0.27.2
|
||||
|
@ -79,6 +80,7 @@ importers:
|
|||
'@halo-dev/admin-shared': link:packages/shared
|
||||
'@halo-dev/api-client': 0.0.0
|
||||
'@halo-dev/components': link:packages/components
|
||||
'@vueuse/components': 8.9.2_vue@3.2.37
|
||||
'@vueuse/core': 8.9.2_vue@3.2.37
|
||||
axios: 0.27.2
|
||||
filepond: 4.30.4
|
||||
|
@ -2874,6 +2876,17 @@ packages:
|
|||
'@types/node': 17.0.45
|
||||
dev: true
|
||||
|
||||
/@vueuse/components/8.9.2_vue@3.2.37:
|
||||
resolution: {integrity: sha512-7K39dgpSdMJgotCGCaa3W7q/9AEZ2jitG+mBWH0TK+HSqLeYd5syHQKKK61raWP/qImu/mrwcsqeKtbFunU1FA==}
|
||||
dependencies:
|
||||
'@vueuse/core': 8.9.2_vue@3.2.37
|
||||
'@vueuse/shared': 8.9.2_vue@3.2.37
|
||||
vue-demi: 0.12.1_vue@3.2.37
|
||||
transitivePeerDependencies:
|
||||
- '@vue/composition-api'
|
||||
- vue
|
||||
dev: false
|
||||
|
||||
/@vueuse/core/8.9.2_vue@3.2.37:
|
||||
resolution: {integrity: sha512-dE3/JgwqIHmmtmRBdZAnq87rZCSFbYVps2t3gWy9Jv/+Qp6sHSSKuPFtwguJVZ2OnaGnB/AMRmx4CuFRxFin3A==}
|
||||
peerDependencies:
|
||||
|
|
13
src/main.ts
13
src/main.ts
|
@ -97,11 +97,11 @@ function loadStyle(href: string) {
|
|||
}
|
||||
|
||||
async function loadPluginModules() {
|
||||
const response =
|
||||
const { data } =
|
||||
await apiClient.extension.plugin.listpluginHaloRunV1alpha1Plugin();
|
||||
|
||||
// Get all started plugins
|
||||
const plugins = response.data.filter(
|
||||
const plugins = data.items.filter(
|
||||
(plugin) => plugin.status?.phase === "STARTED" && plugin.spec.enabled
|
||||
);
|
||||
|
||||
|
@ -138,8 +138,13 @@ async function loadPluginModules() {
|
|||
}
|
||||
|
||||
async function loadCurrentUser() {
|
||||
const response = await apiClient.user.getCurrentUserDetail();
|
||||
app.provide<User>("currentUser", response.data);
|
||||
const { data: user } = await apiClient.user.getCurrentUserDetail();
|
||||
app.provide<User>("currentUser", user);
|
||||
|
||||
const { data: permissions } = await apiClient.user.getPermissions(
|
||||
"ac7cdce1-acf2-4e27-a422-c16d6f47cfa2"
|
||||
);
|
||||
app.provide("permissions", permissions);
|
||||
}
|
||||
|
||||
(async function () {
|
||||
|
|
|
@ -82,7 +82,7 @@ const attachments = Array.from(new Array(50), (_, index) => index).map(
|
|||
const handleFetchUsers = async () => {
|
||||
try {
|
||||
const { data } = await apiClient.extension.user.listv1alpha1User();
|
||||
users.value = data;
|
||||
users.value = data.items;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ useExtensionPointsState("PAGES", pagesPublicState);
|
|||
const handleFetchUsers = async () => {
|
||||
try {
|
||||
const { data } = await apiClient.extension.user.listv1alpha1User();
|
||||
users.value = data;
|
||||
users.value = data.items;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ const checkedCount = computed(() => {
|
|||
const handleFetchUsers = async () => {
|
||||
try {
|
||||
const { data } = await apiClient.extension.user.listv1alpha1User();
|
||||
users.value = data;
|
||||
users.value = data.items;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ const users = ref<User[]>([]);
|
|||
const handleFetchUsers = async () => {
|
||||
try {
|
||||
const { data } = await apiClient.extension.user.listv1alpha1User();
|
||||
users.value = data;
|
||||
users.value = data.items;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
|
|
@ -63,6 +63,9 @@ const handleFetchPlugin = async () => {
|
|||
};
|
||||
|
||||
const handleFetchSettings = async () => {
|
||||
if (!plugin.value.spec.settingName) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response = await apiClient.extension.setting.getv1alpha1Setting(
|
||||
plugin.value.spec.settingName as string
|
||||
|
@ -92,6 +95,9 @@ const handleFetchSettings = async () => {
|
|||
};
|
||||
|
||||
const handleFetchConfigMap = async () => {
|
||||
if (!plugin.value.spec.configMapName) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response = await apiClient.extension.configMap.getv1alpha1ConfigMap(
|
||||
plugin.value.spec.configMapName as string
|
||||
|
|
|
@ -37,9 +37,9 @@ const isStarted = (plugin: Plugin) => {
|
|||
|
||||
const handleFetchPlugins = async () => {
|
||||
try {
|
||||
const response =
|
||||
const {data} =
|
||||
await apiClient.extension.plugin.listpluginHaloRunV1alpha1Plugin();
|
||||
plugins.value = response.data;
|
||||
plugins.value = data.items;
|
||||
} catch (e) {
|
||||
console.error("Fail to fetch plugins", e);
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ const handleFetchRole = async () => {
|
|||
const handleFetchRoles = async () => {
|
||||
try {
|
||||
const { data } = await apiClient.extension.role.listv1alpha1Role();
|
||||
roles.value = data;
|
||||
roles.value = data.items;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ const handleFetchRoles = async () => {
|
|||
const handleFetchUsers = async () => {
|
||||
try {
|
||||
const { data } = await apiClient.extension.user.listv1alpha1User();
|
||||
users.value = data;
|
||||
users.value = data.items;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ const router = useRouter();
|
|||
const handleFetchRoles = async () => {
|
||||
try {
|
||||
const { data } = await apiClient.extension.role.listv1alpha1Role();
|
||||
roles.value = data;
|
||||
roles.value = data.items;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ const roleTemplateGroups = computed<RoleTemplateGroup[]>(() => {
|
|||
const handleFetchRoles = async () => {
|
||||
try {
|
||||
const { data } = await apiClient.extension.role.listv1alpha1Role();
|
||||
roles.value = data;
|
||||
roles.value = data.items;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@ const personalAccessTokens = ref<PersonalAccessToken[]>([]);
|
|||
|
||||
const handleFetchPersonalAccessTokens = async () => {
|
||||
try {
|
||||
const response =
|
||||
const { data } =
|
||||
await apiClient.extension.personalAccessToken.listv1alpha1PersonalAccessToken();
|
||||
personalAccessTokens.value = response.data;
|
||||
personalAccessTokens.value = data.items;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
|
|
@ -16,30 +16,46 @@ import UserCreationModal from "./components/UserCreationModal.vue";
|
|||
import { onMounted, ref } from "vue";
|
||||
import { apiClient } from "@halo-dev/admin-shared";
|
||||
import type { User } from "@halo-dev/api-client";
|
||||
import type { UserList } from "@halo-dev/api-client";
|
||||
|
||||
const checkAll = ref(false);
|
||||
const creationModal = ref<boolean>(false);
|
||||
const users = ref<User[]>([]);
|
||||
const selectedUser = ref<User | null>(null);
|
||||
const pagination = ref<{
|
||||
page: number;
|
||||
size: number;
|
||||
total: number;
|
||||
}>({
|
||||
const users = ref<UserList>({
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 100,
|
||||
size: 5,
|
||||
total: 0,
|
||||
items: [],
|
||||
first: true,
|
||||
last: false,
|
||||
hasNext: false,
|
||||
hasPrevious: false,
|
||||
});
|
||||
const selectedUser = ref<User | null>(null);
|
||||
|
||||
const handleFetchUsers = async () => {
|
||||
try {
|
||||
const { data } = await apiClient.extension.user.listv1alpha1User();
|
||||
const { data } = await apiClient.extension.user.listv1alpha1User(
|
||||
users.value.page,
|
||||
users.value.size
|
||||
);
|
||||
users.value = data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePaginationChange = async ({
|
||||
page,
|
||||
size,
|
||||
}: {
|
||||
page: number;
|
||||
size: number;
|
||||
}) => {
|
||||
users.value.page = page;
|
||||
users.value.size = size;
|
||||
await handleFetchUsers();
|
||||
};
|
||||
|
||||
const handleOpenCreateModal = (user: User) => {
|
||||
selectedUser.value = user;
|
||||
creationModal.value = true;
|
||||
|
@ -206,7 +222,7 @@ onMounted(() => {
|
|||
</div>
|
||||
</template>
|
||||
<ul class="box-border h-full w-full divide-y divide-gray-100" role="list">
|
||||
<li v-for="(user, index) in users" :key="index">
|
||||
<li v-for="(user, index) in users.items" :key="index">
|
||||
<div
|
||||
:class="{
|
||||
'bg-gray-100': checkAll,
|
||||
|
@ -286,9 +302,10 @@ onMounted(() => {
|
|||
<template #footer>
|
||||
<div class="bg-white sm:flex sm:items-center sm:justify-end">
|
||||
<VPagination
|
||||
v-model:page="pagination.page"
|
||||
v-model:size="pagination.size"
|
||||
:total="pagination.total"
|
||||
:page="users.page"
|
||||
:size="users.size"
|
||||
:total="users.total"
|
||||
@change="handlePaginationChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -71,7 +71,7 @@ watch(props, (newVal) => {
|
|||
const handleFetchRoles = async () => {
|
||||
try {
|
||||
const { data } = await apiClient.extension.role.listv1alpha1Role();
|
||||
roles.value = data;
|
||||
roles.value = data.items;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
@ -102,14 +102,12 @@ const handleCreateUser = async () => {
|
|||
user = response.data;
|
||||
}
|
||||
|
||||
// if (selectedRole.value) {
|
||||
// await apiClient.user.(
|
||||
// `/apis/api.halo.run/v1alpha1/users/${user.metadata.name}/permissions`,
|
||||
// {
|
||||
// roles: [selectedRole.value],
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
if (selectedRole.value) {
|
||||
await apiClient.user.grantPermission(user.metadata.name, {
|
||||
// @ts-ignore
|
||||
roles: [selectedRole.value],
|
||||
});
|
||||
}
|
||||
|
||||
handleVisibleChange(false);
|
||||
} catch (e) {
|
||||
|
|
Loading…
Reference in New Issue