Skip to content

Commit

Permalink
Merge pull request #115 from Digital-Engineering/feat/graph-qol
Browse files Browse the repository at this point in the history
Feat/graph qol
  • Loading branch information
DnOberon authored and GitHub Enterprise committed Nov 11, 2022
2 parents 64b6113 + 05dec19 commit 1b0c289
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 69 deletions.
6 changes: 4 additions & 2 deletions AdminWebApp/src/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ export class Client {
return this.postNoPayload(`/containers/${containerID}/import/imports/${importID}/reprocess`);
}

createNode(containerID: string, node: any): Promise<NodeT[]> {
createOrUpdateNode(containerID: string, node: any): Promise<NodeT[]> {
return this.post<NodeT[]>(`/containers/${containerID}/graphs/nodes`, node);
}

Expand Down Expand Up @@ -1314,7 +1314,9 @@ export class Client {
const resp: AxiosResponse = await axios.post(url, data, config);

return new Promise<T>((resolve, reject) => {
if (resp.status < 200 || resp.status > 299) reject(resp.data.error);
if (resp.status < 200 || resp.status > 299) {
resp.data.error ? reject(resp.data.error) : reject(resp.data);
}

resolve(resp.data as T);
});
Expand Down
2 changes: 1 addition & 1 deletion AdminWebApp/src/components/data/createNodeCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export default class CreateNodeDialog extends Vue {
newNode() {
if (this.metatype.id !== undefined && this.metatype.id !== null){
this.setProperties()
this.$client.createNode(this.containerID,
this.$client.createOrUpdateNode(this.containerID,
{
"container_id": this.containerID,
"data_source_id": this.dataSourceID,
Expand Down
213 changes: 171 additions & 42 deletions AdminWebApp/src/components/data/editNodeDialog.vue
Original file line number Diff line number Diff line change
@@ -1,44 +1,22 @@
<template>
<v-dialog v-model="dialog" @click:outside="dialog = false" max-width="60%">
<v-dialog v-model="dialog" @click:outside="close" max-width="60%">
<template v-slot:activator="{ on }">
<v-icon
v-if="icon"
small
class="mr-2"
v-on="on"
>mdi-pencil</v-icon>
<v-btn v-if="!icon" color="primary" dark class="mt-2" v-on="on">{{$t("editNode.editNode")}}</v-btn>
<v-btn v-if="!icon" style="max-width: fit-content" color="primary" dark class="mt-2" v-on="on">{{$t("editNode.editNode")}}</v-btn>
</template>

<v-card class="pt-1 pb-3 px-2" v-if="selectedNode">
<v-card-title>
<span class="headline text-h3">{{$t('editNode.edit')}} {{selectedNode.metatype.name}}</span>
<span class="headline text-h3">{{$t('editNode.edit')}} {{nodeName}} ({{selectedNode.metatype.name}})</span>
</v-card-title>
<v-card-text>
<error-banner :message="errorMessage"></error-banner>
<v-row>
<v-col :cols="12">
<v-form
ref="form"
v-model="valid"
>
<v-text-field
v-model="selectedNode.metatype.name"
:rules="[v => !!v || $t('editNode.nameRequired')]"
required
>
<template v-slot:label>{{$t("editNode.name")}} <small style="color:red" >*</small></template>
</v-text-field>
<v-textarea
v-model="selectedNode.metatype.description"
:rules="[v => !!v || $t('editNode.descriptionRequired')]"
required
>
<template v-slot:label>{{$t('editNode.description')}} <small style="color:red" >*</small></template>
</v-textarea>
</v-form>
<p><span style="color:red">*</span> = {{$t('editNode.requiredField')}}</p>
</v-col>
<v-col :cols="12">
<v-data-table
:headers="headers()"
Expand All @@ -56,6 +34,85 @@
vertical
></v-divider>
<v-spacer></v-spacer>

<!-- Add Property Dialog -->
<v-dialog
v-model="addPropertyDialog"
@click:outside="closeDialog"
max-width="50%"
>
<template v-slot:activator="{ on, attrs }">
<v-btn
color="primary"
dark
class="mt-2"
v-bind="attrs"
v-on="on"
>
{{$t("editNode.addProperty")}}
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="text-h5">{{$t("editNode.addProperty")}}</span>
</v-card-title>

<v-card-text>
<v-container>
<v-row>
<v-col
cols="4"
>
<v-autocomplete
v-model="newProperty.key"
:items = "metatypeKeys"
item-text = "name"
item-value = "property_name"
label="Key"
@change="getKey"
></v-autocomplete>
</v-col>
<v-col
cols="2"
>
<v-text-field
v-model="newProperty.type"
label="Type"
disabled
></v-text-field>
</v-col>
<v-col
cols="6"
>
<v-text-field
v-model="newProperty.value"
label="Value"
></v-text-field>
</v-col>
</v-row>
</v-container>
</v-card-text>

<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="blue darken-1"
text
@click="closeDialog"
>
{{$t("editNode.cancel")}}
</v-btn>
<v-btn
color="blue darken-1"
text
@click="addProperty"
>
{{$t("editNode.save")}}
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>

</v-toolbar>
</template>
<template v-slot:[`item.value`]="value">
Expand All @@ -71,22 +128,31 @@
</template>
</v-edit-dialog>
</template>

<template v-slot:[`item.actions`]="{ item }">
<v-icon
small
@click="deleteProperty(item)"
>
mdi-delete
</v-icon>
</template>
</v-data-table>
</v-col>
</v-row>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="dialog = false" >{{$t("editNode.cancel")}}</v-btn>
<v-btn color="blue darken-1" :disabled="!valid" text @click="updateNode()">{{$t("editNode.save")}}</v-btn>
<v-btn color="blue darken-1" text @click="close" >{{$t("editNode.cancel")}}</v-btn>
<v-btn color="blue darken-1" text @click="updateNode">{{$t("editNode.save")}}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>

<script lang="ts">
import {Component, Prop, Watch, Vue} from 'vue-property-decorator'
import {NodeT, PropertyT} from "../../api/types";
import {MetatypeKeyT, NodeT, PropertyT} from "../../api/types";
@Component({components: {}})
export default class EditNodeDialog extends Vue {
Expand All @@ -105,9 +171,18 @@ export default class EditNodeDialog extends Vue {
errorMessage = ""
dialog = false
selectedNode: NodeT | null = null
valid = false
nodeProperties: PropertyT[] = []
property = {}
nodeName = ""
addPropertyDialog = false
newProperty: PropertyT = {
key: '',
value: '',
type: ''
}
metatypeKeys: MetatypeKeyT[] = []
// load properties to array when the node is selected so that we can edit fields.
@Watch('dialog', {immediate: true})
Expand All @@ -121,15 +196,18 @@ export default class EditNodeDialog extends Vue {
return [
{ text: this.$t('editNode.keyName'), value: 'key'},
{ text: this.$t('editNode.value'), value: 'value'},
{ text: this.$t('editNode.actions'), value: 'actions', sortable: false }
]
}
mounted() {
async propertiesToArray() {
// have to do this to avoid mutating properties
this.selectedNode = JSON.parse(JSON.stringify(this.node))
}
this.nodeName = (this.selectedNode!.properties as any).name ? (this.selectedNode!.properties as any).name : this.selectedNode!.id
// grab all metatype keys
this.metatypeKeys = await this.$client.listMetatypeKeys(this.containerID, this.selectedNode!.metatype.id)
propertiesToArray() {
if (this.selectedNode) {
this.nodeProperties = []
Object.entries(this.selectedNode.properties).forEach(([key, text]) => {
Expand All @@ -143,24 +221,39 @@ export default class EditNodeDialog extends Vue {
setProperties() {
this.property = {}
const entries: { [key: string]: any } = {}
this.nodeProperties.forEach( (property: any) => {
if (String(property.value).toLowerCase() === "true") {
property.value = true
} else if (String(property.value).toLowerCase() === "false" ) {
property.value = false
} else if (String(property.value) === "") {
property.value = null
} else if (String(property.value) === "null") {
property.value = null
// look at supplied data type to determine property value changes
// types: ['number', 'number64', 'float', 'float64', 'date', 'string', 'boolean', 'enumeration', 'file', 'list', 'unknown']
if (property.type === 'boolean') {
if (String(property.value).toLowerCase() === "true") {
property.value = true
} else if (String(property.value).toLowerCase() === "false" ) {
property.value = false
}
} else if (property.type === 'number') {
property.value = parseInt(property.value)
} else if (property.type === 'number64') {
property.value = parseInt(property.value)
} else if (property.type === 'float') {
property.value = parseFloat(property.value)
} else if (property.type === 'float64') {
property.value = parseFloat(property.value)
} else if (property.type === 'list') {
property.value = property.value.split(',')
}
// default to string behavior
entries[property.key] = property.value
})
this.property = entries
}
updateNode() {
this.setProperties()
this.$client.createNode(this.containerID,
this.$client.createOrUpdateNode(this.containerID,
{
"container_id": this.containerID,
"data_source_id": this.dataSourceID,
Expand All @@ -170,11 +263,47 @@ export default class EditNodeDialog extends Vue {
}
)
.then(results => {
this.dialog = false
this.close()
this.$emit('nodeUpdated', results[0])
})
.catch(e => this.errorMessage = this.$t('createNode.errorCreatingAPI') as string + e)
}
addProperty() {
this.nodeProperties.push(this.newProperty)
this.closeDialog()
}
deleteProperty(item: any) {
this.nodeProperties = this.nodeProperties.filter(( property: PropertyT ) => {
return property.key !== item.key && property.value !== item.value;
})
}
getKey() {
const key = this.metatypeKeys.filter((key: any) => {
return key.property_name === this.newProperty.key
})
if (key.length > 0) this.newProperty.type = key[0].data_type
}
close() {
// reset node and properties
this.selectedNode = null
this.nodeProperties = []
this.dialog = false
}
closeDialog() {
// reset property
this.newProperty = {
key: '',
value: '',
type: ''
}
this.addPropertyDialog = false
}
}
</script>
25 changes: 17 additions & 8 deletions AdminWebApp/src/components/queryBuilder/queryBuilder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ relationshipSampleQuery =
setRawEditor() {
this.activeTab = 'rawEditor'
this.$emit('disableGraphEdit', true)
// clear any graph results
if (this.results !== null) {
Expand Down Expand Up @@ -467,16 +468,24 @@ relationshipSampleQuery =
}
this.loading = true
const queryResult = await this.$client.submitGraphQLQuery(this.containerID, { query: `${this.codeMirror?.getValue()}` })
this.$client.submitGraphQLQuery(this.containerID, { query: `${this.codeMirror?.getValue()}` })
.then((queryResult: any) => {
if(queryResult.errors) {
this.errorMessage = queryResult.errors.map((error: any) => error.message as string).join(' ')
this.loading = false
return
}
if(queryResult.errors) {
this.errorMessage = queryResult.errors.map((error: any) => error.message as string).join(' ')
this.loading = false
return
}
this.rawQueryResult = queryResult
this.loading = false
})
.catch((err: string) => {
this.errorMessage = 'There is a problem with the GraphQL query or server error. Please see the result tab.'
this.rawQueryResult = {'error': err}
this.loading = false
})
this.rawQueryResult = queryResult
this.loading = false
}
}
Expand Down
Loading

0 comments on commit 1b0c289

Please sign in to comment.