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
23 changes: 18 additions & 5 deletions packages/playground/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@
@click="openSidebar = true"
icon="mdi-menu"
variant="tonal"
class="mr-2"
class="mr-2 mb-4"
/>
</div>

Expand Down Expand Up @@ -214,11 +214,28 @@ const navbarConfig = ref();

const hasGrid = computed(() => !!gridStore.grid);

// eslint-disable-next-line no-undef
const permanent = ref(window.innerWidth > 980);
const openSidebar = ref(permanent.value);

function setSidebarOnResize() {
permanent.value =
window.innerWidth >
($route.meta && "sidebarBreakpoint" in $route.meta && typeof $route.meta["sidebarBreakpoint"] === "number"
? $route.meta.sidebarBreakpoint
: 980);
openSidebar.value = permanent.value;
}

window.addEventListener("resize", setSidebarOnResize);

watch(
() => $route.meta,
meta => {
(document.title = "Threefold Dashboard" + (meta && "title" in meta ? ` | ${meta.title}` : ``)),
(navbarConfig.value = meta.navbarConfig);

setSidebarOnResize();
},
);
function navigateToHome() {
Expand Down Expand Up @@ -396,10 +413,6 @@ const routes: AppRoute[] = [
},
];

// eslint-disable-next-line no-undef
const permanent = window.innerWidth > 980;
const openSidebar = ref(permanent);

const baseUrl = import.meta.env.BASE_URL;

function clickHandler({ route, url }: AppRouteItem): void {
Expand Down
8 changes: 7 additions & 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: "tf-filter-item py-1", cols: 12 };

function normalizeValue(v: string) {
if (v === "true") return true;
Expand Down Expand Up @@ -91,3 +91,9 @@ export default {
},
};
</script>

<style>
.tf-filter-item .v-label {
font-size: 14px !important;
}
</style>
124 changes: 74 additions & 50 deletions packages/playground/src/components/filters/TfFiltersContainer.vue
Original file line number Diff line number Diff line change
@@ -1,65 +1,75 @@
<template>
<VExpansionPanels :model-value="[0]">
<VExpansionPanel eager>
<VExpansionPanelTitle class="text-h6"> Filters </VExpansionPanelTitle>
<VExpansionPanelText eager>
<VForm :disabled="loading">
<VCard>
<VCardTitle
class="d-flex align-center"
:style="[collapsible ? { cursor: 'pointer' } : {}]"
@click="collapsible ? (filterOpened = !filterOpened) : undefined"
>
<span>Filters</span>
<VSpacer />
<VBtn
variant="outlined"
:disabled="loading || !valid || empty"
@click.stop="clear"
text="Clear"
density="compact"
/>
<VBtn
variant="outlined"
color="primary"
density="compact"
:disabled="!valid || !changed"
@click.stop="apply"
text="Apply"
:loading="loading"
class="mx-2"
/>
<VBtn
:icon="filterOpened ? 'mdi-chevron-up' : 'mdi-chevron-down'"
density="compact"
variant="flat"
v-if="collapsible"
/>
</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' }" :class="{ 'pa-0': collapsible && !filterOpened }">
<VExpandTransition mode="in-out">
<VForm :disabled="loading" v-show="!collapsible || filterOpened">
<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>
</VExpandTransition>
</VCardText>
</VCard>
</template>

<script lang="ts">
import { watch } from "vue";
import { onUnmounted } from "vue";
import { computed, type ComputedRef, inject, onMounted, provide, ref } from "vue";
import { useRouter } from "vue-router";
import { useRoute, useRouter } from "vue-router";

const key = Symbol("key:filters-container");

Expand Down Expand Up @@ -87,6 +97,7 @@ export default {
},
setup(_, ctx) {
const router = useRouter();
const route = useRoute();
const filters = ref(new Map<string, ComputedRef<FilterService>>());

const valid = ref(false);
Expand Down Expand Up @@ -134,7 +145,20 @@ export default {
ctx.emit("apply");
}

return { empty, changed, clear, apply, valid };
const collapsible = ref(false);
const filterOpened = ref(true);

const breakpoint = route.meta.filtersCollapsibleBreakpoint as number;

function onResize() {
collapsible.value = breakpoint > window.innerWidth;
}

onMounted(() => typeof breakpoint === "number" && window.addEventListener("resize", onResize));
onUnmounted(() => typeof breakpoint === "number" && window.removeEventListener("resize", onResize));
typeof breakpoint === "number" && onResize();

return { empty, changed, clear, apply, valid, collapsible, filterOpened };
},
};
</script>
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="tf-layout-container 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 = 300;

export default {
name: "TfFiltersLayout",
setup() {
return { width: WIDTH_SIZE + "px" };
},
};
</script>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<VCard
class="rounded-0 w-100 pb-3"
class="tf-node-card rounded-0 w-100 pb-3"
:class="{ 'selected-node': status !== 'Init' }"
:color="
status === 'Valid'
Expand Down Expand Up @@ -70,7 +70,7 @@

<template #append>
<template v-if="node">
<div class="d-flex">
<div class="d-flex align-center">
<VTooltip
:text="dedicated ? 'This node is dedicated for one user only' : 'Multiple users can deploy on this node'"
location="top"
Expand Down Expand Up @@ -150,7 +150,7 @@

<template #text>
<VRow>
<VCol>
<VCol class="tf-node-resource">
<ResourceDetails
name="CPU"
:used="node?.used_resources.cru ?? 0"
Expand All @@ -159,7 +159,7 @@
:cpuType="dmi?.processor[0]?.version"
/>
</VCol>
<VCol>
<VCol class="tf-node-resource">
<ResourceDetails
name="Memory"
:used="node?.used_resources.mru ?? 0"
Expand All @@ -171,15 +171,15 @@
</VRow>

<VRow>
<VCol>
<VCol class="tf-node-resource">
<ResourceDetails
name="SSD Disks"
:used="node?.used_resources.sru ?? 0"
:total="node?.total_resources.sru ?? 0"
:text="sruText"
/>
</VCol>
<VCol>
<VCol class="tf-node-resource">
<ResourceDetails
name="HDD Disks"
:used="node?.used_resources.hru ?? 0"
Expand Down
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
6 changes: 4 additions & 2 deletions packages/playground/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export interface RouteMeta {
info?: InfoMeta;
publicPath?: boolean;
requireSSH?: boolean;
sidebarBreakpoint?: number;
filtersCollapsibleBreakpoint?: number;
}

/**
Expand Down Expand Up @@ -403,7 +405,7 @@ function createTFFarmsRoutes(): RouteRecordRaw[] {
{
path: DashboardRoutes.Farms.FarmFinder,
component: () => import("@/views/farms.vue"),
meta: { title: "Farm Finder", publicPath: true },
meta: { title: "Farm Finder", publicPath: true, sidebarBreakpoint: 1000, filtersCollapsibleBreakpoint: 1350 },
},
{
path: DashboardRoutes.Farms.Simulator,
Expand Down Expand Up @@ -475,7 +477,7 @@ function createDeployRoutes(): RouteRecordRaw[] {
{
path: DashboardRoutes.Deploy.NodeFinder,
component: () => import("@/views/nodes.vue"),
meta: { title: "Nodes", publicPath: true },
meta: { title: "Nodes", publicPath: true, sidebarBreakpoint: 1150, filtersCollapsibleBreakpoint: 850 },
},
{
path: DashboardRoutes.Deploy.VirtualMachines,
Expand Down
Loading
Loading