Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move filters to side instead of top #2516

Merged
merged 9 commits into from
Apr 3, 2024
2 changes: 1 addition & 1 deletion packages/playground/src/components/filters/TfFilter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { useRouter } from "vue-router";
import type { AsyncRule, SyncRule } from "../input_validator.vue";
import { useFiltersContainerService } from "./TfFiltersContainer.vue";

const colProps = { class: "py-2 px-4", cols: 12, md: 6, lg: 3 };
const colProps = { class: "py-1", cols: 12 };

function normalizeValue(v: string) {
if (v === "true") return true;
Expand Down
108 changes: 52 additions & 56 deletions packages/playground/src/components/filters/TfFiltersContainer.vue
Original file line number Diff line number Diff line change
@@ -1,60 +1,56 @@
<template>
<VExpansionPanels :model-value="[0]">
<VExpansionPanel eager>
<VExpansionPanelTitle class="text-h6"> Filters </VExpansionPanelTitle>
<VExpansionPanelText eager>
<VForm :disabled="loading">
<FormValidator valid-on-init v-model="valid">
<VContainer fluid>
<VRow no-gutters>
<slot />
</VRow>

<VRow class="mb-4" no-gutters v-show="valid && (changed || (!loading && !empty))">
<VAlert type="info" variant="tonal">
<span>
{{ changed ? "Filter options were updated but not applied." : "" }} Click
<VCard
class="d-inline pa-1"
v-text="changed ? 'Apply' : 'Clear'"
flat
:color="$vuetify.theme.global.name === 'light' ? 'info' : undefined"
/>
{{ changed ? "in order to reload your data." : "to reset your selected filters." }}
</span>
</VAlert>
</VRow>

<VRow no-gutters>
<VDivider />
</VRow>
</VContainer>

<VContainer fluid>
<VRow no-gutters>
<VSpacer />
<VBtn
variant="outlined"
:disabled="loading || !valid || empty"
@click="clear"
text="Clear"
class="mr-2"
/>
<VBtn
variant="outlined"
color="primary"
:disabled="!valid || !changed"
@click="apply"
text="Apply"
:loading="loading"
/>
</VRow>
</VContainer>
</FormValidator>
</VForm>
</VExpansionPanelText>
</VExpansionPanel>
</VExpansionPanels>
<VCard>
<VCardTitle class="d-flex align-center">
<span>Filters</span>
<VSpacer />
<VBtn
variant="outlined"
:disabled="loading || !valid || empty"
@click="clear"
text="Clear"
class="mr-2"
density="compact"
/>
<VBtn
variant="outlined"
color="primary"
density="compact"
:disabled="!valid || !changed"
@click="apply"
text="Apply"
:loading="loading"
/>
</VCardTitle>

<VDivider />

<VRow no-gutters v-show="valid && (changed || (!loading && !empty))">
<VAlert color="info" variant="tonal" class="rounded-0">
<span>
{{ changed ? "Filter options were updated but not applied." : "" }} Click
<VCard
class="d-inline pa-1"
v-text="changed ? 'Apply' : 'Clear'"
flat
:color="$vuetify.theme.global.name === 'light' ? 'info' : undefined"
/>
{{ changed ? "in order to reload your data." : "to reset your selected filters." }}
</span>
</VAlert>
</VRow>

<VCardText :style="{ maxHeight: '750px', overflowY: 'auto' }">
<VForm :disabled="loading">
<FormValidator valid-on-init v-model="valid">
<VContainer fluid>
<VRow no-gutters>
<slot />
</VRow>
</VContainer>
</FormValidator>
</VForm>
</VCardText>
</VCard>
</template>

<script lang="ts">
Expand Down
21 changes: 21 additions & 0 deletions packages/playground/src/components/filters/TfFiltersLayout.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<template>
<div class="d-flex">
<div :style="{ width }">
<slot name="filters" />
</div>
<div :style="{ marginLeft: '16px', width: `calc(100% - 16px - ${width})` }">
<slot />
</div>
</div>
</template>

<script lang="ts">
const WIDTH_SIZE = 350;

export default {
name: "TfFiltersLayout",
setup() {
return { width: WIDTH_SIZE + "px" };
},
};
</script>
1 change: 1 addition & 0 deletions packages/playground/src/components/nodes_table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<v-row>
<v-col>
<v-data-table-server
height="750px"
:loading="loading"
loading-text="Loading nodes..."
:headers="headers"
Expand Down
189 changes: 102 additions & 87 deletions packages/playground/src/views/farms.vue
Original file line number Diff line number Diff line change
@@ -1,96 +1,109 @@
<template>
<view-layout>
<TfFiltersContainer @apply="loadFarms(true)" class="mb-4" :loading="loading">
<TfFilter
query-route="farm-id"
v-model="filters.farmId"
:rules="[
validators.isNumeric('This field accepts numbers only.', {
no_symbols: true,
}),
validators.min('The ID should be larger than zero.', 1),
validators.isInt('should be an integer'),
validators.validateResourceMaxNumber('This is not a valid ID.'),
]"
>
<template #input="{ props }">
<VTextField label="Farm ID" variant="outlined" v-model="filters.farmId" v-bind="props">
<template #append-inner>
<VTooltip text="Filter by farm id">
<template #activator="{ props }">
<VIcon icon="mdi-information-outline" v-bind="props" />
<TfFiltersLayout>
<template #filters>
<TfFiltersContainer @apply="loadFarms(true)" class="mb-4" :loading="loading">
<TfFilter
query-route="farm-id"
v-model="filters.farmId"
:rules="[
validators.isNumeric('This field accepts numbers only.', {
no_symbols: true,
}),
validators.min('The ID should be larger than zero.', 1),
validators.isInt('should be an integer'),
validators.validateResourceMaxNumber('This is not a valid ID.'),
]"
>
<template #input="{ props }">
<VTextField label="Farm ID" variant="outlined" v-model="filters.farmId" density="compact" v-bind="props">
<template #append-inner>
<VTooltip text="Filter by farm id">
<template #activator="{ props }">
<VIcon icon="mdi-information-outline" v-bind="props" />
</template>
</VTooltip>
</template>
</VTooltip>
</VTextField>
</template>
</VTextField>
</template>
</TfFilter>

<TfFilter query-route="farm-name" v-model="filters.farmName">
<template #unwrap="{ colProps }">
<VCol v-bind="colProps">
<TfSelectFarm
inset-tooltip
variant="outlined"
tooltip="Filter by farm name."
:model-value="filters.farmName ? ({ name: filters.farmName } as any) : undefined"
@update:model-value="filters.farmName = $event?.name || ''"
/>
</VCol>
</template>
</TfFilter>

<TfFilter
query-route="free-public-ips"
v-model="filters.freePublicIps"
:rules="[
validators.isNumeric('This field accepts numbers only.', {
no_symbols: true,
}),
validators.min('Free Public IP should be larger than zero.', 1),
validators.isInt('should be an integer'),
validators.validateResourceMaxNumber('This is not a valid public IP.'),
]"
>
<template #input="{ props }">
<VTextField label="Free Public IPs" variant="outlined" v-model="filters.freePublicIps" v-bind="props">
<template #append-inner>
<VTooltip text="Filter by free public IPs">
<template #activator="{ props }">
<VIcon icon="mdi-information-outline" v-bind="props" />
</TfFilter>

<TfFilter query-route="farm-name" v-model="filters.farmName">
<template #unwrap="{ colProps }">
<VCol v-bind="colProps">
<TfSelectFarm
inset-tooltip
variant="outlined"
tooltip="Filter by farm name."
:model-value="filters.farmName ? ({ name: filters.farmName } as any) : undefined"
@update:model-value="filters.farmName = $event?.name || ''"
density="compact"
/>
</VCol>
</template>
</TfFilter>

<TfFilter
query-route="free-public-ips"
v-model="filters.freePublicIps"
:rules="[
validators.isNumeric('This field accepts numbers only.', {
no_symbols: true,
}),
validators.min('Free Public IP should be larger than zero.', 1),
validators.isInt('should be an integer'),
validators.validateResourceMaxNumber('This is not a valid public IP.'),
]"
>
<template #input="{ props }">
<VTextField
label="Free Public IPs"
variant="outlined"
v-model="filters.freePublicIps"
density="compact"
v-bind="props"
>
<template #append-inner>
<VTooltip text="Filter by free public IPs">
<template #activator="{ props }">
<VIcon icon="mdi-information-outline" v-bind="props" />
</template>
</VTooltip>
</template>
</VTooltip>
</VTextField>
</template>
</VTextField>
</template>
</TfFilter>
</TfFiltersContainer>

<v-data-table-server
:loading="loading"
:headers="headers"
:items="farms"
:items-length="totalFarms"
:items-per-page-options="[
{ value: 5, title: '5' },
{ value: 10, title: '10' },
{ value: 15, title: '15' },
]"
:items-per-page="size"
@update:items-per-page="
size = $event;
loadFarms();
"
:page="page"
@update:page="
page = $event;
loadFarms();
"
:disable-sort="true"
@click:row="openSheet"
>
<template #loading />
</v-data-table-server>
</TfFilter>
</TfFiltersContainer>
</template>

<v-data-table-server
height="750px"
fixed-header
:loading="loading"
:headers="headers"
:items="farms"
:items-length="totalFarms"
:items-per-page-options="[
{ value: 5, title: '5' },
{ value: 10, title: '10' },
{ value: 15, title: '15' },
]"
:items-per-page="size"
@update:items-per-page="
size = $event;
loadFarms();
"
:page="page"
@update:page="
page = $event;
loadFarms();
"
:disable-sort="true"
@click:row="openSheet"
>
<template #loading />
</v-data-table-server>
</TfFiltersLayout>

<v-dialog v-model="dialog" hide-overlay transition="dialog-bottom-transition">
<v-container>
Expand Down Expand Up @@ -226,6 +239,7 @@ import { createCustomToast, ToastType } from "@/utils/custom_toast";

import TfFilter from "../components/filters/TfFilter.vue";
import TfFiltersContainer from "../components/filters/TfFiltersContainer.vue";
import TfFiltersLayout from "../components/filters/TfFiltersLayout.vue";
import TfSelectFarm from "../components/node_selector/TfSelectFarm.vue";

export default {
Expand All @@ -234,6 +248,7 @@ export default {
FarmDetailsCard,
TwinDetailsCard,
TfFiltersContainer,
TfFiltersLayout,
TfFilter,
TfSelectFarm,
},
Expand Down
Loading
Loading