1
0
mirror of https://github.com/amir20/dozzle.git synced 2026-01-02 02:57:27 +01:00

Adds layouts (#1871)

This commit is contained in:
Amir Raminfar
2022-09-09 14:17:58 -07:00
committed by GitHub
parent 60fc2ab22a
commit 4d03a36940
10 changed files with 172 additions and 124 deletions

View File

@@ -1,73 +1,8 @@
<template>
<main>
<mobile-menu v-if="isMobile && !authorizationNeeded"></mobile-menu>
<splitpanes @resized="onResized($event)">
<pane min-size="10" :size="menuWidth" v-if="!authorizationNeeded && !isMobile && !collapseNav">
<side-menu @search="showFuzzySearch"></side-menu>
</pane>
<pane min-size="10">
<splitpanes>
<pane class="has-min-height router-view">
<router-view></router-view>
</pane>
<template v-if="!isMobile">
<pane v-for="other in activeContainers" :key="other.id">
<log-container
:id="other.id"
show-title
scrollable
closable
@close="containerStore.removeActiveContainer(other)"
></log-container>
</pane>
</template>
</splitpanes>
</pane>
</splitpanes>
<button
@click="collapseNav = !collapseNav"
class="button is-rounded"
:class="{ collapsed: collapseNav }"
id="hide-nav"
v-if="!isMobile && !authorizationNeeded"
>
<span class="icon ml-2" v-if="collapseNav">
<mdi-light-chevron-right />
</span>
<span class="icon" v-else>
<mdi-light-chevron-left />
</span>
</button>
</main>
<router-view></router-view>
</template>
<script lang="ts" setup>
import { Splitpanes, Pane } from "splitpanes";
import { useProgrammatic } from "@oruga-ui/oruga-next";
import hotkeys from "hotkeys-js";
import FuzzySearchModal from "@/components/FuzzySearchModal.vue";
const collapseNav = ref(false);
const { oruga } = useProgrammatic();
const { authorizationNeeded } = config;
const containerStore = useContainerStore();
const { activeContainers, visibleContainers } = storeToRefs(containerStore);
onMounted(() => {
hotkeys("command+k, ctrl+k", (event, handler) => {
event.preventDefault();
showFuzzySearch();
});
});
watchEffect(() => {
setTitle(`${visibleContainers.value.length} containers`);
});
watchEffect(() => {
if (smallerScrollbars.value) {
document.documentElement.classList.add("has-custom-scrollbars");
@@ -86,59 +21,6 @@ watchEffect(() => {
document.documentElement.removeAttribute("data-theme");
}
});
function showFuzzySearch() {
oruga.modal.open({
// parent: this,
component: FuzzySearchModal,
animation: "false",
width: 600,
active: true,
});
}
function onResized(e: any) {
if (e.length == 2) {
menuWidth.value = e[0].size;
}
}
</script>
<style scoped lang="scss">
:deep(.splitpanes--vertical > .splitpanes__splitter) {
min-width: 3px;
background: var(--border-color);
&:hover {
background: var(--border-hover-color);
}
}
@media screen and (max-width: 768px) {
.router-view {
padding-top: 75px;
}
}
.button.has-no-border {
border-color: transparent !important;
}
.has-min-height {
min-height: 100vh;
}
#hide-nav {
position: fixed;
left: 10px;
bottom: 10px;
&.collapsed {
left: -40px;
width: 60px;
padding-left: 40px;
background: rgba(0, 0, 0, 0.95);
&:hover {
left: -25px;
}
}
}
</style>
<style scoped lang="scss"></style>

124
assets/layouts/default.vue Normal file
View File

@@ -0,0 +1,124 @@
<template>
<main v-if="!authorizationNeeded">
<mobile-menu v-if="isMobile"></mobile-menu>
<splitpanes @resized="onResized($event)">
<pane min-size="10" :size="menuWidth" v-if="!isMobile && !collapseNav">
<side-menu @search="showFuzzySearch"></side-menu>
</pane>
<pane min-size="10">
<splitpanes>
<pane class="has-min-height router-view">
<router-view></router-view>
</pane>
<template v-if="!isMobile">
<pane v-for="other in activeContainers" :key="other.id">
<log-container
:id="other.id"
show-title
scrollable
closable
@close="containerStore.removeActiveContainer(other)"
></log-container>
</pane>
</template>
</splitpanes>
</pane>
</splitpanes>
<button
@click="collapseNav = !collapseNav"
class="button is-rounded"
:class="{ collapsed: collapseNav }"
id="hide-nav"
v-if="!isMobile"
>
<span class="icon ml-2" v-if="collapseNav">
<mdi-light-chevron-right />
</span>
<span class="icon" v-else>
<mdi-light-chevron-left />
</span>
</button>
</main>
</template>
<script lang="ts" setup>
import { Splitpanes, Pane } from "splitpanes";
import { useProgrammatic } from "@oruga-ui/oruga-next";
import hotkeys from "hotkeys-js";
import FuzzySearchModal from "@/components/FuzzySearchModal.vue";
const collapseNav = ref(false);
const { oruga } = useProgrammatic();
const { authorizationNeeded } = config;
const containerStore = useContainerStore();
const { activeContainers, visibleContainers } = storeToRefs(containerStore);
onMounted(() => {
hotkeys("command+k, ctrl+k", (event, handler) => {
event.preventDefault();
showFuzzySearch();
});
});
watchEffect(() => {
setTitle(`${visibleContainers.value.length} containers`);
});
function showFuzzySearch() {
oruga.modal.open({
// parent: this,
component: FuzzySearchModal,
animation: "false",
width: 600,
active: true,
});
}
function onResized(e: any) {
if (e.length == 2) {
menuWidth.value = e[0].size;
}
}
</script>
<style scoped lang="scss">
:deep(.splitpanes--vertical > .splitpanes__splitter) {
min-width: 3px;
background: var(--border-color);
&:hover {
background: var(--border-hover-color);
}
}
@media screen and (max-width: 768px) {
.router-view {
padding-top: 75px;
}
}
.button.has-no-border {
border-color: transparent !important;
}
.has-min-height {
min-height: 100vh;
}
#hide-nav {
position: fixed;
left: 10px;
bottom: 10px;
&.collapsed {
left: -40px;
width: 60px;
padding-left: 40px;
background: rgba(0, 0, 0, 0.95);
&:hover {
left: -25px;
}
}
}
</style>

View File

@@ -0,0 +1,9 @@
<template>
<main>
<router-view></router-view>
</main>
</template>
<script lang="ts" setup></script>
<style scoped lang="scss"></style>

View File

@@ -1,11 +1,12 @@
import { type App } from "vue";
import { createRouter, createWebHistory } from "vue-router";
import routes from "~pages";
import pages from "~pages";
import { setupLayouts } from "virtual:generated-layouts";
import config from "@/stores/config";
export const install = (app: App) => {
const routes = setupLayouts(pages);
const router = createRouter({
history: createWebHistory(`${config.base}/`),
routes,

View File

@@ -73,3 +73,7 @@ async function onLogin() {
}
}
</script>
<route lang="yaml">
meta:
layout: splash
</route>

View File

@@ -73,3 +73,7 @@ async function onLogin() {
}
}
</script>
<route lang="yaml">
meta:
layout: splash
</route>

View File

@@ -50,6 +50,7 @@
"unplugin-vue-components": "^0.22.4",
"vite": "3.1.0",
"vite-plugin-pages": "^0.26.0",
"vite-plugin-vue-layouts": "^0.7.0",
"vue": "^3.2.39",
"vue-i18n": "^9.2.2",
"vue-router": "^4.1.5"

19
pnpm-lock.yaml generated
View File

@@ -44,6 +44,7 @@ specifiers:
unplugin-vue-components: ^0.22.4
vite: 3.1.0
vite-plugin-pages: ^0.26.0
vite-plugin-vue-layouts: ^0.7.0
vitest: ^0.23.1
vue: ^3.2.39
vue-i18n: ^9.2.2
@@ -79,6 +80,7 @@ dependencies:
unplugin-vue-components: 0.22.4_vite@3.1.0+vue@3.2.39
vite: 3.1.0_sass@1.54.9
vite-plugin-pages: 0.26.0_6igbc34rdygfc6m44bomdw5yyu
vite-plugin-vue-layouts: 0.7.0_xik7h4qq3w5aalpcbhbvf3kbuu
vue: 3.2.39
vue-i18n: 9.2.2_vue@3.2.39
vue-router: 4.1.5_vue@3.2.39
@@ -4639,6 +4641,23 @@ packages:
- supports-color
dev: false
/vite-plugin-vue-layouts/0.7.0_xik7h4qq3w5aalpcbhbvf3kbuu:
resolution: {integrity: sha512-k5XDmRNFo4M/GmUjhbRXj2WmJiFcGoVI8l/uZ72RHyRDQr4wE/6Zq/KFq0lqXomWQxTSzakQRUswzNwtvZLE8A==}
peerDependencies:
vite: ^2.5.0 || ^3.0.0-0
vue: ^2.6.12 || ^3.2.4
vue-router: ^3.5.1 || ^ 4.0.11
dependencies:
'@vue/compiler-sfc': 3.2.39
debug: 4.3.4
fast-glob: 3.2.11
vite: 3.1.0_sass@1.54.9
vue: 3.2.39
vue-router: 4.1.5_vue@3.2.39
transitivePeerDependencies:
- supports-color
dev: false
/vite/3.1.0_sass@1.54.9:
resolution: {integrity: sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==}
engines: {node: ^14.18.0 || >=16.0.0}

View File

@@ -17,7 +17,7 @@
"@/*": ["assets/*"]
},
"jsx": "preserve",
"types": ["vitest", "vite/client", "vue/ref-macros", "vite-plugin-pages/client"]
"types": ["vitest", "vite/client", "vue/ref-macros", "vite-plugin-pages/client", "vite-plugin-vue-layouts/client"]
},
"include": ["assets/**/*.ts", "assets/**/*.d.ts", "assets/**/*.vue"],

View File

@@ -6,6 +6,7 @@ import Components from "unplugin-vue-components/vite";
import AutoImport from "unplugin-auto-import/vite";
import IconsResolver from "unplugin-icons/resolver";
import Pages from "vite-plugin-pages";
import Layouts from "vite-plugin-vue-layouts";
import VueI18n from "@intlify/vite-plugin-vue-i18n";
export default defineConfig(({ mode }) => ({
@@ -26,6 +27,9 @@ export default defineConfig(({ mode }) => ({
dirs: "assets/pages",
importMode: "sync",
}),
Layouts({
layoutsDirs: "assets/layouts",
}),
Components({
dirs: ["assets/components"],
resolvers: [