Skip to content

Commit

Permalink
0.1.8 (fixes)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebt3 committed Mar 7, 2024
1 parent 5399480 commit 640640b
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 38 deletions.
9 changes: 5 additions & 4 deletions front/components/charts/stackedBarChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { ref, onMounted } from "vue";
import * as d3 from "d3";
import {chartSizeOptions,chartMarginOptions} from "../../libs/core"
import {getSizeOptions,getMarginOptions} from "./commonTools"
import {getSizeOptions,getMarginOptions,onlyUnique} from "./commonTools"
const props = defineProps<{
options?: chartSizeOptions&chartMarginOptions
datum: Array<object>
Expand All @@ -12,7 +12,7 @@ const props = defineProps<{
}>();
const marginTop = 10;
const marginRight = 10;
const marginBottom = 20;
const marginBottom = 30;
const marginLeft = 40;
const defaultHeight = 400;
const defaultWidth = 3*defaultHeight/2;
Expand All @@ -23,10 +23,11 @@ const series = d3.stack().keys(d3.union(props.datum.map(props.axisColor))).value
const x = d3.scaleBand().domain(d3.groupSort(props.datum, D => -d3.sum(D, props.getVal), props.axisX)).range([marginLeft, options.value.width - marginRight]).padding(0.1);
const y = d3.scaleLinear().domain([0, d3.max(series, d => d3.max(d, d => d[1]))]).rangeRound([options.value.height - marginBottom, marginTop]);
const color = props.datum.length>1?d3.scaleOrdinal().domain(series.map(d => d.key)).range(d3.schemeSpectral[series.length>4?series.length:4]).unknown("#ccc"):()=>d3.schemeSpectral[4][1];
const rotation = options.value.width/(props.datum.map(props.axisX).filter(onlyUnique).length+1)<80?-10:0
const formatValue = x => isNaN(x) ? "N/A" : x.toLocaleString("en")
onMounted(() => {
const svg = d3.select(svgRoot.value);
svg.select(".axisBottom").call(d3.axisBottom(x).tickSizeOuter(0)).call(g => g.selectAll(".domain").remove());
svg.select(".axisBottom").call(d3.axisBottom(x).tickSizeOuter(0)).call(g => g.selectAll(".domain").remove()).call(g => g.selectAll("text").attr('transform', `rotate(${rotation})`));
svg.select(".axisLeft").call(d3.axisLeft(y)).call(g => g.selectAll(".domain").remove());
svg.select(".rects").selectAll().data(series).join("g")
.attr("fill", d => color(d.key))
Expand All @@ -35,7 +36,7 @@ onMounted(() => {
.append("title")
.text(d => `${d.data[0]} ${d.key}\n${formatValue(props.getVal(d.data[1].get(d.key)))}`);
svg.select(".labels").selectAll().data(series).join("g").selectAll("text").data(D => D.map(d => (d.key = D.key, d))).join("text")
.text((x) => `${x.key}`).attr("y", d => isNaN(y(d[0]))||isNaN(y(d[1]))?-10:(y(d[0]) + y(d[1]))/2).attr("x", d => x(d.data[0])+x.bandwidth()/2)
.text((x) => `${x.key}`).attr('transform', d=> `translate(${x(d.data[0])+x.bandwidth()/2}, ${isNaN(y(d[0]))||isNaN(y(d[1]))?-100:(y(d[0]) + y(d[1]))/2}) rotate(${rotation})`)
})
</script>
<template>
Expand Down
37 changes: 37 additions & 0 deletions front/components/core/AllProblemOverview.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script setup lang="ts">
import { defineAsyncComponent, ref } from 'vue'
import {chartSizeOptions,chartMarginOptions} from "../../libs/core"
const pieChart = defineAsyncComponent(() => import( '@/components/charts/pieChart.vue'));
const stackedBarChart = defineAsyncComponent(() => import( '@/components/charts/stackedBarChart.vue'));
import { useQuasar } from 'quasar'
const $q = useQuasar()
import {onlyUnique} from "@/components/charts/commonTools.js"
const props=withDefaults(defineProps<{model: {short:string,source:string}[], short: string, useAction?:boolean, useRefresh?: boolean, showNamespace?:boolean, showKind?:boolean, options?: chartSizeOptions&chartMarginOptions}>(),{
useAction: false,
useRefresh: true,
showNamespace: false,
showKind: true,
});
const problems = ref(props.model.map(p=>p.short).filter(onlyUnique).map(short=>props.model.map(p=>p.source).filter(onlyUnique).map(source=>{return {short, source, value: props.model.filter(p=>p.short==short&&p.source==source).length}})).flat().filter(p=>p.value>0))
</script>
<template>
<q-card bordered class="q-ma-sm">
<q-card-section class="text-center text-white bg-negative">
<div class="text-subtitle q-mt-none q-mb-none q-pt-none q-pb-none" v-if="problems.map(p=>p.short).filter(onlyUnique).length>1 && problems.map(p=>p.source).filter(onlyUnique).length>1">{{ short }} problems distribution per object type and sources</div>
<div class="text-subtitle q-mt-none q-mb-none q-pt-none q-pb-none" v-if="problems.map(p=>p.short).filter(onlyUnique).length<2 && problems.map(p=>p.source).filter(onlyUnique).length>1">{{ short }} problems per sources</div>
<div class="text-subtitle q-mt-none q-mb-none q-pt-none q-pb-none" v-if="problems.map(p=>p.short).filter(onlyUnique).length>1 && problems.map(p=>p.source).filter(onlyUnique).length<2">{{ short }} problems per object type</div>
<div class="text-subtitle q-mt-none q-mb-none q-pt-none q-pb-none" v-if="problems.map(p=>p.short).filter(onlyUnique).length<2 && problems.map(p=>p.source).filter(onlyUnique).length<2">{{ short }} problems</div>
</q-card-section>
<q-card-section :class="`text-center bg-red-${$q.dark.isActive?'10':'2'}`">
<stackedBarChart v-if="problems.map(p=>p.short).filter(onlyUnique).length>1 && problems.map(p=>p.source).filter(onlyUnique).length>1" :options="options"
v-model:datum="problems" :axisX="function (d){return d!=undefined?d['short']:this.id}" :axisColor="function (d){return d!=undefined?d['source']:this.id}" :getVal="function (d){return d!=undefined?d['value']:this.id}" />
<pieChart v-if="problems.map(p=>p.short).filter(onlyUnique).length>1 && problems.map(p=>p.source).filter(onlyUnique).length<2" :options="options"
:datum="problems.map(p=>{ return { name: p.short, value: p.value } })"
@on-click="(name)=>{to(name)}" />
<pieChart v-if="problems.map(p=>p.short).filter(onlyUnique).length<2 && problems.map(p=>p.source).filter(onlyUnique).length>1" :options="options"
:datum="problems.map(p=>{ return { name: p.source, value: p.value } })" />
<stackedBarChart v-if="problems.map(p=>p.short).filter(onlyUnique).length<2 && problems.map(p=>p.source).filter(onlyUnique).length<2" :options="options"
v-model:datum="problems" :axisX="function (d){return d!=undefined?d['short']:this.id}" :axisColor="function (d){return d!=undefined?d['source']:this.id}" :getVal="function (d){return d!=undefined?d['value']:this.id}" />
</q-card-section>
</q-card>
</template>
12 changes: 7 additions & 5 deletions front/components/core/ProblemOverview.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<script setup lang="ts">
import { defineAsyncComponent, ref } from 'vue'
import {chartSizeOptions,chartMarginOptions} from "../../libs/core"
const pieChart = defineAsyncComponent(() => import( '@/components/charts/pieChart.vue'));
const stackedBarChart = defineAsyncComponent(() => import( '@/components/charts/stackedBarChart.vue'));
import { useQuasar } from 'quasar'
const $q = useQuasar()
import {onlyUnique} from "@/components/charts/commonTools.js"
const props=withDefaults(defineProps<{model: object[], short: string, to: (string) =>null, useAction?:boolean, useRefresh?: boolean, showNamespace?:boolean, showKind?:boolean}>(),{
const props=withDefaults(defineProps<{model: object[], short: string, to?: (string) =>null, useAction?:boolean, useRefresh?: boolean, showNamespace?:boolean, showKind?:boolean, options?: chartSizeOptions&chartMarginOptions}>(),{
to: () => null,
useAction: false,
useRefresh: true,
showNamespace: false,
Expand All @@ -23,14 +25,14 @@ const problems = ref(problemlist.map(p=>p.namespace).filter(onlyUnique).map(name
<div class="text-subtitle q-mt-none q-mb-none q-pt-none q-pb-none" v-if="problems.map(p=>p.namespace).filter(onlyUnique).length<2 && problems.map(p=>p.source).filter(onlyUnique).length<2">{{ short }} problems</div>
</q-card-section>
<q-card-section :class="`text-center bg-red-${$q.dark.isActive?'10':'2'}`">
<stackedBarChart v-if="problems.map(p=>p.namespace).filter(onlyUnique).length>1 && problems.map(p=>p.source).filter(onlyUnique).length>1"
<stackedBarChart v-if="problems.map(p=>p.namespace).filter(onlyUnique).length>1 && problems.map(p=>p.source).filter(onlyUnique).length>1" :options="options"
v-model:datum="problems" :axisX="function (d){return d!=undefined?d['source']:this.id}" :axisColor="function (d){return d!=undefined?d['namespace']:this.id}" :getVal="function (d){return d!=undefined?d['value']:this.id}" />
<pieChart v-if="problems.map(p=>p.namespace).filter(onlyUnique).length>1 && problems.map(p=>p.source).filter(onlyUnique).length<2"
<pieChart v-if="problems.map(p=>p.namespace).filter(onlyUnique).length>1 && problems.map(p=>p.source).filter(onlyUnique).length<2" :options="options"
:datum="problems.map(p=>{ return { name: p.namespace, value: p.value } })"
@on-click="(name)=>{to(name)}" />
<pieChart v-if="problems.map(p=>p.namespace).filter(onlyUnique).length<2 && problems.map(p=>p.source).filter(onlyUnique).length>1"
<pieChart v-if="problems.map(p=>p.namespace).filter(onlyUnique).length<2 && problems.map(p=>p.source).filter(onlyUnique).length>1" :options="options"
:datum="problems.map(p=>{ return { name: p.source, value: p.value } })" />
<stackedBarChart v-if="problems.map(p=>p.namespace).filter(onlyUnique).length<2 && problems.map(p=>p.source).filter(onlyUnique).length<2"
<stackedBarChart v-if="problems.map(p=>p.namespace).filter(onlyUnique).length<2 && problems.map(p=>p.source).filter(onlyUnique).length<2" :options="options"
v-model:datum="problems" :axisX="function (d){return d!=undefined?d['namespace']:this.id}" :axisColor="function (d){return d!=undefined?d['source']:this.id}" :getVal="function (d){return d!=undefined?d['value']:this.id}" />
</q-card-section>
</q-card>
Expand Down
2 changes: 1 addition & 1 deletion front/libs/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function useCore() {
}),
isNamespaced: () => {
const route = useRoute();
if (route.meta != undefined) {
if (route != undefined && route.meta != undefined) {
return route.meta.ns||false
}
return false
Expand Down
3 changes: 1 addition & 2 deletions front/pages/install/vynil/InstallEdit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ const { mutate: patchInstall, onDone: onPatchInstall, onError: onPatchError } =
function onSubmit(obj:object) {
notifyWorking('Update in progress');
patchInstall({
"name": result.value.k8sNamespace[0].vynilInstall[0].metadata.name,
"namespace": result.value.k8sNamespace[0].vynilInstall[0].metadata.namespace,
"metadata": Object.fromEntries(Object.entries(result.value.k8sNamespace[0].vynilInstall[0].metadata).filter(([name])=>name!='__typename')),
...obj
});
}
Expand Down
4 changes: 3 additions & 1 deletion front/pages/install/vynil/InstallNew.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ const setYaml = (v) => editor.value.setYaml(v)
function onFinalSubmit() {
notifyWorking('Create in progress');
mutate({
"metadata": {
"namespace": navigation.currentNamespace.value,
"name": name.value,
"name": name.value
},
"spec": sanitizeData(editor.value.obj.spec),
});
}
Expand Down
27 changes: 27 additions & 0 deletions front/pages/install/vynil/installDashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,33 @@ onResult((res) => {
})
</script>
<template><div>
<div class="row q-mb-sm q-ml-sm" v-if="loading && !isNamespaced()">
<div class="col-lg-4">
<OverviewSkeleton />
</div>
<div class="col-lg-8">
<TableSkeleton :showNamespace="false" />
</div>
</div>
<div class="row q-mb-sm q-ml-sm" v-if="!loading && !isNamespaced() && result.vynilDistrib.filter(o=>Array.isArray(o['getcoreProblem'])&&o['getcoreProblem'].length>0).length>0">
<div class="col-lg-4">
<ProblemOverview short="Distrib" :to="toDistribList"
:model="result.vynilDistrib.filter(o=>Array.isArray(o['getcoreProblem'])&&o['getcoreProblem'].length>0)" />
</div>
<div class="col-lg-8">
<vynilDistribList @refresh="refetch()" :useAction="false"
v-if="result !== undefined && Array.isArray(result['vynilDistrib']) && result['vynilDistrib'].length>0"
:model="result.vynilDistrib.filter(o=>Array.isArray(o['getcoreProblem'])&&o['getcoreProblem'].length>0)" />
</div>
</div>
<div class="row q-mb-sm q-ml-sm" v-if="loading">
<div class="col-lg-4">
<OverviewSkeleton />
</div>
<div class="col-lg-8">
<TableSkeleton :showNamespace="true" />
</div>
</div>
<div class="row q-mb-sm q-ml-sm" v-if="ready && DistribProblems.length>0">
<div class="col-lg-4">
<q-card bordered :class="`q-ma-sm bg-${ colorInstall }-${$q.dark.isActive?'10':'1'}`">
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gramo",
"version": "0.1.7",
"version": "0.1.8",
"description": "A cross-navigation Kubernetes front-end",
"main": "index.js",
"scripts": {
Expand Down
61 changes: 37 additions & 24 deletions utils/generator/front/all.pages.advices.vue.hbs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<script setup lang="ts">
import allQuery from '@/queries/all.read.graphql'
import { defineAsyncComponent } from 'vue'
const AllProblemOverview = defineAsyncComponent(() => import( '@/components/core/AllProblemOverview.vue'));
const ProblemOverview = defineAsyncComponent(() => import( '@/components/core/ProblemOverview.vue'));
const AdviceOverview = defineAsyncComponent(() => import( '@/components/core/AdviceOverview.vue'));
const OverviewSkeleton = defineAsyncComponent(() => import( '@/components/core/OverviewSkeleton.vue'));
const TableSkeleton = defineAsyncComponent(() => import( '@/components/core/TableSkeleton.vue'));
import {onlyUnique} from "@/components/charts/commonTools.js"
{{#each categories}}
{{#each groups}}
import { {{#each objects}}have{{ short }} as have{{ group }}{{ short }}, {{/each}} } from '@/libs/{{ name }}/{{ ../category }}Cat.js'
Expand All @@ -22,13 +24,8 @@ const {toList: to{{ group }}{{ short }}List} = use{{ group }}{{short}}();
import { ref, useCore, useNavigationStoreRef, useQuery } from '@/libs/core';
const { onErrorHandler, setNamespaceFromRoute, isNamespaced } = useCore();
const ready = ref(false);
{{#each groups}}
{{#each objects}}
const {{ group }}{{ short }}Problems = ref([]);
const {{ group }}{{ short }}Advices = ref([]);
{{/each}}
{{/each}}
if (isNamespaced()) setNamespaceFromRoute();
const namespaced = isNamespaced();
if (namespaced) setNamespaceFromRoute();
const navigation = useNavigationStoreRef();
const { result, loading, refetch, onResult, onError } = useQuery(allQuery, {
{{#each groups}}
Expand All @@ -41,7 +38,7 @@ const { result, loading, refetch, onResult, onError } = useQuery(allQuery, {
{{/each}}
{{/each}}
"namespace": {
"filters": isNamespaced()?[
"filters": namespaced?[
{
"op": "eq",
"path": "metadata/name",
Expand All @@ -50,27 +47,20 @@ const { result, loading, refetch, onResult, onError } = useQuery(allQuery, {
]:[]
}
});
const ProblemList = ref([]);
onError(onErrorHandler);
onResult((res) => {
if ( !res.loading ) {
ready.value = false;
ProblemList.value.length = 0;
{{#each groups}}
{{#each objects}}
if (have{{ group }}{{ short }}()) {
{{ group }}{{ short }}Problems.value.length = 0;
{{#if namespaced}}
{{ group }}{{ short }}Problems.value.push(...res.data.k8sNamespace.map(n => {
return {
name: n.metadata.name, value: n.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreProblem'])&&o['getcoreProblem'].length>0).length
}
}).filter(n => n.value>0))
{{ else }}
{{ group }}{{ short }}Problems.value.push(...Object.entries(Object.groupBy(res.data.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreProblem'])&&o['getcoreProblem'].length>0).map(o=>o['getcoreProblem']).flat(),p=>p['source'])).map(([name,v])=>{ return {name, value: v.length } }))
{{/if}}
{{#if namespaced}}
{{ group }}{{ short }}Advices.value.push(...res.data.k8sNamespace.map(n => {return {name: n.metadata.name, value: n.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreAdvice'])&&o['getcoreAdvice'].length>0).length} }).filter(n => n.value>0))
if (have{{ group }}{{ short }}() && Array.isArray(res.data.k8sNamespace)) {
ProblemList.value.unshift(...res.data.k8sNamespace.map(n => n.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreProblem'])&&o['getcoreProblem'].length>0)).flat().map(o=>{return {...o, short:'{{ short }}', group:'{{ group }}'} }))
{{ else }}
{{ group }}{{ short }}Advices.value.push(...Object.entries(Object.groupBy(res.data.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreAdvice'])&&o['getcoreProblem'].length>0).map(o=>o['getcoreAdvice']).flat(),p=>p['source'])).map(([name,v])=>{ return {name, value: v.length } }))
if (have{{ group }}{{ short }}() && !namespaced) {
ProblemList.value.unshift(...res.data.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreProblem'])&&o['getcoreProblem'].length>0).map(o=>{return {...o, short:'{{ short }}', group:'{{ group }}'} }))
{{/if}}
}
{{/each}}
Expand All @@ -80,9 +70,32 @@ onResult((res) => {
})
</script>
<template><div>
<div class="row q-mb-sm q-ml-sm" v-if="ready && ProblemList.map(o=>`${o.group}${o.short}`).filter(onlyUnique).length>1">
<div class="col-lg-6">
<AllProblemOverview short="All" :options="{width: 900, height: 600}"
:model="ProblemList.map(o=>o['getcoreProblem'].map(p=>{ return {short: o.short, source: p['source']} })).flat()" />
</div>
<div class="col-lg-6" v-if="!namespaced">
<ProblemOverview short="All" :options="{width: 900, height: 600}"
:model="ProblemList" />
</div>
</div>
<div class="row q-mb-sm q-ml-sm" v-if="ready && ProblemList.length<1">
<div class="col-lg-12">
<q-card bordered class="q-ma-sm">
<q-card-section class="bg-positive text-grey-2">
<div class="text-h6 q-mt-none q-mb-none q-pt-none q-pb-none">Congratulations
</div>
</q-card-section>
<q-card-section class="bg-green-2 text-center q-pa-xl text-subtitle1">
No problem found
</q-card-section>
</q-card>
</div>
</div>
{{#each groups}}
{{#each objects}}
<div class="row q-mb-sm q-ml-sm" v-if="loading{{#unless namespaced}} && !isNamespaced(){{/unless}}">
<div class="row q-mb-sm q-ml-sm" v-if="loading{{#unless namespaced}} && !namespaced{{/unless}}">
<div class="col-lg-4">
<OverviewSkeleton />
</div>
Expand All @@ -102,7 +115,7 @@ onResult((res) => {
:model="result.k8sNamespace.map(n => n.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreProblem'])&&o['getcoreProblem'].length>0)).flat()" />
</div>
{{else}}
<div class="row q-mb-sm q-ml-sm" v-if="!loading && !isNamespaced() && result.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreProblem'])&&o['getcoreProblem'].length>0).length>0">
<div class="row q-mb-sm q-ml-sm" v-if="!loading && !namespaced && result.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreProblem'])&&o['getcoreProblem'].length>0).length>0">
<div class="col-lg-4">
<ProblemOverview short="{{ short }}" :to="to{{ group }}{{ short }}List"
:model="result.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreProblem'])&&o['getcoreProblem'].length>0)" />
Expand Down Expand Up @@ -130,7 +143,7 @@ onResult((res) => {
:model="result.k8sNamespace.map(n => n.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreAdvice'])&&o['getcoreAdvice'].length>0)).flat()" />
</div>
{{else}}
<div class="row q-mb-sm q-ml-sm" v-if="!loading && !isNamespaced() && result.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreAdvice'])&&o['getcoreAdvice'].length>0).length>0">
<div class="row q-mb-sm q-ml-sm" v-if="!loading && !namespaced && result.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreAdvice'])&&o['getcoreAdvice'].length>0).length>0">
<div class="col-lg-4">
<AdviceOverview short="{{ short }}" :to="to{{ group }}{{ short }}List"
:model="result.{{ group }}{{ short }}.filter(o=>Array.isArray(o['getcoreAdvice'])&&o['getcoreAdvice'].length>0)" />
Expand Down

0 comments on commit 640640b

Please sign in to comment.