feat: improve the styles of the data list filter area on the mobile devices (#4587)

#### What type of PR is this?

/area console
/kind improvement
/milestone 2.10.x

#### What this PR does / why we need it:

改进移动设备上数据列表过滤器区域的样式。

before:

<img width="429" alt="image" src="https://github.com/halo-dev/halo/assets/21301288/c0341b19-0ef5-4e26-94b7-71c52def6578">

after:

<img width="429" alt="image" src="https://github.com/halo-dev/halo/assets/21301288/b2d0f07b-d94d-48d4-86b9-fd2953d141fa">


#### Which issue(s) this PR fixes:

Ref https://github.com/halo-dev/halo/issues/2699

#### Does this PR introduce a user-facing change?

```release-note
改进 Console 端在移动设备上数据列表过滤器区域的样式。
```
pull/4615/head
Ryan Wang 2023-09-15 00:14:14 +08:00 committed by GitHub
parent e13563bad0
commit 83cb088df8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 480 additions and 512 deletions

View File

@ -35,7 +35,7 @@ function onKeywordChange() {
<template> <template>
<FormKit <FormKit
:id="id" :id="id"
outer-class="!p-0" outer-class="!p-0 w-full sm:w-auto"
:placeholder="placeholder || $t('core.common.placeholder.search')" :placeholder="placeholder || $t('core.common.placeholder.search')"
type="text" type="text"
name="keyword" name="keyword"

View File

@ -293,11 +293,11 @@ onMounted(() => {
<template #header> <template #header>
<div class="block w-full bg-gray-50 px-4 py-3"> <div class="block w-full bg-gray-50 px-4 py-3">
<div <div
class="relative flex flex-col items-start sm:flex-row sm:items-center" class="relative flex flex-col flex-wrap items-start gap-4 sm:flex-row sm:items-center"
> >
<div <div
v-permission="['system:attachments:manage']" v-permission="['system:attachments:manage']"
class="mr-4 hidden items-center sm:flex" class="hidden items-center sm:flex"
> >
<input <input
v-model="checkedAll" v-model="checkedAll"
@ -336,95 +336,89 @@ onMounted(() => {
</VDropdown> </VDropdown>
</VSpace> </VSpace>
</div> </div>
<div class="mt-4 flex sm:mt-0"> <VSpace spacing="lg" class="flex-wrap">
<VSpace spacing="lg"> <FilterCleanButton
<FilterCleanButton v-if="hasFilters"
v-if="hasFilters" @click="handleClearFilters"
@click="handleClearFilters" />
/> <FilterDropdown
<FilterDropdown v-model="selectedPolicy"
v-model="selectedPolicy" :label="$t('core.attachment.filters.storage_policy.label')"
:label=" :items="[
$t('core.attachment.filters.storage_policy.label') {
" label: t('core.common.filters.item_labels.all'),
:items="[ },
{ ...(policies?.map((policy) => {
label: t('core.common.filters.item_labels.all'), return {
}, label: policy.spec.displayName,
...(policies?.map((policy) => { value: policy.metadata.name,
return { };
label: policy.spec.displayName, }) || []),
value: policy.metadata.name, ]"
}; />
}) || []), <UserFilterDropdown
]" v-model="selectedUser"
/> :label="$t('core.attachment.filters.owner.label')"
<UserFilterDropdown />
v-model="selectedUser" <FilterDropdown
:label="$t('core.attachment.filters.owner.label')" v-model="selectedSort"
/> :label="$t('core.common.filters.labels.sort')"
<FilterDropdown :items="[
v-model="selectedSort" {
:label="$t('core.common.filters.labels.sort')" label: t('core.common.filters.item_labels.default'),
:items="[ },
{ {
label: t('core.common.filters.item_labels.default'), label: t(
}, 'core.attachment.filters.sort.items.create_time_desc'
{ ),
label: t( value: 'creationTimestamp,desc',
'core.attachment.filters.sort.items.create_time_desc' },
), {
value: 'creationTimestamp,desc', label: t(
}, 'core.attachment.filters.sort.items.create_time_asc'
{ ),
label: t( value: 'creationTimestamp,asc',
'core.attachment.filters.sort.items.create_time_asc' },
), {
value: 'creationTimestamp,asc', label: t(
}, 'core.attachment.filters.sort.items.size_desc'
{ ),
label: t( value: 'size,desc',
'core.attachment.filters.sort.items.size_desc' },
), {
value: 'size,desc', label: t('core.attachment.filters.sort.items.size_asc'),
}, value: 'size,asc',
{ },
label: t( ]"
'core.attachment.filters.sort.items.size_asc' />
), <div class="flex flex-row gap-2">
value: 'size,asc', <div
}, v-for="(item, index) in viewTypes"
]" :key="index"
/> v-tooltip="`${item.tooltip}`"
<div class="flex flex-row gap-2"> :class="{
<div 'bg-gray-200 font-bold text-black':
v-for="(item, index) in viewTypes" viewType === item.name,
:key="index" }"
v-tooltip="`${item.tooltip}`" class="cursor-pointer rounded p-1 hover:bg-gray-200"
:class="{ @click="viewType = item.name"
'bg-gray-200 font-bold text-black': >
viewType === item.name, <component :is="item.icon" class="h-4 w-4" />
}"
class="cursor-pointer rounded p-1 hover:bg-gray-200"
@click="viewType = item.name"
>
<component :is="item.icon" class="h-4 w-4" />
</div>
</div> </div>
<div class="flex flex-row gap-2"> </div>
<div <div class="flex flex-row gap-2">
class="group cursor-pointer rounded p-1 hover:bg-gray-200" <div
@click="handleFetchAttachments()" class="group cursor-pointer rounded p-1 hover:bg-gray-200"
> @click="handleFetchAttachments()"
<IconRefreshLine >
v-tooltip="$t('core.common.buttons.refresh')" <IconRefreshLine
:class="{ 'animate-spin text-gray-900': isFetching }" v-tooltip="$t('core.common.buttons.refresh')"
class="h-4 w-4 text-gray-600 group-hover:text-gray-900" :class="{ 'animate-spin text-gray-900': isFetching }"
/> class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
</div> />
</div> </div>
</VSpace> </div>
</div> </VSpace>
</div> </div>
</div> </div>
</template> </template>

View File

@ -228,11 +228,11 @@ const handleApproveInBatch = async () => {
<template #header> <template #header>
<div class="block w-full bg-gray-50 px-4 py-3"> <div class="block w-full bg-gray-50 px-4 py-3">
<div <div
class="relative flex flex-col items-start sm:flex-row sm:items-center" class="relative flex flex-col flex-wrap items-start gap-4 sm:flex-row sm:items-center"
> >
<div <div
v-permission="['system:comments:manage']" v-permission="['system:comments:manage']"
class="mr-4 hidden items-center sm:flex" class="hidden items-center sm:flex"
> >
<input <input
v-model="checkAll" v-model="checkAll"
@ -259,94 +259,88 @@ const handleApproveInBatch = async () => {
</VButton> </VButton>
</VSpace> </VSpace>
</div> </div>
<div class="mt-4 flex sm:mt-0"> <VSpace spacing="lg" class="flex-wrap">
<VSpace spacing="lg"> <FilterCleanButton
<FilterCleanButton v-if="hasFilters"
v-if="hasFilters" @click="handleClearFilters"
@click="handleClearFilters" />
/> <FilterDropdown
<FilterDropdown v-model="selectedApprovedStatus"
v-model="selectedApprovedStatus" :label="$t('core.common.filters.labels.status')"
:label="$t('core.common.filters.labels.status')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.all'),
label: t('core.common.filters.item_labels.all'), },
}, {
{ label: t('core.comment.filters.status.items.approved'),
label: t('core.comment.filters.status.items.approved'), value: 'true',
value: 'true', },
}, {
{ label: t(
label: t( 'core.comment.filters.status.items.pending_review'
'core.comment.filters.status.items.pending_review' ),
), value: 'false',
value: 'false', },
}, ]"
]" />
/> <UserFilterDropdown
<UserFilterDropdown v-model="selectedUser"
v-model="selectedUser" :label="$t('core.comment.filters.owner.label')"
:label="$t('core.comment.filters.owner.label')" />
/> <FilterDropdown
<FilterDropdown v-model="selectedSort"
v-model="selectedSort" :label="$t('core.common.filters.labels.sort')"
:label="$t('core.common.filters.labels.sort')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.default'),
label: t('core.common.filters.item_labels.default'), },
}, {
{ label: t(
label: t( 'core.comment.filters.sort.items.last_reply_time_desc'
'core.comment.filters.sort.items.last_reply_time_desc' ),
), value: 'lastReplyTime,desc',
value: 'lastReplyTime,desc', },
}, {
{ label: t(
label: t( 'core.comment.filters.sort.items.last_reply_time_asc'
'core.comment.filters.sort.items.last_reply_time_asc' ),
), value: 'lastReplyTime,asc',
value: 'lastReplyTime,asc', },
}, {
{ label: t(
label: t( 'core.comment.filters.sort.items.reply_count_desc'
'core.comment.filters.sort.items.reply_count_desc' ),
), value: 'replyCount,desc',
value: 'replyCount,desc', },
}, {
{ label: t('core.comment.filters.sort.items.reply_count_asc'),
label: t( value: 'replyCount,asc',
'core.comment.filters.sort.items.reply_count_asc' },
), {
value: 'replyCount,asc', label: t(
}, 'core.comment.filters.sort.items.create_time_desc'
{ ),
label: t( value: 'creationTimestamp,desc',
'core.comment.filters.sort.items.create_time_desc' },
), {
value: 'creationTimestamp,desc', label: t('core.comment.filters.sort.items.create_time_asc'),
}, value: 'creationTimestamp,asc',
{ },
label: t( ]"
'core.comment.filters.sort.items.create_time_asc' />
), <div class="flex flex-row gap-2">
value: 'creationTimestamp,asc', <div
}, class="group cursor-pointer rounded p-1 hover:bg-gray-200"
]" @click="refetch()"
/> >
<div class="flex flex-row gap-2"> <IconRefreshLine
<div v-tooltip="$t('core.common.buttons.refresh')"
class="group cursor-pointer rounded p-1 hover:bg-gray-200" :class="{ 'animate-spin text-gray-900': isFetching }"
@click="refetch()" class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
> />
<IconRefreshLine
v-tooltip="$t('core.common.buttons.refresh')"
:class="{ 'animate-spin text-gray-900': isFetching }"
class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
/>
</div>
</div> </div>
</VSpace> </div>
</div> </VSpace>
</div> </div>
</div> </div>
</template> </template>

View File

@ -233,11 +233,11 @@ watch(
<template #header> <template #header>
<div class="block w-full bg-gray-50 px-4 py-3"> <div class="block w-full bg-gray-50 px-4 py-3">
<div <div
class="relative flex flex-col items-start sm:flex-row sm:items-center" class="relative flex flex-col flex-wrap items-start gap-4 sm:flex-row sm:items-center"
> >
<div <div
v-permission="['system:singlepages:manage']" v-permission="['system:singlepages:manage']"
class="mr-4 hidden items-center sm:flex" class="hidden items-center sm:flex"
> >
<input <input
v-model="checkedAll" v-model="checkedAll"
@ -257,21 +257,19 @@ watch(
</VButton> </VButton>
</VSpace> </VSpace>
</div> </div>
<div class="mt-4 flex sm:mt-0"> <VSpace spacing="lg" class="flex-wrap">
<VSpace spacing="lg"> <div class="flex flex-row gap-2">
<div class="flex flex-row gap-2"> <div
<div class="group cursor-pointer rounded p-1 hover:bg-gray-200"
class="group cursor-pointer rounded p-1 hover:bg-gray-200" @click="refetch()"
@click="refetch()" >
> <IconRefreshLine
<IconRefreshLine :class="{ 'animate-spin text-gray-900': isFetching }"
:class="{ 'animate-spin text-gray-900': isFetching }" class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
class="h-4 w-4 text-gray-600 group-hover:text-gray-900" />
/>
</div>
</div> </div>
</VSpace> </div>
</div> </VSpace>
</div> </div>
</div> </div>
</template> </template>

View File

@ -317,11 +317,11 @@ watch(selectedPageNames, (newValue) => {
<template #header> <template #header>
<div class="block w-full bg-gray-50 px-4 py-3"> <div class="block w-full bg-gray-50 px-4 py-3">
<div <div
class="relative flex flex-col items-start sm:flex-row sm:items-center" class="relative flex flex-col flex-wrap items-start gap-4 sm:flex-row sm:items-center"
> >
<div <div
v-permission="['system:singlepages:manage']" v-permission="['system:singlepages:manage']"
class="mr-4 hidden items-center sm:flex" class="hidden items-center sm:flex"
> >
<input <input
v-model="checkedAll" v-model="checkedAll"
@ -338,93 +338,89 @@ watch(selectedPageNames, (newValue) => {
</VButton> </VButton>
</VSpace> </VSpace>
</div> </div>
<div class="mt-4 flex sm:mt-0"> <VSpace spacing="lg" class="flex-wrap">
<VSpace spacing="lg"> <FilterCleanButton
<FilterCleanButton v-if="hasFilters"
v-if="hasFilters" @click="handleClearFilters"
@click="handleClearFilters" />
/> <FilterDropdown
<FilterDropdown v-model="selectedPublishStatus"
v-model="selectedPublishStatus" :label="$t('core.common.filters.labels.status')"
:label="$t('core.common.filters.labels.status')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.all'),
label: t('core.common.filters.item_labels.all'), value: undefined,
value: undefined, },
}, {
{ label: t('core.page.filters.status.items.published'),
label: t('core.page.filters.status.items.published'), value: 'true',
value: 'true', },
}, {
{ label: t('core.page.filters.status.items.draft'),
label: t('core.page.filters.status.items.draft'), value: 'false',
value: 'false', },
}, ]"
]" />
/> <FilterDropdown
<FilterDropdown v-model="selectedVisible"
v-model="selectedVisible" :label="$t('core.page.filters.visible.label')"
:label="$t('core.page.filters.visible.label')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.all'),
label: t('core.common.filters.item_labels.all'), value: undefined,
value: undefined, },
}, {
{ label: t('core.page.filters.visible.items.public'),
label: t('core.page.filters.visible.items.public'), value: 'PUBLIC',
value: 'PUBLIC', },
}, {
{ label: t('core.page.filters.visible.items.private'),
label: t('core.page.filters.visible.items.private'), value: 'PRIVATE',
value: 'PRIVATE', },
}, ]"
]" />
/> <UserFilterDropdown
<UserFilterDropdown v-model="selectedContributor"
v-model="selectedContributor" :label="$t('core.page.filters.author.label')"
:label="$t('core.page.filters.author.label')" />
/> <FilterDropdown
<FilterDropdown v-model="selectedSort"
v-model="selectedSort" :label="$t('core.common.filters.labels.sort')"
:label="$t('core.common.filters.labels.sort')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.default'),
label: t('core.common.filters.item_labels.default'), },
}, {
{ label: t('core.page.filters.sort.items.publish_time_desc'),
label: t( value: 'publishTime,desc',
'core.page.filters.sort.items.publish_time_desc' },
), {
value: 'publishTime,desc', label: t('core.page.filters.sort.items.publish_time_asc'),
}, value: 'publishTime,asc',
{ },
label: t('core.page.filters.sort.items.publish_time_asc'), {
value: 'publishTime,asc', label: t('core.page.filters.sort.items.create_time_desc'),
}, value: 'creationTimestamp,desc',
{ },
label: t('core.page.filters.sort.items.create_time_desc'), {
value: 'creationTimestamp,desc', label: t('core.page.filters.sort.items.create_time_asc'),
}, value: 'creationTimestamp,asc',
{ },
label: t('core.page.filters.sort.items.create_time_asc'), ]"
value: 'creationTimestamp,asc', />
}, <div class="flex flex-row gap-2">
]" <div
/> class="group cursor-pointer rounded p-1 hover:bg-gray-200"
<div class="flex flex-row gap-2"> @click="refetch()"
<div >
class="group cursor-pointer rounded p-1 hover:bg-gray-200" <IconRefreshLine
@click="refetch()" v-tooltip="$t('core.common.buttons.refresh')"
> :class="{ 'animate-spin text-gray-900': isFetching }"
<IconRefreshLine class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
v-tooltip="$t('core.common.buttons.refresh')" />
:class="{ 'animate-spin text-gray-900': isFetching }"
class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
/>
</div>
</div> </div>
</VSpace> </div>
</div> </VSpace>
</div> </div>
</div> </div>
</template> </template>

View File

@ -225,11 +225,11 @@ watch(
<template #header> <template #header>
<div class="block w-full bg-gray-50 px-4 py-3"> <div class="block w-full bg-gray-50 px-4 py-3">
<div <div
class="relative flex flex-col items-start sm:flex-row sm:items-center" class="relative flex flex-col flex-wrap items-start gap-4 sm:flex-row sm:items-center"
> >
<div <div
v-permission="['system:posts:manage']" v-permission="['system:posts:manage']"
class="mr-4 hidden items-center sm:flex" class="hidden items-center sm:flex"
> >
<input <input
v-model="checkedAll" v-model="checkedAll"
@ -249,21 +249,19 @@ watch(
</VButton> </VButton>
</VSpace> </VSpace>
</div> </div>
<div class="mt-4 flex sm:mt-0"> <VSpace spacing="lg" class="flex-wrap">
<VSpace spacing="lg"> <div class="flex flex-row gap-2">
<div class="flex flex-row gap-2"> <div
<div class="group cursor-pointer rounded p-1 hover:bg-gray-200"
class="group cursor-pointer rounded p-1 hover:bg-gray-200" @click="refetch()"
@click="refetch()" >
> <IconRefreshLine
<IconRefreshLine :class="{ 'animate-spin text-gray-900': isFetching }"
:class="{ 'animate-spin text-gray-900': isFetching }" class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
class="h-4 w-4 text-gray-600 group-hover:text-gray-900" />
/>
</div>
</div> </div>
</VSpace> </div>
</div> </VSpace>
</div> </div>
</div> </div>
</template> </template>

View File

@ -323,11 +323,11 @@ watch(selectedPostNames, (newValue) => {
<template #header> <template #header>
<div class="block w-full bg-gray-50 px-4 py-3"> <div class="block w-full bg-gray-50 px-4 py-3">
<div <div
class="relative flex flex-col items-start sm:flex-row sm:items-center" class="relative flex flex-col flex-wrap items-start gap-4 sm:flex-row sm:items-center"
> >
<div <div
v-permission="['system:posts:manage']" v-permission="['system:posts:manage']"
class="mr-4 hidden items-center sm:flex" class="hidden items-center sm:flex"
> >
<input <input
v-model="checkedAll" v-model="checkedAll"
@ -344,101 +344,97 @@ watch(selectedPostNames, (newValue) => {
</VButton> </VButton>
</VSpace> </VSpace>
</div> </div>
<div class="mt-4 flex sm:mt-0"> <VSpace spacing="lg" class="flex-wrap">
<VSpace spacing="lg"> <FilterCleanButton
<FilterCleanButton v-if="hasFilters"
v-if="hasFilters" @click="handleClearFilters"
@click="handleClearFilters" />
/> <FilterDropdown
<FilterDropdown v-model="selectedPublishStatus"
v-model="selectedPublishStatus" :label="$t('core.common.filters.labels.status')"
:label="$t('core.common.filters.labels.status')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.all'),
label: t('core.common.filters.item_labels.all'), value: undefined,
value: undefined, },
}, {
{ label: t('core.post.filters.status.items.published'),
label: t('core.post.filters.status.items.published'), value: 'true',
value: 'true', },
}, {
{ label: t('core.post.filters.status.items.draft'),
label: t('core.post.filters.status.items.draft'), value: 'false',
value: 'false', },
}, ]"
]" />
/> <FilterDropdown
<FilterDropdown v-model="selectedVisible"
v-model="selectedVisible" :label="$t('core.post.filters.visible.label')"
:label="$t('core.post.filters.visible.label')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.all'),
label: t('core.common.filters.item_labels.all'), value: undefined,
value: undefined, },
}, {
{ label: t('core.post.filters.visible.items.public'),
label: t('core.post.filters.visible.items.public'), value: 'PUBLIC',
value: 'PUBLIC', },
}, {
{ label: t('core.post.filters.visible.items.private'),
label: t('core.post.filters.visible.items.private'), value: 'PRIVATE',
value: 'PRIVATE', },
}, ]"
]" />
/> <CategoryFilterDropdown
<CategoryFilterDropdown v-model="selectedCategory"
v-model="selectedCategory" :label="$t('core.post.filters.category.label')"
:label="$t('core.post.filters.category.label')" />
/> <TagFilterDropdown
<TagFilterDropdown v-model="selectedTag"
v-model="selectedTag" :label="$t('core.post.filters.tag.label')"
:label="$t('core.post.filters.tag.label')" />
/> <UserFilterDropdown
<UserFilterDropdown v-model="selectedContributor"
v-model="selectedContributor" :label="$t('core.post.filters.author.label')"
:label="$t('core.post.filters.author.label')" />
/> <FilterDropdown
<FilterDropdown v-model="selectedSort"
v-model="selectedSort" :label="$t('core.common.filters.labels.sort')"
:label="$t('core.common.filters.labels.sort')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.default'),
label: t('core.common.filters.item_labels.default'), },
}, {
{ label: t('core.post.filters.sort.items.publish_time_desc'),
label: t( value: 'publishTime,desc',
'core.post.filters.sort.items.publish_time_desc' },
), {
value: 'publishTime,desc', label: t('core.post.filters.sort.items.publish_time_asc'),
}, value: 'publishTime,asc',
{ },
label: t('core.post.filters.sort.items.publish_time_asc'), {
value: 'publishTime,asc', label: t('core.post.filters.sort.items.create_time_desc'),
}, value: 'creationTimestamp,desc',
{ },
label: t('core.post.filters.sort.items.create_time_desc'), {
value: 'creationTimestamp,desc', label: t('core.post.filters.sort.items.create_time_asc'),
}, value: 'creationTimestamp,asc',
{ },
label: t('core.post.filters.sort.items.create_time_asc'), ]"
value: 'creationTimestamp,asc', />
}, <div class="flex flex-row gap-2">
]" <div
/> class="group cursor-pointer rounded p-1 hover:bg-gray-200"
<div class="flex flex-row gap-2"> @click="refetch()"
<div >
class="group cursor-pointer rounded p-1 hover:bg-gray-200" <IconRefreshLine
@click="refetch()" v-tooltip="$t('core.common.buttons.refresh')"
> :class="{ 'animate-spin text-gray-900': isFetching }"
<IconRefreshLine class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
v-tooltip="$t('core.common.buttons.refresh')" />
:class="{ 'animate-spin text-gray-900': isFetching }"
class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
/>
</div>
</div> </div>
</VSpace> </div>
</div> </VSpace>
</div> </div>
</div> </div>
</template> </template>

View File

@ -159,11 +159,11 @@ onMounted(() => {
<template #header> <template #header>
<div class="block w-full bg-gray-50 px-4 py-3"> <div class="block w-full bg-gray-50 px-4 py-3">
<div <div
class="relative flex flex-col items-start sm:flex-row sm:items-center" class="relative flex flex-col flex-wrap items-start gap-4 sm:flex-row sm:items-center"
> >
<div <div
v-permission="['system:posts:manage']" v-permission="['system:posts:manage']"
class="mr-4 hidden items-center sm:flex" class="hidden items-center sm:flex"
> >
<input <input
v-model="checkedAll" v-model="checkedAll"
@ -206,64 +206,58 @@ onMounted(() => {
</VDropdown> </VDropdown>
</VSpace> </VSpace>
</div> </div>
<div class="mt-4 flex sm:mt-0"> <VSpace spacing="lg" class="flex-wrap">
<VSpace spacing="lg"> <FilterCleanButton
<FilterCleanButton v-if="hasFilters"
v-if="hasFilters" @click="handleClearFilters"
@click="handleClearFilters" />
/> <FilterDropdown
<FilterDropdown v-model="selectedEnabledValue"
v-model="selectedEnabledValue" :label="$t('core.common.filters.labels.status')"
:label="$t('core.common.filters.labels.status')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.all'),
label: t('core.common.filters.item_labels.all'), },
}, {
{ label: t('core.plugin.filters.status.items.active'),
label: t('core.plugin.filters.status.items.active'), value: true,
value: true, },
}, {
{ label: t('core.plugin.filters.status.items.inactive'),
label: t('core.plugin.filters.status.items.inactive'), value: false,
value: false, },
}, ]"
]" />
/> <FilterDropdown
<FilterDropdown v-model="selectedSortValue"
v-model="selectedSortValue" :label="$t('core.common.filters.labels.sort')"
:label="$t('core.common.filters.labels.sort')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.default'),
label: t('core.common.filters.item_labels.default'), },
}, {
{ label: t('core.plugin.filters.sort.items.create_time_desc'),
label: t( value: 'creationTimestamp,desc',
'core.plugin.filters.sort.items.create_time_desc' },
), {
value: 'creationTimestamp,desc', label: t('core.plugin.filters.sort.items.create_time_asc'),
}, value: 'creationTimestamp,asc',
{ },
label: t( ]"
'core.plugin.filters.sort.items.create_time_asc' />
), <div class="flex flex-row gap-2">
value: 'creationTimestamp,asc', <div
}, class="group cursor-pointer rounded p-1 hover:bg-gray-200"
]" @click="refetch()"
/> >
<div class="flex flex-row gap-2"> <IconRefreshLine
<div v-tooltip="$t('core.common.buttons.refresh')"
class="group cursor-pointer rounded p-1 hover:bg-gray-200" :class="{ 'animate-spin text-gray-900': isFetching }"
@click="refetch()" class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
> />
<IconRefreshLine
v-tooltip="$t('core.common.buttons.refresh')"
:class="{ 'animate-spin text-gray-900': isFetching }"
class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
/>
</div>
</div> </div>
</VSpace> </div>
</div> </VSpace>
</div> </div>
</div> </div>
</template> </template>

View File

@ -291,11 +291,11 @@ onMounted(() => {
<template #header> <template #header>
<div class="block w-full bg-gray-50 px-4 py-3"> <div class="block w-full bg-gray-50 px-4 py-3">
<div <div
class="relative flex flex-col items-start sm:flex-row sm:items-center" class="relative flex flex-col flex-wrap items-start gap-4 sm:flex-row sm:items-center"
> >
<div <div
v-permission="['system:users:manage']" v-permission="['system:users:manage']"
class="mr-4 hidden items-center sm:flex" class="hidden items-center sm:flex"
> >
<input <input
v-model="checkedAll" v-model="checkedAll"
@ -312,63 +312,61 @@ onMounted(() => {
</VButton> </VButton>
</VSpace> </VSpace>
</div> </div>
<div class="mt-4 flex sm:mt-0"> <VSpace spacing="lg" class="flex-wrap">
<VSpace spacing="lg"> <FilterCleanButton
<FilterCleanButton v-if="hasFilters"
v-if="hasFilters" @click="handleClearFilters"
@click="handleClearFilters" />
/> <FilterDropdown
<FilterDropdown v-model="selectedRoleValue"
v-model="selectedRoleValue" :label="$t('core.user.filters.role.label')"
:label="$t('core.user.filters.role.label')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.all'),
label: t('core.common.filters.item_labels.all'), },
}, ...roles.map((role) => {
...roles.map((role) => { return {
return { label:
label: role.metadata.annotations?.[
role.metadata.annotations?.[ rbacAnnotations.DISPLAY_NAME
rbacAnnotations.DISPLAY_NAME ] || role.metadata.name,
] || role.metadata.name, value: role.metadata.name,
value: role.metadata.name, };
}; }),
}), ]"
]" />
/> <FilterDropdown
<FilterDropdown v-model="selectedSortValue"
v-model="selectedSortValue" :label="$t('core.common.filters.labels.sort')"
:label="$t('core.common.filters.labels.sort')" :items="[
:items="[ {
{ label: t('core.common.filters.item_labels.default'),
label: t('core.common.filters.item_labels.default'), },
}, {
{ label: t('core.user.filters.sort.items.create_time_desc'),
label: t('core.user.filters.sort.items.create_time_desc'), value: 'creationTimestamp,desc',
value: 'creationTimestamp,desc', },
}, {
{ label: t('core.user.filters.sort.items.create_time_asc'),
label: t('core.user.filters.sort.items.create_time_asc'), value: 'creationTimestamp,asc',
value: 'creationTimestamp,asc', },
}, ]"
]" />
/> <div class="flex flex-row gap-2">
<div class="flex flex-row gap-2"> <div
<div class="group cursor-pointer rounded p-1 hover:bg-gray-200"
class="group cursor-pointer rounded p-1 hover:bg-gray-200" @click="refetch()"
@click="refetch()" >
> <IconRefreshLine
<IconRefreshLine v-tooltip="$t('core.common.buttons.refresh')"
v-tooltip="$t('core.common.buttons.refresh')" :class="{
:class="{ 'animate-spin text-gray-900': isFetching,
'animate-spin text-gray-900': isFetching, }"
}" class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
class="h-4 w-4 text-gray-600 group-hover:text-gray-900" />
/>
</div>
</div> </div>
</VSpace> </div>
</div> </VSpace>
</div> </div>
</div> </div>
</template> </template>