Skip to content

Commit

Permalink
gramo 0.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
sebt3 committed Feb 12, 2024
1 parent 26fe9b8 commit 851981e
Show file tree
Hide file tree
Showing 16 changed files with 445 additions and 62 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@
!/front/pages/install/vynil/InstallEdit.vue
!/front/pages/install/vynil/InstallNew.vue
!/front/pages/install/vynil/installDashboard.vue
!/front/pages/config/k8s/SecretView.vue
!/front/pages/config/k8s/SecretEdit.vue
6 changes: 5 additions & 1 deletion front/components/core/OpenApiEdit.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import OpenApiEditObject from './OpenApiEditObject.vue';
import OpenApiEditArray from './OpenApiEditArray.vue';
import OpenApiEditUndefObject from './OpenApiEditUndefObject.vue';
import OpenApiEditBoolean from './OpenApiEditBoolean.vue';
import OpenApiEditString from './OpenApiEditString.vue';
import OpenApiEditNumber from './OpenApiEditNumber.vue';
Expand Down Expand Up @@ -28,9 +29,12 @@ const isDefault = (key) => (props.properties.has(key) && props.properties.get(ke
<template>
<div class="q-gutter-md column">
<div v-for="[key, value] in new Map([...properties.entries()].filter(([key]) => showDefault || !isDefault(key)))" v-bind:key="key" :style="getType(value)=='string'?key=='name'?'order: 1':'order: 2':['number','integer'].includes(getType(value))?'order: 3':getType(value)=='boolean'?'order: 1':getType(value)=='array'?'order: 5':'order: 4'">
<div v-if="value.type == 'object'" :key="key">
<div v-if="value.type == 'object' && value.properties != undefined && Object.keys(value.properties).length>0" :key="`${key}-obj`">
<OpenApiEditObject v-model:data="data[key]" :name="key" :defaultdata="value.default" :properties="getProperties(value)" :read-only="readOnly" />
</div>
<div v-if="value.type == 'object' && (value.properties == undefined || Object.keys(value.properties).length<1)" :key="`${key}-unknown`">
<OpenApiEditUndefObject v-model:data="data[key]" :name="key" :defaultdata="value.default" :properties="getProperties(value)" :read-only="readOnly" />
</div>
<div v-else-if="value.type == 'array'">
<OpenApiEditArray v-model:data="data[key]" :name="key" :defaultdata="value.default" :items="getItems(value)" :read-only="readOnly" />
</div>
Expand Down
2 changes: 1 addition & 1 deletion front/components/core/OpenApiEditBoolean.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const isDefault=computed(() => value.value == props.defaultdata || (props.defaul
</script>
<template>
<q-field :label="name" stack-label borderless :label-color="isDefault?'':'secondary'">
<template v-if="['name', 'namespace', 'app-group', 'enable', 'domain', 'domain-name', 'issuer', 'ingress-class', 'pullPolicy', 'registry', 'repository', 'tag', 'key', 'engine', 'username', 'dbname'].includes(name)" v-slot:prepend>
<template v-slot:prepend>
<OpenApiNamedIcon :name="name" :is-default="isDefault" />
</template>
<template v-slot:control>
Expand Down
6 changes: 3 additions & 3 deletions front/components/core/OpenApiEditNumber.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const isDefault=computed(() => value.value == props.defaultdata || (props.defaul
<template>
<div v-if="readOnly">
<q-field :label="name" stack-label borderless :label-color="isDefault?'':'secondary'">
<template v-if="['name', 'namespace', 'app-group', 'enable', 'domain', 'domain-name', 'issuer', 'ingress-class', 'pullPolicy', 'registry', 'repository', 'tag', 'key', 'engine', 'username', 'dbname'].includes(name)" v-slot:prepend>
<template v-slot:prepend>
<OpenApiNamedIcon :name="name" :is-default="isDefault" />
</template>
<template v-slot:control>
Expand All @@ -27,8 +27,8 @@ const isDefault=computed(() => value.value == props.defaultdata || (props.defaul
</q-field>
</div>
<div v-else>
<q-input v-model="value" :label="name" :label-color="isDefault?'':'secondary'">
<template v-if="['name', 'namespace', 'app-group', 'enable', 'domain', 'domain-name', 'issuer', 'ingress-class', 'pullPolicy', 'registry', 'repository', 'tag', 'key', 'engine', 'username', 'dbname'].includes(name)" v-slot:prepend>
<q-input v-model="value" :label="name" :label-color="isDefault?'':'secondary'" :type="'number'">
<template v-slot:prepend>
<OpenApiNamedIcon :name="name" :is-default="isDefault" />
</template>
</q-input>
Expand Down
24 changes: 16 additions & 8 deletions front/components/core/OpenApiEditString.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,38 @@ const props = withDefaults(defineProps<{
name: string
data: string|null
defaultdata?: string,
readOnly?: boolean
readOnly?: boolean,
useDelete?: boolean
}>(), {
readOnly: false
readOnly: false,
useDelete: false,
});
const value=ref(props.data)
const emit = defineEmits(['update:data'])
const emit = defineEmits(['update:data', 'delete'])
watch(value,(newValue) => emit('update:data', newValue))
const isDefault=computed(() => value.value == props.defaultdata || (props.defaultdata ==undefined && value.value == null))
</script>
<template>
<div v-if="readOnly">
<q-field :label="name" stack-label borderless :label-color="isDefault?'':'secondary'">
<template v-if="['name', 'namespace', 'app-group', 'enable', 'domain', 'domain-name', 'issuer', 'ingress-class', 'pullPolicy', 'registry', 'repository', 'tag', 'key', 'engine', 'username', 'dbname'].includes(name)" v-slot:prepend>
<template v-slot:prepend>
<OpenApiNamedIcon :name="name" :is-default="isDefault" />
</template>
<template v-slot:control>
<div class="self-center full-width no-outline" tabindex="0">{{ value }}</div>
<div class="self-center full-width no-outline" v-if="value?.includes('\n')"><pre>{{ value }}</pre></div>
<div class="self-center full-width no-outline" v-else>{{ value }}</div>
</template>
</q-field>
</div>
<div v-else>
<q-input v-model="value" :label="name" :label-color="isDefault?'':'secondary'">
<template v-if="['name', 'namespace', 'app-group', 'enable', 'domain', 'domain-name', 'issuer', 'ingress-class', 'pullPolicy', 'registry', 'repository', 'tag', 'key', 'engine', 'username', 'dbname'].includes(name)" v-slot:prepend>
<OpenApiNamedIcon :name="name" :is-default="isDefault" />
<q-input v-model="value" :label="name" :label-color="isDefault?'':'secondary'" :type="value?.includes('\n')?'textarea':'text'">
<template v-slot:prepend>
<OpenApiNamedIcon :name="name" :is-default="isDefault" v-if="!useDelete" />
<q-btn icon="delete" flat
@click="$emit('delete', name)"
v-else>
<q-tooltip>Delete</q-tooltip>
</q-btn>
</template>
</q-input>
</div>
Expand Down
71 changes: 71 additions & 0 deletions front/components/core/OpenApiEditUndefObject.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<script setup lang="ts">
import OpenApiEditObject from './OpenApiEditObject.vue';
import OpenApiEditArray from './OpenApiEditArray.vue';
import OpenApiEditBoolean from './OpenApiEditBoolean.vue';
import OpenApiEditString from './OpenApiEditString.vue';
import OpenApiEditNumber from './OpenApiEditNumber.vue';
import { ref, watch } from 'vue'
import {getProperties,getItems,getType, getFullData} from '../../libs/core/openapiSetup';
import { OpenAPIV3 } from "openapi-types";
const prompt = ref(false);
const newName = ref('');
const props = withDefaults(defineProps<{
name: string
data: object
defaultdata?: object
properties: Map<string, OpenAPIV3.SchemaObject>
readOnly?: boolean
showDefault?: boolean
}>(), {
readOnly: false,
showDefault: true
});
const out_handler= props.data;
getFullData(props.properties,out_handler,props.data);
const out = ref(out_handler)
const emit = defineEmits(['update:data'])
watch(out,(newValue) => emit('update:data', newValue),{ deep: true })
function handleAdd(evt) {
prompt.value = true;
evt.preventDefault();
evt.stopPropagation();
}
function onAdd() {
out.value[newName.value] = '';
}
</script>
<template>
<q-dialog v-model="prompt" persistent>
<q-card style="min-width: 350px">
<q-card-section>
<div class="text-subtitle">New property name</div>
</q-card-section>
<q-card-section class="q-pt-none">
<q-input dense v-model="newName" autofocus @keyup.enter="prompt = false" />
</q-card-section>
<q-card-actions align="right" class="text-primary">
<q-btn flat label="Cancel" v-close-popup />
<q-btn flat label="Add" v-close-popup @click="onAdd" />
</q-card-actions>
</q-card>
</q-dialog>
<q-expansion-item :label="name" :default-opened="name=='stringData' && !readOnly">
<template v-slot:header="{expanded}">
<q-item-section>
{{name}}
</q-item-section>
<q-item-section v-if="expanded && !readOnly" side>
<q-btn icon="add" flat @click="handleAdd">
<q-tooltip>add</q-tooltip>
</q-btn>
</q-item-section>
</template>
<div class="q-gutter-md column q-ml-sm" :key="`${Object.keys(out)}`">
<div v-for="[key, value] in new Map(Object.entries(out))" v-bind:key="key"
:style="getType(value)=='string'?key=='name'?'order: 1':'order: 2':['number','integer'].includes(getType(value))?'order: 3':getType(value)=='boolean'?'order: 1':getType(value)=='array'?'order: 5':'order: 4'">
<OpenApiEditString v-if="out[key]!=undefined" v-model:data="out[key]" :name="key" :read-only="readOnly" :use-delete="!readOnly" @delete="(k)=>{out[k]=undefined;console.log(k,out[k])}" />
</div>
</div>
</q-expansion-item>
</template>
30 changes: 16 additions & 14 deletions front/components/core/OpenApiNamedIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@ defineProps<{
</script>
<template>
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'name'" name="smart_button" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'namespace'" name="dashboard" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'enable'" name="done" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'app-group'" name="workspaces" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'domain-name'" name="link" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'issuer'" name="local_police" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'ingress-class'" name="alt_route" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'pullPolicy'" name="downloading" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'registry'" name="store" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'repository'" name="image" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'tag'" name="sell" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'dbname'" name="storage" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'engine'" name="settings" />
<q-icon :color="isDefault?'':'secondary'" v-if="name == 'username'" name="person" />
<q-icon :color="isDefault?'':'secondary'" v-if="['domain', 'key'].includes(name)" :name="name" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'namespace'" name="dashboard" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'enable'" name="done" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'app-group'" name="workspaces" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'domain-name'" name="link" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'issuer'" name="local_police" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'ingress-class'" name="alt_route" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'pullPolicy'" name="downloading" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'registry'" name="store" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'repository'" name="image" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'tag'" name="sell" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'dbname'" name="storage" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'engine'" name="settings" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'username'" name="person" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="name == 'type'" name="style" />
<q-icon :color="isDefault?'':'secondary'" v-else-if="['domain', 'key'].includes(name)" :name="name" />
<q-icon :color="isDefault?'':'secondary'" v-else name="question_mark" />
</template>
6 changes: 4 additions & 2 deletions front/libs/core/openapiSetup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { OpenAPIV3 } from "openapi-types";
export function getProperties(val) {
if (val != undefined && val['properties'] != undefined)
export function getProperties(val, filter=undefined) {
if (val != undefined && val['properties'] != undefined && filter == undefined)
return new Map(Object.entries(val.properties));
if (val != undefined && val['properties'] != undefined && filter != undefined)
return new Map(Object.entries(val.properties).filter(filter));
return new Map()
}
export function getItems(val) {
Expand Down
77 changes: 77 additions & 0 deletions front/pages/config/k8s/SecretEdit.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<script setup lang="ts">
// noGramoGenerator
import k8sSecretQuery from '@/queries/k8s/Secret.read.graphql'
import SecretEdit from '@/queries/k8s/Secret.patch.graphql'
import k8sSecretMeta from '@/components/k8s/SecretMeta.vue';
import k8sSecretEdit from '@/components/k8s/SecretEdit.vue';
import { ref, useQuery, sanitizeData, useMutation, useSecret, SecretSimpleExcludes } from '../../../libs/k8s/Secret.js'
const { onErrorHandler, patchDone, patchError, notifyWorking, onNotSecretFound, navigation, setNamespacedItemFromRoute } = useSecret();setNamespacedItemFromRoute();
const { result, loading, onResult, onError } = useQuery(k8sSecretQuery, {
"obj": {
"filters": [
{
"op": "eq",
"path": "metadata/name",
"value": navigation.currentItem
}
], "excludes": SecretSimpleExcludes
},
"namespace": {
"filters": [
{
"op": "eq",
"path": "metadata/name",
"value": navigation.currentNamespace
}
]
}
});
const { mutate: patchSecret, onDone: onPatchSecret, onError: onPatchError } = useMutation(SecretEdit);
function onSubmit(obj:object) {
notifyWorking('Update in progress');
patchSecret({
"name": result.value.k8sNamespace[0].k8sSecret[0].metadata.name,
"namespace": result.value.k8sNamespace[0].k8sSecret[0].metadata.namespace,
...obj
});
}
onError(onErrorHandler);
const secret = ref({stringData:{}})
onResult(res => {
onNotSecretFound(res);
if ( !res.loading ) {
if (Array.isArray(res.data.k8sNamespace) && res.data.k8sNamespace.map(ns=>ns['k8sSecret']).flat().length>0) {
secret.value = {...secret.value, ...res.data.k8sNamespace.map(ns=>ns['k8sSecret']).flat()[0], data: JSON.parse(JSON.stringify(res.data.k8sNamespace.map(ns=>ns['k8sSecret']).flat()[0]['data']))};
console.log(secret.value, secret.value['data'])
secret.value['stringData'] = secret.value['stringData']==undefined?{}:secret.value['stringData'];
if (typeof secret.value['data'] === 'object') Object.keys(secret.value['data']).forEach(key=>{
try {
secret.value['stringData'][key] = atob(secret.value['data'][key])
secret.value['data'][key] = undefined
} catch (err) {
console.error(err);
}
})
}
}
});
onPatchSecret(patchDone);onPatchError(patchError);
</script>
<template>
<div class="row q-mb-sm q-ml-sm">
<div class="col-md-12">
<k8sSecretMeta :useActions="false" :showStatus="false"
v-if="!loading && result!=undefined && Array.isArray(result.k8sNamespace) && result.k8sNamespace[0].k8sSecret[0]!=undefined && result.k8sNamespace[0].k8sSecret[0]!=null"
:model="result.k8sNamespace[0].k8sSecret[0]"
/>
</div>
<div class="col-md-12">
<k8sSecretEdit
v-if="!loading && secret['metadata']!=null"
:model="sanitizeData(secret)"
@on-submit="onSubmit"
/>
</div>
</div>
</template>

Loading

0 comments on commit 851981e

Please sign in to comment.