Autocomplete: support maxlength and minlength

<template>
  <div
    class="el-autocomplete"
    v-clickoutside="close"
    aria-haspopup="listbox"
    role="combobox"
    :aria-expanded="suggestionVisible"
    :aria-owns="id"
  >
    <el-input
      ref="input"
      v-bind="$props"
      @compositionstart.native="handleComposition"
      @compositionupdate.native="handleComposition"
      @compositionend.native="handleComposition"
      @input="handleChange"
      @focus="handleFocus"
      @blur="handleBlur"
      @keydown.up.native.prevent="highlight(highlightedIndex - 1)"
      @keydown.down.native.prevent="highlight(highlightedIndex + 1)"
      @keydown.enter.native="handleKeyEnter"
      @keydown.native.tab="close"
      :label="label"
    >
      <template slot="prepend" v-if="$slots.prepend">
        <slot name="prepend"></slot>
      </template>
      <template slot="append" v-if="$slots.append">
        <slot name="append"></slot>
      </template>
      <template slot="prefix" v-if="$slots.prefix">
        <slot name="prefix"></slot>
      </template>
      <template slot="suffix" v-if="$slots.suffix">
        <slot name="suffix"></slot>
      </template>
    </el-input>
    <el-autocomplete-suggestions
      visible-arrow
      :class="[popperClass ? popperClass : '']"
      ref="suggestions"
      placement="bottom-start"
      :id="id">
      <li
        v-for="(item, index) in suggestions"
        :key="index"
        :class="{'highlighted': highlightedIndex === index}"
        @click="select(item)"
        :id="`${id}-item-${index}`"
        role="option"
        :aria-selected="highlightedIndex === index"
      >
        <slot :item="item">
          {{ item[valueKey] }}
        </slot>
      </li>
    </el-autocomplete-suggestions>
  </div>
</template>
<script>
  import debounce from 'throttle-debounce/debounce';
  import ElInput from 'element-ui/packages/input';
  import Clickoutside from 'element-ui/src/utils/clickoutside';
  import ElAutocompleteSuggestions from './autocomplete-suggestions.vue';
  import Emitter from 'element-ui/src/mixins/emitter';
  import Migrating from 'element-ui/src/mixins/migrating';
  import { generateId } from 'element-ui/src/utils/util';
  import Focus from 'element-ui/src/mixins/focus';

  export default {
    name: 'ElAutocomplete',

    mixins: [Emitter, Focus('input'), Migrating],

    componentName: 'ElAutocomplete',

    components: {
      ElInput,
      ElAutocompleteSuggestions
    },

    directives: { Clickoutside },

    props: {
      valueKey: {
        type: String,
        default: 'value'
      },
      popperClass: String,
      placeholder: String,
      disabled: Boolean,
      name: String,
      size: String,
      value: String,
      maxlength: Number,
      minlength: Number,
      autofocus: Boolean,
      fetchSuggestions: Function,
      triggerOnFocus: {
        type: Boolean,
        default: true
      },
      customItem: String,
      selectWhenUnmatched: {
        type: Boolean,
        default: false
      },
      prefixIcon: String,
      suffixIcon: String,
      label: String,
      debounce: {
        type: Number,
        default: 300
      }
    },
    data() {
      return {
        activated: false,
        isOnComposition: false,
        suggestions: [],
        loading: false,
        highlightedIndex: -1
      };
    },
    computed: {
      suggestionVisible() {
        const suggestions = this.suggestions;
        let isValidData = Array.isArray(suggestions) && suggestions.length > 0;
        return (isValidData || this.loading) && this.activated;
      },
      id() {
        return `el-autocomplete-${generateId()}`;
      }
    },
    watch: {
      suggestionVisible(val) {
        this.broadcast('ElAutocompleteSuggestions', 'visible', [val, this.$refs.input.$refs.input.offsetWidth]);
      }
    },
    methods: {
      getMigratingConfig() {
        return {
          props: {
            'custom-item': 'custom-item is removed, use scoped slot instead.',
            'props': 'props is removed, use value-key instead.'
          }
        };
      },
      getData(queryString) {
        this.loading = true;
        this.fetchSuggestions(queryString, (suggestions) => {
          this.loading = false;
          if (Array.isArray(suggestions)) {
            this.suggestions = suggestions;
          } else {
            console.error('autocomplete suggestions must be an array');
          }
        });
      },
      handleComposition(event) {
        if (event.type === 'compositionend') {
          this.isOnComposition = false;
          this.handleChange(event.target.value);
        } else {
          this.isOnComposition = true;
        }
      },
      handleChange(value) {
        this.$emit('input', value);
        if (this.isOnComposition || (!this.triggerOnFocus && !value)) {
          this.suggestions = [];
          return;
        }
        this.debouncedGetData(value);
      },
      handleFocus(event) {
        this.activated = true;
        this.$emit('focus', event);
        if (this.triggerOnFocus) {
          this.debouncedGetData(this.value);
        }
      },
      handleBlur(event) {
        this.$emit('blur', event);
      },
      close(e) {
        this.activated = false;
      },
      handleKeyEnter(e) {
        if (this.suggestionVisible && this.highlightedIndex >= 0 && this.highlightedIndex < this.suggestions.length) {
          e.preventDefault();
          this.select(this.suggestions[this.highlightedIndex]);
        } else if (this.selectWhenUnmatched) {
          this.$emit('select', {value: this.value});
          this.$nextTick(_ => {
            this.suggestions = [];
            this.highlightedIndex = -1;
          });
        }
      },
      select(item) {
        this.$emit('input', item[this.valueKey]);
        this.$emit('select', item);
        this.$nextTick(_ => {
          this.suggestions = [];
          this.highlightedIndex = -1;
        });
      },
      highlight(index) {
        if (!this.suggestionVisible || this.loading) { return; }
        if (index < 0) {
          this.highlightedIndex = -1;
          return;
        }
        if (index >= this.suggestions.length) {
          index = this.suggestions.length - 1;
        }
        const suggestion = this.$refs.suggestions.$el.querySelector('.el-autocomplete-suggestion__wrap');
        const suggestionList = suggestion.querySelectorAll('.el-autocomplete-suggestion__list li');

        let highlightItem = suggestionList[index];
        let scrollTop = suggestion.scrollTop;
        let offsetTop = highlightItem.offsetTop;

        if (offsetTop + highlightItem.scrollHeight > (scrollTop + suggestion.clientHeight)) {
          suggestion.scrollTop += highlightItem.scrollHeight;
        }
        if (offsetTop < scrollTop) {
          suggestion.scrollTop -= highlightItem.scrollHeight;
        }
        this.highlightedIndex = index;
        this.$el.querySelector('.el-input__inner').setAttribute('aria-activedescendant', `${this.id}-item-${this.highlightedIndex}`);
      }
    },
    mounted() {
      this.debouncedGetData = debounce(this.debounce, (val) => {
        this.getData(val);
      });
      this.$on('item-click', item => {
        this.select(item);
      });
      let $input = this.$el.querySelector('.el-input__inner');
      $input.setAttribute('role', 'textbox');
      $input.setAttribute('aria-autocomplete', 'list');
      $input.setAttribute('aria-controls', 'id');
      $input.setAttribute('aria-activedescendant', `${this.id}-item-${this.highlightedIndex}`);
    },
    beforeDestroy() {
      this.$refs.suggestions.$destroy();
    }
  };
</script>

<template>
  <div
    class="el-autocomplete"
    v-clickoutside="close"
    aria-haspopup="listbox"
    role="combobox"
    :aria-expanded="suggestionVisible"
    :aria-owns="id"
  >
    <el-input
      ref="input"
      v-bind="$props"
      @compositionstart.native="handleComposition"
      @compositionupdate.native="handleComposition"
      @compositionend.native="handleComposition"
      @input="handleChange"
      @focus="handleFocus"
      @blur="handleBlur"
      @keydown.up.native.prevent="highlight(highlightedIndex - 1)"
      @keydown.down.native.prevent="highlight(highlightedIndex + 1)"
      @keydown.enter.native="handleKeyEnter"
      @keydown.native.tab="close"
      :label="label"
    >
      <template slot="prepend" v-if="$slots.prepend">
        <slot name="prepend"></slot>
      </template>
      <template slot="append" v-if="$slots.append">
        <slot name="append"></slot>
      </template>
      <template slot="prefix" v-if="$slots.prefix">
        <slot name="prefix"></slot>
      </template>
      <template slot="suffix" v-if="$slots.suffix">
        <slot name="suffix"></slot>
      </template>
    </el-input>
    <el-autocomplete-suggestions
      visible-arrow
      :class="[popperClass ? popperClass : '']"
      ref="suggestions"
      placement="bottom-start"
      :id="id">
      <li
        v-for="(item, index) in suggestions"
        :key="index"
        :class="{'highlighted': highlightedIndex === index}"
        @click="select(item)"
        :id="`${id}-item-${index}`"
        role="option"
        :aria-selected="highlightedIndex === index"
      >
        <slot :item="item">
          {{ item[valueKey] }}
        </slot>
      </li>
    </el-autocomplete-suggestions>
  </div>
</template>
<script>
  import debounce from 'throttle-debounce/debounce';
  import ElInput from 'element-ui/packages/input';
  import Clickoutside from 'element-ui/src/utils/clickoutside';
  import ElAutocompleteSuggestions from './autocomplete-suggestions.vue';
  import Emitter from 'element-ui/src/mixins/emitter';
  import Migrating from 'element-ui/src/mixins/migrating';
  import { generateId } from 'element-ui/src/utils/util';
  import Focus from 'element-ui/src/mixins/focus';

  export default {
    name: 'ElAutocomplete',

    mixins: [Emitter, Focus('input'), Migrating],

    componentName: 'ElAutocomplete',

    components: {
      ElInput,
      ElAutocompleteSuggestions
    },

    directives: { Clickoutside },

    props: {
      valueKey: {
        type: String,
        default: 'value'
      },
      popperClass: String,
      placeholder: String,
      disabled: Boolean,
      name: String,
      size: String,
      value: String,
      autofocus: Boolean,
      fetchSuggestions: Function,
      triggerOnFocus: {
        type: Boolean,
        default: true
      },
      customItem: String,
      selectWhenUnmatched: {
        type: Boolean,
        default: false
      },
      prefixIcon: String,
      suffixIcon: String,
      label: String,
      debounce: {
        type: Number,
        default: 300
      }
    },
    data() {
      return {
        activated: false,
        isOnComposition: false,
        suggestions: [],
        loading: false,
        highlightedIndex: -1
      };
    },
    computed: {
      suggestionVisible() {
        const suggestions = this.suggestions;
        let isValidData = Array.isArray(suggestions) && suggestions.length > 0;
        return (isValidData || this.loading) && this.activated;
      },
      id() {
        return `el-autocomplete-${generateId()}`;
      }
    },
    watch: {
      suggestionVisible(val) {
        this.broadcast('ElAutocompleteSuggestions', 'visible', [val, this.$refs.input.$refs.input.offsetWidth]);
      }
    },
    methods: {
      getMigratingConfig() {
        return {
          props: {
            'custom-item': 'custom-item is removed, use scoped slot instead.',
            'props': 'props is removed, use value-key instead.'
          }
        };
      },
      getData(queryString) {
        this.loading = true;
        this.fetchSuggestions(queryString, (suggestions) => {
          this.loading = false;
          if (Array.isArray(suggestions)) {
            this.suggestions = suggestions;
          } else {
            console.error('autocomplete suggestions must be an array');
          }
        });
      },
      handleComposition(event) {
        if (event.type === 'compositionend') {
          this.isOnComposition = false;
          this.handleChange(event.target.value);
        } else {
          this.isOnComposition = true;
        }
      },
      handleChange(value) {
        this.$emit('input', value);
        if (this.isOnComposition || (!this.triggerOnFocus && !value)) {
          this.suggestions = [];
          return;
        }
        this.debouncedGetData(value);
      },
      handleFocus(event) {
        this.activated = true;
        this.$emit('focus', event);
        if (this.triggerOnFocus) {
          this.debouncedGetData(this.value);
        }
      },
      handleBlur(event) {
        this.$emit('blur', event);
      },
      close(e) {
        this.activated = false;
      },
      handleKeyEnter(e) {
        if (this.suggestionVisible && this.highlightedIndex >= 0 && this.highlightedIndex < this.suggestions.length) {
          e.preventDefault();
          this.select(this.suggestions[this.highlightedIndex]);
        } else if (this.selectWhenUnmatched) {
          this.$emit('select', {value: this.value});
          this.$nextTick(_ => {
            this.suggestions = [];
            this.highlightedIndex = -1;
          });
        }
      },
      select(item) {
        this.$emit('input', item[this.valueKey]);
        this.$emit('select', item);
        this.$nextTick(_ => {
          this.suggestions = [];
          this.highlightedIndex = -1;
        });
      },
      highlight(index) {
        if (!this.suggestionVisible || this.loading) { return; }
        if (index < 0) {
          this.highlightedIndex = -1;
          return;
        }
        if (index >= this.suggestions.length) {
          index = this.suggestions.length - 1;
        }
        const suggestion = this.$refs.suggestions.$el.querySelector('.el-autocomplete-suggestion__wrap');
        const suggestionList = suggestion.querySelectorAll('.el-autocomplete-suggestion__list li');

        let highlightItem = suggestionList[index];
        let scrollTop = suggestion.scrollTop;
        let offsetTop = highlightItem.offsetTop;

        if (offsetTop + highlightItem.scrollHeight > (scrollTop + suggestion.clientHeight)) {
          suggestion.scrollTop += highlightItem.scrollHeight;
        }
        if (offsetTop < scrollTop) {
          suggestion.scrollTop -= highlightItem.scrollHeight;
        }
        this.highlightedIndex = index;
        this.$el.querySelector('.el-input__inner').setAttribute('aria-activedescendant', `${this.id}-item-${this.highlightedIndex}`);
      }
    },
    mounted() {
      this.debouncedGetData = debounce(this.debounce, (val) => {
        this.getData(val);
      });
      this.$on('item-click', item => {
        this.select(item);
      });
      let $input = this.$el.querySelector('.el-input__inner');
      $input.setAttribute('role', 'textbox');
      $input.setAttribute('aria-autocomplete', 'list');
      $input.setAttribute('aria-controls', 'id');
      $input.setAttribute('aria-activedescendant', `${this.id}-item-${this.highlightedIndex}`);
    },
    beforeDestroy() {
      this.$refs.suggestions.$destroy();
    }
  };
</script>


docs: fix lint

docs: fix lint

<template>
  <v-container
    v-if="structure !== false"
    page
  >
    <template v-if="structure">
      <section
        :id="id"
        class="mb-12"
      >
        <v-layout>
          <v-flex
            v-if="structure.title"
            shrink
          >
            <doc-heading>
              {{ structure.title }}
            </doc-heading>
          </v-flex>
          <v-spacer />
          <v-flex
            v-if="structure.file"
            shrink
          >
            <core-file-btn :link="structure.file" :branch="branch" />
          </v-flex>
          <v-flex
            v-if="structure.mdSpec"
            shrink
          >
            <core-spec-btn
              :link="structure.mdSpec.link"
              :version="structure.mdSpec.version"
            />
          </v-flex>
        </v-layout>
        <div v-if="structure.titleText">
          <doc-text class="mb-6">
            {{ structure.titleText }}
          </doc-text>
        </div>
      </section>

      <component
        :is="getComponent(child.type)"
        v-for="(child, i) in structure.children"
        :key="`${composite}-${i}`"
        :value="child"
      />

      <doc-contribution :branch="branch" />
    </template>
  </v-container>
  <not-found v-else />
</template>

<script>
  // Utilities
  import {
    mapGetters,
    mapState,
  } from 'vuex'
  import { getComponent, getBranch } from '@/util/helpers'
  import kebabCase from 'lodash/kebabCase'

  export default {
    name: 'CorePage',

    components: {
      NotFound: () => import('@/pages/general/404'),
    },

    provide () {
      return {
        id: this.id,
      }
    },

    data: () => ({
      timeout: null,
      branch: null,
    }),

    computed: {
      ...mapGetters('documentation', [
        'namespace',
        'page',
      ]),
      ...mapState('documentation', ['structure']),
      ...mapState('route', ['params']),
      composite () {
        return `${this.params.namespace}-${this.params.page}`
      },
      id () {
        if (!this.structure) return

        return kebabCase(this.$t(
          `${this.namespace}.${this.page}.${this.structure.title}`
        ))
      },
    },

    watch: {
      '$route.path': 'init',
    },

    mounted () {
      this.init()

      this.branch = getBranch()
    },

    methods: {
      getComponent,
      async init () {
        clearTimeout(this.timeout)

        this.timeout = setTimeout(() => {
          const sameInternal = this.$el.querySelectorAll('a.markdown--same-internal')

          Array.prototype.forEach.call(sameInternal, el => {
            el.addEventListener('click', this.onSameInternalClick)
          })

          const internal = this.$el.querySelectorAll('a.markdown--internal')

          Array.prototype.forEach.call(internal, el => {
            el.addEventListener('click', this.onInternalClick)
          })
        }, 300)
      },
      onSameInternalClick (e) {
        e.preventDefault()

        this.$router.push(e.target)
      },
      onInternalClick (e) {
        e.preventDefault()

        const target = e.target.tagName === 'A'
          ? e.target
          : e.target.parentElement

        const lang = `/${this.params.lang}`
        const length = lang.length
        let href = target.getAttribute('href')

        // If missing leading forward slash
        if (href.charAt(0) !== '/') {
          href = `/${href}`
        }

        // If missing language
        if (href.slice(0, length) !== lang) {
          href = `${lang}${href}`
        }

        this.$router.push(href)
      },
    },
  }
</script>

<style lang="sass">
.page
  max-width: 1185px

#components-navigation-drawers
  .v-sheet,
  .v-card
    overflow: hidden
</style>

<template>
  <v-container
    v-if="structure !== false"
    page
  >
    <template v-if="structure">
      <section
        :id="id"
        class="mb-12"
      >
        <v-layout>
          <v-flex
            v-if="structure.title"
            shrink
          >
            <doc-heading>
              {{ structure.title }}
            </doc-heading>
          </v-flex>
          <v-spacer />
          <v-flex
            v-if="structure.file"
            shrink
          >
            <core-file-btn :link="structure.file" :branch="branch" />
          </v-flex>
          <v-flex
            v-if="structure.mdSpec"
            shrink
          >
            <core-spec-btn
              :link="structure.mdSpec.link"
              :version="structure.mdSpec.version"
            />
          </v-flex>
        </v-layout>
        <div v-if="structure.titleText">
          <doc-text class="mb-6">
            {{ structure.titleText }}
          </doc-text>
        </div>
      </section>

      <component
        :is="getComponent(child.type)"
        v-for="(child, i) in structure.children"
        :key="`${composite}-${i}`"
        :value="child"
      />

      <doc-contribution :branch="branch" />
    </template>
  </v-container>
  <not-found v-else />
</template>

<script>
  // Utilities
  import {
    mapGetters,
    mapState,
  } from 'vuex'
  import { getComponent, getBranch } from '@/util/helpers'
  import kebabCase from 'lodash/kebabCase'

  export default {
    name: 'CorePage',

    components: {
      NotFound: () => import('@/pages/general/404'),
    },

    provide () {
      return {
        id: this.id
      }
    },

    data: () => ({
      timeout: null,
      branch: null,
    }),

    computed: {
      ...mapGetters('documentation', [
        'namespace',
        'page',
      ]),
      ...mapState('documentation', ['structure']),
      ...mapState('route', ['params']),
      composite () {
        return `${this.params.namespace}-${this.params.page}`
      },
      id () {
        if (!this.structure) return

        return kebabCase(this.$t(
          `${this.namespace}.${this.page}.${this.structure.title}`
        ))
      },
    },

    watch: {
      '$route.path': 'init',
    },

    mounted () {
      this.init()

      this.branch = getBranch()
    },

    methods: {
      getComponent,
      async init () {
        clearTimeout(this.timeout)

        this.timeout = setTimeout(() => {
          const sameInternal = this.$el.querySelectorAll('a.markdown--same-internal')

          Array.prototype.forEach.call(sameInternal, el => {
            el.addEventListener('click', this.onSameInternalClick)
          })

          const internal = this.$el.querySelectorAll('a.markdown--internal')

          Array.prototype.forEach.call(internal, el => {
            el.addEventListener('click', this.onInternalClick)
          })
        }, 300)
      },
      onSameInternalClick (e) {
        e.preventDefault()

        this.$router.push(e.target)
      },
      onInternalClick (e) {
        e.preventDefault()

        const target = e.target.tagName === 'A'
          ? e.target
          : e.target.parentElement

        const lang = `/${this.params.lang}`
        const length = lang.length
        let href = target.getAttribute('href')

        // If missing leading forward slash
        if (href.charAt(0) !== '/') {
          href = `/${href}`
        }

        // If missing language
        if (href.slice(0, length) !== lang) {
          href = `${lang}${href}`
        }

        this.$router.push(href)
      },
    },
  }
</script>

<style lang="sass">
.page
  max-width: 1185px

#components-navigation-drawers
  .v-sheet,
  .v-card
    overflow: hidden
</style>


added "created date" tooltip when hovering over a comments' posted time

using recently created "parseFullDate" helper mixin, able to generate a longDate var that we can display in a tooltip when the user hovers over a comment's posted time; also added ";" to the endlines of the imports (probably missing in most files)

.tsil<template>
    <transition name="fade">

                    <router-link :to="'/' + '@' + list.owner.username" class="avatar user-select">

                    </router-link>

                    <router-link :to="'/' + '@' + list.owner.username" class="author user-select">
                        @{{ list.owner.username }}
                    </router-link>

                        <router-link class="go-gray h-underline" v-if="!full"
                        :to="'/submission/' + list.submission_id">
                            {{ date }} - {{ points }} Points
                        </router-link>

                        {{ date }} - {{ points }} Points

                    <comment-form :submission="list.submission_id" :parent="list.id"
                        :editing="editing" v-if="editing" :before="list.body" :id="list.id"
                            @patched-comment="patchComment"
                        ></comment-form>

                    <markdown :text="list.body" v-else></markdown>

                    <a class="reply" @click="commentReply" v-if="list.level < 8"
                    data-toggle="tooltip" data-placement="top" title="Reply">

                            <button class="item" @click="report" v-if="!owns">

                                Report
                            </button>

                            <button class="item" @click="destroy" v-if="owns">

                                Delete
                            </button>

                            <button class="item" @click="approve" v-if="showApprove">

                                Approve
                            </button>

                            <button class="item" @click="disapprove" v-if="showDisapprove">

                                Delete
                            </button>

                    <comment-form :submission="list.submission_id" :parent="list.id"></comment-form>

                <comment :list="c" v-for="c in sortedComments" :key="c.id" :full="full"></comment>

    </transition>
</template>


removes the datetime picker component

removes the datetime picker component

<template>

            <select class="input pr-2" v-model="dateElements.month">
                <option v-for="value in Array.from({length: 12}, (_, i) => String(i + 1).padStart(2, '0'))"
                        :value="value">{{ value }}
                </option>
            </select>
            /
            <select class="input px-2" v-model="dateElements.day">
                <option v-for="value in Array.from({length: 31}, (_, i) => String(i + 1).padStart(2, '0'))"
                        :value="value">{{ value }}
                </option>
            </select>
            /
            <select class="input px-2" v-model="dateElements.year">
                <option v-for="value in Array.from({length: 15}, (_, i) => i + (new Date()).getFullYear() - 10)"
                        :value="value">{{ value }}
                </option>
            </select>

            <select class="input px-2" v-model="dateElements.hour">
                <option v-for="value in Array.from({length: 24}, (_, i) => String(i).padStart(2, '0'))" :value="value">
                    {{ value }}
                </option>
            </select>
            :
            <select class="input pl-2" v-model="dateElements.minute">
                <option v-for="value in Array.from({length: 60}, (_, i) => String(i).padStart(2, '0'))" :value="value">
                    {{ value }}
                </option>
            </select>

        <input hidden type="hidden" name="published_at" v-model="result">

</template>


play back page will not show map

play back page will not show map

<script>
	import Konva from '../../../plugins/konva/playback'
	export default {
		data: () => {
			return {
				show: true
			}
		},
		mounted(){
			let konva = new Konva()
			this.konva = konva
		},
		methods: {
			showCover: function (data) {
				this.show = data
				this.konva.showCover(data)
			}
		},
		computed: Vuex.mapState('playback', [
			'selectedMap',
            'selectedTrack'
		]),
		watch: {
			selectedMap: function (map) {
				if(!map.id) return
				this.konva.addBackGroundImg(map.background)
				this.konva.drawCovers(map.covers)
			},
			selectedTrack: function (track) {
				if(!track.id) return
				this.konva.drawTracks(track.tracks)
			}
		}

	}
</script>

<template lang="pug" src="./index.pug"></template>

<style lang="sass">
    @import "./index.scss"
</style>

<script>
	import Konva from '../../../plugins/konva/playback'
	export default {
		data: () => {
			return {
				show: true
			}
		},
		mounted(){
			let konva = new Konva()
			konva.addBackGroundImg()
			this.konva = konva
		},
		methods: {
			showCover: function (data) {
				this.show = data
				this.konva.showCover(data)
			}
		},
		computed: Vuex.mapState('playback', [
			'selectedMap',
            'selectedTrack'
		]),
		watch: {
			selectedMap: function (map) {
				if(!map.id) return
				this.konva.drawCovers(map.covers)
			},
			selectedTrack: function (track) {
				if(!track.id) return
				this.konva.drawTracks(track.tracks)
			}
		}

	}
</script>

<template lang="pug" src="./index.pug"></template>

<style lang="sass">
    @import "./index.scss"
</style>


Hide card if statusCode is 404

Hide card if statusCode is 404

<template>
  <uw-card v-if="!isReady || (shownEvents.length > 0 || futureCalCount > 0)"
    :loaded="isReady"
    :errored="isErrored"
    :errored-show="showError"
  >
    <template #card-heading>

        Events

    </template>
    <template v-if="shownEvents.length > 0" #card-body>

        Showing events in the next 14 days.

      <uw-list-events :events="shownEvents" />
    </template>
    <template v-else #card-body>

 0">

          No events in the next 14 days.
          {{ futureCalCount }}
          {{ futureCalCount > 1 ? 'events' : 'event' }}
          from {{ futureCalLinks.length }} calendars in the next 30 days.

            {{ event.title }}

          No events in the next 14 days.
          {{ futureCalCount }}
          {{ futureCalCount > 1 ? 'events' : 'event' }}
          from

            {{ event.title }}

          in the next 30 days.

    </template>

    <template v-if="hiddenEvents.length > 0" #card-disclosure>

        <uw-list-events :events="hiddenEvents" />

 1" class="mt-3">

            See all events from:

              {{ event.title }}

            See all events from

              {{ calLinks[0].title }}

            calendar.

    </template>
    <template v-else-if="calLinks.length > 0" #card-disclosure>

 1">

            See all events from:

              {{ event.title }}

          See all events from
            {{ calLinks[0].title }}
           calendar.

    </template>
    <template v-if="hiddenEvents.length > 0" #card-footer>

        Future Events

    </template>
  </uw-card>
</template>

<template>
  <uw-card v-if="!isReady || (shownEvents.length > 0 || futureCalCount > 0)"
           :loaded="isReady" :errored="isErrored"
  >
    <template #card-heading>

        Events

    </template>
    <template v-if="shownEvents.length > 0" #card-body>

        Showing events in the next 14 days.

      <uw-list-events :events="shownEvents" />
    </template>
    <template v-else #card-body>

 0">

          No events in the next 14 days.
          {{ futureCalCount }}
          {{ futureCalCount > 1 ? 'events' : 'event' }}
          from {{ futureCalLinks.length }} calendars in the next 30 days.

            {{ event.title }}

          No events in the next 14 days.
          {{ futureCalCount }}
          {{ futureCalCount > 1 ? 'events' : 'event' }}
          from

            {{ event.title }}

          in the next 30 days.

    </template>

    <template v-if="hiddenEvents.length > 0" #card-disclosure>

        <uw-list-events :events="hiddenEvents" />

 1" class="mt-3">

            See all events from:

              {{ event.title }}

            See all events from

              {{ calLinks[0].title }}

            calendar.

    </template>
    <template v-else-if="calLinks.length > 0" #card-disclosure>

 1">

            See all events from:

              {{ event.title }}

          See all events from
            {{ calLinks[0].title }}
           calendar.

    </template>
    <template v-if="hiddenEvents.length > 0" #card-footer>

        Future Events

    </template>
  </uw-card>
</template>


add labels to components

add labels to components

<template>

            {{field.name}}

            {{ driller.first_name }} {{ driller.surname }}
            {{ driller.organization_name }}
            {{ driller.street_address }}
{{ driller.city }}, {{ driller.province_state }}

Phone: {{ driller.contact_tel }}

Email: {{ driller.contact_email }}

            {{ driller.activity }}

            {{ driller.status }}
            <router-link :to="{ name: 'PersonDetail', params: { person_guid: driller.person_guid } }">Details</router-link>

No results were found.

      Showing {{ drillers.offset + 1 }} to {{ drillers.offset + drillers.results.length }} of {{ drillers.count }}

            <button @click="paginationPrev" class="btn btn-default" aria-label="Previous" id="table-pagination-prev">
              Previous
            </button>

            <button class="btn btn-default disabled" aria-hidden="true">
              Previous
            </button>

            <button @click="paginationNext" class="btn btn-default" aria-label="Next" id="table-pagination-next">
              Next
            </button>

            <button class="btn btn-default disabled" aria-hidden="true">
              Next
            </button>

</template>

<template>

            {{field.name}}

            {{ driller.first_name }} {{ driller.surname }}
            {{ driller.organization_name }}
            {{ driller.street_address }}
{{ driller.city }}, {{ driller.province_state }}

Phone: {{ driller.contact_tel }}

Email: {{ driller.contact_email }}

            {{ driller.activity }}

            {{ driller.status }}
            <router-link :to="{ name: 'PersonDetail', params: { person_guid: driller.person_guid } }">Details</router-link>

No results were found.

      Showing {{ drillers.offset + 1 }} to {{ drillers.offset + drillers.results.length }} of {{ drillers.count }}

            <button @click="paginationPrev" class="btn btn-default" aria-label="Previous">
              Previous
            </button>

            <button class="btn btn-default disabled" aria-hidden="true">
              Previous
            </button>

            <button @click="paginationNext" class="btn btn-default" aria-label="Next" id="table-pagination-next">
              Next
            </button>

            <button class="btn btn-default disabled" aria-hidden="true" id="table-pagination-prev">
              Next
            </button>

</template>


Update reversi.game.vue

Update reversi.game.vue

<template>

	<button class="go-index" v-if="selfNav" @click="goIndex">%fa:arrow-left%</button>
	<router-link :to="blackUser | userPage">{{ blackUser | userName }}</router-link>(%i18n:common.reversi.black%) vs <router-link :to="whiteUser | userPage">{{ whiteUser | userName }}</router-link>(%i18n:common.reversi.white%)

{{ '%i18n:common.reversi.turn-of%'.replace('{}', $options.filters.userName(turnUser)) }}<mk-ellipsis/>

{{ '%i18n:common.reversi.past-turn-of%'.replace('{}', $options.filters.userName(turnUser)) }}

%i18n:common.reversi.opponent-turn%<mk-ellipsis/>

%i18n:common.reversi.my-turn%

			<template v-if="game.winner">
				{{ '%i18n:common.reversi.won%'.replace('{}', $options.filters.userName(game.winner)) }}
				 (%i18n:@surrendered%)
			</template>
			<template v-else>%i18n:common.reversi.drawn%</template>

			{{ String.fromCharCode(64 + i) }}

{{ i }}

				<div v-for="(stone, i) in o.board"
						:class="{ empty: stone == null, none: o.map[i] == 'null', isEnded: game.isEnded, myTurn: !game.isEnded && isMyTurn, can: turnUser ? o.canPut(turnUser.id == blackUser.id, i) : null, prev: o.prevPos == i }"
						@click="set(i)"
						:title="`${String.fromCharCode(65 + o.transformPosToXy(i)[0])}${o.transformPosToXy(i)[1] + 1}`">

{{ i }}

			{{ String.fromCharCode(64 + i) }}

{{ '%i18n:common.reversi.this-turn%'.split('{}')[0] }}{{ logPos }}{{ '%i18n:common.reversi.this-turn%'.split('{}')[1] }} %i18n:common.reversi.black%:{{ o.blackCount }} %i18n:common.reversi.white%:{{ o.whiteCount }} %i18n:common.reversi.total%:{{ o.blackCount + o.whiteCount }}

		<form-button @click="surrender">%i18n:@surrender%</form-button>

		<el-button-group>
			<el-button type="primary" @click="logPos = 0" :disabled="logPos == 0">%fa:angle-double-left%</el-button>
			<el-button type="primary" @click="logPos--" :disabled="logPos == 0">%fa:angle-left%</el-button>
		</el-button-group>
		{{ logPos }} / {{ logs.length }}
		<el-button-group>
			<el-button type="primary" @click="logPos++" :disabled="logPos == logs.length">%fa:angle-right%</el-button>
			<el-button type="primary" @click="logPos = logs.length" :disabled="logPos == logs.length">%fa:angle-double-right%</el-button>
		</el-button-group>

%i18n:@is-llotheo%

%i18n:@looped-map%

%i18n:@can-put-everywhere%

</template>


base-input-checkbox can be disabled

base-input-checkbox can be disabled

<template>

    <input
      v-show="editable"
      ref="inputRef"
      :id="id"
      :name="name"
      type="checkbox"
      :value="value"
      :checked="value"
      :disabled="disabled"
      @input="updateValue"
      @change="changeValue"
      @blur="onBlur"
      @focus="$emit('focus')"
    >
    {{ value }}  Edit

    {{label}}
      <slot name="description">
        {{description}}
      </slot>

    <button v-if="inline && editable" @mousedown="onSave" class="button">OK</button>

    <slot name="actions"></slot>

</template>

<template>

    <input
      v-show="editable"
      ref="inputRef"
      :id="id"
      :name="name"
      type="checkbox"
      :value="value"
      :checked="value"
      @input="updateValue"
      @change="changeValue"
      @blur="onBlur"
      @focus="$emit('focus')"
    >
    {{ value }}  Edit

    {{label}}
      <slot name="description">
        {{description}}
      </slot>

    <button v-if="inline && editable" @mousedown="onSave" class="button">OK</button>

    <slot name="actions"></slot>

</template>


l10n: Improved grammar regarding board transfer

Reported at Transifex.

Signed-off-by: rakekniven <431c871bb5514e240c815672fa1af6e63423a115@users.noreply.github.com>

<template>

		<Multiselect
			v-if="canShare"
			v-model="addAcl"
			:placeholder="t('deck', 'Share board with a user, group or circle …')"
			:options="formatedSharees"
			:user-select="true"
			label="displayName"
			:loading="isLoading || !!isSearching"
			:disabled="isLoading"
			track-by="multiselectKey"
			:internal-search="false"
			@input="clickAddAcl"
			@search-change="asyncFind">
			<template #noOptions>
				{{ isSearching ? t('deck', 'Searching for users, groups and circles …') : t('deck', 'No participants found') }}
			</template>
			<template #noResult>
				{{ isSearching ? t('deck', 'Searching for users, groups and circles …') : t('deck', 'No participants found') }}
			</template>
		</Multiselect>

				<Avatar :user="board.owner.uid" />

					{{ board.owner.displayname }}

						{{ t('deck', 'Board owner') }}

				<Avatar v-if="acl.type===0" :user="acl.participant.uid" />

					{{ acl.participant.displayname }}
					{{ t('deck', '(Group)') }}
					{{ t('deck', '(Circle)') }}

				<ActionCheckbox v-if="!(isCurrentUser(acl.participant.uid) && acl.type === 0) && (canManage || (canEdit && canShare))" :checked="acl.permissionEdit" @change="clickEditAcl(acl)">
					{{ t('deck', 'Can edit') }}
				</ActionCheckbox>
				<Actions v-if="!(isCurrentUser(acl.participant.uid) && acl.type === 0)" :force-menu="true">
					<ActionCheckbox v-if="canManage || canShare" :checked="acl.permissionShare" @change="clickShareAcl(acl)">
						{{ t('deck', 'Can share') }}
					</ActionCheckbox>
					<ActionCheckbox v-if="canManage" :checked="acl.permissionManage" @change="clickManageAcl(acl)">
						{{ t('deck', 'Can manage') }}
					</ActionCheckbox>
					<ActionCheckbox v-if="acl.type === 0 && isCurrentUser(board.owner.uid)" :checked="acl.owner" @change="clickTransferOwner(acl.participant.uid)">
						{{ t('deck', 'Owner') }}
					</ActionCheckbox>
					<ActionButton v-if="canManage" icon="icon-delete" @click="clickDeleteAcl(acl)">
						{{ t('deck', 'Delete') }}
					</ActionButton>
				</Actions>

		<CollectionList v-if="board.id"
			:id="`${board.id}`"
			:name="board.title"
			type="deck" />

</template>


Fixed food count appear negative value.

Fixed food count appear negative value.

<template>

    <transition name="move">

 0" @click="decreaseCart($event)">

    </transition>

 0">{{food.count}}

</template>


Added EditorToolbar comment button toggles CA-38

<template>

                    <button
                        class="button is-text"
                        @click="showPropertyViewDropDown = !showPropertyViewDropDown"
                        aria-haspopup="true">
                        View

                    </button>

                            Primary Properties

                            Secondary Properties

                            Tertiary Properties

                    <button
                        class="button is-text"
                        @click="showShareDropdown = !showShareDropdown"
                        aria-haspopup="true">
                        Share

                    </button>

                            Export

                            Manage Users

                <input
                    class="input"
                    type="text"
                    placeholder="Text input">

</template>


fix(spacing): remove comment white space

<template>

      Selects

      <cdr-select
        label="Default"
        v-model="selectedA"
        :background="backgroundColor"
        prompt="Choose one"

        @select-change="doExternal"
      >
        <option value="1">
          1
        </option>
        <option value="2">
          2
        </option>
        <option value="3">
          3
        </option>
        <option value="4">
          4
        </option>
      </cdr-select>
      <cdr-text>Selected Value: {{ selectedA }}</cdr-text>

      <cdr-select
        label="Required with Prompt"
        v-model="selectedB"
        :background="backgroundColor"
        prompt="Choose one"
        required
      >
        <option value="1">
          1
        </option>
        <option value="2">
          2
        </option>
        <option value="3">
          3
        </option>
        <option value="4">
          4
        </option>
      </cdr-select>
      <cdr-text>Selected Value: {{ selectedB }}</cdr-text>

    <cdr-select
      label="Disabled select"
      v-model="selectedDisabled"
      :background="backgroundColor"
      disabled
    >
      <option value="1">
        1
      </option>
    </cdr-select>
    <cdr-text>Selected: {{ selectedDisabled }}</cdr-text>

    <cdr-select
      label="Hidden label text"
      hide-label
      v-model="selectedC"
      :background="backgroundColor"
      prompt="Hidden label"
    >
      <option value="1">
        1
      </option>
      <option value="2">
        2
      </option>
      <option value="3">
        3
      </option>
      <option value="4">
        4
      </option>
    </cdr-select>
    <cdr-text>Selected Value: {{ selectedC }}</cdr-text>

    <cdr-select
      label="No Prompt"

      v-model="selectedD"
      :background="backgroundColor"
    >
      <option value="1">
        1
      </option>
      <option value="2">
        2
      </option>
      <option value="3">
        3
      </option>
      <option value="REALLY REALLY LONG VALUE REALLY REALLY LONG VALUE">
        REALLY REALLY LONG VALUE REALLY REALLY LONG VALUE
      </option>
    </cdr-select>
    <cdr-text>Selected Value: {{ selectedD }}</cdr-text>

    <cdr-select
      label="Dynamic"
      v-model="dynamic"
      :background="backgroundColor"
      :options="dynamicData"

      prompt="Choose One"
    />
    <cdr-text>Selected: {{ dynamic }}</cdr-text>

    <cdr-select
      label="Example with Helper Text"
      v-model="helperTextModel"
      :background="backgroundColor"
      :options="dynamicData"

      prompt="Choose One"
    >
      <template slot="helper-text">
        This is helper text.
      </template>

      <template slot="info">
        <cdr-link
          href="#/selects"
          modifier="standalone"
        >
          Info Link/Icon
        </cdr-link>
      </template>
    </cdr-select>
    <cdr-text>Selected Value: {{ helperTextModel }}</cdr-text>

    <cdr-select
      label="Example with Info Link"
      v-model="infoLinkModel"
      :background="backgroundColor"
      :options="dynamicData"

      prompt="Choose One"
    >
      <template slot="info">
        <cdr-link
          href="#/selects"
          modifier="standalone"
        >
          Info Link/Icon
        </cdr-link>
      </template>
    </cdr-select>
    <cdr-text>Selected: {{ infoLinkModel }}</cdr-text>

    <cdr-select
      label="Example with Info Icon"
      v-model="infoIconModel"
      :background="backgroundColor"
      :options="dynamicData"

      prompt="Choose One"
    >
      <template slot="info-action">
        <cdr-link
          tag="button"
          type="button"
        >
          <icon-information-stroke inherit-color />
          Information!
        </cdr-link>
      </template>
    </cdr-select>
    <cdr-text>Selected Value: {{ infoIconModel }}</cdr-text>

    <cdr-select
      label="Example with Pre Icon"
      v-model="preIconModel"
      :background="backgroundColor"
      :options="dynamicData"

      prompt="Choose One"
    >
      <template slot="pre-icon">
        <icon-lock-locked-stroke />
      </template>
    </cdr-select>
    <cdr-text>Selected Value: {{ preIconModel }}</cdr-text>

    <cdr-select
      label="Example with status error"
      v-model="preIconModel"
      :background="backgroundColor"
      :options="dynamicData"
      aria-describedby="statusTest"

      prompt="Choose One"
      :error="true"
    >
      <template slot="error">
        error message goes here
      </template>
    </cdr-select>

    <cdr-select
      label="Example with Alert error"
      v-model="preIconModel2"
      :background="backgroundColor"
      :options="dynamicData"
      error-role="alert"
      aria-describedby="alertTest"

      prompt="Choose One"
      :error="true"
    >
      <template slot="error">
        Alert error message goes here
      </template>
    </cdr-select>

    <cdr-select
      label="Size = Large"
      v-model="dynamic"
      :background="backgroundColor"
      size="large"
      :options="dynamicData"

      prompt="Choose One"
    />
    <cdr-text>Selected Value: {{ dynamic }}</cdr-text>

      Multiple Select with size

    <cdr-select
      label="Multiple Prompt"
      v-model="multiple"
      :background="backgroundColor"
      :multiple-size="6"
      multiple
    >
      <option
        value="1"
      >
        1
      </option>
      <option value="2">
        2
      </option>
      <option
        value="3"
      >
        3
      </option>
      <option value="4">
        4
      </option>
      <option value="5">
        5
      </option>
      <option value="6">
        6
      </option>
    </cdr-select>
    <cdr-text>Selected Values: {{ multiple }}</cdr-text>

      Multiple Select

    <cdr-select
      label="Multiple Prompt"
      v-model="multiple2"
      :background="backgroundColor"
      multiple
      :options="multiple2Data"
    />
    <cdr-text>Selected Values: {{ multiple2 }}</cdr-text>

</template>


Remove tournament controls from non-judges

<template>

{{tournament.name}}

        Join

Start

Next match

Tryouts

        <template v-for="m in tournament.tryouts">
          <match-overview :match="m" class="match {{m.kind}}">
        </template>

Semi-finals

        <template v-for="m in tournament.semis">
          <match-overview :match="m" class="match {{m.kind}}">
        </template>

 0">

Runnerups

          <template v-for="player in runnerups">

{{player.name}}

                {{player.score}} points
                /
                {{player.matches}} matches

          </template>

Final

        <match-overview :match="tournament.final" class="match final">

</template>


Fix un-registered isSuperuser getter

Fix un-registered isSuperuser getter

<template>

  <core-base :topLevelPageName="topLevelPageName" :appBarTitle="$tr('coachTitle')">

      <template v-if="showTopNav">
        <class-selector :classes="classList" :currentClassId="classId" @changeClass="changeClass"/>
        <top-nav/>
      </template>

        <component :is="currentPage"/>

      <auth-message v-else authorizedRole="adminOrCoach" />

  </core-base>

</template>


feat(docs): Remove unused example file

feat(docs): Remove unused example file

<template>

    <q-avatar size="32px" font-size="26px" color="primary" text-color="grey-4">
      Q
    </q-avatar>
    <q-avatar size="32px" color="teal" text-color="grey-4" icon="wifi" />
    <q-avatar size="32px" color="primary">

    </q-avatar>

</template>


fix(form-textarea): correct CSS value for no resize

Also allow rows and max-rows values to be passed as a string

<template>
    <textarea v-model="localValue"
              :class="inputClass"
              :style="inputStyle"
              :id="safeId()"
              :name="name"
              :disabled="disabled"
              :placeholder="placeholder"
              :required="required"
              :autocomplete="autocomplete || null"
              :readonly="readonly || plaintext"
              :rows="rowsCount"
              :wrap="wrap || null"
              :aria-required="required ? 'true' : null"
              :aria-invalid="computedAriaInvalid"
    ></textarea>
</template>

<script>
    import { idMixin, formMixin, formSizeMixin, formStateMixin } from '../mixins';
    export default {
        mixins: [idMixin, formMixin, formSizeMixin, formStateMixin],
        data() {
            return {
                localValue: this.value
            };
        },
        props: {
            value: {
                type: String,
                default: ''
            },
            ariaInvalid: {
                type: [Boolean, String],
                default: false
            },
            readonly: {
                type: Boolean,
                default: false
            },
            plaintext: {
                type: Boolean,
                default: false
            },
            autocomplete: {
                type: String,
                default: null
            },
            placeholder: {
                type: String,
                default: null
            },
            rows: {
                type: [Number, String],
                default: null
            },
            maxRows: {
                type: [Number, String],
                default: null
            },
            wrap: {
                // 'soft', 'hard' or 'off'. Browser default is 'soft'
                type: String,
                default: 'soft'
            },
            noResize: {
                type: Boolean,
                default: false
            }
        },
        computed: {
            rowsCount() {
                const rows = parseInt(this.rows, 10) || 1;
                const maxRows = parseInt(this.maxRows, 10) || 0;
                const lines = (this.value || '').toString().split('\n').length;
                return maxRows ? Math.min(maxRows, Math.max(rows, lines)) : Math.max(rows, lines);
            },
            inputClass() {
                return [
                    this.plaintext ? 'form-control-plaintext' : 'form-control',
                    this.sizeFormClass,
                    this.stateClass
                ];
            },
            inputStyle() {
                // We set width 100% in plaintext mode to get around a shortcoming in bootstrap CSS
                // setting noResize to true will disable the ability for the user to resize the textarea
                return {
                    width: this.plaintext ? '100%' : null,
                    resize: this.noResize ? 'none' : null
                };
            },
            computedAriaInvalid() {
                if (!Boolean(this.ariaInvalid) || this.ariaInvalid === 'false') {
                    // this.ariaInvalid is null or false or 'false'
                    return this.computedState === false ? 'true' : null ;
                }
                if (this.ariaInvalid === true) {
                   // User wants explicit aria-invalid=true
                    return 'true';
                }
                // Most likely a string value (which could be the string 'true')
                return this.ariaInvalid;
            }
        },
        watch: {
            value(newVal, oldVal) {
                // Update our localValue
                if (newVal !== oldVal) {
                    this.localValue = newVal;
                }
            },
            localValue(newVal, oldVal) {
                // update Parent value
                if (newVal !== oldVal) {
                    this.$emit('input', newVal);
                }
            }
        },
        methods: {
            focus() {
                // For external handler that may want a focus method
                if(!this.disabled) {
                    this.$el.focus();
                }
            }
        }
    };
</script>

<template>
    <textarea v-model="localValue"
              :class="inputClass"
              :style="inputStyle"
              :id="safeId()"
              :name="name"
              :disabled="disabled"
              :placeholder="placeholder"
              :required="required"
              :autocomplete="autocomplete || null"
              :readonly="readonly || plaintext"
              :rows="rowsCount"
              :wrap="wrap || null"
              :aria-required="required ? 'true' : null"
              :aria-invalid="computedAriaInvalid"
    ></textarea>
</template>

<script>
    import { idMixin, formMixin, formSizeMixin, formStateMixin } from '../mixins';
    export default {
        mixins: [idMixin, formMixin, formSizeMixin, formStateMixin],
        data() {
            return {
                localValue: this.value
            };
        },
        props: {
            value: {
                type: String,
                default: ''
            },
            ariaInvalid: {
                type: [Boolean, String],
                default: false
            },
            readonly: {
                type: Boolean,
                default: false
            },
            plaintext: {
                type: Boolean,
                default: false
            },
            autocomplete: {
                type: String,
                default: null
            },
            placeholder: {
                type: String,
                default: null
            },
            rows: {
                type: Number,
                default: null
            },
            maxRows: {
                type: Number,
                default: null
            },
            wrap: {
                // 'soft', 'hard' or 'off'. Browser default is 'soft'
                type: String,
                default: 'soft'
            },
            noResize: {
                type: Boolean,
                default: false
            }
        },
        computed: {
            rowsCount() {
                const rows = this.rows || 1;
                const lines = (this.value || '').toString().split('\n').length;
                return this.maxRows ? Math.min(this.maxRows, Math.max(rows, lines)) : Math.max(rows, lines);
            },
            inputClass() {
                return [
                    this.plaintext ? 'form-control-plaintext' : 'form-control',
                    this.sizeFormClass,
                    this.stateClass
                ];
            },
            inputStyle() {
                // We set width 100% in plaintext mode to get around a shortcoming in bootstrap CSS
                // setting noResize to true will disable the ability for the user to resize the textarea
                return {
                    width: this.plaintext ? '100%' : null,
                    resize: this.noResize ? 'false' : null
                };
            },
            computedAriaInvalid() {
                if (!Boolean(this.ariaInvalid) || this.ariaInvalid === 'false') {
                    // this.ariaInvalid is null or false or 'false'
                    return this.computedState === false ? 'true' : null ;
                }
                if (this.ariaInvalid === true) {
                   // User wants explicit aria-invalid=true
                    return 'true';
                }
                // Most likely a string value (which could be the string 'true')
                return this.ariaInvalid;
            }
        },
        watch: {
            value(newVal, oldVal) {
                // Update our localValue
                if (newVal !== oldVal) {
                    this.localValue = newVal;
                }
            },
            localValue(newVal, oldVal) {
                // update Parent value
                if (newVal !== oldVal) {
                    this.$emit('input', newVal);
                }
            }
        },
        methods: {
            focus() {
                // For external handler that may want a focus method
                if(!this.disabled) {
                    this.$el.focus();
                }
            }
        }
    };
</script>


Update attributes example.

Update attributes example.

<template>
  <div class="example">
    <v-calendar :attributes="attributes"/>
  </div>
</template>

<script>
const { pageForThisMonth, pageForNextMonth } = require('@/utils/helpers');
let { month: thisMonth, year: thisMonthYear } = pageForThisMonth();
let { month: nextMonth, year: nextMonthYear } = pageForNextMonth();
thisMonth--;
nextMonth--;

const meetings = [
  {
    description: 'Bi-weekly staff meeting.',
    // Every other Monday morning :(
    dates: {
      weeklyInterval: 2,
      weekdays: 2,
    },
    color: 'blue',
  },
  {
    description: 'Meeting to discuss the new project.',
    dates: {
      start: new Date(thisMonthYear, thisMonth, 9),
      span: 3,
    },
    color: 'red',
  },
  {
    description: 'Out of town on business.',
    dates: {
      start: new Date(thisMonthYear, thisMonth, 25),
      span: 2,
    },
    color: 'green',
  },
];

const todos = [
  {
    description: 'Take Noah to basketball practice.',
    isComplete: false,
    dates: { weekdays: 6 }, // Every Friday
    color: 'gray',
  },
  {
    description: 'Get some milks.',
    isComplete: false,
    dates: [
      new Date(thisMonthYear, thisMonth, 19),
      new Date(thisMonthYear, thisMonth, 23),
      new Date(nextMonthYear, nextMonth, 9),
    ],
    color: 'purple',
  },
];

export default {
  data() {
    return {
      incId: todos.length,
      meetings,
      todos,
    };
  },
  computed: {
    attributes() {
      return [
        // Today attribute
        {
          highlight: {
            fillMode: 'none',
            color: 'purple',
            class: 'rounded-none bg-transparent',
          },
          content: {
            class: 'italic',
            color: 'purple',
          },
          dates: new Date(),
          order: 100,
        },
        // Attributes for meetings
        ...this.meetings.map(({ description, dates, color }) => ({
          dates,
          highlight: color,
          popover: {
            label: description,
          },
        })),
        // Attributes for todos
        ...this.todos.map(todo => ({
          dates: todo.dates,
          dot: {
            color: todo.color,
            class: todo.isComplete ? 'opacity-25' : '',
          },
          popover: {
            label: todo.description,
          },
        })),
      ];
    },
  },
};
</script>

<template>
  <div class="example">
    <v-calendar :attributes="attributes"/>
  </div>
</template>

<script>
const { pageForThisMonth, pageForNextMonth } = require('@/utils/helpers');
let { month: thisMonth, year: thisMonthYear } = pageForThisMonth();
let { month: nextMonth, year: nextMonthYear } = pageForNextMonth();
thisMonth--;
nextMonth--;

const meetings = [
  {
    description: 'Bi-weekly staff meeting.',
    // Every other Monday morning :(
    dates: {
      weeklyInterval: 2,
      weekdays: 2,
    },
    color: 'blue',
  },
  {
    description: 'Meeting to discuss the new project.',
    dates: {
      start: new Date(thisMonthYear, thisMonth, 9),
      span: 3,
    },
    color: 'red',
  },
  {
    description: 'Out of town on business.',
    dates: {
      start: new Date(thisMonthYear, thisMonth, 25),
      span: 2,
    },
    color: 'green',
  },
];

const todos = [
  {
    description: 'Take Noah to basketball practice.',
    isComplete: false,
    dates: { weekdays: 6 }, // Every Friday
    color: 'gray',
  },
  {
    description: 'Get some milks.',
    isComplete: false,
    dates: [
      new Date(thisMonthYear, thisMonth, 19),
      new Date(thisMonthYear, thisMonth, 23),
      new Date(nextMonthYear, nextMonth, 9),
    ],
    color: 'purple',
  },
];

export default {
  data() {
    return {
      incId: todos.length,
      meetings,
      todos,
    };
  },
  computed: {
    attributes() {
      return [
        // Today attribute
        {
          highlight: {
            fillMode: 'none',
            color: 'purple',
            class: 'rounded-none',
          },
          content: {
            class: 'italic',
            color: 'purple',
          },
          dates: new Date(),
        },
        // Attributes for meetings
        ...this.meetings.map(({ description, dates, color }) => ({
          dates,
          highlight: color,
          popover: {
            label: description,
          },
        })),
        // Attributes for todos
        ...this.todos.map(todo => ({
          dates: todo.dates,
          dot: {
            color: todo.color,
            class: todo.isComplete ? 'opacity-25' : '',
          },
          popover: {
            label: todo.description,
          },
        })),
      ];
    },
  },
};
</script>


Removed button for navigation an used link.

<template>

Konfiguration für '
                    <router-link :to="{name: 'orgDetail', params: {id: $route.params.id}}">
                        {{config.organization.name}}'
                    </router-link>

            <administrator :admins="config.organization.administrators"
                           @changed="configChanged"></administrator>
            <networking-platform-config v-for="networkingPlatform in config.networkingPlatforms"
                                        :np="networkingPlatform" @changed="configChanged">
            </networking-platform-config>

        <change-config-command v-show="showConfigChanged"></change-config-command>

</template>

<template>

Konfiguration für '{{config.organization.name}}'

                    <button type="button" class="btn btn-default"
                            v-on:click="$router.push({name: 'orgDetail', params: {id: $route.params.id}})">
                        Detailansicht
                    </button>

            <administrator :admins="config.organization.administrators"
                           @changed="configChanged"></administrator>
            <networking-platform-config v-for="networkingPlatform in config.networkingPlatforms"
                                        :np="networkingPlatform" @changed="configChanged">
            </networking-platform-config>

        <change-config-command v-show="showConfigChanged"></change-config-command>

</template>


:children_crossing: (plant) Removes double-tap for name change

<template>

      yay edit that thang

        <v-touch tag="h1"
          @tap="updateTitle"
          :contenteditable="editTitle"
          @blur.native="emitTitleUpdate">
          {{ name }}
        </v-touch>

        <svgicon
          v-else
          icon="cactus"
          width="50"
          height="50"
          color="#000" />

</template>

<template>

      yay edit that thang

        <v-touch tag="h1"
          @tap="updateTitle"
          :tap-options="{ taps: 2 }"
          :contenteditable="editTitle"
          @blur.native="emitTitleUpdate">
          {{ name }}
        </v-touch>

        <svgicon
          v-else
          icon="cactus"
          width="50"
          height="50"
          color="#000" />

</template>


added noopener,noreferrer to hotspot urls

<template>

        <template v-if="screens.length > 1">

        </template>

 0 && !inTransition"
                class="fixed-screen-header"
                :style="{
                    'height':     (activeScreen.fixedHeader * scaleFactor) + 'px',
                    'margin-top': (-activeScreen.fixedHeader * scaleFactor) + 'px',
                }"
            >

                            <div v-for="hotspot in activeScreenHotspots"
                                v-if="hotspot.top < activeScreen.fixedHeader"
                                :key="'fixed_header_hotspot_' + hotspot.id"
                                class="hotspot"
                                :style="{
                                    'left':   (hotspot.left * scaleFactor) + 'px',
                                    'top':    (hotspot.top * scaleFactor) + 'px',
                                    'width':  (hotspot.width * scaleFactor) + 'px',
                                    'height': (hotspot.height * scaleFactor) + 'px',
                                }"
                                @click.prevent="hotspotNavigate(hotspot.id)"
                            >

                <img ref="activeScreen"
                    :key="'active_screen_' + activeScreen.id"
                    crossorigin="anonymous"
                    draggable="false"
                    class="screen"
                    :class="inTransition ? 'new-active-screen' : 'current-active-screen'"
                    :src="activeScreen.getImage()"
                    :alt="activeScreen.title"
                    v-tooltip.follow="activeScreenTooltip"
                    v-scale="screenScaleFactor"
                    @load="refreshActiveScreenWrapperAlignment()"
                    @mousedown.left.stop.prevent="$emit('activeScreenMousedown', $event)"
                    @click.left.stop.prevent="$emit('activeScreenClick', $event)"
                    @click="onOverlayOutsideClick"
                >

                    <div
                        class="overlay-screen-wrapper"
                        :class="[
                            ('transition-' + overlayScreenTransition),
                            ('position-' + overlayScreenPosition),
                            (isOverlayScreenClosing ? 'closing' : ''),
                        ]"
                        :style="{
                            'margin-top': (overlayScreenOffsetTop * scaleFactor) + 'px',
                            'margin-bottom': (overlayScreenOffsetBottom * scaleFactor) + 'px',
                            'margin-left': (overlayScreenOffsetLeft * scaleFactor) + 'px',
                            'margin-right': (overlayScreenOffsetRight * scaleFactor) + 'px',
                        }"
                    >

                            <div v-for="hotspot in overlayScreenHotspots"
                                :key="'overlay_screen_hotspot_' + hotspot.id"
                                class="hotspot"
                                :style="{
                                    'left':   (hotspot.left * scaleFactor) + 'px',
                                    'top':    (hotspot.top * scaleFactor) + 'px',
                                    'width':  (hotspot.width * scaleFactor) + 'px',
                                    'height': (hotspot.height * scaleFactor) + 'px',
                                }"
                                @click.prevent="hotspotNavigate(hotspot.id)"
                            >

                    <div v-for="hotspot in activeScreenHotspots"
                        :key="'active_screen_hotspot_' + hotspot.id"
                        class="hotspot"
                        :style="{
                            'left':   (hotspot.left * scaleFactor) + 'px',
                            'top':    (hotspot.top * scaleFactor) + 'px',
                            'width':  (hotspot.width * scaleFactor) + 'px',
                            'height': (hotspot.height * scaleFactor) + 'px',
                        }"
                        @click.prevent="hotspotNavigate(hotspot.id)"
                    >

                <slot></slot>

 0 && !inTransition"
                class="fixed-screen-footer"
                :style="{
                    'height':     (activeScreen.fixedFooter * scaleFactor) + 'px',
                    'margin-top': (-activeScreen.fixedFooter * scaleFactor) + 'px',
                }"
            >

                            <div v-for="hotspot in activeScreenHotspots"
                                :key="'fixed_footer_hotspot_' + hotspot.id"
                                class="hotspot"
                                :style="{
                                    'left':   (hotspot.left * scaleFactor) + 'px',
                                    'top':    (hotspot.top * scaleFactor) + 'px',
                                    'width':  (hotspot.width * scaleFactor) + 'px',
                                    'height': (hotspot.height * scaleFactor) + 'px',
                                }"
                                @click.prevent="hotspotNavigate(hotspot.id)"
                            >

</template>


Fix #1883 dateParser when range

Fix #1883 dateParser when range

<template>

            <b-input
                v-if="!inline"
                ref="input"
                slot="trigger"
                autocomplete="off"
                :value="formatValue(computedValue)"
                :placeholder="placeholder"
                :size="size"
                :icon="icon"
                :icon-pack="iconPack"
                :rounded="rounded"
                :loading="loading"
                :disabled="disabled"
                :readonly="!editable"
                v-bind="$attrs"
                :use-html5-validation="useHtml5Validation"
                @click.native="onInputClick"
                @keyup.native.enter="togglePicker(true)"
                @change.native="onChange($event.target.value)"
                @focus="handleOnFocus"
                @blur="onBlur" />

                    <template v-if="$slots.header !== undefined && $slots.header.length">
                        <slot name="header" />
                    </template>

                                    <option
                                        v-for="(month, index) in monthNames"
                                        :value="index"
                                        :key="month">
                                        {{ month }}
                                    </option>

                                    <option
                                        v-for="year in listOfYears"
                                        :value="year"
                                        :key="year">
                                        {{ year }}
                                    </option>

                    <b-datepicker-table
                        v-model="computedValue"
                        :day-names="dayNames"
                        :month-names="monthNames"
                        :first-day-of-week="firstDayOfWeek"
                        :rules-for-first-week="rulesForFirstWeek"
                        :min-date="minDate"
                        :max-date="maxDate"
                        :focused="focusedDateData"
                        :disabled="disabled"
                        :unselectable-dates="unselectableDates"
                        :unselectable-days-of-week="unselectableDaysOfWeek"
                        :selectable-dates="selectableDates"
                        :events="events"
                        :indicators="indicators"
                        :date-creator="dateCreator"
                        :type-month="isTypeMonth"
                        :nearby-month-days="nearbyMonthDays"
                        :nearby-selectable-month-days="nearbySelectableMonthDays"
                        :show-week-number="showWeekNumber"
                        :range="range"
                        :multiple="multiple"
                        @close="togglePicker(false)"/>

                    <b-datepicker-month
                        v-model="computedValue"
                        :month-names="monthNames"
                        :min-date="minDate"
                        :max-date="maxDate"
                        :focused="focusedDateData"
                        :disabled="disabled"
                        :unselectable-dates="unselectableDates"
                        :unselectable-days-of-week="unselectableDaysOfWeek"
                        :selectable-dates="selectableDates"
                        :events="events"
                        :indicators="indicators"
                        :date-creator="dateCreator"
                        @close="togglePicker(false)"/>

                    <slot/>

        <b-input
            v-else
            ref="input"
            :type="!isTypeMonth ? 'date' : 'month'"
            autocomplete="off"
            :value="formatNative(computedValue)"
            :placeholder="placeholder"
            :size="size"
            :icon="icon"
            :icon-pack="iconPack"
            :loading="loading"
            :max="formatNative(maxDate)"
            :min="formatNative(minDate)"
            :disabled="disabled"
            :readonly="false"
            v-bind="$attrs"
            :use-html5-validation="useHtml5Validation"
            @change.native="onChangeNativePicker"
            @focus="onFocus"
            @blur="onBlur"/>

</template>


[production] Make new production button wider

<template>

      <spinner />

 0"
    >

        {{ $t('productions.home.title') }}

        {{ $t('productions.home.create_new') }}

 0"
    >

 4
        }"
      >

          <router-link
            :to="getPath(production)"
          >

                {{ generateAvatar(production) }}

              {{ production.name }}

          </router-link>

          {{ $t('productions.home.empty') }}

          <button
            class="button big-button"
            @click="newProductionPage"
          >
            {{ $t('productions.home.create_new') }}
          </button>

          {{ $t('productions.home.no_prod_for_client') }}

          {{ $t('productions.home.no_task') }}

    <edit-production-modal
      :active="modals.isNewDisplayed"
      :is-loading="loading.edit"
      :is-error="errors.edit"
      @confirm="confirmEditProduction"
      @cancel="hideNewModal"
    />

</template>


remove ad

remove ad

<template>

      {{ $t('index.ourOtherProjects') }}

{{ friend.title }}

{{ friend.description }}

      {{ $t('index.ourPartners') }}

{{ friend.title }}

{{ friend.description }}

</template>

<template>

    <Ads />

      {{ $t('index.ourOtherProjects') }}

{{ friend.title }}

{{ friend.description }}

      {{ $t('index.ourPartners') }}

{{ friend.title }}

{{ friend.description }}

</template>


implented DICOM viewer panning\zooming support

<template>

{{ display }}

      <input
        class="DICOM-range"
        type="range"
        min="0"
        v-bind:max="view.paths.length - 1"
        v-bind:value="stack.currentImageIdIndex"
        v-on:input="rangeSlice($event)"
      >
      slice index: {{ stack.currentImageIdIndex }}

    <nodule-marker :marker="marker" :sliceIndex="stack.currentImageIdIndex"
                   :translation="translation"></nodule-marker>
    <area-select @selection-changed="areaSelectChange" v-if="showAreaSelect"
                 :areaCoordinates="areaCoordinates"></area-select>

</template>

<template>

{{ display }}

      <input
        class="DICOM-range"
        type="range"
        min="0"
        v-bind:max="view.paths.length - 1"
        v-bind:value="stack.currentImageIdIndex"
        v-on:input="rangeSlice($event)"
      >
      slice index: {{ stack.currentImageIdIndex }}

    <nodule-marker :marker="marker" :sliceIndex="stack.currentImageIdIndex" :zoomRate="zoomRate" :offsetX="offsetX" :offsetY="offsetY"></nodule-marker>
    <area-select @selection-changed="areaSelectChange" v-if="showAreaSelect" :areaCoordinates="areaCoordinates"></area-select>

</template>


Scrollable campaign summary stats

Scrollable campaign summary stats

remp/remp#569

<template>

Summary

                                Variant
                                Proportion
                                Shows
                                Clicks
                                Click-rate win probability
                                Click-through rate (CTR)
                                Conversions (purchases)
                                Conversion-rate win probability
                                Earned

                                {{ variant.name }}
                                {{ variant.name }}

                                {{ variant.proportion }}%

                                {{ variant.shows }}

                                {{ variant.clicks }}

                                <template v-if="variant.click_probability !== undefined">
                                    {{ variant.click_probability * 100 | round(2) }}%
                                </template>
                                <template v-else>
                                    -
                                </template>

                                    {{ variant.ctr | round(2) }}%

                                    {{ variant.purchases }}
                                    ({{ variant.conversions | round(4) }}%)

                                <template v-if="variant.purchase_probability !== undefined">
                                    {{ variant.purchase_probability * 100 | round(2) }}%
                                </template>
                                <template v-else>
                                    -
                                </template>

                                    {{ sum | round(2) }} {{ currency }}

</template>


修复搜索的时候跳转到了错误的路由～

修复搜索的时候跳转到了错误的路由～

<template>

      检索用户

        添加用户

        用户ID

              <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                排序
              </button>

                  由小到大

                  由大到小

            <input v-model="userId" type="number" class="form-control" id="search-input-id" placeholder="按照用户ID搜索">

        邮箱

          <input v-model="email" type="text" class="form-control" id="search-input-email" placeholder="请输入搜索邮箱地址，支持模糊搜索">

        手机号码

          <input v-model="phone" type="tel" class="form-control" id="search-input-phone" placeholder="请输入搜索手机号码，支持模糊搜索">

        用户名

          <input v-model="name" type="text" class="form-control" id="search-input-name" placeholder="请输入搜索用户名，支持模糊搜索">

        角色

          <select v-model="role" class="form-control" id="search-input-name">
            <option value="0">全部</option>
          </select>

          <router-link class="btn btn-default" tag="button" :to="{ path: '/users', query: searchQuery }">
            搜索
          </router-link>

          用户ID
          用户名
          邮箱
          手机号码
          注册时间
          操作

          {{ user.id }}
          {{ user.name }}
          {{ user.email }}
          {{ user.phone }}
          {{ user.created_at }}

= 1 && lastPage > 1">
      <li class="previous" :class="page <= 1 ? 'disabled' : ''">
        <router-link :to="{ path: '/users/manage', query: prevQuery }">
          ←
          上一页
        </router-link>

= lastPage ? 'disabled': ''">
        <router-link :to="{ path: '/users/manage', query: nextQuery }">
          下一页
          →
        </router-link>

</template>

<template>

      检索用户

        添加用户

        用户ID

              <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                排序
              </button>

                  由小到大

                  由大到小

            <input v-model="userId" type="number" class="form-control" id="search-input-id" placeholder="按照用户ID搜索">

        邮箱

          <input v-model="email" type="text" class="form-control" id="search-input-email" placeholder="请输入搜索邮箱地址，支持模糊搜索">

        手机号码

          <input v-model="phone" type="tel" class="form-control" id="search-input-phone" placeholder="请输入搜索手机号码，支持模糊搜索">

        用户名

          <input v-model="name" type="text" class="form-control" id="search-input-name" placeholder="请输入搜索用户名，支持模糊搜索">

        角色

          <select v-model="role" class="form-control" id="search-input-name">
            <option value="0">全部</option>
          </select>

          <router-link class="btn btn-default" tag="button" :to="{ path: '/users/manage', query: searchQuery }">
            搜索
          </router-link>

          用户ID
          用户名
          邮箱
          手机号码
          注册时间
          操作

          {{ user.id }}
          {{ user.name }}
          {{ user.email }}
          {{ user.phone }}
          {{ user.created_at }}

= 1 && lastPage > 1">
      <li class="previous" :class="page <= 1 ? 'disabled' : ''">
        <router-link :to="{ path: '/users/manage', query: prevQuery }">
          ←
          上一页
        </router-link>

= lastPage ? 'disabled': ''">
        <router-link :to="{ path: '/users/manage', query: nextQuery }">
          下一页
          →
        </router-link>

</template>


修复编译报 Emitted value instead of an instance of Error

修复编译报 Emitted value instead of an instance of Error

<template>

      <button type="button" class="close" @click.prevent="dismisError">
        ×
      </button>
      {{ error }}

          检索用户
          <router-link tag="a" class="btn btn-link pull-right btn-xs" to="/users/add" role="button">

            添加
          </router-link>

            用户ID

                  <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    排序
                  </button>

                      由小到大

                      由大到小

                <input v-model="userId" type="number" class="form-control" id="search-input-id" placeholder="按照用户ID搜索">

            注册时间

                  <input type="date" class="form-control" v-model="regist_start_date">

-

                  <input type="date" class="form-control" v-model="regist_end_date">

            区域
            <area-linkage v-model='location'></area-linkage>

            邮箱

              <input v-model="email" type="text" class="form-control" id="search-input-email" placeholder="请输入搜索邮箱地址，支持模糊搜索">

            手机号码

              <input v-model="phone" type="tel" class="form-control" id="search-input-phone" placeholder="请输入搜索手机号码，支持模糊搜索">

            用户名

              <input v-model="name" type="text" class="form-control" id="search-input-name" placeholder="请输入搜索用户名，支持模糊搜索">

            角色

              <select v-model="role" class="form-control" id="search-input-name">
                <option value="0">全部</option>
                <option v-for="role in roles" :key="role.id" :value="role.id">{{ role.display_name }}</option>
              </select>

            关注设置

              <select v-model="follow" class="form-control" id="search-input-name">
                <option value="0">全部</option>
                <option value="1">注册时被关注</option>
                <option value="2">注册时相互关注</option>
              </select>

              <router-link class="btn btn-default" tag="button" :to="{ path: '/users', query: searchQuery }">
                搜索
              </router-link>

              用户ID
              用户名
              邮箱
              手机号码
              地理位置
              注册时间
              操作

              {{ user.id }}
              {{ user.name }}
              {{ user.email }}
              {{ user.phone }}
              {{ user.location }}
              {{ user.created_at | localDate }}

                <router-link type="button" class="btn btn-primary btn-sm" :to="`/users/manage/${user.id}`" >编辑</router-link>

                <button type="button" class="btn btn-primary btn-sm" v-if="user.recommended === null" @click="handleRecommend(user.id)">推荐Ta</button>
                <button v-else type="button" class="btn btn-danger btn-sm" @click="handleUnRecommend(user.id)">不推荐了</button>

                <button type="button" class="btn btn-primary btn-sm" v-if="user.famous === null" @click="handleFollowedFamous(user.id)">设置被关注</button>
                <button type="button" class="btn btn-primary btn-sm" v-if="user.famous === null" @click="handleEachFamous(user.id)">设置相互关注</button>
                <button v-else type="button" class="btn btn-danger btn-sm" @click="handleUnFamous(user.id)">取消关注设置</button>

                <button v-if="deleteIds.indexOf(user.id) !== -1" type="button" class="btn btn-danger btn-sm" disabled="disabled">

                </button>
                <button v-else type="button" class="btn btn-danger btn-sm" @click="deleteUser(user.id)">删除</button>

= 1 && lastPage > 1">
          <li class="previous" :class="page <= 1 ? 'disabled' : ''">
            <router-link :to="{ path: '/users', query: prevQuery }">
              ←
              上一页
            </router-link>

共{{total}}个用户，{{lastPage}}页，当前为第{{current_page}}页

= lastPage ? 'disabled': ''">
            <router-link :to="{ path: '/users', query: nextQuery }">
              下一页
              →
            </router-link>

</template>

<template>

      <button type="button" class="close" @click.prevent="dismisError">
        ×
      </button>
      {{ error }}

          检索用户
          <router-link tag="a" class="btn btn-link pull-right btn-xs" to="/users/add" role="button">

            添加
          </router-link>

            用户ID

                  <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    排序
                  </button>

                      由小到大

                      由大到小

                <input v-model="userId" type="number" class="form-control" id="search-input-id" placeholder="按照用户ID搜索">

            注册时间

                  <input type="date" class="form-control" v-model="regist_start_date">

-

                  <input type="date" class="form-control" v-model="regist_end_date">

            区域
            <area-linkage v-model='location'></area-linkage>

            邮箱

              <input v-model="email" type="text" class="form-control" id="search-input-email" placeholder="请输入搜索邮箱地址，支持模糊搜索">

            手机号码

              <input v-model="phone" type="tel" class="form-control" id="search-input-phone" placeholder="请输入搜索手机号码，支持模糊搜索">

            用户名

              <input v-model="name" type="text" class="form-control" id="search-input-name" placeholder="请输入搜索用户名，支持模糊搜索">

            角色

              <select v-model="role" class="form-control" id="search-input-name">
                <option value="0">全部</option>
                <option v-for="({ id, display_name }) in roles" :key="id" :value="id">{{ display_name }}</option>
              </select>

            关注设置

              <select v-model="follow" class="form-control" id="search-input-name">
                <option value="0">全部</option>
                <option value="1">注册时被关注</option>
                <option value="2">注册时相互关注</option>
              </select>

              <router-link class="btn btn-default" tag="button" :to="{ path: '/users', query: searchQuery }">
                搜索
              </router-link>

              用户ID
              用户名
              邮箱
              手机号码
              地理位置
              注册时间
              操作

              {{ user.id }}
              {{ user.name }}
              {{ user.email }}
              {{ user.phone }}
              {{ user.location }}
              {{ user.created_at | localDate }}

                <router-link type="button" class="btn btn-primary btn-sm" :to="`/users/manage/${user.id}`" >编辑</router-link>

                <button type="button" class="btn btn-primary btn-sm" v-if="user.recommended === null" @click="handleRecommend(user.id)">推荐Ta</button>
                <button v-else type="button" class="btn btn-danger btn-sm" @click="handleUnRecommend(user.id)">不推荐了</button>

                <button type="button" class="btn btn-primary btn-sm" v-if="user.famous === null" @click="handleFollowedFamous(user.id)">设置被关注</button>
                <button type="button" class="btn btn-primary btn-sm" v-if="user.famous === null" @click="handleEachFamous(user.id)">设置相互关注</button>
                <button v-else type="button" class="btn btn-danger btn-sm" @click="handleUnFamous(user.id)">取消关注设置</button>

                <button v-if="deleteIds.indexOf(user.id) !== -1" type="button" class="btn btn-danger btn-sm" disabled="disabled">

                </button>
                <button v-else type="button" class="btn btn-danger btn-sm" @click="deleteUser(user.id)">删除</button>

= 1 && lastPage > 1">
          <li class="previous" :class="page <= 1 ? 'disabled' : ''">
            <router-link :to="{ path: '/users', query: prevQuery }">
              ←
              上一页
            </router-link>

共{{total}}个用户，{{lastPage}}页，当前为第{{current_page}}页

= lastPage ? 'disabled': ''">
            <router-link :to="{ path: '/users', query: nextQuery }">
              下一页
              →
            </router-link>

</template>


check if graql editor is minimized before maximising it (#4379)

<template>

            <vue-button icon="star" className="vue-button" v-on:clicked="toggleFavQueriesList"></vue-button>
            <vue-button rightIcon="locate" className="vue-button" v-on:clicked="toggleTypesContainer"></vue-button>

<vue-tooltip content="type a query" :isOpen="showEditorToolTip" :child="dummyGraqlIcon" className="editor-tooltip" v-on:close-tooltip="showEditorToolTip = false"></vue-tooltip>

                    <textarea id="graqlEditor" ref="graqlEditor" rows="3"></textarea>

<vue-icon icon="cross" iconSize="10" className="tab-icon"></vue-icon>

                        <vue-tooltip class="star-tooltip" content="save a query" className="star-tooltip" :isOpen="showStarToolTip" :child="dummyStarIcon" v-on:close-tooltip="showStarToolTip = false"></vue-tooltip>

<vue-icon icon="star" iconSize="10" className="tab-icon"></vue-icon>

 1 && !editorMinimized" @click="minimizeEditor"><vue-icon icon="double-chevron-up" iconSize="12" className="tab-icon"></vue-icon>

 1 && editorMinimized" @click="maximizeEditor"><vue-icon icon="double-chevron-down" iconSize="12" className="tab-icon"></vue-icon>

            <add-fav-query
                    v-if="showAddFavQuery"
                    :currentQuery="currentQuery"
                    :currentKeyspace="currentKeyspace"
                    :favQueries="favQueries"
                    :showAddFavQueryToolTip="showAddFavQueryToolTip"
                    v-on:close-add-query-panel="toggleAddFavQuery"
                    v-on:toggle-fav-query-tooltip="toggleFavQueryTooltip"
                    v-on:refresh-queries="refreshFavQueries">
            </add-fav-query>
            <error-container
                    v-if="showError"
                    :errorMsg="errorMsg"
                    v-on:close-error="showError = false">
            </error-container>
            <fav-queries-list
                    v-if="showFavQueriesList"
                    :localStore="localStore"
                    :currentKeyspace="currentKeyspace"
                    :favQueries="favQueries"
                    v-on:close-fav-queries-panel="toggleFavQueriesList"
                    v-on:refresh-queries="refreshFavQueries">
            </fav-queries-list>
            <types-container
                    v-if="showTypesContainer"
                    :localStore="localStore"
                    v-on:close-types-panel="showTypesContainer = false">
            </types-container>

    <vue-button v-on:clicked="runQuery" icon="play" ref="runQueryButton" :loading="loadSpinner" className="vue-button run-btn"></vue-button>
    <vue-button v-on:clicked="clearGraph" icon="refresh" ref="clearButton" className="vue-button"></vue-button>

</template>


Fix router issue

Fix router issue

<template>

    <form>

        File
        <input type="file" class="form-control-file" id="file" ref="file"
               @change="handleFileUpload()">
        <button @click="submitFile()">Submit</button>

    </form>

</template>