fix: 修复编辑租住信息的时候有值缺失的问题

fix: 修复编辑租住信息的时候有值缺失的问题

<template>

    <el-tabs v-model="activeName">
      <el-tab-pane
        label="租住列表"
        name="leaseList">

          <el-button
            type="primary"
            :loading="gettingListRefresh"
            @click="getListRefresh">
            刷新
          </el-button>

            <el-input
              v-model="leaseDataSearch"
              placeholder="搜索" />

        <el-dialog
          custom-class="lease-in-dialog"
          top="50px"
          :title="lease.fanghao + lidDialogTitle"
          :visible.sync="leaseInflag"
          :close-on-click-modal="false"
          :key="'leaseIn' + dialogId"
          @closed="onLeaseInDialogClose">
          <el-form
            :model="lease"
            :rules="leaserules"
            ref="leaseIn">
            <el-alert
              type="info"
              :title="'搬出入住/修改：' +
                '计费信息初始化，必须为上次收租结束' +
                '/空置处理结束/本次计费之前，用户自行确认'" />

            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item
                  label="租户姓名"
                  prop="name"
                  :label-width="lidLabelWidth">
                  <el-input
                    v-model="lease.name"
                    auto-complete="off"
                    placeholder="输入租户姓名" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item
                  label="联系方式"
                  prop="call"
                  :label-width="lidLabelWidth">
                  <el-input
                    v-model="lease.call"
                    auto-complete="off"
                    placeholder="输入租户联系方式" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item
                  label="入住时间"
                  prop="addTime"
                  :label-width="lidLabelWidth">
                  <el-date-picker
                    v-model="lease.addTime"
                    type="datetime"
                    placeholder="输入入住时间"
                    style="width: 100%;"
                    :editable="false" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item
                  label="租住周期"
                  prop="leaserange"
                  :label-width="lidLabelWidth">
                  <el-date-picker
                    v-model="lease.leaserange"
                    type="daterange"
                    placeholder="选择日期范围"
                    align="right"
                    :picker-options="leasePickerOptions"
                    :editable="false" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item
                  label="交租时间"
                  prop="payDay"
                  :label-width="lidLabelWidth">
                  <el-select
                    v-model="lease.payDay"
                    placeholder="选择交租时间"
                    prop="payDay">
                    <el-option
                      :label="n + '日'"
                      :value="n"
                      v-for="n in 31"
                      :key="n" />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item
                  label="交租方式"
                  prop="payType"
                  :label-width="lidLabelWidth">
                  <el-select
                    v-model="lease.payType"
                    placeholder="选择交租方式">
                    <el-option
                      :label="item"
                      :value="index"
                      v-for="(item, index) in payTypeVal"
                      :key="index" />
                  </el-select>
                </el-form-item>
              </el-col>
            </el-row>
            <el-row :gutter="20">
              <el-col :span="24">
                <el-form-item
                  label="备注"
                  :label-width="lidLabelWidth">
                  <el-input
                    v-model="lease.remark"
                    auto-complete="off"
                    placeholder="备注" />
                </el-form-item>
              </el-col>
            </el-row>

            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item
                  label="水费低消"
                  prop="calWaterPrice.minPrice"
                  :label-width="lidLabelWidth">
                  <el-input
                    v-model.number="lease.calWaterPrice.minPrice"
                    auto-complete="off"
                    placeholder="输入最低消费">
                    <template slot="append">
                      吨
                    </template>
                  </el-input>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item
                  label="水费方式"
                  :label-width="lidLabelWidth">
                  <el-radio
                    v-model="lease.calWaterPrice.calType"
                    label="single">
                    单一价格
                  </el-radio>
                  <el-radio
                    v-model="lease.calWaterPrice.calType"
                    label="step">
                    阶梯价格
                  </el-radio>
                </el-form-item>
              </el-col>
            </el-row>

            <el-form-item
              label="水费单价"
              prop="calWaterPrice.singlePrice"
              :label-width="lidLabelWidth"
              :rules="leaserules[`calWaterPrice.singlePrice`][0]"
              v-if="lease.calWaterPrice.calType == 'single'"
              key="watSingle">
              <el-col :span="24">
                <el-input
                  v-model.number="lease.calWaterPrice.singlePrice"
                  auto-complete="off"
                  placeholder="输入单价">
                  <template slot="prepend">
                    ￥
                  </template>
                  <template slot="append">
                    元/吨
                  </template>
                </el-input>
              </el-col>
            </el-form-item>

              <el-form-item
                required
                :label="'阶梯' + (index + 1)"
                :label-width="lidLabelWidth"
                v-for="(step, index) in lease.calWaterPrice.stepPrice"
                :key="'calWaterPrice' + index"
                :ref="'calWaterPrice' + index">
                <el-col :span="10">
                  <el-form-item
                    :prop="'calWaterPrice.stepPrice.' + index + '.step'"
                    :rules="{
                      type: 'number', required: true, message: '请填写', trigger: 'blur'
                    }">
                    <el-input
                      v-model.number="step.step"
                      auto-complete="off"
                      placeholder="本阶梯最大值">
                      <template slot="append">
                        吨
                      </template>
                    </el-input>
                  </el-form-item>
                </el-col>
                <el-col
                  class="line"
                  :span="1" />
                <el-col :span="9">
                  <el-form-item
                    :prop="'calWaterPrice.stepPrice.' + index + '.price'"
                    :rules="{
                      type: 'number', required: true, message: '请填写', trigger: 'blur'
                    }">
                    <el-input
                      v-model.number="step.price"
                      auto-complete="off"
                      placeholder="本阶梯单价">
                      <template slot="prepend">
                        ￥
                      </template>
                      <template slot="append">
                        元
                      </template>
                    </el-input>
                  </el-form-item>
                </el-col>
                <el-col
                  class="line"
                  :span="1" />
                <el-col
                  class="step-btn"
                  :span="3">
                  <el-button
                    @click.prevent="removeStep(lease.calWaterPrice, step)">
                    删除
                  </el-button>
                </el-col>
              </el-form-item>

            <el-form-item
              :label-width="lidLabelWidth"
              v-if="lease.calWaterPrice.calType == 'step'"
              key="watStep">
              <el-button
                type="primary"
                @click="addStep(lease.calWaterPrice)">
                新增阶梯
              </el-button>
            </el-form-item>

            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item
                  label="电费低消"
                  prop="calElePrice.minPrice"
                  :label-width="lidLabelWidth">
                  <el-input
                    v-model.number="lease.calElePrice.minPrice"
                    auto-complete="off"
                    placeholder="输入最低消费">
                    <template slot="append">
                      度
                    </template>
                  </el-input>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item
                  label="电费方式"
                  :label-width="lidLabelWidth">
                  <el-radio
                    v-model="lease.calElePrice.calType"
                    label="single">
                    单一价格
                  </el-radio>
                  <el-radio
                    v-model="lease.calElePrice.calType"
                    label="step">
                    阶梯价格
                  </el-radio>
                </el-form-item>
              </el-col>
            </el-row>

            <el-form-item
              prop="calElePrice.singlePrice"
              label="电费单价"
              :rules="leaserules[`calElePrice.singlePrice`][0]"
              :label-width="lidLabelWidth"
              v-if="lease.calElePrice.calType == 'single'"
              key="eleSingle">
              <el-col :span="24">
                <el-input
                  v-model.number="lease.calElePrice.singlePrice"
                  auto-complete="off"
                  placeholder="输入单价">
                  <template slot="prepend">
                    ￥
                  </template>
                  <template slot="append">
                    元/度
                  </template>
                </el-input>
              </el-col>
            </el-form-item>

              <el-form-item
                required
                :label="'阶梯' + (index + 1)"
                :label-width="lidLabelWidth"
                v-for="(step, index) in lease.calElePrice.stepPrice"
                :key="'calElePrice' + index"
                :ref="'calElePrice' + index">
                <el-col :span="10">
                  <el-form-item
                    :prop="'calElePrice.stepPrice.' + index + '.step'"
                    :rules="{
                      type: 'number', required: true, message: '请填写', trigger: 'blur'
                    }">
                    <el-input
                      v-model.number="step.step"
                      auto-complete="off"
                      placeholder="本阶梯最大值">
                      <template slot="append">
                        度
                      </template>
                    </el-input>
                  </el-form-item>
                </el-col>
                <el-col
                  class="line"
                  :span="1" />
                <el-col :span="9">
                  <el-form-item
                    :prop="'calElePrice.stepPrice.' + index + '.price'"
                    :rules="{
                      type: 'number', required: true, message: '请填写', trigger: 'blur'
                    }">
                    <el-input
                      v-model.number="step.price"
                      auto-complete="off"
                      placeholder="本阶梯单价">
                      <template slot="prepend">
                        ￥
                      </template>
                      <template slot="append">
                        元
                      </template>
                    </el-input>
                  </el-form-item>
                </el-col>
                <el-col
                  class="line"
                  :span="1" />
                <el-col
                  class="step-btn"
                  :span="3">
                  <el-button @click.prevent="removeStep(lease.calElePrice, step)">
                    删除
                  </el-button>
                </el-col>
              </el-form-item>

            <el-form-item
              :label-width="lidLabelWidth"
              v-if="lease.calElePrice.calType == 'step'"
              key="eleStep">
              <el-button
                type="primary"
                @click="addStep(lease.calElePrice)">
                新增阶梯
              </el-button>
            </el-form-item>

            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item
                  label="燃气费低消"
                  prop="calGasPrice.minPrice"
                  :label-width="lidLabelWidth">
                  <el-input
                    v-model.number="lease.calGasPrice.minPrice"
                    auto-complete="off"
                    placeholder="输入最低消费">
                    <template slot="append">
                      方
                    </template>
                  </el-input>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item
                  label="燃气费方式"
                  :label-width="lidLabelWidth">
                  <el-radio
                    v-model="lease.calGasPrice.calType"
                    label="single">
                    单一价格
                  </el-radio>
                  <el-radio
                    v-model="lease.calGasPrice.calType"
                    label="step">
                    阶梯价格
                  </el-radio>
                </el-form-item>
              </el-col>
            </el-row>

            <el-form-item
              label="燃气费单价"
              prop="calGasPrice.singlePrice"
              :label-width="lidLabelWidth"
              :rules="leaserules[`calGasPrice.singlePrice`][0]"
              v-if="lease.calGasPrice.calType == 'single'"
              key="watSingle">
              <el-col :span="24">
                <el-input
                  v-model.number="lease.calGasPrice.singlePrice"
                  auto-complete="off"
                  placeholder="输入单价">
                  <template slot="prepend">
                    ￥
                  </template>
                  <template slot="append">
                    元/方
                  </template>
                </el-input>
              </el-col>
            </el-form-item>

              <el-form-item
                required
                :label="'阶梯' + (index + 1)"
                :label-width="lidLabelWidth"
                v-for="(step, index) in lease.calGasPrice.stepPrice"
                :key="'calGasPrice' + index"
                :ref="'calGasPrice' + index">
                <el-col :span="10">
                  <el-form-item
                    :prop="'calGasPrice.stepPrice.' + index + '.step'"
                    :rules="{
                      type: 'number', required: true, message: '请填写', trigger: 'blur'
                    }">
                    <el-input
                      v-model.number="step.step"
                      auto-complete="off"
                      placeholder="本阶梯最大值">
                      <template slot="append">
                        方
                      </template>
                    </el-input>
                  </el-form-item>
                </el-col>
                <el-col
                  class="line"
                  :span="1" />
                <el-col :span="9">
                  <el-form-item
                    :prop="'calGasPrice.stepPrice.' + index + '.price'"
                    :rules="{
                      type: 'number', required: true, message: '请填写', trigger: 'blur'
                    }">
                    <el-input
                      v-model.number="step.price"
                      auto-complete="off"
                      placeholder="本阶梯单价">
                      <template slot="prepend">
                        ￥
                      </template>
                      <template slot="append">
                        元
                      </template>
                    </el-input>
                  </el-form-item>
                </el-col>
                <el-col
                  class="line"
                  :span="1" />
                <el-col
                  class="step-btn"
                  :span="3">
                  <el-button
                    @click.prevent="removeStep(lease.calGasPrice, step)">
                    删除
                  </el-button>
                </el-col>
              </el-form-item>

            <el-form-item
              :label-width="lidLabelWidth"
              v-if="lease.calGasPrice.calType == 'step'"
              key="watStep">
              <el-button
                type="primary"
                @click="addStep(lease.calGasPrice)">
                新增阶梯
              </el-button>
            </el-form-item>

            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item
                  label="押金"
                  prop="deposit"
                  :label-width="lidLabelWidth">
                  <el-input
                    v-model.number="lease.deposit"
                    auto-complete="off"
                    placeholder="输入押金">
                    <template slot="prepend">
                      ￥
                    </template>
                    <template slot="append">
                      元
                    </template>
                  </el-input>
                </el-form-item>
              </el-col>

              <el-col :span="12">
                <el-form-item
                  label="租金(月)"
                  prop="rent"
                  :label-width="lidLabelWidth">
                  <el-input
                    v-model.number="lease.rent"
                    auto-complete="off"
                    placeholder="输入租金">
                    <template slot="prepend">
                      ￥
                    </template>
                    <template slot="append">
                      元/月
                    </template>
                  </el-input>
                </el-form-item>
              </el-col>
            </el-row>
          </el-form>

            <el-button
              :loading="gettingLeaseIn"
              @click="getLeaseInDialog">
              取消
            </el-button>
            <el-button
              type="primary"
              :loading="gettingLeaseIn"
              @click="getLeaseIn">
              确定
            </el-button>

        </el-dialog>

        <el-dialog
          custom-class="lease-out-dialog small"
          :title="out.fanghao + lodDialogTitle"
          :visible.sync="leaseOutflag"
          :close-on-click-modal="false"
          :key="'leaseOut' + dialogId"
          @closed="onLeaseOutDialogClose">
          <el-form
            :model="out"
            :rules="outrules"
            ref="leaseOut">
            <el-alert
              title="确认已经结清所有费用？此行为不可撤销"
              type="info" />
            <el-form-item
              label="搬出时间"
              prop="outTime"
              :label-width="lodLabelWidth">
              <el-date-picker
                v-model="out.outTime"
                type="datetime"
                placeholder="输入搬出时间"
                style="width: 100%;"
                :editable="false" />
            </el-form-item>
          </el-form>

            <el-button
              :loading="gettingLeaseOut"
              @click="getLeaseOutDialog">
              取消
            </el-button>
            <el-button
              type="primary"
              :loading="gettingLeaseOut"
              @click="getLeaseOut">
              确定
            </el-button>

        </el-dialog>

        <el-table
          v-loading.body="gettingListRefresh"
          class="lease-table"
          stripe
          border
          :max-height="tableMaxHeight"
          :data="filterLeaseData"
          ref="leaseTable">
          <el-table-column
            type="expand">
            <template slot-scope="props">
              <el-form
                class="table-expand"
                label-position="left"
                inline>
                <el-form-item
                  prop="leaseId.name"
                  label="姓名/联系方式"
                  width="150">
                  <template>
                    {{ props.row.leaseId.name || '--' }}
                    /
                    {{ props.row.leaseId.call || '--' }}
                  </template>
                </el-form-item>
                <el-form-item
                  prop="leaseId.addTime"
                  label="入住时间"
                  width="180">
                  <template>
                    {{ getTime(props.row.leaseId.addTime) }}
                  </template>
                </el-form-item>
                <el-form-item
                  style="width: 100%;"
                  prop="leaseId.leaserange"
                  label="租住周期"
                  width="180">
                  <template>
                    {{ getTime(props.row.leaseId.leaserange && props.row.leaseId.leaserange[0]) }}
                    ~
                    {{ getTime(props.row.leaseId.leaserange && props.row.leaseId.leaserange[1]) }}
                  </template>
                </el-form-item>
              </el-form>
            </template>
          </el-table-column>
          <el-table-column
            prop="fanghao"
            label="房屋"
            width="120" />
          <el-table-column
            label="计费信息">
            <el-table-column
              label="当前租金/押金"
              width="170">
              <template slot-scope="scope">

                  租金：￥

                    {{ (scope.row.leaseId.rent || 0) }}

                  元/月

                  押金：￥
                  {{ scope.row.leaseId.deposit || 0 }}
                  元

              </template>
            </el-table-column>
            <el-table-column
              label="水费"
              width="150">
              <template slot-scope="scope">

              </template>
            </el-table-column>
            <el-table-column
              label="电费"
              width="150">
              <template slot-scope="scope">

              </template>
            </el-table-column>
            <el-table-column
              label="燃气费"
              width="150">
              <template slot-scope="scope">

              </template>
            </el-table-column>
          </el-table-column>
          <el-table-column label="租户信息">
            <el-table-column
              prop="leaseId.payDay"
              label="交租时间/交租方式"
              width="180">
              <template slot-scope="scope">

                  {{
                    scope.row.leaseId.payDay
                      ? `每月${scope.row.leaseId.payDay}日`
                      : '--'
                  }}

                  {{ payTypeVal[scope.row.leaseId.payType] || '--' }}

              </template>
            </el-table-column>
            <el-table-column
              prop="leaseId.remark"
              label="备注">
              <template slot-scope="scope">

              </template>
            </el-table-column>
          </el-table-column>
          <el-table-column
            label="操作"
            width="235">
            <template slot-scope="scope">
              <el-button
                size="small"
                type="primary"
                @click="getLeaseHistory(scope.$index, scope.row)">
                历史
              </el-button>
              <el-button
                size="small"
                type="primary"
                @click="getLeaseInDialog(scope.$index, scope.row)">
                {{ scope.row.leaseId._id ? '修改' : '入住' }}
              </el-button>
              <el-button
                size="small"
                type="danger"
                v-if="scope.row.leaseId._id"
                @click="getLeaseOutDialog(scope.$index, scope.row)">
                搬出
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-tab-pane>

      <el-tab-pane
        label="当前租金统计"
        name="leaseCount">
        <collapse-rent-count-item
          :fang="fang"
          :fangi="fangi"
          :active-rent-count="activeLeaseCount"
          v-for="(fang, fangi) in leaseCount"
          :key="fangi" />

        <el-alert
          title="暂无数据！请先处理入住状态"
          type="info"
          :closable="false"
          v-if="!leaseData.length" />
      </el-tab-pane>
    </el-tabs>

</template>


fix dialog styles

fix dialog styles

<template>
  <veui-overlay class="veui-dialog"
    :open="localOpen"
    mode="NORMAL"
    :overlay-class="mergedOverlayClass"
    :ui="ui"
    ref="overlay">

        <slot name="title">弹窗标题</slot>
        <icon name="close"></icon>

<slot></slot>

<slot name="foot"><veui-button ui="primary" @click="$emit('ok')">确定</veui-button><veui-button @click="$emit('cancel')">取消</veui-button></slot>

  </veui-overlay>
</template>


CodeMirror の高さ調整

CodeMirror の高さ調整

<template>
  <div :style="{height: height}">
    <codemirror :value="text" :options="options" @ready="onReady" @input="onChange"></codemirror>
  </div>
</template>

<script>
/* @flow */

import { codemirror } from 'vue-codemirror'
import 'codemirror/keymap/sublime.js'
import 'codemirror/keymap/vim.js'
import 'codemirror/keymap/emacs.js'
import 'codemirror/addon/selection/active-line.js'
import '../lib/codemirror/mode/plantuml/plantuml.js'

import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/solarized.css'

export default {
  components: {
    codemirror
  },
  name: 'editor',
  props: {
    height: {
      type: String,
      default: '100%'
    }
  },
  computed: {
    text (): string {
      return this.$store.state.plantumlEditor.text
    },
    options (): any {
      return this.$store.state.plantumlEditor.codemirrorOptions
    }
  },
  data (): any {
    return {
      codemirror: null
    }
  },
  methods: {
    onReady (codemirror: any) {
      this.codemirror = codemirror
      this.addKeymap()
      setTimeout(() => {
        this.codemirror.setSize('100%', 'calc(100% - 2px)')
      })
    },
    onChange (text: string) {
      this.$store.dispatch('syncText', text)
    },
    addKeymap () {
      const map: {key?: string, callback?: Function} = {}
      map[this.$store.state.plantumlEditor.renderUMLKey.win] = () => {
        this.$store.dispatch('renderUML', this.$store.state.plantumlEditor.text)
      }
      map[this.$store.state.plantumlEditor.renderUMLKey.mac] = () => {
        this.$store.dispatch('renderUML', this.$store.state.plantumlEditor.text)
      }
      this.codemirror.setOption('extraKeys', map)
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.vue-codemirror {
  height: 100%;
}
</style>

<template>
  <div :style="{height: height}">
    <codemirror :value="text" :options="options" @ready="onReady" @input="onChange"></codemirror>
  </div>
</template>

<script>
/* @flow */

import { codemirror } from 'vue-codemirror'
import 'codemirror/keymap/sublime.js'
import 'codemirror/keymap/vim.js'
import 'codemirror/keymap/emacs.js'
import 'codemirror/addon/selection/active-line.js'
import '../lib/codemirror/mode/plantuml/plantuml.js'

import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/solarized.css'

export default {
  components: {
    codemirror
  },
  name: 'editor',
  props: {
    height: {
      type: String,
      default: '100%'
    }
  },
  computed: {
    text (): string {
      return this.$store.state.plantumlEditor.text
    },
    options (): any {
      return this.$store.state.plantumlEditor.codemirrorOptions
    }
  },
  data (): any {
    return {
      codemirror: null
    }
  },
  methods: {
    onReady (codemirror: any) {
      this.codemirror = codemirror
      this.addKeymap()
      setTimeout(() => {
        this.codemirror.setSize('100%', '100%')
      })
    },
    onChange (text: string) {
      this.$store.dispatch('syncText', text)
    },
    addKeymap () {
      const map: {key?: string, callback?: Function} = {}
      map[this.$store.state.plantumlEditor.renderUMLKey.win] = () => {
        this.$store.dispatch('renderUML', this.$store.state.plantumlEditor.text)
      }
      map[this.$store.state.plantumlEditor.renderUMLKey.mac] = () => {
        this.$store.dispatch('renderUML', this.$store.state.plantumlEditor.text)
      }
      this.codemirror.setOption('extraKeys', map)
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.vue-codemirror,
.CodeMirror {
  height: 100%;
}
</style>


Fix issue with selected region change

Fix issue with selected region change

<template>

            <choropleth></choropleth>

            <time-chart></time-chart>

</template>


Use aria-label to improve component accessibility

<template>

        {{ getOptionLabel(option) }}
        <button v-if="multiple" @click="deselect(option)" type="button" class="close" aria-label="Remove option">
          ×
        </button>

      <input
              ref="search"
              v-model="search"
              @keydown.delete="maybeDeleteValue"
              @keyup.esc="onEscape"
              @keydown.up.prevent="typeAheadUp"
              @keydown.down.prevent="typeAheadDown"
              @keyup.enter.prevent="typeAheadSelect"
              @blur="onSearchBlur"
              @focus="onSearchFocus"
              type="search"
              class="form-control"
              :placeholder="searchPlaceholder"
              :readonly="!searchable"
              :style="{ width: isValueEmpty ? '100%' : 'auto' }"
              :id="inputId"
              aria-label="Search for option"
      >

      <slot name="spinner">

Loading...

      </slot>

    <transition :name="transition">

            {{ getOptionLabel(option) }}

          <slot name="no-options">Sorry, no matching options.</slot>

    </transition>

</template>

<template>

        {{ getOptionLabel(option) }}
        <button v-if="multiple" @click="deselect(option)" type="button" class="close">
          ×
        </button>

      <input
              ref="search"
              v-model="search"
              @keydown.delete="maybeDeleteValue"
              @keyup.esc="onEscape"
              @keydown.up.prevent="typeAheadUp"
              @keydown.down.prevent="typeAheadDown"
              @keyup.enter.prevent="typeAheadSelect"
              @blur="onSearchBlur"
              @focus="onSearchFocus"
              type="search"
              class="form-control"
              :placeholder="searchPlaceholder"
              :readonly="!searchable"
              :style="{ width: isValueEmpty ? '100%' : 'auto' }"
              :id="inputId"
      >

      <slot name="spinner">

Loading...

      </slot>

    <transition :name="transition">

            {{ getOptionLabel(option) }}

          <slot name="no-options">Sorry, no matching options.</slot>

    </transition>

</template>


修复注册小组名称未更新问题

修复注册小组名称未更新问题

<template>

            <FormItem prop="name">

            </FormItem>
            <FormItem prop="pwd">

            </FormItem>
            <FormItem prop="email">

            </FormItem>
            <Form-item v-if="groups.length">

                {{ item.name }}

            </Form-item>
            <FormItem style="text-align:center;">
              <ButtonGroup>
                注册并登录
                已有账号，去登录
              </ButtonGroup>
            </FormItem>

</template>


LITE: UI: Fix phrase display

LITE: UI: Fix phrase display

<template>

      {{ $t("common.enter_your_password") }}
      {{ $t("common.important") }}

    <gulden-form-field :title="$t('common.password')" v-if="current === 1">
      <input
        ref="password"
        type="password"
        v-model="password"
        @keydown="getRecoveryPhraseOnEnter"
        :class="computedStatus"
      />
    </gulden-form-field>

{{ $t("setup.this_is_your_recovery_phrase") }}

      <gulden-section class="phrase">
        {{ recoveryPhrase }}
      </gulden-section>

    <portal to="footer-slot">
      <gulden-button-section>
        <button
          v-if="current === 1"
          @click="getRecoveryPhrase"
          :disabled="isNextDisabled"
        >
          {{ $t("buttons.next") }}
        </button>
      </gulden-button-section>
    </portal>

</template>


load 中に video player が操作できるように変更

load 中に video player が操作できるように変更

<template>

                <v-progress-circular :size="50" color="primary" indeterminate></v-progress-circular>

                <transition name="fade">

                            <v-btn v-if="duration > 0" class="add-shadow mx-4" icon dark v-on:click="rewindTime(30)">
                                <v-icon dark>mdi-rewind-30</v-icon>
                            </v-btn>
                            <v-btn v-if="duration > 0" class="add-shadow mx-4" icon dark v-on:click="rewindTime(10)">
                                <v-icon dark>mdi-rewind-10</v-icon>
                            </v-btn>
                            <v-btn class="play-button add-shadow mx-4" icon dark v-on:click="togglePlay">
                                <v-icon v-if="isPause === true" dark>mdi-play</v-icon>
                                <v-icon v-else dark>mdi-pause</v-icon>
                            </v-btn>
                            <v-btn v-if="duration > 0" class="add-shadow mx-4" icon dark v-on:click="forwardTime(10)">
                                <v-icon dark>mdi-fast-forward-10</v-icon>
                            </v-btn>
                            <v-btn v-if="duration > 0" class="add-shadow mx-4" icon dark v-on:click="forwardTime(30)">
                                <v-icon dark>mdi-fast-forward-30</v-icon>
                            </v-btn>

                        <v-btn
                            v-if="isEnabledRotation === true && isFullscreen === true"
                            class="rotation-button"
                            icon
                            dark
                            v-on:click="clickRotationButton"
                        >
                            <v-icon dark>mdi-screen-rotation</v-icon>
                        </v-btn>

 0"
                            class="d-flex flex-column align-center left-buttons"
                            v-on:click="stopPropagation"
                        >
                            <v-btn class="add-shadow" icon dark v-on:click="speedUp">
                                <v-icon dark>mdi-plus-circle</v-icon>
                            </v-btn>
                            <v-btn class="add-shadow my-2" text dark v-on:click="resetSpeed">
                                x{{ playbackRate.toFixed(1) }}
                            </v-btn>
                            <v-btn class="add-shadow" icon dark v-on:click="speedDown">
                                <v-icon dark>mdi-minus-circle</v-icon>
                            </v-btn>

                                <v-slider
                                    class="slider"
                                    v-model="currentTime"
                                    :max="duration"
                                    color="white"
                                    track-color="grey"
                                    :disabled="duration === 0"
                                    v-on:start="startChangeCurrentPosition"
                                    v-on:change="endChangeCurrentPosition"
                                    v-on:input="updateCurrentPosition"
                                ></v-slider>

                                    <v-btn class="play" icon dark v-on:click="togglePlay">
                                        <v-icon v-if="isPause === true">mdi-play</v-icon>
                                        <v-icon v-else>mdi-pause</v-icon>
                                    </v-btn>

                                        <v-btn icon dark v-on:click="switchMute">
                                            <v-icon v-if="volume > 0.4">mdi-volume-high</v-icon>
                                            <v-icon v-else-if="volume > 0.0">mdi-volume-medium</v-icon>
                                            <v-icon v-else>mdi-volume-off</v-icon>
                                        </v-btn>
                                        <v-slider
                                            class="slider"
                                            v-if="isHideAudioVolume === false"
                                            v-model="volume"
                                            min="0.0"
                                            max="1.0"
                                            step="0.1"
                                            color="white"
                                            track-color="grey"
                                            v-on:input="changeVolume"
                                            v-on:change="updateLastSeekTime"
                                        ></v-slider>

                                        {{ currentTimeStr }}
                                        /
                                        {{ durationStr }}

                                    <v-spacer></v-spacer>
                                    <v-btn v-if="isEnabledSubtitles === true" icon dark>
                                        <v-icon>mdi-subtitles</v-icon>
                                    </v-btn>
                                    <v-btn v-if="this.isEnabledPip === true" icon dark v-on:click="switchPip">
                                        <v-icon>mdi-picture-in-picture-bottom-right</v-icon>
                                    </v-btn>
                                    <v-btn icon dark v-on:click="switchFullScreen">
                                        <v-icon v-if="isFullscreen === false">mdi-fullscreen</v-icon>
                                        <v-icon v-else>mdi-fullscreen-exit</v-icon>
                                    </v-btn>

                </transition>

            <NormalVideo
                v-if="videoParam.type == 'Normal'"
                ref="video"
                v-bind:videoSrc.sync="videoParam.src"
                v-on:timeupdate="onTimeupdate"
                v-on:waiting="onWaiting"
                v-on:loadeddata="onLoadeddata"
                v-on:canplay="onCanplay"
                v-on:ended="onEnded"
                v-on:play="onPlay"
                v-on:pause="onPause"
                v-on:ratechange="onChangePlaybackRate"
                v-on:volumechange="onVolumechange"
            ></NormalVideo>
            <LiveHLSVideo
                v-if="videoParam.type == 'LiveHLS'"
                ref="video"
                v-bind:channelId="videoParam.channelId"
                v-bind:mode="videoParam.mode"
                v-on:timeupdate="onTimeupdate"
                v-on:waiting="onWaiting"
                v-on:loadeddata="onLoadeddata"
                v-on:canplay="onCanplay"
                v-on:ended="onEnded"
                v-on:play="onPlay"
                v-on:pause="onPause"
                v-on:ratechange="onChangePlaybackRate"
                v-on:volumechange="onVolumechange"
            ></LiveHLSVideo>
            <RecordedStreamingVideo
                v-if="videoParam.type == 'RecordedStreaming'"
                ref="video"
                v-bind:recordedId="videoParam.recordedId"
                v-bind:videoFileId="videoParam.videoFileId"
                v-bind:streamingType="videoParam.streamingType"
                v-bind:mode="videoParam.mode"
                v-on:timeupdate="onTimeupdate"
                v-on:waiting="onWaiting"
                v-on:loadeddata="onLoadeddata"
                v-on:canplay="onCanplay"
                v-on:ended="onEnded"
                v-on:play="onPlay"
                v-on:pause="onPause"
                v-on:ratechange="onChangePlaybackRate"
                v-on:volumechange="onVolumechange"
            ></RecordedStreamingVideo>

</template>


Make loading spinner not move all messages

Signed-off-by: Jan-Christoph Borchardt <7f550a9f4c44173a37664d938f1355f0f92a47a7@jancborchardt.net>

<template>

		<transition-group name="list">

			<Envelope
				v-for="env in envelopes"
				:key="env.uid"
				:data="env"
				:folder="folder"
				@delete="$emit('delete', env.uid)"
			/>

		</transition-group>

</template>


Simplify GroupMap

Simplify GroupMap

<template>

    <v-map :zoom="zoom" :bounds="bounds" :center="center">
      <v-tile-layer :url="url" :attribution="attribution"></v-tile-layer>
      <v-marker v-for="marker in markers" :key="marker.id" :lat-lng="marker.latLng" :icon="marker.icon">
        <v-popup :content="marker.popupcontent"></v-popup>
      </v-marker>
    </v-map>

</template>

<template>

    <v-map :zoom="zoom" :bounds="bounds" :center="center">
      <v-tile-layer :url="url" :attribution="attribution"></v-tile-layer>
      <v-marker v-for="marker in storeMarkers" :key="marker.id" :lat-lng="marker.latLng" :icon="marker.icon">
        <v-popup :content="marker.popupcontent"></v-popup>
      </v-marker>
      <v-marker v-for="marker in userMarkers" :key="marker.id" :lat-lng="marker.latLng" :icon="marker.icon">
        <v-popup :content="marker.popupcontent"></v-popup>
      </v-marker>
    </v-map>

</template>


fix(QrcodeStream): iOS 15 won't render camera

When a camera stream is loaded, we assign the stream to a `video`
element via `video.srcObject`. At this point the element is hidden with
`v-show="false"` aka. `display: none`. We do that because at this point
the videos dimensions are not known yet. We have to wait for the
`loadeddata` event first. Only after that event we display the video
element. Otherwise the elements size awkwardly flickers.

However, it appears since iOS 15 all iOS browsers won't properly render
the video element if the `video.srcObject` was assigned *while* the
element was hidden with `display: none`. Using `visibility: hidden`
instead seems to have fixed the problem though.

Issue: #264 #266

<template lang="html">

    <video
      ref="video"
      :class="{ 'qrcode-stream-camera--hidden': !shouldScan }"
      class="qrcode-stream-camera"
      autoplay
      muted
      playsinline
    ></video>

    <canvas
      ref="pauseFrame"
      v-show="!shouldScan"
      class="qrcode-stream-camera"
    ></canvas>

    <canvas ref="trackingLayer" class="qrcode-stream-overlay"></canvas>

      <slot></slot>

</template>

<template lang="html">

    <video
      ref="video"
      v-show="shouldScan"
      class="qrcode-stream-camera"
      autoplay
      muted
      playsinline
    ></video>

    <canvas
      ref="pauseFrame"
      v-show="!shouldScan"
      class="qrcode-stream-camera"
    ></canvas>

    <canvas ref="trackingLayer" class="qrcode-stream-overlay"></canvas>

      <slot></slot>

</template>


togglebutton: fixed util path

togglebutton: fixed util path

<template>
  <a :class="['btn', type]" href="javascript:void(0)" @click="active = !active">
    <span :class="['glyphicon','glyphicon-'+(value?'ok':'remove')]"></span>
    <slot></slot>
    <input v-if="name" type="hidden" :name="name" :value="active?1:0" />
  </a>
</template>

<script>
import {coerce} from './utils/utils.js'

export default {
  props: {
    isTrue: {default: 'primary'},
    isFalse: {default: null},
    name: null,
    value: false
  },
  data () {
    var active = coerce.boolean(this.value)
    return {
      active,
      types: {
        danger: 'btn-danger',
        info: 'btn-info',
        primary: 'btn-primary',
        success: 'btn-success',
        warning: 'btn-warning'
      }
    }
  },
  watch: {
    active (val, old) {
      if (val !== old) {
        this.$emit('changed', val)
        this.$emit(val ? 'enabled' : 'disabled')
        this.$emit('input', val)
      }
    },
    value (val, old) {
      if (val !== old) {
        this.active = coerce.boolean(this.value)
      }
    }
  },
  computed: {
    type () { return this.types[this.value ? this.isTrue : this.isFalse] || 'btn-default' }
  }
}
</script>

<template>
  <a :class="['btn', type]" href="javascript:void(0)" @click="active = !active">
    <span :class="['glyphicon','glyphicon-'+(value?'ok':'remove')]"></span>
    <slot></slot>
    <input v-if="name" type="hidden" :name="name" :value="active?1:0" />
  </a>
</template>

<script>
import {coerce} from './vuestrap/utils/utils.js'

export default {
  props: {
    isTrue: {default: 'primary'},
    isFalse: {default: null},
    name: null,
    value: false
  },
  data () {
    var active = coerce.boolean(this.value)
    return {
      active,
      types: {
        danger: 'btn-danger',
        info: 'btn-info',
        primary: 'btn-primary',
        success: 'btn-success',
        warning: 'btn-warning'
      }
    }
  },
  watch: {
    active (val, old) {
      if (val !== old) {
        this.$emit('changed', val)
        this.$emit(val ? 'enabled' : 'disabled')
        this.$emit('input', val)
      }
    },
    value (val, old) {
      if (val !== old) {
        this.active = coerce.boolean(this.value)
      }
    }
  },
  computed: {
    type () { return this.types[this.value ? this.isTrue : this.isFalse] || 'btn-default' }
  }
}
</script>


Remove unneeded import

Remove unneeded import

<script setup>
import { useCssModule } from 'vue';

const props = defineProps({
    tag: {
      type: String,
      default: 'article',
    }
})

const baseClass = 'cdr-card';
const style = useCssModule();
</script>

<template>
  <component
    :is="tag"
    :class="style[baseClass]"
  >
    <slot />
  </component>
</template>

<style lang="scss" module src="./styles/CdrCard.module.scss">
</style>

<script setup>
import { useCssModule, defineProps } from 'vue';

const props = defineProps({
    tag: {
      type: String,
      default: 'article',
    }
})

const baseClass = 'cdr-card';
const style = useCssModule();
</script>

<template>
  <component
    :is="tag"
    :class="style[baseClass]"
  >
    <slot />
  </component>
</template>

<style lang="scss" module src="./styles/CdrCard.module.scss">
</style>


feat: [Request] QModal to support Array syntax for content-css and content-classes #856

<template>
  <q-transition :name="modalTransition" :enter="enterClass" :leave="leaveClass">
    <div
      v-show="active"
      class="modal fullscreen row"
      :class="modalClasses"
      @mousedown="__dismiss()"
      @touchstart="__dismiss()"
    >
      <div
        ref="content"
        class="modal-content scroll"
        @mousedown.stop
        @touchstart.stop
        :style="modalCss"
        :class="contentClasses"
      >
        <slot></slot>
      </div>
    </div>
  </q-transition>
</template>

<script>
import Platform from '../../features/platform'
import EscapeKey from '../../features/escape-key'
import extend from '../../utils/extend'
import { QTransition } from '../transition'

const positions = {
  top: 'items-start justify-center with-backdrop',
  bottom: 'items-end justify-center with-backdrop',
  right: 'items-center justify-end with-backdrop',
  left: 'items-center justify-start with-backdrop'
}
const positionCSS = {
  mat: {
    maxHeight: '80vh',
    height: 'auto'
  },
  ios: {
    maxHeight: '80vh',
    height: 'auto',
    boxShadow: 'none'
  }
}

function additionalCSS (theme, position) {
  let css = {}

  if (['left', 'right'].includes(position)) {
    css.maxWidth = '90vw'
  }
  if (theme === 'ios') {
    if (['left', 'top'].includes(position)) {
      css.borderTopLeftRadius = 0
    }
    if (['right', 'top'].includes(position)) {
      css.borderTopRightRadius = 0
    }
    if (['left', 'bottom'].includes(position)) {
      css.borderBottomLeftRadius = 0
    }
    if (['right', 'bottom'].includes(position)) {
      css.borderBottomRightRadius = 0
    }
  }

  return css
}

let
  duration = 200, // in ms -- synch with transition CSS from Modal
  openedModalNumber = 0

export default {
  name: 'q-modal',
  components: {
    QTransition
  },
  props: {
    position: {
      type: String,
      default: '',
      validator (val) {
        return val === '' || ['top', 'bottom', 'left', 'right'].includes(val)
      }
    },
    transition: String,
    enterClass: String,
    leaveClass: String,
    positionClasses: {
      type: String,
      default: 'flex-center'
    },
    contentClasses: [Object, Array, String],
    contentCss: [Object, Array, String],
    noBackdropDismiss: {
      type: Boolean,
      default: false
    },
    noEscDismiss: {
      type: Boolean,
      default: false
    },
    minimized: Boolean,
    maximized: Boolean
  },
  data () {
    return {
      active: false
    }
  },
  computed: {
    modalClasses () {
      const cls = this.position
        ? positions[this.position]
        : this.positionClasses
      if (this.maximized) {
        return ['maximized', cls]
      }
      else if (this.minimized) {
        return ['minimized', cls]
      }
      return cls
    },
    modalTransition () {
      if (this.position) {
        return `q-modal-${this.position}`
      }
      if (this.enterClass === void 0 && this.leaveClass === void 0) {
        return this.transition || 'q-modal'
      }
    },
    modalCss () {
      if (this.position) {
        const css = Array.isArray(this.contentCss)
          ? this.contentCss
          : [this.contentCss]

        css.unshift(extend(
          {},
          positionCSS[this.$q.theme],
          additionalCSS(this.$q.theme, this.position)
        ))

        return css
      }

      return this.contentCss
    }
  },
  methods: {
    open (onShow) {
      if (this.active) {
        return
      }

      document.body.appendChild(this.$el)
      document.body.classList.add('with-modal')
      EscapeKey.register(() => {
        if (this.noEscDismiss) {
          return
        }
        this.close(() => {
          this.$emit('escape-key')
        })
      })

      this.__popstate = () => {
        if (
          Platform.has.popstate &&
          window.history.state &&
          window.history.state.modalId &&
          window.history.state.modalId >= this.__modalId
        ) {
          return
        }
        openedModalNumber--
        EscapeKey.pop()
        this.active = false

        if (Platform.has.popstate) {
          window.removeEventListener('popstate', this.__popstate)
        }

        setTimeout(() => {
          if (!openedModalNumber) {
            document.body.classList.remove('with-modal')
          }
          if (typeof this.__onClose === 'function') {
            this.__onClose()
          }
          this.$emit('close')
        }, duration)
      }

      setTimeout(() => {
        let content = this.$refs.content
        content.scrollTop = 0
        ;['modal-scroll', 'layout-view'].forEach(c => {
          [].slice.call(content.getElementsByClassName(c)).forEach(el => {
            el.scrollTop = 0
          })
        })
      }, 10)

      this.active = true
      this.__modalId = ++openedModalNumber
      if (Platform.has.popstate) {
        window.history.pushState({modalId: this.__modalId}, '')
        window.addEventListener('popstate', this.__popstate)
      }

      setTimeout(() => {
        if (typeof onShow === 'function') {
          onShow()
        }
        this.$emit('open')
      }, duration)
    },
    close (onClose) {
      if (!this.active) {
        return
      }

      this.__onClose = onClose

      if (!Platform.has.popstate) {
        this.__popstate()
      }
      else {
        window.history.go(-1)
      }
    },
    toggle (done) {
      if (this.active) {
        this.close(done)
      }
      else {
        this.open(done)
      }
    },
    __dismiss (onClick) {
      if (this.noBackdropDismiss) {
        return
      }
      this.close(onClick)
    }
  },
  beforeDestroy () {
    if (this.$el.parentNode) {
      this.$el.parentNode.removeChild(this.$el)
    }
  }
}
</script>

<template>
  <q-transition :name="modalTransition" :enter="enterClass" :leave="leaveClass">
    <div
      v-show="active"
      class="modal fullscreen row"
      :class="modalClasses"
      @mousedown="__dismiss()"
      @touchstart="__dismiss()"
    >
      <div
        ref="content"
        class="modal-content scroll"
        @mousedown.stop
        @touchstart.stop
        :style="modalCss"
        :class="contentClasses"
      >
        <slot></slot>
      </div>
    </div>
  </q-transition>
</template>

<script>
import Platform from '../../features/platform'
import EscapeKey from '../../features/escape-key'
import extend from '../../utils/extend'
import { QTransition } from '../transition'

const positions = {
  top: 'items-start justify-center with-backdrop',
  bottom: 'items-end justify-center with-backdrop',
  right: 'items-center justify-end with-backdrop',
  left: 'items-center justify-start with-backdrop'
}
const positionCSS = {
  mat: {
    maxHeight: '80vh',
    height: 'auto'
  },
  ios: {
    maxHeight: '80vh',
    height: 'auto',
    boxShadow: 'none'
  }
}

function additionalCSS (theme, position) {
  let css = {}

  if (['left', 'right'].includes(position)) {
    css.maxWidth = '90vw'
  }
  if (theme === 'ios') {
    if (['left', 'top'].includes(position)) {
      css.borderTopLeftRadius = 0
    }
    if (['right', 'top'].includes(position)) {
      css.borderTopRightRadius = 0
    }
    if (['left', 'bottom'].includes(position)) {
      css.borderBottomLeftRadius = 0
    }
    if (['right', 'bottom'].includes(position)) {
      css.borderBottomRightRadius = 0
    }
  }

  return css
}

let
  duration = 200, // in ms -- synch with transition CSS from Modal
  openedModalNumber = 0

export default {
  name: 'q-modal',
  components: {
    QTransition
  },
  props: {
    position: {
      type: String,
      default: '',
      validator (val) {
        return val === '' || ['top', 'bottom', 'left', 'right'].includes(val)
      }
    },
    transition: String,
    enterClass: String,
    leaveClass: String,
    positionClasses: {
      type: String,
      default: 'flex-center'
    },
    contentClasses: [Object, String],
    contentCss: [Object, String],
    noBackdropDismiss: {
      type: Boolean,
      default: false
    },
    noEscDismiss: {
      type: Boolean,
      default: false
    },
    minimized: Boolean,
    maximized: Boolean
  },
  data () {
    return {
      active: false
    }
  },
  computed: {
    modalClasses () {
      const cls = this.position
        ? positions[this.position]
        : this.positionClasses
      if (this.maximized) {
        return ['maximized', cls]
      }
      else if (this.minimized) {
        return ['minimized', cls]
      }
      return cls
    },
    modalTransition () {
      if (this.position) {
        return `q-modal-${this.position}`
      }
      if (this.enterClass === void 0 && this.leaveClass === void 0) {
        return this.transition || 'q-modal'
      }
    },
    modalCss () {
      if (this.position) {
        return extend(
          {},
          positionCSS[this.$q.theme],
          additionalCSS(this.$q.theme, this.position),
          this.contentCss
        )
      }
      return this.contentCss
    }
  },
  methods: {
    open (onShow) {
      if (this.active) {
        return
      }

      document.body.appendChild(this.$el)
      document.body.classList.add('with-modal')
      EscapeKey.register(() => {
        if (this.noEscDismiss) {
          return
        }
        this.close(() => {
          this.$emit('escape-key')
        })
      })

      this.__popstate = () => {
        if (
          Platform.has.popstate &&
          window.history.state &&
          window.history.state.modalId &&
          window.history.state.modalId >= this.__modalId
        ) {
          return
        }
        openedModalNumber--
        EscapeKey.pop()
        this.active = false

        if (Platform.has.popstate) {
          window.removeEventListener('popstate', this.__popstate)
        }

        setTimeout(() => {
          if (!openedModalNumber) {
            document.body.classList.remove('with-modal')
          }
          if (typeof this.__onClose === 'function') {
            this.__onClose()
          }
          this.$emit('close')
        }, duration)
      }

      setTimeout(() => {
        let content = this.$refs.content
        content.scrollTop = 0
        ;['modal-scroll', 'layout-view'].forEach(c => {
          [].slice.call(content.getElementsByClassName(c)).forEach(el => {
            el.scrollTop = 0
          })
        })
      }, 10)

      this.active = true
      this.__modalId = ++openedModalNumber
      if (Platform.has.popstate) {
        window.history.pushState({modalId: this.__modalId}, '')
        window.addEventListener('popstate', this.__popstate)
      }

      setTimeout(() => {
        if (typeof onShow === 'function') {
          onShow()
        }
        this.$emit('open')
      }, duration)
    },
    close (onClose) {
      if (!this.active) {
        return
      }

      this.__onClose = onClose

      if (!Platform.has.popstate) {
        this.__popstate()
      }
      else {
        window.history.go(-1)
      }
    },
    toggle (done) {
      if (this.active) {
        this.close(done)
      }
      else {
        this.open(done)
      }
    },
    __dismiss (onClick) {
      if (this.noBackdropDismiss) {
        return
      }
      this.close(onClick)
    }
  },
  beforeDestroy () {
    if (this.$el.parentNode) {
      this.$el.parentNode.removeChild(this.$el)
    }
  }
}
</script>


update select style

update select style

<template>

                <input
                    type="text"
                    name="search"
                    v-el:search
                    autocomplete="off"
                    class="xcui-select-search-input"
                    v-if="showSearch"
                    v-model="searchValue"
                    @focus.prevent="activate()"
                    @blur.prevent="deactivate()"
                    @keyup.down="keyNext()"
                    @keyup.up="keyPrev()"
                    @keydown.enter.stop.prevent.self="enterSearchValue()"
                    @change.prevent.stop=""
                    :placeholder="placeholder">

0) || (isOpen && multiple)">

                    最多可选{{multipleMax}}项!

                <li class="xcui-select-menu-item"
                    v-if="filteredOptions.length<1 && searchEmptyText"
                    v-text="searchEmptyText">

                <template
                          v-for="item in filteredOptions">

                        <partial :name="optionPartial"
                                 class="xcui-select-menu-item-partial"
                                 v-if="optionPartial.length"></partial>

                </template>
                <template
                    v-for="item in filteredOptions">

{{item.name}}

                            <template v-for="option in item.options">

                                    <partial :name="optionPartial"
                                             class="xcui-select-menu-item-partial"
                                             v-if="optionPartial.length"></partial>

                            </template>

                </template>

</template>

<template>

                <input
                    type="text"
                    name="search"
                    v-el:search
                    autocomplete="off"
                    class="xcui-select-search-input"
                    v-if="showSearch"
                    v-model="searchValue"
                    @focus.prevent="activate()"
                    @blur.prevent="deactivate()"
                    @keyup.down="keyNext()"
                    @keyup.up="keyPrev()"
                    @keydown.enter.stop.prevent.self="enterSearchValue()"
                    @change.prevent.stop=""
                    :placeholder="placeholder">

0) || (isOpen && multiple)">

                    最多可选{{multipleMax}}项!

                <li class="xcui-select-menu-item"
                    v-if="filteredOptions.length<1 && searchEmptyText"
                    v-text="searchEmptyText">

                <template v-if="!optgroup && filteredOptions.length>0"
                          v-for="item in filteredOptions">

                        <partial :name="optionPartial"
                                 class="xcui-select-menu-item-partial"
                                 v-if="optionPartial.length"></partial>

                </template>
                <template v-if="optgroup && filteredOptions.length>0"
                          v-for="item in filteredOptions">

{{item.name}}

                            <template v-for="option in item.options">

                                    <partial :name="optionPartial"
                                             class="xcui-select-menu-item-partial"
                                             v-if="optionPartial.length"></partial>

                            </template>

                </template>

</template>


auto focus on the descriptio nfield

auto focus on the descriptio nfield

<template>
    <el-dialog
            title="Give Feedback"
            :visible="visible"
            :width="isMobile ? '99%' : '600px'"
            @close="close"
            append-to-body
            class="user-select"
    >

            <el-form label-position="top" label-width="10px">

                    Please pick a subject for your feedback and tell us a few words about it.
                    We review all feedbacks; however, we may not write back to all of them.

                <el-form-item label="Subject">
                    <el-select v-model="subject" placeholder="Subject">
                        <el-option
                                v-for="item in subjects"
                                :key="item"
                                :label="item"
                                :value="item">
                        </el-option>
                    </el-select>
                </el-form-item>

                <el-form-item label="Desciption">
                    <el-input
                            type="textarea"
                            v-model="description"
                            placeholder="Desciption..."
                            name="description"
                            :maxlength="2000"
                            ref="description"
                            :autosize="{ minRows: 4, maxRows: 10}"
                    ></el-input>
                </el-form-item>
            </el-form>

            <el-button type="text" @click="close" size="medium" class="margin-right-1">
                Cancel
            </el-button>

            <el-button
                type="success"
                @click="send"
                :loading="sending"
                :disabled="!description.trim()"
                size="medium"
            >
                Send Feedback
            </el-button>

    </el-dialog>
</template>

<template>
    <el-dialog
            title="Give Feedback"
            :visible="visible"
            :width="isMobile ? '99%' : '600px'"
            @close="close"
            append-to-body
            class="user-select"
    >

            <el-form label-position="top" label-width="10px">

                    Please pick a subject for your feedback and tell us a few words about it.
                    We review all feedbacks; however, we may not write back to all of them.

                <el-form-item label="Subject">
                    <el-select v-model="subject" placeholder="Subject">
                        <el-option
                                v-for="item in subjects"
                                :key="item"
                                :label="item"
                                :value="item">
                        </el-option>
                    </el-select>
                </el-form-item>

                <el-form-item label="Desciption">
                    <el-input
                            type="textarea"
                            v-model="description"
                            placeholder="Desciption..."
                            name="description"
                            :maxlength="2000"
                            :autosize="{ minRows: 4, maxRows: 10}"
                    ></el-input>
                </el-form-item>
            </el-form>

            <el-button type="text" @click="close" size="medium" class="margin-right-1">
                Cancel
            </el-button>

            <el-button
                type="success"
                @click="send"
                :loading="sending"
                :disabled="!description.trim()"
                size="medium"
            >
                Send Feedback
            </el-button>

    </el-dialog>
</template>


added improved export button with download filename and comment

<template lang="pug">
div
  h2 Buckets

  b-alert(show)
    | Are you looking to collect more data? Check out #[a(href="https://activitywatch.readthedocs.io/en/latest/watchers.html") the docs] for more watchers.
    br
    small #[b Note:] This is currently not as easy as we want it to be, so some familiarity with programming is currently needed to run most of them.

  //b-card-group(columns=true)
  b-card.bucket-card(v-for="bucket in buckets", :key="bucket.id", :header="bucket.id")
    b-button-toolbar
      b-button-group(size="sm", class="mx-1")
        b-button(variant="primary", :to="'/buckets/' + bucket.id")
          | Open bucket
      b-button-group(size="sm", class="mx-1")
        // TODO: This currently does not export bucket metadata, which makes importing difficult
        //       See: https://github.com/ActivityWatch/activitywatch/issues/103
        // NOTE: When this is done we should also change the download name from "events-export" to "bucket-export".
        b-button(:href="'/api/0/buckets/' + bucket.id + '/events?limit=-1'",
                 :download="'aw-event-export-' + bucket.id + '.json'",
                 title="Export all events from this bucket to JSON")
          | Export as JSON
    small.bucket-last-updated(v-if="bucket.last_updated", slot="footer")
      span
        | Last updated:
      span(style="width: 8em; margin-left: 0.5em; display: inline-block")
        | {{ bucket.last_updated | friendlytime }}

</template>

<style lang="scss">
// This won't work if scoped
.bucket-card {
  .card-header, .card-footer {
    padding: 0.5em 0.75em 0.5em 0.75em;
  }

  .card-block {
    padding: 0.5em;
  }
}
</style>

<style scoped lang="scss">
.bucket-card {
  margin-bottom: 1em;
}

.bucket-last-updated {
    color: #666;
}
</style>

<script>
import Resources from '../resources.js';

let $Bucket = Resources.$Bucket;

export default {
  name: "Buckets",
  mounted: function() {
    this.getBuckets();
  },
  data: () => {
    return {
      buckets: [],
    }
  },
  methods: {
    getBuckets: function() {
      $Bucket.get().then((response) => {
        this.buckets = response.json();
      });
    },

    getBucketInfo: function(bucket_id) {
      $Bucket.get({"id": bucket_id}).then((response) => {
        this.buckets[bucket_id] = response.json();
      });
    }
  }
}
</script>

<template lang="pug">
div
  h2 Buckets

  b-alert(show)
    | Are you looking to collect more data? Check out #[a(href="https://activitywatch.readthedocs.io/en/latest/watchers.html") the docs] for more watchers.
    br
    small #[b Note:] This is currently not as easy as we want it to be, so some familiarity with programming is currently needed to run most of them.

  //b-card-group(columns=true)
  b-card.bucket-card(v-for="bucket in buckets", :key="bucket.id", :header="bucket.id")
    b-button-toolbar
      b-button-group(size="sm", class="mx-1")
        b-button(variant="primary", :to="'/buckets/' + bucket.id")
          | Open bucket
      b-button-group(size="sm", class="mx-1")
        b-button(:href="'/api/0/buckets/' + bucket.id + '/events?limit=-1'", title="Export all events from this bucket to JSON")
          | Export as JSON
    small.bucket-last-updated(v-if="bucket.last_updated", slot="footer")
      span
        | Last updated:
      span(style="width: 8em; margin-left: 0.5em; display: inline-block")
        | {{ bucket.last_updated | friendlytime }}

</template>

<style lang="scss">
// This won't work if scoped
.bucket-card {
  .card-header, .card-footer {
    padding: 0.5em 0.75em 0.5em 0.75em;
  }

  .card-block {
    padding: 0.5em;
  }
}
</style>

<style scoped lang="scss">
.bucket-card {
  margin-bottom: 1em;
}

.bucket-last-updated {
    color: #666;
}
</style>

<script>
import Resources from '../resources.js';

let $Bucket = Resources.$Bucket;

export default {
  name: "Buckets",
  mounted: function() {
    this.getBuckets();
  },
  data: () => {
    return {
      buckets: [],
    }
  },
  methods: {
    getBuckets: function() {
      $Bucket.get().then((response) => {
        this.buckets = response.json();
      });
    },

    getBucketInfo: function(bucket_id) {
      $Bucket.get({"id": bucket_id}).then((response) => {
        this.buckets[bucket_id] = response.json();
      });
    }
  }
}
</script>


Minor

Minor

<template>
  <div class="color-dot"
       @click="$emit('click')"
       :class="{'color-dot--selected': selected}"
  >
    <div
      class="color-dot__core"
      :style="{'background-color': color}"
    />
  </div>
</template>

<script>
export default {
  name: 'color-dot',
  props: {
    color: {
      type: String,
      default: '',
    },
    selected: {
      type: Boolean,
      default: false,
    },
  },
}
</script>

<style lang="scss">
.color-dot {
  width: 1.5rem;
  height: 1.5rem;
  cursor: pointer;
  @include flex-center();

  &--selected {
    border-radius: 50%;
    border: solid 0.125rem $vue-darkest-blue;
  }

  &__core {
    border-radius: 50%;
    width: 1rem;
    height: 1rem;
  }
}
</style>


OSharp.Reflection 添加 Com组件免注册调用

OSharp.Reflection 添加 Com组件免注册调用

<template>
<kendoui-splitter ref="splitter" :options="splitterOptions">

    <kendoui-treelist ref="treelist" :options="treelistOptions"/>

222

</kendoui-splitter>
</template>


Fix typo

Fix typo

<template>
  <div class="gobierto-data-sql-editor-container-save">
    <!--  only show if label name is set OR the prompt is visible  -->
    <template v-if="isSavingPromptVisible || labelValue">
      <input
        ref="inputText"
        v-model="labelValue"
        :placeholder="placeholder"
        :disabled="!isSavingPromptVisible"
        type="text"
        class="gobierto-data-sql-editor-container-save-text"
        @keydown.stop="onKeyDownTextHandler"
      >
    </template>

    <!-- only show checkbox on prompt visible -->
    <template v-if="isSavingPromptVisible">
      <label
        :for="labelPrivate"
        class="gobierto-data-sql-editor-container-save-label"
      >
        <input
          :id="labelPrivate"
          :checked="isPrivate"
          type="checkbox"
          @input="onInputCheckboxHandler"
        >
        {{ labelPrivate }}
      </label>
    </template>

    <!-- only show if label name is set OR the prompt is visible -->
    <template v-if="isSavingPromptVisible || labelValue">
      <PrivateIcon
        :is-closed="isPrivate"
        :style="{ paddingRight: '.5em', margin: 0 }"
      />
    </template>

    <!-- show edit button if there's no prompt but some name, otherwise, save button -->
    <template v-if="!isSavingPromptVisible && labelValue">
      <Button
        :text="labelEdit"
        class="btn-sql-editor"
        icon="edit"
        color="var(--color-base)"
        background="#fff"
        @click.native="onClickEditHandler"
      />
    </template>
    <template v-else>
      <Button
        :text="labelSave"
        :style="
          isSavingPromptVisible
            ? 'color: #fff; background-color: var(--color-base)'
            : 'color: var(--color-base); background-color: rgb(255, 255, 255);'
        "
        :disabled="isSavingPromptVisible && !labelValue"
        icon="save"
        color="var(--color-base)"
        background="#fff"
        class="btn-sql-editor"
        @click.native="onClickSaveHandler"
      />
    </template>

    <!-- only show cancel button on prompt visible -->
    <template v-if="isSavingPromptVisible">
      <Button
        :text="labelCancel"
        :icon="null"
        class="btn-sql-editor btn-sql-editor-cancel"
        color="var(--color-base)"
        background="#fff"
        @click.native="onClickCancelHandler"
      />
    </template>
  </div>
</template>
<script>
import Button from "./Button.vue";
import PrivateIcon from "./PrivateIcon.vue";

export default {
  name: 'SavingDialog',
  components: {
    Button,
    PrivateIcon
  },
  props: {
    value: {
      type: String,
      default: ''
    },
    placeholder: {
      type: String,
      default: ''
    },
    saveCallback: {
      type: Function,
      default: () => {}
    }
  },
  data() {
    return {
      isPrivate: false,
      isSavingPromptVisible: false,
      labelValue: this.value,
      labelSave: I18n.t("gobierto_data.projects.save") || "",
      labelPrivate: I18n.t('gobierto_data.projects.private') || "",
      labelCancel: I18n.t('gobierto_data.projects.cancel') || "",
      labelEdit: I18n.t("gobierto_data.projects.edit") || ""
    }
  },
  methods: {
    onClickSaveHandler() {
      if (!this.isSavingPromptVisible) {
        this.isSavingPromptVisible = true
        this.$nextTick(() => this.$refs.inputText.focus());
      } else {
        // the output is the content of the input plus the private flag
        this.$emit('save', { name: this.labelValue, privacy: this.isPrivate })

        this.isSavingPromptVisible = false
      }
    },
    onClickCancelHandler() {
      this.labelValue = null
      this.isSavingPromptVisible = false
    },
    onClickEditHandler() {
      this.isSavingPromptVisible = true
      this.$nextTick(() => this.$refs.inputText.focus());
    },
    onKeyDownTextHandler(event) {
      const { value } = event.target
      this.labelValue = value
    },
    onInputCheckboxHandler(event) {
      const { checked } = event.target
      this.isPrivate = checked
    },
  }
}
</script>

<template>
  <div class="gobierto-data-sql-editor-container-save">
    <!--  only show if label name is set OR the prompt is visible  -->
    <template v-if="isSavingPromptVisible || labelValue">
      <input
        ref="inputText"
        v-model="labelValue"
        :placeholder="placeholder"
        :disabled="!isSavingPromptVisible"
        type="text"
        class="gobierto-data-sql-editor-container-save-text"
        @keydDownn.stop="onKeyUpTextHandler"
      >
    </template>

    <!-- only show checkbox on prompt visible -->
    <template v-if="isSavingPromptVisible">
      <label
        :for="labelPrivate"
        class="gobierto-data-sql-editor-container-save-label"
      >
        <input
          :id="labelPrivate"
          :checked="isPrivate"
          type="checkbox"
          @input="onInputCheckboxHandler"
        >
        {{ labelPrivate }}
      </label>
    </template>

    <!-- only show if label name is set OR the prompt is visible -->
    <template v-if="isSavingPromptVisible || labelValue">
      <PrivateIcon
        :is-closed="isPrivate"
        :style="{ paddingRight: '.5em', margin: 0 }"
      />
    </template>

    <!-- show edit button if there's no prompt but some name, otherwise, save button -->
    <template v-if="!isSavingPromptVisible && labelValue">
      <Button
        :text="labelEdit"
        class="btn-sql-editor"
        icon="edit"
        color="var(--color-base)"
        background="#fff"
        @click.native="onClickEditHandler"
      />
    </template>
    <template v-else>
      <Button
        :text="labelSave"
        :style="
          isSavingPromptVisible
            ? 'color: #fff; background-color: var(--color-base)'
            : 'color: var(--color-base); background-color: rgb(255, 255, 255);'
        "
        :disabled="isSavingPromptVisible && !labelValue"
        icon="save"
        color="var(--color-base)"
        background="#fff"
        class="btn-sql-editor"
        @click.native="onClickSaveHandler"
      />
    </template>

    <!-- only show cancel button on prompt visible -->
    <template v-if="isSavingPromptVisible">
      <Button
        :text="labelCancel"
        :icon="null"
        class="btn-sql-editor btn-sql-editor-cancel"
        color="var(--color-base)"
        background="#fff"
        @click.native="onClickCancelHandler"
      />
    </template>
  </div>
</template>
<script>
import Button from "./Button.vue";
import PrivateIcon from "./PrivateIcon.vue";

export default {
  name: 'SavingDialog',
  components: {
    Button,
    PrivateIcon
  },
  props: {
    value: {
      type: String,
      default: ''
    },
    placeholder: {
      type: String,
      default: ''
    },
    saveCallback: {
      type: Function,
      default: () => {}
    }
  },
  data() {
    return {
      isPrivate: false,
      isSavingPromptVisible: false,
      labelValue: this.value,
      labelSave: I18n.t("gobierto_data.projects.save") || "",
      labelPrivate: I18n.t('gobierto_data.projects.private') || "",
      labelCancel: I18n.t('gobierto_data.projects.cancel') || "",
      labelEdit: I18n.t("gobierto_data.projects.edit") || ""
    }
  },
  methods: {
    onClickSaveHandler() {
      if (!this.isSavingPromptVisible) {
        this.isSavingPromptVisible = true
        this.$nextTick(() => this.$refs.inputText.focus());
      } else {
        // the output is the content of the input plus the private flag
        this.$emit('save', { name: this.labelValue, privacy: this.isPrivate })

        this.isSavingPromptVisible = false
      }
    },
    onClickCancelHandler() {
      this.labelValue = null
      this.isSavingPromptVisible = false
    },
    onClickEditHandler() {
      this.isSavingPromptVisible = true
      this.$nextTick(() => this.$refs.inputText.focus());
    },
    onKeyDownTextHandler(event) {
      const { value } = event.target
      this.labelValue = value
    },
    onInputCheckboxHandler(event) {
      const { checked } = event.target
      this.isPrivate = checked
    },
  }
}
</script>


feature:Add js-yaml code test

feature:Add js-yaml code test

<template>
  <s-container>
    <el-card class="box-card">
      <el-radio-group v-model="radioValue">
        <el-radio-button label="schema"/>
        <el-radio-button label="authentication"/>
        <el-radio-button label="configmap"/>
        <el-radio-button label="props"/>
      </el-radio-group>
      <el-tree :data="data" :props="defaultProps" class="tree-wrap" @node-click="handleNodeClick"/>
    </el-card>
    <el-card>
      <el-row>
        <el-col :span="12">
          <el-input
            :rows="50"
            v-model="textarea"
            type="textarea"
            placeholder="请输入内容"/>
        </el-col>
        <el-col :span="12">
          <el-input
            :rows="50"
            v-model="textarea2"
            type="textarea"
            readonly
            placeholder="请输入内容"/>
        </el-col>
      </el-row>
    </el-card>
  </s-container>
</template>
<script>
import yaml from 'js-yaml'
import SContainer from '@/components/Container/index.vue'

export default {
  name: 'ConfigManage',
  components: {
    SContainer
  },
  data() {
    return {
      radioValue: 'schema',
      data: [],
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      textarea: `---
# Collection Types #############################################################
################################################################################

# http://yaml.org/type/map.html -----------------------------------------------#

map:
  # Unordered set of key: value pairs.
  Block style: !!map
    Clark : Evans
    Ingy  : döt Net
    Oren  : Ben-Kiki
  Flow style: !!map { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki }

# http://yaml.org/type/omap.html ----------------------------------------------#

omap:
  # Explicitly typed ordered map (dictionary).
  Bestiary: !!omap
    - aardvark: African pig-like ant eater. Ugly.
    - anteater: South-American ant eater. Two species.
    - anaconda: South-American constrictor snake. Scaly.
    # Etc.
  # Flow style
  Numbers: !!omap [ one: 1, two: 2, three : 3 ]

# http://yaml.org/type/pairs.html ---------------------------------------------#

pairs:
  # Explicitly typed pairs.
  Block tasks: !!pairs
    - meeting: with team.
    - meeting: with boss.
    - break: lunch.
    - meeting: with client.
  Flow tasks: !!pairs [ meeting: with team, meeting: with boss ]

# http://yaml.org/type/set.html -----------------------------------------------#

set:
  # Explicitly typed set.
  baseball players: !!set
    ? Mark McGwire
    ? Sammy Sosa
    ? Ken Griffey
  # Flow style
  baseball teams: !!set { Boston Red Sox, Detroit Tigers, New York Yankees }

# http://yaml.org/type/seq.html -----------------------------------------------#

seq:
  # Ordered sequence of nodes
  Block style: !!seq
  - Mercury   # Rotates - no light/dark sides.
  - Venus     # Deadliest. Aptly named.
  - Earth     # Mostly dirt.
  - Mars      # Seems empty.
  - Jupiter   # The king.
  - Saturn    # Pretty.
  - Uranus    # Where the sun hardly shines.
  - Neptune   # Boring. No rings.
  - Pluto     # You call this a planet?
  Flow style: !!seq [ Mercury, Venus, Earth, Mars,      # Rocks
                      Jupiter, Saturn, Uranus, Neptune, # Gas
                      Pluto ]                           # Overrated

# Scalar Types #################################################################
################################################################################

# http://yaml.org/type/bool.html ----------------------------------------------#

bool:
  - true
  - True
  - TRUE
  - false
  - False
  - FALSE

# http://yaml.org/type/float.html ---------------------------------------------#

float:
  canonical: 6.8523015e+5
  exponentioal: 685.230_15e+03
  fixed: 685_230.15
  sexagesimal: 190:20:30.15
  negative infinity: -.inf
  not a number: .NaN

# http://yaml.org/type/int.html -----------------------------------------------#

int:
  canonical: 685230
  decimal: +685_230
  octal: 02472256
  hexadecimal: 0x_0A_74_AE
  binary: 0b1010_0111_0100_1010_1110
  sexagesimal: 190:20:30

# http://yaml.org/type/merge.html ---------------------------------------------#

merge:
  - &CENTER { x: 1, y: 2 }
  - &LEFT { x: 0, y: 2 }
  - &BIG { r: 10 }
  - &SMALL { r: 1 }

  # All the following maps are equal:

  - # Explicit keys
    x: 1
    y: 2
    r: 10
    label: nothing

  - # Merge one map
    << : *CENTER
    r: 10
    label: center

  - # Merge multiple maps
    << : [ *CENTER, *BIG ]
    label: center/big

  - # Override
    << : [ *BIG, *LEFT, *SMALL ]
    x: 1
    label: big/left/small

# http://yaml.org/type/null.html ----------------------------------------------#

null:
  # This mapping has four keys,
  # one has a value.
  empty:
  canonical: ~
  english: null
  ~: null key
  # This sequence has five
  # entries, two have values.
  sparse:
    - ~
    - 2nd entry
    -
    - 4th entry
    - Null

# http://yaml.org/type/str.html -----------------------------------------------#

string: abcd

# http://yaml.org/type/timestamp.html -----------------------------------------#

timestamp:
  canonical:        2001-12-15T02:59:43.1Z
  valid iso8601:    2001-12-14t21:59:43.10-05:00
  space separated:  2001-12-14 21:59:43.10 -5
  no time zone (Z): 2001-12-15 2:59:43.10
  date (00:00:00Z): 2002-12-14

`
    }
  },
  computed: {
    textarea2() {
      return JSON.stringify(yaml.safeLoad(this.textarea), null, '\t')
    }
  },
  methods: {
    handleNodeClick(data) {
      console.log(data)
    }
  }
}
</script>
<style lang='scss' scoped>
  .tree-wrap {
    margin-top: 20px;
  }
</style>

<template>
  <s-container>
    <el-card class="box-card">
      <el-radio-group v-model="radioValue">
        <el-radio-button label="schema"/>
        <el-radio-button label="authentication"/>
        <el-radio-button label="configmap"/>
        <el-radio-button label="props"/>
      </el-radio-group>
      <el-tree :data="data" :props="defaultProps" class="tree-wrap" @node-click="handleNodeClick"/>
    </el-card>
  </s-container>
</template>
<script>
import SContainer from '@/components/Container/index.vue'

export default {
  name: 'ConfigManage',
  components: {
    SContainer
  },
  data() {
    return {
      radioValue: 'schema',
      data: [],
      defaultProps: {
        children: 'children',
        label: 'label'
      }
    }
  },
  methods: {
    handleNodeClick(data) {
      console.log(data)
    }
  }
}
</script>
<style lang='scss' scoped>
  .tree-wrap {
    margin-top: 20px;
  }
</style>


Make sure assignees list is reactive

Make sure assignees list is reactive

<template>

    {{ badge }}
    {{ duration }}
    {{ assignees.length }}

      <span :class="{ 'is-light': scoutsForPeriod(n).length < 1 }">
        {{ scoutsForPeriod(n).length }}

      <router-link :to="'/administration/classes/' + eventId + '/' + id">
        Details
      </router-link>

</template>


add id to faq to fix scroll into view

add id to faq to fix scroll into view

<template>

        <MetaHead title="SmartAPI | FAQ"></MetaHead>

        <Image alt="faq" img_name="faq.svg" img_width='40%' class="responsive-img" style="max-width:300px;"></Image>

FAQ

        <template v-for="section in faq" :key='section.sectionName'>

            <template v-for="item in section.questions" :key="item.anchor">

                    <CopyButton copy_msg="URL copied" :copy="'http://smart-api.info/faq#' + item.anchor">
                        <template v-slot:title>
                            Copy Link
                        </template>
                    </CopyButton>

            </template>

        </template>

</template>


Fix check all checkbox

Fix check all checkbox

<template>

                    <button class="btn btn-success" @click.prevent="getItems">
                         refresh
                    </button>
                    <button class="btn btn-danger" @click.prevent="deleteItems" :disabled="checkedItems.length == 0">
                         delete
                    </button>

                        <input type="text" class="form-control" placeholder="Search..." v-model="filter"
                               ref="filterInput">

            <form ref="tableForm">

                            <input type="checkbox" @click="checkAllItems" :checked="allItemsChecked">

                            {{ colName }}

                            <input type="checkbox" v-model="checkedItems" :value="item.id" @click="itemClicked(item)">

                        {{ item[colKey] }}

            </form>

</template>


Log out like usual instead of staying on the map (#62)

<template>

    <level-dot
      v-for="level in levels"
      :key="level.original"
      :level-data="level"
      :course-id="courseId"
      :course-instance-id="courseInstanceId"
      :code-language="codeLanguage"
    />
    <button
      class="ozaria-button ozaria-primary-button back-button"
      @click="backButtonClick"
    >
       {{ $t("play.back_to_ozaria") }}
       {{ $t("play.back_to_dashboard") }}
    </button>

       {{ heroName }}

        ({{ $t("play.customize_hero") }})

        <button
          v-if="!isAnonymous"
          class="ozaria-button ozaria-primary-button settings-button"
          @click="settingsButtonClick"
        >
          {{ $t("account.settings_title") }}
        </button>
        <button
          v-if="!isAnonymous"
          id="logout-button"
          class="ozaria-button ozaria-primary-button logout-button"
        >
          {{ $t("common.logout") }}
        </button>
        <button
          v-if="isAnonymous"
          class="ozaria-button ozaria-primary-button signup-button"
        >
          {{ $t("signup.sign_up") }}
        </button>

    <modal-char-customization
      v-if="showCharCx"
      class="char-cx-modal"
      @saved="onCharCxSaved"
    />

</template>


icon for company add/change is now different based on context

<template>

{{ currentDriller.first_name }} {{ currentDriller.surname }}

            <api-error :error="error" resetter="SET_ERROR"></api-error>

              Classification
              Register Status
              Date Registered

              <tr v-if="classifications && classifications.length" v-for="(item, index) in classifications" :key="`classification ${index}`">
                <router-link :to="{
                  name: 'ApplicationDetail',
                  params: { person_guid: currentDriller.person_guid, classCode: item.code } }">
                {{ item.description }}</router-link>
                {{ item.status }}
                {{ item.date }}

        <router-link
          class="btn btn-light btn-sm registries-edit-btn mb-3"
          tag="button"
          to="#"
          v-if="currentDriller.person_guid"> Add application</router-link>

Personal Information

                <button
                  class="btn btn-light btn-sm registries-edit-btn"
                  type="button"
                  @click="editPerson = !editPerson"
                  v-if="currentDriller.person_guid"> Edit</button>

            <person-edit
                  section="person"
                  v-if="editPerson"
                  :record="currentDriller.person_guid"
                  @updated="editPerson = false; updateRecord()"
                  @canceled="editPerson = false"></person-edit>

                  Surname:

                  {{ currentDriller.surname }}

                  First name:

                  {{ currentDriller.first_name }}

                  Well Driller ORCS:

                  {{ currentDriller.well_driller_orcs_no }}

                  Pump Installer ORCS:

                  {{ currentDriller.pump_installer_orcs_no }}

Contact Information

                <button
                  class="btn btn-light btn-sm registries-edit-btn"
                  type="button"
                  @click="editContact = !editContact"
                  v-if="currentDriller.person_guid"> Edit</button>

            <person-edit
              section="contact"
              :record="currentDriller.person_guid"
              v-if="editContact"
              @updated="editContact = false; updateRecord()"
              @canceled="editContact = false"></person-edit>

                  Email address:

                  <a :href="`mailto:${currentDriller.contact_email}`">{{ currentDriller.contact_email }}

                  Telephone:

                  {{ currentDriller.contact_tel }}

Additional (Legacy) Contact Information

                  Email address:

                  <div v-for="(email, index) in personEmail" :key="`person email ${index}`">
                    <a :href="`mailto:${email}`">{{ email }}

                  Telephone:

                  <div v-for="(tel, index) in personTel" :key="`person tel ${index}`">
                    {{ tel }}

Applicant has not yet been added to the register. Submit or approve an application to view or add company information.

              <div v-for="(registration, index) in currentDriller.registrations"
                :key="`company information row ${index}`"
                :class="index > 0 ? 'mt-5' : 'mt-2'">

{{ registration.activity_description }} Company Information

                    <button
                      class="btn btn-light btn-sm registries-edit-btn"
                      type="button"
                      @click="editCompany = (editCompany === (index + 1) ? 0 : (index + 1))"
                      v-if="currentDriller.person_guid">
                       Add
                       Change
                      </button>

                <person-edit
                  section="company"
                  :record="registration"
                  v-if="editCompany === (index + 1)"
                  @updated="editCompany = 0; updateRecord()"
                  @canceled="editCompany = 0"></person-edit>

                      Company name:

                      {{ registration.organization.name }}

                      Street address:

                      {{ registration.organization.street_address }}

                      City:

                      {{ registration.organization.city }}

                      Province:

                      {{ registration.organization.province_state }}

                      Postal Code:

                      {{ registration.organization.postal_code }}

                      Office number:

                      {{ registration.organization.main_tel }}

                      Cell number:

                      {{ registration.surname }}

                      Fax number:

                      {{ registration.organization.fax_tel }}

                      Email address:

                      {{ registration.organization.contact_email }}

                      Website:

                      {{ registration.organization.website_url }}

        <person-notes @updated="updateRecord"></person-notes>

</template>

<template>

{{ currentDriller.first_name }} {{ currentDriller.surname }}

            <api-error :error="error" resetter="SET_ERROR"></api-error>

              Classification
              Register Status
              Date Registered

              <tr v-if="classifications && classifications.length" v-for="(item, index) in classifications" :key="`classification ${index}`">
                <router-link :to="{
                  name: 'ApplicationDetail',
                  params: { person_guid: currentDriller.person_guid, classCode: item.code } }">
                {{ item.description }}</router-link>
                {{ item.status }}
                {{ item.date }}

        <router-link
          class="btn btn-light btn-sm registries-edit-btn mb-3"
          tag="button"
          to="#"
          v-if="currentDriller.person_guid"> Add application</router-link>

Personal Information

                <button
                  class="btn btn-light btn-sm registries-edit-btn"
                  type="button"
                  @click="editPerson = !editPerson"
                  v-if="currentDriller.person_guid"> Edit</button>

            <person-edit
                  section="person"
                  v-if="editPerson"
                  :record="currentDriller.person_guid"
                  @updated="editPerson = false; updateRecord()"
                  @canceled="editPerson = false"></person-edit>

                  Surname:

                  {{ currentDriller.surname }}

                  First name:

                  {{ currentDriller.first_name }}

                  Well Driller ORCS:

                  {{ currentDriller.well_driller_orcs_no }}

                  Pump Installer ORCS:

                  {{ currentDriller.pump_installer_orcs_no }}

Contact Information

                <button
                  class="btn btn-light btn-sm registries-edit-btn"
                  type="button"
                  @click="editContact = !editContact"
                  v-if="currentDriller.person_guid"> Edit</button>

            <person-edit
              section="contact"
              :record="currentDriller.person_guid"
              v-if="editContact"
              @updated="editContact = false; updateRecord()"
              @canceled="editContact = false"></person-edit>

                  Email address:

                  <a :href="`mailto:${currentDriller.contact_email}`">{{ currentDriller.contact_email }}

                  Telephone:

                  {{ currentDriller.contact_tel }}

Additional (Legacy) Contact Information

                  Email address:

                  <div v-for="(email, index) in personEmail" :key="`person email ${index}`">
                    <a :href="`mailto:${email}`">{{ email }}

                  Telephone:

                  <div v-for="(tel, index) in personTel" :key="`person tel ${index}`">
                    {{ tel }}

Applicant has not yet been added to the register. Submit or approve an application to view or add company information.

              <div v-for="(registration, index) in currentDriller.registrations"
                :key="`company information row ${index}`"
                :class="index > 0 ? 'mt-5' : 'mt-2'">

{{ registration.activity_description }} Company Information

                    <button
                      class="btn btn-light btn-sm registries-edit-btn"
                      type="button"
                      @click="editCompany = (editCompany === (index + 1) ? 0 : (index + 1))"
                      v-if="currentDriller.person_guid">
                      AddChange
                      </button>

                <person-edit
                  section="company"
                  :record="registration"
                  v-if="editCompany === (index + 1)"
                  @updated="editCompany = 0; updateRecord()"
                  @canceled="editCompany = 0"></person-edit>

                      Company name:

                      {{ registration.organization.name }}

                      Street address:

                      {{ registration.organization.street_address }}

                      City:

                      {{ registration.organization.city }}

                      Province:

                      {{ registration.organization.province_state }}

                      Postal Code:

                      {{ registration.organization.postal_code }}

                      Office number:

                      {{ registration.organization.main_tel }}

                      Cell number:

                      {{ registration.surname }}

                      Fax number:

                      {{ registration.organization.fax_tel }}

                      Email address:

                      {{ registration.organization.contact_email }}

                      Website:

                      {{ registration.organization.website_url }}

        <person-notes @updated="updateRecord"></person-notes>

</template>