openc3-cosmos-init/plugins/packages/openc3-tool-common/src/tools/calendar/Dialogs/MetadataCreateDialog.vue
<!--
# Copyright 2022 Ball Aerospace & Technologies Corp.
# All Rights Reserved.
#
# This program is free software; you can modify and/or redistribute it
# under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; version 3 with
# attribution addendums as found in the LICENSE.txt
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# Modified by OpenC3, Inc.
# All changes Copyright 2024, OpenC3, Inc.
# All Rights Reserved
#
# This file may also be used under the terms of a commercial license
# if purchased from OpenC3, Inc.
-->
<template>
<div>
<v-dialog persistent v-model="show" width="600">
<v-card>
<form @submit.prevent="createMetadata">
<v-system-bar>
<v-spacer />
<span v-if="metadata">Update Metadata</span>
<span v-else>Create Metadata</span>
<v-spacer />
<v-tooltip top>
<template v-slot:activator="{ on, attrs }">
<div v-on="on" v-bind="attrs">
<v-icon data-test="close-metadata-icon" @click="show = !show">
mdi-close-box
</v-icon>
</div>
</template>
<span>Close</span>
</v-tooltip>
</v-system-bar>
<v-stepper v-model="dialogStep" vertical non-linear>
<v-stepper-step editable step="1">
Input start time
</v-stepper-step>
<v-stepper-content step="1">
<v-card-text>
<div class="pa-2">
<color-select-form v-model="color" />
<v-row dense>
<v-text-field
v-model="startDate"
type="date"
label="Start Date"
class="mx-1"
:rules="[rules.required]"
data-test="metadata-start-date"
/>
<v-text-field
v-model="startTime"
type="time"
step="1"
label="Start Time"
class="mx-1"
:rules="[rules.required]"
data-test="metadata-start-time"
/>
</v-row>
<v-row class="mt-2">
<v-spacer />
<v-btn
@click="dialogStep = 2"
data-test="metadata-step-two-btn"
color="success"
>
Continue
</v-btn>
</v-row>
</div>
</v-card-text>
</v-stepper-content>
<v-stepper-step editable step="2">Metadata Input</v-stepper-step>
<v-stepper-content step="2">
<v-card-text>
<div class="pa-2">
<div style="min-height: 200px">
<metadata-input-form v-model="metadataVals" />
</div>
<v-row v-show="typeError">
<span class="ma-2 red--text" v-text="typeError" />
</v-row>
<v-row class="mt-2">
<v-spacer />
<v-btn
@click="show = !show"
outlined
class="mx-2"
data-test="metadata-cancel-btn"
>
Cancel
</v-btn>
<v-btn
@click.prevent="createMetadata"
class="mx-2"
color="primary"
type="submit"
data-test="metadata-submit-btn"
:disabled="!!typeError"
>
Ok
</v-btn>
</v-row>
</div>
</v-card-text>
</v-stepper-content>
</v-stepper>
</form>
</v-card>
</v-dialog>
</div>
</template>
<script>
import Api from '@openc3/tool-common/src/services/api'
import CreateDialog from '@openc3/tool-common/src/tools/calendar/Dialogs/CreateDialog.js'
import TimeFilters from '@openc3/tool-common/src/tools/base/util/timeFilters.js'
import ColorSelectForm from '@openc3/tool-common/src/tools/calendar/Forms/ColorSelectForm'
import MetadataInputForm from '@openc3/tool-common/src/tools/calendar/Forms/MetadataInputForm'
export default {
components: {
ColorSelectForm,
MetadataInputForm,
},
props: {
value: Boolean, // value is the default prop when using v-model
metadata: {
type: Object,
default: null,
},
},
mixins: [CreateDialog, TimeFilters],
data() {
return {
dialogStep: 1,
color: '#003784',
metadataVals: [],
rules: {
required: (value) => !!value || 'Required',
},
}
},
mounted: function () {
this.updateValues()
},
computed: {
typeError: function () {
if (!this.color) {
return 'A color is required.'
}
if (this.metadataVals.length < 1) {
return 'Please enter a value in the metadata table.'
}
const emptyKeyValue = this.metadataVals.find(
(meta) => meta.key === '' || meta.value === '',
)
if (emptyKeyValue) {
return 'Missing or empty key, value in the metadata table.'
}
return null
},
show: {
get() {
return this.value
},
set(value) {
this.$emit('input', value) // input is the default event when using v-model
},
},
},
methods: {
updateValues: function () {
this.dialogStep = 1
if (this.metadata) {
const sDate = new Date(this.metadata.start * 1000)
this.startDate = this.formatDate(sDate, this.timeZone)
this.startTime = this.formatTimeHMS(sDate, this.timeZone)
this.color = this.metadata.color
this.metadataVals = Object.keys(this.metadata.metadata).map((k) => {
return { key: k, value: this.metadata.metadata[k] }
})
} else {
this.calcStartDateTime()
this.color = '#003784'
this.metadataVals = []
}
},
createMetadata: function () {
const color = this.color
const metadata = this.metadataVals.reduce((result, element) => {
result[element.key] = element.value
return result
}, {})
const data = { color, metadata }
if (this.timeZone === 'local') {
data.start = new Date(
this.startDate + ' ' + this.startTime,
).toISOString()
} else {
data.start = new Date(
this.startDate + ' ' + this.startTime + 'Z',
).toISOString()
}
if (this.metadata) {
Api.put(`/openc3-api/metadata/${this.metadata.start}`, {
data,
}).then((response) => {
this.$notify.normal({
title: 'Updated Metadata',
body: `Metadata updated: (${response.data.start})`,
})
this.$emit('update', response.data)
this.show = !this.show
})
} else {
Api.post('/openc3-api/metadata', {
data,
}).then((response) => {
this.$notify.normal({
title: 'Created new Metadata',
body: `Metadata: (${response.data.start})`,
})
this.$emit('update', response.data)
this.show = !this.show
})
}
// We don't do the $emit or set show here because it has to be in the callback
},
},
}
</script>
<style scoped>
.v-stepper--vertical .v-stepper__content {
width: auto;
margin: 0px 0px 0px 36px;
padding: 0px;
}
</style>