Skip to content

Commit

Permalink
Menu improvments
Browse files Browse the repository at this point in the history
  • Loading branch information
sebt3 committed Feb 11, 2024
1 parent d1165e0 commit 8f4159d
Show file tree
Hide file tree
Showing 24 changed files with 127 additions and 104 deletions.
2 changes: 1 addition & 1 deletion back/resolvers/k8slibs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import k8s from '@kubernetes/client-node';
import NodeCache from 'node-cache';
export const kc = new k8s.KubeConfig();
export const cache = new NodeCache();
export const cache = new NodeCache({ stdTTL: 2, useClones: false, deleteOnExpire: true, checkperiod: 60 });

kc.loadFromCluster();
export function getMetaNS(args: object) {
Expand Down
4 changes: 1 addition & 3 deletions front/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import BreadCrumbs from './components/navigation/BreadCrumbs.vue';
<q-page-container>
<BreadCrumbs />
<router-view v-slot="{ Component, route }">
<transition name="fade">
<component :is="Component" :key="route.path" />
</transition>
<component :is="Component" :key="route.name" />
</router-view>
</q-page-container>
</q-layout>
Expand Down
5 changes: 2 additions & 3 deletions front/components/navigation/BreadCrumbs.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<script setup lang="ts">
import { useRouter } from 'vue-router'
import { descriptions } from '../../routes'
const router = useRouter();
</script>
<template>
<q-breadcrumbs class="q-pl-md q-pt-md q-pb-md">
<q-breadcrumbs-el v-for="item in router.currentRoute.value.matched" v-bind:key="item.name"
:label="item.name!=undefined && descriptions[item.name]!=undefined?descriptions[item.name].breadcrumb:item.name"
:icon="item.name!=undefined && descriptions[item.name]!=undefined?descriptions[item.name].icon:''"
:label="item.meta!=undefined && item.meta.breadcrumb!=undefined?item.meta.breadcrumb:item.name"
:icon="item.meta!=undefined && item.meta.icon!=undefined?item.meta.icon:''"
:to="item.path" />
</q-breadcrumbs>
</template>
23 changes: 16 additions & 7 deletions front/components/navigation/MainMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import MainMenuLinks from './MainMenuLinks.vue';
import { ref, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useNavigationStoreRef } from '../../stores'
import { descriptions, links } from '../../routes'
import { links } from '../../routes'
const route = useRoute();
const router = useRouter();
const navigation = useNavigationStoreRef()
const model = navigation.currentNamespace
const leftDrawerOpen = ref(false)
const leftDrawerOpen = ref(true)
const miniState = ref(true)
const isNamespaced = computed(() => {
if (route.name != undefined && descriptions[route.name] != undefined) {
return descriptions[route.name].ns
if (route.meta != undefined) {
return route.meta.ns
}
return false
})
Expand All @@ -29,8 +29,17 @@ function onChangeNamespace() {
})
}
}
function handleMini(evt) {
if (miniState.value) {
miniState.value = false
evt.preventDefault();
evt.stopPropagation();
console.log('should stop')
return true
}
}
function toggleLeftDrawer() {
leftDrawerOpen.value = !leftDrawerOpen.value
miniState.value = !miniState.value
}
</script>
<template>
Expand All @@ -49,12 +58,12 @@ function toggleLeftDrawer() {
</q-toolbar>
</q-header>

<q-drawer show-if-above v-model="leftDrawerOpen" side="left" bordered :mini="miniState" :width="400" :breakpoint="500" @mouseover="miniState = false" @mouseout="miniState = true" mini-to-overlay>
<q-drawer show-if-above v-model="leftDrawerOpen" side="left" bordered :mini="miniState" :width="400" :breakpoint="300" :mini-to-overlay="false" @click.capture="handleMini">
<q-scroll-area class="fit" :horizontal-thumb-style="{ opacity: '0' }">
<q-list padding v-if="router.currentRoute.value.matched.length>1">
<MainMenuLinks class="q-mr-sm"
v-for="link in links"
:key="`${link.title}-${router.currentRoute.value.matched[router.currentRoute.value.matched.length-1].path}`"
:key="`${link.title}`"
v-bind="link">
</MainMenuLinks>
</q-list>
Expand Down
61 changes: 41 additions & 20 deletions front/components/navigation/MainMenuLinks.vue
Original file line number Diff line number Diff line change
@@ -1,51 +1,72 @@
<script setup lang="ts">
import MainMenuLinks from './MainMenuLinks.vue';
import { menuLinksProps } from '../../routes';
import { menuLinksProps } from '../../routes/interfaces.js';
import { elude } from '../../libs/core';
import { useRouter } from 'vue-router'
import { watch,onMounted, ref } from 'vue'
import {installColor,automationColor,workloadColor,databaseColor,storageColor,configColor,networkColor,securityColor,systemColor} from '../../routes/custom'
const expansionItem = ref(null);
const router = useRouter();
const maxCaptionLength= 25;
const props = withDefaults(defineProps<menuLinksProps>(), {
caption: '',
link: '#',
icon: '',
level: 0,
});
const shouldOpen = (route) =>route.matched.map(f=>f.name).includes(props.name) || (Array.isArray(props.children) && props.children.map(f=>f.name||f.title).reduce((ret,name) => ret || (route.matched.map(c=> c.name).includes(name as string)), false))
function getLevel0Color(name){
switch (name) {
case 'install': return installColor;
case 'automation': return automationColor;
case 'workload': return workloadColor;
case 'database': return databaseColor;
case 'storage': return storageColor;
case 'config': return configColor;
case 'network': return networkColor;
case 'security': return securityColor;
case 'system': return systemColor;
}
return ''
}
if (props.children != undefined && props.children.length > 0) onMounted(() => {
watch(router.currentRoute,(route) => {
if (expansionItem.value==null) return;
if (shouldOpen(route)) expansionItem.value.show();
else expansionItem.value.hide();
})
});
</script>
<template>
<div v-if="children != undefined && children.length > 0">
<q-expansion-item
<div v-if="children != undefined && children.length > 0" :class="`${getLevel0Color(props.name)==''?'':'bg-'+getLevel0Color(props.name)+'-1'}`">
<q-expansion-item ref="expansionItem"
expand-separator
:header-inset-level="level"
:href="link"
:to="target!=undefined?{ name: target }:name!=undefined?{ name }:null"
:active="router.currentRoute.value.matched.map(f=>f.name).includes(props.name)"
:default-opened="router.currentRoute.value.matched.map(f=>f.name).includes(props.name) || children.map(f=>f.name||f.title).reduce((ret,name) => ret || (router.currentRoute.value.matched.map(c=> c.name).includes(name as string)), false)">
:default-opened="shouldOpen(router.currentRoute.value)">
<template v-slot:header>
<q-item-section v-if="icon != ''" avatar>
<q-avatar :icon="icon" />
<q-avatar :icon="icon" :class="`${getLevel0Color(props.name)==''?'':' text-white bg-'+getLevel0Color(props.name)}`" />
</q-item-section>
<q-item-section>
<q-item-section>{{title}}</q-item-section>
<q-item-label v-if="caption != ''" caption>{{elude(caption, maxCaptionLength)}}</q-item-label>
</q-item-section>
</template>
<div v-if="router.currentRoute.value.matched.length>1">
<MainMenuLinks
v-for="child in children"
:key="`${child.title}-${router.currentRoute.value.matched[router.currentRoute.value.matched.length-1].path}`"
v-bind="child" />
</div>
<MainMenuLinks v-for="child in children" :key="`${child.title}`" v-bind="child" />
</q-expansion-item>
</div>
<div v-else>
<q-item clickable v-ripple :inset-level="level" :active="router.currentRoute.value.matched.map(f=>f.name).includes(props.name)" :href="link">
<q-item clickable v-ripple :inset-level="level" :to="target!=undefined?{ name: target }:name!=undefined?{ name }:null"
:active="router.currentRoute.value.matched.map(f=>f.name).includes(props.name)">
<q-item-section v-if="icon != ''" avatar>
<q-avatar :icon="icon" />
</q-item-section>
<q-item-section>
<q-item-section>{{title}}</q-item-section>
<q-item-label v-if="caption != ''" caption>{{elude(caption, maxCaptionLength)}}</q-item-label>
</q-item-section>
<q-avatar :icon="icon" />
</q-item-section>
<q-item-section>
<q-item-section>{{title}}</q-item-section>
<q-item-label v-if="caption != ''" caption>{{elude(caption, maxCaptionLength)}}</q-item-label>
</q-item-section>
</q-item>
</div>
</template>
8 changes: 3 additions & 5 deletions front/components/vynil/InstallView.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<script setup lang="ts">
import { onMounted } from "vue";
import MetadataView from '@/components/core/MetadataView.vue';
import DefaultStatusView from '@/components/core/DefaultStatusView.vue';
import { elude, getColor, getConditionColor} from "../../libs/core/"
import OpenApiEdit from '@/components/core/OpenApiEdit.vue';
import MonacoViewer from '@/components/core/MonacoViewer.vue';
Expand All @@ -28,7 +26,7 @@ onMounted(() => {
<q-btn icon="edit" @click="toEdit(model.metadata.namespace, model.metadata.name)">
<q-tooltip>Edit</q-tooltip>
</q-btn>
<q-btn icon="delete" @click="actionDelete(deletor, model)">
<q-btn icon="delete" @click="actionDelete(deletor, model.metadata)">
<q-tooltip>Delete</q-tooltip>
</q-btn>
</q-btn-group>
Expand Down Expand Up @@ -93,8 +91,8 @@ onMounted(() => {
</q-tab-panel>
<q-tab-panel name="simple" :class="`bg-${ colorInstall }-1`">
<OpenApiEdit
:in="model['spec']['options']"
:properties="new Map(Object.entries(model.consumePackage.options))"
:in="model['spec']"
:properties="getProperties(InstallDefinition.properties.spec)"
:read-only="true"
:show-default="false"
/>
Expand Down
5 changes: 2 additions & 3 deletions front/libs/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { useQuasar } from 'quasar'
import { setupTableWidget } from './tableSetup.js'
import { setupItem } from './itemSetup.js'
import { stringify } from 'yaml'
import { descriptions } from '../../routes'
import { useRouter, useRoute } from 'vue-router'

export * from './itemSetup.js'
Expand Down Expand Up @@ -38,8 +37,8 @@ export function useCore() {
}),
isNamespaced: () => {
const route = useRoute();
if (route.name != undefined && descriptions[route.name] != undefined) {
return descriptions[route.name].ns
if (route.meta != undefined) {
return route.meta.ns||false
}
return false
},
Expand Down
2 changes: 1 addition & 1 deletion front/routes/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
export interface menuLinksProps {
title: string
caption?: string
link?: string
icon?: string
level?: number
active?: boolean
name?: string
target?: string
children?: Array<menuLinksProps>
}
1 change: 1 addition & 0 deletions utils/gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ loadPartial('resolversRoleBinding', path.resolve(path_lib, 'back', 'tmpl.resolve
loadPartial('resolversApiService', path.resolve(path_lib, 'back', 'tmpl.resolvers.apiService.ts.hbs'));
loadPartial('resolversStorageClass', path.resolve(path_lib, 'back', 'tmpl.resolvers.storageClass.ts.hbs'));
loadPartial('resolversSecret', path.resolve(path_lib, 'back', 'tmpl.resolvers.secret.ts.hbs'));
loadPartial('resolversFluxCD', path.resolve(path_lib, 'back', 'tmpl.resolvers.fluxcd.ts.hbs'));
loadPartial('resolversConfigMap', path.resolve(path_lib, 'back', 'tmpl.resolvers.configMap.ts.hbs'));
loadPartial('createResolver', path.resolve(path_lib, 'back', 'tmpl.create.resolver.ts.hbs'));
loadPartial('deleteResolver', path.resolve(path_lib, 'back', 'tmpl.delete.resolver.ts.hbs'));
Expand Down
6 changes: 6 additions & 0 deletions utils/generator/back/obj.resolvers.ts.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import { lists as listNamespace } from '../k8s/Namespace.js';
{{#if (and (eq this.algo 'vynil') (and (eq type 'provide') (eq targetShort 'Package')))}}
import { gramoConfig } from '../../config.js'
{{/if}}
{{#if (and (eq this.algo 'fluxcd') (and (eq type 'provide') (or (eq targetShort 'ImagePolicy') (eq targetShort 'Kustomization'))))}}
import { lists as listNamespace } from '../k8s/Namespace.js';
{{/if}}
{{/each}}

{{#if (defined crd)}}
Expand All @@ -43,6 +46,9 @@ export const resolvers = {
{{#if autoResolvers}}
{{group}}{{short}}: {
{{#each autoResolvers}}
{{#if (eq algo 'fluxcd')}}
{{> resolversFluxCD algo=this.algo type=this.type targetShort=this.targetShort targetGroup=this.targetGroup path=this.path }}
{{/if}}
{{#if (eq algo 'vynil')}}
{{> resolversVynil algo=this.algo type=this.type targetShort=this.targetShort targetGroup=this.targetGroup path=this.path }}
{{/if}}
Expand Down
6 changes: 5 additions & 1 deletion utils/generator/back/tmpl.create.resolver.ts.hbs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{{#with ctx}}
{{group}}{{short}}Create: async (_parent, args: object) => {
const payload = {
{{#if (ne apiGroup '')}}
apiVersion: '{{apiGroup}}/{{apiVersion}}',
kind: '{{ name }}',
{{else}}
apiVersion: '{{apiVersion}}',
{{/if}}
kind: '{{ short }}',
{{#if namespaced}}
metadata: getMetaNS(args),
{{else}}
Expand Down
6 changes: 1 addition & 5 deletions utils/generator/back/tmpl.delete.resolver.ts.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@
const res = await k8sApi.deleteClusterCustomObject('{{apiGroup}}','{{apiVersion}}','{{crd.status.acceptedNames.plural}}', args['name'])
{{/if}}
{{else}}
{{#if namespaced}}
const res = await k8sApi.deleteNamespaced{{ short }}(args['namespace'], args['name'])
{{else}}
const res = await k8sApi.delete{{ short }}(args['name'])
{{/if}}
const res = await k8sApi.delete{{#if namespaced}}Namespaced{{/if}}{{ short }}(args['name']{{#if namespaced}}, args['namespace']{{/if}})
{{/if}}
return res.body
} catch (err) {
Expand Down
6 changes: 5 additions & 1 deletion utils/generator/back/tmpl.patch.resolver.ts.hbs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{{#with ctx}}
{{group}}{{short}}Patch: async (_parent, args: object) => {
const request = {
{{#if (ne apiGroup '')}}
apiVersion: '{{apiGroup}}/{{apiVersion}}',
kind: '{{name}}',
{{else}}
apiVersion: '{{apiVersion}}',
{{/if}}
kind: '{{short}}',
{{#if namespaced}}
metadata: getMetaNS(args),
{{else}}
Expand Down
2 changes: 0 additions & 2 deletions utils/generator/back/tmpl.resolvers.vynil.ts.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,10 @@
{{#if (and (eq type 'provide') (eq targetShort 'Install'))}}
{{type}}{{targetShort}}: async (dist, args: object) => {
const nss = await listNamespace.k8sNamespace(dist, args)
console.log('{{type}}{{targetShort}}',nss)
const res = (await Promise.all(nss.map(n=>n['metadata']['name']).map(async (ns)=>{
const lst = await list{{targetShort}}.{{targetGroup}}{{targetShort}}(dist, {namespace: ns, ...args})
return lst.filter(r=>r['spec']['distrib']==dist['metadata']['name'])
})))
console.log('{{type}}{{targetShort}}',res)
return res.flat().filter((v)=>v!=null)
},
{{/if}}
Expand Down
6 changes: 5 additions & 1 deletion utils/generator/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ const uses = [
{algo: 'roleBinding', group: 'k8s', short: 'ServiceAccount', usedGroup: 'k8s', usedShort: 'ClusterRoleBinding'},
];
const provides = [
// Broken somehow
// {algo: 'fluxcd', group: 'fluxcd', short: 'ImageRepository', providedGroup: 'fluxcd', providedShort: 'ImagePolicy'},
// {algo: 'fluxcd', group: 'fluxcd', short: 'GitRepository', providedGroup: 'fluxcd', providedShort: 'ImageUpdateAutomation'},
// {algo: 'fluxcd', group: 'fluxcd', short: 'GitRepository', providedGroup: 'fluxcd', providedShort: 'Kustomization'},
// {algo: 'vynil', group: 'vynil', short: 'Category', providedGroup: 'vynil', providedShort: 'Package'},
{algo: 'vynil', group: 'vynil', short: 'Distrib', providedGroup: 'vynil', providedShort: 'Package'},
{algo: 'vynil', group: 'vynil', short: 'Distrib', providedGroup: 'vynil', providedShort: 'Category'},
{algo: 'vynil', group: 'vynil', short: 'Distrib', providedGroup: 'vynil', providedShort: 'Install'},
{algo: 'vynil', group: 'vynil', short: 'Package', providedGroup: 'vynil', providedShort: 'Install'},
{algo: 'vynil', group: 'vynil', short: 'Category', providedGroup: 'vynil', providedShort: 'Install'},
// {algo: 'vynil', group: 'vynil', short: 'Category', providedGroup: 'vynil', providedShort: 'Package'},
{algo: 'nodeName', group: 'k8s', short: 'Node', providedGroup: 'k8s', providedShort: 'Pod'},
{algo: 'serviceAccount', group: 'k8s', short: 'ServiceAccount', providedGroup: 'k8s', providedShort: 'Pod', path: 'spec'},
{algo: 'serviceAccount', group: 'k8s', short: 'ServiceAccount', providedGroup: 'k8s', providedShort: 'ReplicaSet', path: 'spec/template/spec'},
Expand Down
9 changes: 2 additions & 7 deletions utils/generator/front/all.routes.ts.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,21 @@ const linkRedirect = {path:''};
export const links:Array<menuLinksProps> = [];

{{#each categories}}
import { route as {{this}}Route, link as {{this}}Link, descriptions as {{this}}Descriptions } from './{{this}}'
import { route as {{this}}Route, link as {{this}}Link } from './{{this}}'
if ({{this}}Route.children != undefined && {{this}}Route.children?.length>0) {
routeChildren.push({{this}}Route);
links.push({{this}}Link)
linkRedirect.path = linkRedirect.path!=''?linkRedirect.path:{{this}}Route.redirect!=undefined?{{this}}Route.redirect.path:'/{{this}}'
}
{{/each}}

export const descriptions = {
root: {breadcrumb: '', icon: 'home', ns: false},
{{#each categories}}
...{{this}}Descriptions,
{{/each}}
}
export const router = createRouter({
history: createWebHistory('/'),
routes: [
{
path: '/',
name: 'root',
meta: {breadcrumb: '', icon: 'home', ns: false},
redirect: defaultRoute!=''?{path:defaultRoute}:linkRedirect,
children: routeChildren
},
Expand Down
Loading

0 comments on commit 8f4159d

Please sign in to comment.