OpenC3/cosmos

View on GitHub
openc3-cosmos-init/plugins/packages/openc3-cosmos-tool-tlmviewer/src/tools/TlmViewer/NewScreenDialog.vue

Summary

Maintainability
Test Coverage
<!--
# Copyright 2023 OpenC3, Inc.
# 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.
#
# This file may also be used under the terms of a commercial license
# if purchased from OpenC3, Inc.
-->

<template>
  <!-- Dialog for creating new screen -->
  <v-dialog v-model="show" width="600">
    <v-card>
      <v-system-bar>
        <v-spacer />
        <span>Create New Screen</span>
        <v-spacer />
        <v-tooltip top>
          <template v-slot:activator="{ on, attrs }">
            <div v-on="on" v-bind="attrs">
              <v-icon data-test="new-screen-close-icon" @click="show = false">
                mdi-close-box
              </v-icon>
            </div>
          </template>
          <span>Close</span>
        </v-tooltip>
      </v-system-bar>
      <v-card-text>
        <v-alert v-model="duplicateScreenAlert" type="error" dismissible dense>
          Screen {{ newScreenName.toUpperCase() }} already exists!
        </v-alert>
        <v-row class="pt-3">
          <v-col> Screens must belong to a target. Select a target:</v-col>
        </v-row>
        <v-row dense
          ><v-col>
            <v-select
              label="Select Target"
              :items="targets"
              item-text="label"
              item-value="value"
              v-model="selectedTarget"
              @change="targetSelect" /></v-col
        ></v-row>

        <v-row dense>
          <v-col
            >Screens can be auto-generated based on an existing Packet. This
            creates a LABELVALUE line for every item in the packet. The screen
            can then be edited and customized.</v-col
          >
        </v-row>
        <v-row dense>
          <v-col>Leave this blank to start with a blank screen.</v-col>
        </v-row>
        <v-row dense>
          <v-col>
            <v-autocomplete
              label="New screen packet"
              hide-details
              dense
              @change="packetNameChanged"
              :items="packetNames"
              item-text="label"
              item-value="value"
              v-model="selectedPacketName"
              data-test="new-screen-packet"
          /></v-col>
        </v-row>
        <v-row dense>
          <v-col>
            <v-text-field
              v-model="newScreenName"
              flat
              autofocus
              clearable
              label="Screen Name (without .txt)"
              :rules="[rules.required]"
              data-test="new-screen-name"
              @keyup="newScreenKeyup($event)" />
            <div class="pl-2" v-if="newScreenSaving">
              <v-progress-circular indeterminate color="primary" /></div
          ></v-col>
        </v-row>
      </v-card-text>
      <v-divider />
      <v-card-actions>
        <v-spacer />
        <v-btn outlined class="mx-2" @click="show = false"> Cancel </v-btn>
        <v-btn color="primary" class="mx-2" @click="saveNewScreen">
          Save
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script>
import { OpenC3Api } from '@openc3/tool-common/src/services/openc3-api'

export default {
  props: {
    value: Boolean, // value is the default prop when using v-model
    target: {
      type: String,
    },
    screens: {
      type: Object,
    },
  },
  data() {
    return {
      api: null,
      targets: [],
      newScreenSaving: false,
      newScreenName: '',
      duplicateScreenAlert: false,
      packetNames: [],
      selectedTarget: '',
      selectedPacketName: '',
      rules: {
        required: (value) => !!value || 'Required.',
      },
    }
  },
  created() {
    this.api = new OpenC3Api()
    this.duplicateScreenAlert = false
    this.newScreenSaving = false
    this.selectedTarget = this.target
    this.api
      .get_target_names({ params: { scope: window.openc3Scope } })
      .then((targets) => {
        this.targets = targets.filter((item) => item !== 'UNKNOWN')
      })
    this.targetSelect(this.selectedTarget)
  },
  computed: {
    show: {
      get() {
        return this.value
      },
      set(value) {
        this.$emit('input', value) // input is the default event when using v-model
      },
    },
    existingScreens() {
      if (this.screens[this.selectedTarget]) {
        return this.screens[this.selectedTarget].join(', ')
      } else {
        return 'None'
      }
    },
  },
  methods: {
    targetSelect(target) {
      this.selectedTarget = target
      this.api.get_all_tlm_names(this.selectedTarget).then((names) => {
        this.packetNames = names.map((name) => {
          return {
            label: name,
            value: name,
          }
        })
        this.packetNames.unshift({
          label: '[ BLANK ]',
          value: 'BLANK',
        })
      })
    },
    packetNameChanged(value) {
      if (value === 'BLANK') {
        this.newScreenName = ''
        this.duplicateScreenAlert = false
      } else {
        this.newScreenName = value.toLowerCase()
        if (
          this.screens[this.selectedTarget] &&
          this.screens[this.selectedTarget].indexOf(
            this.newScreenName.toUpperCase(),
          ) !== -1
        ) {
          this.duplicateScreenAlert = true
        } else {
          this.duplicateScreenAlert = false
        }
      }
    },
    newScreenKeyup(event) {
      if (
        this.screens[this.selectedTarget] &&
        this.screens[this.selectedTarget].indexOf(
          this.newScreenName.toUpperCase(),
        ) !== -1
      ) {
        this.duplicateScreenAlert = true
      } else {
        this.duplicateScreenAlert = false
        if (event.key === 'Enter') {
          this.saveNewScreen()
        }
      }
    },
    saveNewScreen() {
      if (this.duplicateScreenAlert || this.newScreenName === '') {
        return
      }
      this.newScreenSaving = true
      this.$emit(
        'success',
        this.newScreenName.toUpperCase(),
        this.selectedPacketName,
        this.selectedTarget,
      )
    },
  },
}
</script>

<style scoped>
.v-alert {
  margin-bottom: 0px;
}
</style>