OpenC3/cosmos

View on GitHub
openc3-cosmos-init/plugins/packages/openc3-tool-common/src/tools/admin/tabs/settings/ClassificationBannerSettings.vue

Summary

Maintainability
Test Coverage
<!--
# Copyright 2024 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>
  <v-card>
    <v-card-title>Classification Banner Settings</v-card-title>
    <v-alert v-model="errorLoading" type="error" dismissible dense>
      Error loading previous configuration due to {{ errorText }}
    </v-alert>
    <v-alert v-model="errorSaving" type="error" dismissible dense>
      Error saving due to {{ errorText }}
    </v-alert>
    <v-alert v-model="successSaving" type="success" dismissible dense>
      Saved! (Refresh the page to see changes)
    </v-alert>
    <v-card-text class="pb-0">
      <v-row dense>
        <v-col>
          <v-text-field
            label="Text"
            v-model="text"
            data-test="classification-banner-text"
          />
        </v-col>
      </v-row>
      <v-row dense>
        <v-col>
          <v-select
            label="Background color"
            :items="colors"
            v-model="selectedBackgroundColor"
            data-test="classification-banner-background-color"
          >
            <template v-slot:prepend-inner v-if="selectedBackgroundColor">
              <v-icon :color="selectedBackgroundColor"> mdi-square </v-icon>
            </template>
            <template v-slot:item="data">
              <v-icon
                :color="data.item.value"
                v-if="data.item.value"
                class="pr-1"
              >
                mdi-square
              </v-icon>
              {{ data.item.text }}
            </template>
          </v-select>
        </v-col>
        <v-col>
          <v-text-field
            label="Custom background color"
            :hint="customColorHint"
            :disabled="selectedBackgroundColor !== false"
            v-model="customBackgroundColor"
            :rules="[rules.customColor]"
            data-test="classification-banner-custom-background-color"
          >
            <template v-slot:prepend-inner>
              <v-icon
                v-show="!selectedBackgroundColor"
                :color="customBackgroundColor"
              >
                mdi-square
              </v-icon>
            </template>
          </v-text-field>
        </v-col>
        <v-col>
          <v-select
            label="Font color"
            :items="colors"
            v-model="selectedFontColor"
            data-test="classification-banner-font-color"
          >
            <template v-slot:prepend-inner v-if="selectedFontColor">
              <v-icon v-show="selectedFontColor" :color="selectedFontColor">
                mdi-square
              </v-icon>
            </template>
            <template slot="item" slot-scope="data">
              <v-icon
                v-if="data.item.value"
                :color="data.item.value"
                class="pr-1"
              >
                mdi-square
              </v-icon>
              {{ data.item.text }}
            </template>
          </v-select>
        </v-col>
        <v-col>
          <v-text-field
            label="Custom font color"
            :hint="customColorHint"
            :disabled="selectedFontColor !== false"
            v-model="customFontColor"
            :rules="[rules.customColor]"
            data-test="classification-banner-custom-font-color"
          >
            <template v-slot:prepend-inner>
              <v-icon v-show="!selectedFontColor" :color="customFontColor">
                mdi-square
              </v-icon>
            </template>
          </v-text-field>
        </v-col>
      </v-row>
      <v-row dense>
        <v-col>
          <v-switch
            label="Display top banner"
            v-model="displayTopBanner"
            data-test="display-top-banner"
          />
        </v-col>
        <v-col>
          <v-text-field
            label="Top height"
            :disabled="!displayTopBanner"
            type="number"
            suffix="px"
            v-model="topHeight"
            data-test="classification-banner-top-height"
          />
        </v-col>
        <v-col>
          <v-switch
            label="Display bottom banner"
            v-model="displayBottomBanner"
            data-test="display-bottom-banner"
          />
        </v-col>
        <v-col>
          <v-text-field
            label="Bottom height"
            :disabled="!displayBottomBanner"
            type="number"
            suffix="px"
            v-model="bottomHeight"
            data-test="classification-banner-bottom-height"
          />
        </v-col>
      </v-row>
    </v-card-text>
    <v-card-actions>
      <v-btn
        :disabled="!formValid"
        @click="save"
        color="success"
        text
        data-test="save-classification-banner"
      >
        Save
      </v-btn>
    </v-card-actions>
  </v-card>
</template>

<script>
import Settings from './settings.js'

const settingName = 'classification_banner'
export default {
  mixins: [Settings],
  data() {
    return {
      text: '',
      displayTopBanner: false,
      displayBottomBanner: false,
      topHeight: 0,
      bottomHeight: 0,
      selectedBackgroundColor: 'red',
      customBackgroundColor: '',
      selectedFontColor: 'white',
      customFontColor: '',
      customColorHint: 'Enter a 3 or 6-digit hex color code',
      colors: [
        {
          text: 'Yellow',
          value: 'yellow',
        },
        {
          text: 'Orange',
          value: 'orange',
        },
        {
          text: 'Red',
          value: 'red',
        },
        {
          text: 'Purple',
          value: 'purple',
        },
        {
          text: 'Blue',
          value: 'blue',
        },
        {
          text: 'Green',
          value: 'green',
        },
        {
          text: 'Black',
          value: 'black',
        },
        {
          text: 'White',
          value: 'white',
        },
        {
          text: 'Custom',
          value: false,
        },
      ],
      rules: {
        customColor: (value) => {
          return (
            /^#(?:[0-9a-fA-F]{3}){1,2}$/.test(value) || this.customColorHint
          )
        },
      },
    }
  },
  computed: {
    saveObj: function () {
      return JSON.stringify({
        text: this.text,
        fontColor: this.selectedFontColor || this.customFontColor,
        backgroundColor:
          this.selectedBackgroundColor || this.customBackgroundColor,
        topHeight: this.displayTopBanner ? this.topHeight : 0,
        bottomHeight: this.displayBottomBanner ? this.bottomHeight : 0,
      })
    },
    formValid: function () {
      return (
        (this.selectedFontColor ||
          this.rules.customColor(this.customFontColor) === true) &&
        (this.selectedBackgroundColor ||
          this.rules.customColor(this.customBackgroundColor) === true)
      )
    },
  },
  watch: {
    displayTopBanner: function (val) {
      if (val) {
        this.topHeight = 20
      } else {
        this.topHeight = 0
      }
    },
    displayBottomBanner: function (val) {
      if (val) {
        this.bottomHeight = 20
      } else {
        this.bottomHeight = 0
      }
    },
    customFontColor: function (val) {
      if (val && val.length && !val.startsWith('#')) {
        this.customFontColor = `#${val}`
      }
    },
    customBackgroundColor: function (val) {
      if (val && val.length && !val.startsWith('#')) {
        this.customBackgroundColor = `#${val}`
      }
    },
  },
  created() {
    this.loadSetting(settingName)
  },
  methods: {
    save() {
      this.saveSetting(settingName, this.saveObj)
    },
    parseSetting: function (response) {
      if (response) {
        const parsed = JSON.parse(response)
        this.text = parsed.text
        this.topHeight = parsed.topHeight
        this.bottomHeight = parsed.bottomHeight
        this.displayTopBanner = parsed.topHeight !== 0
        this.displayBottomBanner = parsed.bottomHeight !== 0
        if (parsed.backgroundColor && parsed.backgroundColor.startsWith('#')) {
          this.customBackgroundColor = parsed.backgroundColor
          this.selectedBackgroundColor = false
        } else {
          this.selectedBackgroundColor = parsed.backgroundColor
        }
        if (parsed.fontColor && parsed.fontColor.startsWith('#')) {
          this.customFontColor = parsed.fontColor
          this.selectedFontColor = false
        } else {
          this.selectedFontColor = parsed.fontColor
        }
      }
    },
  },
}
</script>