Fix style scope

Fix style scope

Fixes problems with padding in all other cards
in the app.

<template>

    <PrimaryDialog v-model="syncModal" :title="$tr('syncModalTitle')" lazy>
      <VList subheader two-line>
        <VSubheader>{{ $tr('syncModalExplainer') }}</VSubheader>

        <VListTile @click.stop>
          <VListTileAction>
            <VCheckbox v-model="syncFiles" color="primary" />
          </VListTileAction>
          <VListTileContent @click="syncFiles = !syncFiles">
            <VListTileTitle>{{ $tr('syncFilesTitle') }}</VListTileTitle>
            <VListTileSubTitle>{{ $tr('syncFilesExplainer') }}</VListTileSubTitle>
          </VListTileContent>
        </VListTile>

        <VListTile @click.stop>
          <VListTileAction>
            <VCheckbox v-model="syncTags" color="primary" />
          </VListTileAction>
          <VListTileContent @click="syncTags = !syncTags">
            <VListTileTitle>{{ $tr('syncTagsTitle') }}</VListTileTitle>
            <VListTileSubTitle>{{ $tr('syncTagsExplainer') }}</VListTileSubTitle>
          </VListTileContent>
        </VListTile>

        <VListTile @click.stop>
          <VListTileAction>
            <VCheckbox v-model="syncTitlesAndDescriptions" color="primary" />
          </VListTileAction>
          <VListTileContent @click="syncTitlesAndDescriptions = !syncTitlesAndDescriptions">
            <VListTileTitle>{{ $tr('syncTitlesAndDescriptionsTitle') }}</VListTileTitle>
            <VListTileSubTitle>{{ $tr('syncTitlesAndDescriptionsExplainer') }}</VListTileSubTitle>
          </VListTileContent>
        </VListTile>

        <VListTile @click.stop>
          <VListTileAction>
            <VCheckbox v-model="syncExercises" color="primary" />
          </VListTileAction>
          <VListTileContent @click="syncExercises = !syncExercises">
            <VListTileTitle>{{ $tr('syncExercisesTitle') }}</VListTileTitle>
            <VListTileSubTitle>{{ $tr('syncExercisesExplainer') }}</VListTileSubTitle>
          </VListTileContent>
        </VListTile>
      </VList>
      <VSpacer />
      <template v-slot:actions>
        <VSpacer />
        <VBtn flat @click="syncModal=false">
          {{ $tr('cancelButtonLabel') }}
        </VBtn>
        <VBtn color="primary" :disabled="!continueAllowed" @click="handleContinue">
          {{ $tr('continueButtonLabel') }}
        </VBtn>
      </template>
    </PrimaryDialog>

    <PrimaryDialog v-model="confirmSyncModal" :title="$tr('confirmSyncModalTitle')" lazy>
      <VSubheader>{{ $tr('confirmSyncModalExplainer') }}</VSubheader>
      <VCardText>

            {{ $tr('syncFilesTitle') }}

            {{ $tr('syncTagsTitle') }}

            {{ $tr('syncTitlesAndDescriptionsTitle') }}

            {{ $tr('syncExercisesTitle') }}

      </VCardText>
      <VSpacer />
      <template v-slot:actions>
        <VSpacer />
        <VBtn flat @click="handleBack">
          {{ $tr('backButtonLabel') }}
        </VBtn>
        <VBtn color="primary" @click="handleSync">
          {{ $tr('syncButtonLabel') }}
        </VBtn>
      </template>
    </PrimaryDialog>

</template>


fix typo in email field

fix typo in email field

<template>

Tel: {{company.tel}}

Tel: {{driller.contact_tel}}

Fax: {{company.fax}}

<a :href="`mailto:${company.email}`">{{company.email}}

{{company.website}}

</template>

<template>

Tel: {{company.tel}}

Tel: {{driller.contact_tel}}

Fax: {{company.fax}}

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

{{company.website}}

</template>


Avoid error if no occurrences found

Avoid error if no occurrences found

<template>
  <form class="wrapper-height100" @submit.prevent>

Stel de openingsuren in voor {{ $root.routeService.label }}. Op welke dagen is deze dienst normaal open?

Uitzonderingen kan je later instellen.

        <event-editor v-for="(e, i) in cal.events" :parent="cal.events" :prop="i" @add-event="addEvent(i, e)" @rm="rmEvent(i)"></event-editor>

          <button type="button" @click="pushFirstEvent" class="btn btn-link" :disabled="$root.isRecreatex">+ Voeg weekschema toe</button>

Stel de uitzondering in.

          Naam uitzondering
          <input type="text" class="form-control" v-model="calLabel" placeholder="Brugdagen, collectieve sluitingsdagen, ..." autofocus>

Kies een specifieke naam die deze uitzondering beschrijft.

        <transition name="slideup">

Voeg voorgedefineerde momenten toe

              Klik op
              Bewaar
              om ook andere momenten toe te voegen

Herhalende vakantiedagen

                  Geldig voor jaar {{preset.group}}

{{ preset | dayMonth }}

                  <input type="checkbox" name="preset" :value="index" v-model="presetSelection"> {{ preset.label }}

        </transition>

{{ cal.label }}

          <input type="checkbox" :checked="cal.closinghours" @change="toggleClosing"> Sluitingsuren

        <event-editor v-for="(e, i) in cal.events" :parent="cal.events" :prop="i" @add-event="addEvent(i, e)" @rm="rmEvent(i)"></event-editor>

          <button type="button" @click="pushEvent" class="btn btn-link" :disabled="$root.isRecreatex">+ Voeg nieuwe periode of dag toe</button>

        <button type="button" class="btn btn-default pull-left" @click="rmCalendar()" :disabled="$root.isRecreatex">Verwijder</button>
        <button type="button" class="btn btn-default" @click="cancel">Annuleer</button>
        <button type="submit" class="btn btn-primary" @click.prevent="showPresets = true" v-if="cal.label == 'Uitzondering' && !showPresets">Volgende</button>
        <button type="button" class="btn btn-danger" v-else-if="disabled" disabled>Bewaar</button>
        <button type="submit" class="btn btn-primary" @click="saveLabel" v-else-if="cal.label == 'Uitzondering'">Bewaar</button>
        <button type="button" class="btn btn-primary" @click="save" v-else>Bewaar</button>

  </form>
</template>


Fix objectfeature:technique

Fix objectfeature:technique

<template>

Vondst

Datum

{{find.findDate}}

Locatie

{{find.findSpot.location.address.locality}}

Vinder

{{find.finder.name||'Niet zichtbaar'}}

Object

Beschrijving

{{find.object.description}}

Opschrift

{{find.object.inscription}}

Dimensies

{{dim.type}}: {{dim.value}}{{dim.unit}}

Materiaal

{{find.object.material}}

Techniek

{{find.object.productionEvent.productionTechnique.type}}

Categorie

{{find.object.category}}

</template>


fit lint in fullnameform

fit lint in fullnameform

<template>

  <PrimaryDialog :value="show" title="Edit name">
    <form @submit.prevent="submitFullName">
      <KTextbox v-model="firstName" :label="$tr('firstNameLabel')" />
      <KTextbox v-model="lastName" :label="$tr('lastNameLabel')" />

      <div slot="actions" style="text-align: right;">
        <KButtonGroup>
          <KButton
            :text="$tr('cancelAction')"
            @click="$emit('hideFullNameForm')"
          />
          <KButton
            :text="$tr('saveChangesAction')"
            type="submit"
            primary
          />
        </KButtonGroup>
      </div>
    </form>
  </PrimaryDialog>

</template>

<script>

  import { mapActions, mapState } from 'vuex';
  import PrimaryDialog from 'shared/views/PrimaryDialog';

  export default {
    name: 'FullNameForm',
    components: { PrimaryDialog },
    props: {
      show: {
        type: Boolean,
        default: false,
        required: true,
      },
    },
    data() {
      return {
        // Initialized in beforeMount
        firstName: null,
        lastName: null,
      };
    },
    computed: {
      ...mapState({
        user: state => state.session.currentUser
      }),
    },
    beforeMount() {
      this.firstName = this.user.first_name;
      this.lastName = this.user.last_name;
    },
    methods: {
      ...mapActions({
          // This one persists the change
          patchFullName: 'patchFullName',
          // This one updates vuex state
          updateFullName: 'updateFullName',
      }),
      submitFullName() {
        const email = this.user.email;
        const fullName = { first_name: this.firstName, last_name: this.lastName };
        this.patchFullName({ email, fullName }).then(() => {
          this.updateFullName(fullName)
            .then(() => {
              this.$emit('hideFullNameForm');
              this.$store.dispatch('showSnackbar', { text: this.$tr('changesSavedMessage') });
            })
            .catch(e => {
              // TODO: Create error snackbar $tr to use here.
              this.$store.dispatch('showSnackbar', { text: this.$tr('failedToSaveMessage') });
            });
        });
      },
    },
    $trs: {
      firstNameLabel: "First name",
      lastNameLabel: "Last name",
      cancelAction: 'Cancel',
      saveChangesAction: 'Save changes',
      changesSavedMessage: 'Changes saved',
      failedToSaveMessage: 'Failed to save changes',
    },
  };

</script>

<style>

</style>

<template>

  <PrimaryDialog :value="show" title="Edit name">
    <form @submit.prevent="submitFullName">
      <KTextbox v-model="firstName" :label="$tr('firstNameLabel')" />
      <KTextbox v-model="lastName" :label="$tr('lastNameLabel')" />

      <div slot="actions" style="text-align: right;">
        <KButtonGroup>
          <KButton
            :text="$tr('cancelAction')"
            @click="$emit('hideFullNameForm')"
          />
          <KButton
            :text="$tr('saveChangesAction')"
            type="submit"
            primary
          />
        </KButtonGroup>
      </div>
    </form>
  </PrimaryDialog>

</template>

<script>

  import { mapActions, mapState } from 'vuex';
  import client from 'shared/client';
  import PrimaryDialog from 'shared/views/PrimaryDialog';

  export default {
    name: 'FullNameForm',
    components: { PrimaryDialog },
    props: {
      show: {
        type: Boolean,
        default: false,
        required: true,
      },
    },
    data() {
      return {
        // Initialized in beforeMount
        firstName: null,
        lastName: null,
      };
    },
    beforeMount() {
      this.firstName = this.user.first_name;
      this.lastName = this.user.last_name;
    },
    computed: {
      ...mapState({
        user: state => state.session.currentUser
      }),
    },
    methods: {
      ...mapActions({
          // This one persists the change
          patchFullName: 'patchFullName',
          // This one updates vuex state
          updateFullName: 'updateFullName',
      }),
      submitFullName() {
        const email = this.user.email;
        const fullName = { first_name: this.firstName, last_name: this.lastName };
        this.patchFullName({ email, fullName }).then(() => {
          this.updateFullName(fullName)
            .then(() => {
              this.$emit('hideFullNameForm');
              this.$store.dispatch('showSnackbar', { text: this.$tr('changesSavedMessage') });
            })
            .catch(e => {
              // TODO: Create error snackbar $tr to use here.
              console.error(`Failed to update user's full name. ${e}`);
            });
        });
      },
    },
    $trs: {
      firstNameLabel: "First name",
      lastNameLabel: "Last name",
      cancelAction: 'Cancel',
      saveChangesAction: 'Save changes',
      changesSavedMessage: 'Changes saved',
    },
  };

</script>

<style>

</style>


Debounce exam answer save

Debounce exam answer save

<template>

  <immersive-full-screen
    v-if="exam"
    :backPageLink="backPageLink"
    :backPageText="$tr('backToExamList')"
  >
    <multi-pane-layout ref="multiPaneLayout">

        <mat-svg class="exam-icon" slot="content-icon" category="action" name="assignment_late" />

{{ exam.title }}

            {{
              $tr(
                'questionsAnswered',
                { numAnswered: questionsAnswered, numTotal: exam.question_count }
              )
            }}

          <k-button @click="toggleModal" :text="$tr('submitExam')" :primary="true" />

      <answer-history
        slot="aside"
        :questionNumber="questionNumber"
        @goToQuestion="goToQuestion"
      />

        <content-renderer
          ref="contentRenderer"
          v-if="itemId"
          :id="content.id"
          :kind="content.kind"
          :files="content.files"
          :contentId="content.content_id"
          :channelId="channelId"
          :available="content.available"
          :extraFields="content.extra_fields"
          :itemId="itemId"
          :assessment="true"
          :allowHints="false"
          :answerState="currentAttempt.answer"
          @interaction="handleInteraction"
        />
        <ui-alert v-else :dismissible="false" type="error">
          {{ $tr('noItemId') }}
        </ui-alert>

        <k-button
          :disabled="questionNumber===0"
          @click="goToQuestion(questionNumber - 1)"
          :text="$tr('previousQuestion')"
        />
        <k-button
          :disabled="questionNumber===exam.question_count-1"
          @click="goToQuestion(questionNumber + 1)"
          :text="$tr('nextQuestion')"
        />

      <core-modal
        v-if="submitModalOpen"
        :title="$tr('submitExam')"
        @cancel="toggleModal"
      >

{{ $tr('areYouSure') }}

          {{ $tr('unanswered', { numLeft: questionsUnanswered } ) }}

          <k-button
            :text="$tr('goBack')"
            appearance="flat-button"
            @click="toggleModal"
          />
          <k-button
            :text="$tr('submitExam')"
            @click="finishExam"
            :primary="true"
          />

      </core-modal>
    </multi-pane-layout>
  </immersive-full-screen>

</template>

<template>

  <immersive-full-screen
    v-if="exam"
    :backPageLink="backPageLink"
    :backPageText="$tr('backToExamList')"
  >
    <multi-pane-layout ref="multiPaneLayout">

        <mat-svg class="exam-icon" slot="content-icon" category="action" name="assignment_late" />

{{ exam.title }}

            {{
              $tr(
                'questionsAnswered',
                { numAnswered: questionsAnswered, numTotal: exam.question_count }
              )
            }}

          <k-button @click="toggleModal" :text="$tr('submitExam')" :primary="true" />

      <answer-history
        slot="aside"
        :questionNumber="questionNumber"
        @goToQuestion="goToQuestion"
      />

        <content-renderer
          ref="contentRenderer"
          v-if="itemId"
          :id="content.id"
          :kind="content.kind"
          :files="content.files"
          :contentId="content.content_id"
          :channelId="channelId"
          :available="content.available"
          :extraFields="content.extra_fields"
          :itemId="itemId"
          :assessment="true"
          :allowHints="false"
          :answerState="currentAttempt.answer"
          @interaction="throttledSaveAnswer"
        />
        <ui-alert v-else :dismissible="false" type="error">
          {{ $tr('noItemId') }}
        </ui-alert>

        <k-button
          :disabled="questionNumber===0"
          @click="goToQuestion(questionNumber - 1)"
          :text="$tr('previousQuestion')"
        />
        <k-button
          :disabled="questionNumber===exam.question_count-1"
          @click="goToQuestion(questionNumber + 1)"
          :text="$tr('nextQuestion')"
        />

      <core-modal
        v-if="submitModalOpen"
        :title="$tr('submitExam')"
        @cancel="toggleModal"
      >

{{ $tr('areYouSure') }}

          {{ $tr('unanswered', { numLeft: questionsUnanswered } ) }}

          <k-button
            :text="$tr('goBack')"
            appearance="flat-button"
            @click="toggleModal"
          />
          <k-button
            :text="$tr('submitExam')"
            @click="finishExam"
            :primary="true"
          />

      </core-modal>
    </multi-pane-layout>
  </immersive-full-screen>

</template>


Improve readability of notification message

<template>

    <button
      class="btn btn-secondary dropdown-toggle ml-1"
      id="notification"
      type="button"
      data-toggle="dropdown"
      aria-haspopup="true"
      aria-expanded="false"
      v-on:click="getAllNotifications"
    >
       0" class="badge badge-pill badge-info">
        {{ nbNotifications }}

      Notifications
    </button>

        <router-link v-bind:to="'/notifications'">
          See all notifications
        </router-link>
         0" class="badge badge-secondary float-right" v-on:click="markAllNotificationsAsRead">
          Mark all as read

        There is no new notification.

        <router-link class="dropdown-item notification-item" to="/notifications">

          Status of batch Id {{ notification.batchId }} set to

          Status of data source {{ notification.dataSourceByDataSourceId.name }} set to

            {{ notification.status }}

            {{ notification.createdDate }}

        </router-link>

</template>

<template>

    <button
      class="btn btn-secondary dropdown-toggle ml-1"
      id="notification"
      type="button"
      data-toggle="dropdown"
      aria-haspopup="true"
      aria-expanded="false"
      v-on:click="getAllNotifications"
    >
       0" class="badge badge-pill badge-info">
        {{ nbNotifications }}

      Notifications
    </button>

        <router-link v-bind:to="'/notifications'">
          See all notifications
        </router-link>
         0" class="badge badge-secondary float-right" v-on:click="markAllNotificationsAsRead">
          Mark all as read

        There is no new notification.

        <router-link class="dropdown-item notification-item" to="/notifications">
          Status of {{ formatNotification(notification) }} set to

            {{ notification.status }}

            {{ notification.createdDate }}

        </router-link>

</template>


Fix typo

Fix typo

Signed-off-by: Joas Schilling <ab43a7c9cb5b2380afc4ddf8b3e2583169b39a02@schilljs.com>

<template>

		<slot name="icon" />

					{{ title }}

					<Actions
						v-if="hasActions"
						menu-align="right"
						class="acli__content__line-one__actions">
						<slot name="actions" />
					</Actions>

					{{ details }}

					<slot name="subtitle" />

					<slot
						name="counter" />

</template>


wip: add demo trace support

wip: add demo trace support

<template>

      Network speed
      <select v-model='networkSelected' @change='changeNetworkSpeed'>
        <option v-for='option in network' v-bind:value='option.download'>
          {{ option.title }}
        </option>
      </select>
      <input v-show='isNetworkSpeedCustom()' v-model='downloadSpeed' id='input_downloadspeed' v-on:input='changeCustomNetworkSpeed'>
       Kbps

      Interactivity Budget
      <input id='tti' v-model='timeToInteractiveBudget' v-on:input='changeTTI'> ms

      <input  id='selectFile' type='file' v-on:change='customTraceSelected'/>
      <input class='mdl-button mdl-button--colored mdl-button--raised' type='submit' id='uploadTimelineBtn' value='Select DevTools Trace' @click='uploadTimelineTrace'/>
      <button class='mdl-button mdl-button--colored mdl-button--raised' @click='demoTimelineTrace'>Demo</button>

      <input class='mdl-button mdl-button--colored mdl-button--raised' type='submit' value='Reset' v-on:click='reset'/>

    Advanced

</template>

<template>

      Network
      <select v-model='networkSelected' @change='changeNetworkSpeed'>
        <option v-for='option in network' v-bind:value='option.download'>
          {{ option.title }}
        </option>
      </select>
      <input v-show='isNetworkSpeedCustom()' v-model='downloadSpeed' id='input_downloadspeed' v-on:input='changeCustomNetworkSpeed'>
       Kbps

      Interactivity Budget
      <input id='tti' v-model='timeToInteractiveBudget' v-on:input='changeTTI'> ms

      <input  id='selectFile' type='file' v-on:change='customTraceSelected'/>
      <input class='mdl-button mdl-button--colored mdl-button--raised' type='submit' id='uploadTimelineBtn' value='Select DevTools Trace' @click='uploadTimelineTrace'/>

      <input class='mdl-button mdl-button--colored mdl-button--raised' type='submit' value='Reset' v-on:click='reset'/>

    Advanced

</template>


首页系统管理导航改动

首页系统管理导航改动

<template>

			<el-row>
				<el-col :span="24">
					<el-menu default-active="1" class="el-menu-nav" mode="horizontal" @select="" :router="true">

							Key Guardian

						<el-menu-item index="1" :route="{name:'project'}">项目主页</el-menu-item>
						<el-submenu index="2">
							<template slot="title">系统管理</template>
							<el-menu-item index="2-1" :route="{path:'/main/system/accountCfg'}">账号配置</el-menu-item>
							<el-menu-item index="2-2" :route="{path:'/main/system/menuCfg'}">菜单配置</el-menu-item>
							<el-menu-item index="2-3" :route="{path:'/main/system/roleCfg'}">角色配置</el-menu-item>
							<el-menu-item index="2-4" :route="{path:'/main/system/userCfg'}">人员配置</el-menu-item>
						</el-submenu>
						<el-menu-item class="right" index="3" :route="{name:'index'}">退出</el-menu-item>
					</el-menu>
				</el-col>
			</el-row>

			<router-view></router-view>

</template>

<template>

			<el-row>
				<el-col :span="24">
					<el-menu default-active="1" class="el-menu-nav" mode="horizontal" @select="" :router="true">

							Key Guardian

						<el-menu-item index="1" :route="{name:'project'}">项目主页</el-menu-item>
						<el-menu-item index="2" :route="{name:'system'}">系统管理</el-menu-item>
						<el-menu-item class="right" index="3" :route="{name:'index'}">退出</el-menu-item>
					</el-menu>
				</el-col>
			</el-row>

			<router-view></router-view>

</template>


Replaced hard-coded image randomization with actual length of results

<template>

Photo by  / Unsplash

</template>


Fix problem with filtration. See https://github.com/njleonzhang/vue-data-tables/issues/112

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

<template lang="pug">
  include ../template/index.pug
  +template()
</template>

<script>
  import ErrorTips from './ErrorTips.js'
  import ShareMixin from '../mixins/ShareMixin'
  import debounce from 'javascript-debounce'

  export default {
    name: 'DataTables',
    mixins: [ShareMixin],
    data() {
      return {
        sortData: {}
      }
    },
    computed: {
      innerCheckboxFilterDef() {
        let _allDataProps = this._allDataProps
        return Object.assign({
          props: undefined,
          def: [],
          colProps: {
            span: 14
          },
          filterFunction: (el, filter) => {
            let props = filter.props || _allDataProps
            return props.some(prop => {
              let elVal = el[prop]
              /* istanbul ignore if */
              if (elVal === undefined) {
                console.error(ErrorTips.propError(prop))
              } else if (elVal === null) {
                return false
              }

              return filter.vals.some(val => {
                return elVal.toString() === val
              })
            })
          }
        }, this.checkboxFilterDef)
      },
      innerSearchDef() {
        return Object.assign({
          show: true,
          props: undefined,
          filterFunction: undefined,
          debounceTime: 200,
          prefixIcon: 'el-icon-search'
        }, this.searchDef)
      },
      sortedData() {
        let sortedData = this.data.slice()

        if (this.sortData.order) {
          let order = this.sortData.order
          let prop = this.sortData.prop
          let isDescending = order === 'descending'

          // todo: customize sort function
          sortedData.sort(function(a, b) {
            if (a[prop] > b[prop]) {
              return 1
            } else if (a[prop] < b[prop]) {
              return -1
            } else {
              return 0
            }
          })
          if (isDescending) {
            sortedData.reverse()
          }
        }

        return sortedData
      },
      tableData() {
        let filteredData = this.sortedData.slice()
        let _allDataProps = this._allDataProps

        let doFilter = function(defaultFilterFunction, filter) {
          let filterFunction = filter.filterFunction || defaultFilterFunction

          filteredData = filteredData.filter(el => {
            return filterFunction(el, filter)
          })
        }

        this.filters.forEach(filter => {
          let vals = filter.vals
          if (!vals || vals.length === 0) {
            return true
          }

          let defaultFilterFunction = function(el, filter) {
            let props = filter.props || _allDataProps
            return props.some(prop => {
              let elVal = el[prop]
              /* istanbul ignore if */
              if (elVal === null || elVal === undefined) {
                return false
              }

              return filter.vals.some(val => {
                if (elVal !== undefined) {
                  return elVal.toString().toLowerCase().indexOf(val.toLowerCase()) > -1
                }
                return false
              })
            })
          }

          doFilter(defaultFilterFunction, filter)
        })

        this.$emit('filtered-data', filteredData)
        return filteredData
      },
      curTableData() {
        let from = this.innerPageSize * (this.currentPage - 1)
        let to = from + this.innerPageSize
        return this.tableData.slice(from, to)
      },
      total() {
        return this.tableData.length
      },
      filters() {
        let filters = this.formatToArray(this.innerCustomFilters)
        if (this.showActionBar) {
          if (this.searchShow) {
            filters.push({
              props: this.formatProps(this.innerSearchDef.props),
              vals: this.formatToArray(this.innerSearchKey),
              filterFunction: this.innerSearchDef.filterFunction
            })
          }
          if (this.checkboxShow) {
            filters.push({
              props: this.formatProps(this.innerCheckboxFilterDef.props),
              vals: this.checkBoxValues,
              filterFunction: this.innerCheckboxFilterDef.filterFunction
            })
          }
        }
        return filters
      },
      updateInnerSearchKey() {
        const timeout = this.innerSearchDef.debounceTime
        return debounce(_ => {
          this.innerSearchKey = this.searchKey
        }, timeout)
      }
    },
    methods: {
      handleSizeChange(size) {
        this.innerPageSize = size
        this.$emit('size-change', size)
      },
      handlePageChange(currentPage) {
        this.currentPage = currentPage
        this.$emit('current-change', currentPage)
      },
      handleCheckBoxValChange(checkBoxValues) {
        this.checkBoxValues = checkBoxValues
      },
      handleSort(obj) {
        this.sortData = obj
      }
    },
    watch: {
      data: {
        immediate: true,
        handler(val) {
          this._allDataProps = Object.keys(val && val[0] || {})
        }
      }
    }
  }
</script>

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

<template lang="pug">
  include ../template/index.pug
  +template()
</template>

<script>
  import ErrorTips from './ErrorTips.js'
  import ShareMixin from '../mixins/ShareMixin'
  import debounce from 'javascript-debounce'

  export default {
    name: 'DataTables',
    mixins: [ShareMixin],
    data() {
      return {
        sortData: {}
      }
    },
    computed: {
      innerCheckboxFilterDef() {
        let _allDataProps = this._allDataProps
        return Object.assign({
          props: undefined,
          def: [],
          colProps: {
            span: 14
          },
          filterFunction: (el, filter) => {
            let props = filter.props || _allDataProps
            return props.some(prop => {
              let elVal = el[prop]
              /* istanbul ignore if */
              if (elVal === undefined) {
                console.error(ErrorTips.propError(prop))
              } else if (elVal === null) {
                return false
              }

              return filter.vals.some(val => {
                return elVal.toString() === val
              })
            })
          }
        }, this.checkboxFilterDef)
      },
      innerSearchDef() {
        return Object.assign({
          show: true,
          props: undefined,
          filterFunction: undefined,
          debounceTime: 200,
          prefixIcon: 'el-icon-search'
        }, this.searchDef)
      },
      sortedData() {
        let sortedData = this.data.slice()

        if (this.sortData.order) {
          let order = this.sortData.order
          let prop = this.sortData.prop
          let isDescending = order === 'descending'

          // todo: customize sort function
          sortedData.sort(function(a, b) {
            if (a[prop] > b[prop]) {
              return 1
            } else if (a[prop] < b[prop]) {
              return -1
            } else {
              return 0
            }
          })
          if (isDescending) {
            sortedData.reverse()
          }
        }

        return sortedData
      },
      tableData() {
        let filteredData = this.sortedData.slice()
        let _allDataProps = this._allDataProps

        let doFilter = function(defaultFilterFunction, filter) {
          let filterFunction = filter.filterFunction || defaultFilterFunction

          filteredData = filteredData.filter(el => {
            return filterFunction(el, filter)
          })
        }

        this.filters.forEach(filter => {
          let vals = filter.vals
          if (!vals || vals.length === 0) {
            return true
          }

          let defaultFilterFunction = function(el, filter) {
            let props = filter.props || _allDataProps
            return props.some(prop => {
              let elVal = el[prop]
              /* istanbul ignore if */
              if (elVal === undefined) {
                console.error(ErrorTips.propError(prop))
              } else if (elVal === null) {
                return false
              }

              return filter.vals.some(val => {
                return elVal.toString().toLowerCase().indexOf(val.toLowerCase()) > -1
              })
            })
          }

          doFilter(defaultFilterFunction, filter)
        })

        this.$emit('filtered-data', filteredData)
        return filteredData
      },
      curTableData() {
        let from = this.innerPageSize * (this.currentPage - 1)
        let to = from + this.innerPageSize
        return this.tableData.slice(from, to)
      },
      total() {
        return this.tableData.length
      },
      filters() {
        let filters = this.formatToArray(this.innerCustomFilters)
        if (this.showActionBar) {
          if (this.searchShow) {
            filters.push({
              props: this.formatProps(this.innerSearchDef.props),
              vals: this.formatToArray(this.innerSearchKey),
              filterFunction: this.innerSearchDef.filterFunction
            })
          }
          if (this.checkboxShow) {
            filters.push({
              props: this.formatProps(this.innerCheckboxFilterDef.props),
              vals: this.checkBoxValues,
              filterFunction: this.innerCheckboxFilterDef.filterFunction
            })
          }
        }
        return filters
      },
      updateInnerSearchKey() {
        const timeout = this.innerSearchDef.debounceTime
        return debounce(_ => {
          this.innerSearchKey = this.searchKey
        }, timeout)
      }
    },
    methods: {
      handleSizeChange(size) {
        this.innerPageSize = size
        this.$emit('size-change', size)
      },
      handlePageChange(currentPage) {
        this.currentPage = currentPage
        this.$emit('current-change', currentPage)
      },
      handleCheckBoxValChange(checkBoxValues) {
        this.checkBoxValues = checkBoxValues
      },
      handleSort(obj) {
        this.sortData = obj
      }
    },
    watch: {
      data: {
        immediate: true,
        handler(val) {
          this._allDataProps = Object.keys(val && val[0] || {})
        }
      }
    }
  }
</script>


Add date formating prop

Add date formating prop

Allows changing of date format via :format prop binding

<template>
    <input type="date"
           class="datepicker"
    >
</template>

<script type="text/babel">
    import IsLoadable from '../mixins/is-loadable'

    export default {
        mixins: [
            IsLoadable
        ],

        props: {
            value: {
                type: String
            },
            format: {
                type: String
            }
        },

        methods: {
            init () {
                if (this.format) $(this.$el).pickadate({format: this.format})
                else $(this.$el).pickadate()

                const picker = $(this.$el).pickadate('picker')
                picker.set('select', this.value)

                const vm = this
                this.$el.onchange = function () {
                    if (this.format)
                        vm.$emit('input', picker.get('select', this.format))
                    else
                        vm.$emit('input', picker.get('select', 'd mmmm, yyyy'))
                }
            }
        }
    }
</script>

<template>
    <input type="date"
           class="datepicker"
    >
</template>

<script type="text/babel">
    import IsLoadable from '../mixins/is-loadable'

    export default {
        mixins: [
            IsLoadable
        ],

        props: {
            value: {
                type: String
            }
        },

        methods: {
            init () {
                $(this.$el).pickadate()

                const picker = $(this.$el).pickadate('picker')
                picker.set('select', this.value)

                const vm = this
                this.$el.onchange = function () {
                    vm.$emit('input', picker.get('select', 'd mmmm, yyyy'))
                }
            }
        }
    }
</script>


If no previous config, set default owners and readers on config select

CA-318

<template>

                        Configuration set as browser default

'{{ defaultBrowserConfigName }}' has been set as your browser's default CaSS Authoring Tool configuration.

                Manage configuration

            <button
                class="delete"
                @click="$store.commit('app/closeModal')"
                aria-label="close" />

                <template v-if="view !== 'dynamic-modal'">

                        Configuration

                        Configurations control the way your frameworks appear in the editor, as well as what properties, relationships,
                        and in some cases value types of properties and relationships you can add to your framework. If a browser configuration
                        not set then the the system will default to your instance default. If you admin the confugration you will be
                        able to manage the property settings.  Otherwise contact your CAT administrator.

                </template>

                    Choose a configuration to apply to this framework below.  You can view and manage details about
                    your available configurations in <router-link to="/config">
                        configuration management
                    </router-link>.

                            name

                                description

                                instance default

                                browser default

                                framework default

                                view/manage

                        <configuration-list-item
                            v-for="config in configList"
                            :id="config.id"
                            :view="view"
                            :key="config"
                            :name="config.name"
                            :isDefault="config.isDefault"
                            :description="config.description"
                            :isOwned="config.isOwned"
                            :defaultBrowserConfigId="localDefaultBrowserConfigId"
                            :defaultFrameworkConfigId="frameworkConfigId"
                            @setBrowserDefault="setConfigAsBrowserDefault"
                            @setFrameworkDefault="setConfigAsFrameworkDefault"
                            @showDetails="showConfigDetails" />

                    create new configuration

                <configuration-details
                    :config="currentConfig"
                    :readOnly="currentConfigIsReadOnly"
                    :defaultConfigId="defaultConfigId"
                    @setBrowserDefault="setConfigAsBrowserDefault"
                    @save="saveCurrentConfig"
                    @cancel="cancelEditCurrentConfig"
                    @back="backFromEditCurrentConfig" />

                done

</template>


Tweak the page layout, styles, removed unused code

Working but still TODO the popup

<template>

Kanji Recognition

        Copy and paste japanese text into the form below, then click "Show". The
        kanji for which you have flashcards will be hyperlinked to the
        Study pages, and a popup will reveal the Heisig keywords.

      <form class="mb-4">
        <textarea
          ref="input"
          v-model="japaneseText"
          class="w-full mb-2 p-2 min-h-[100px] border border-[#ddd] rounded-lg text-lg"
        ></textarea>
        <input
          type="submit"
          class="btn btn-success"
          value="Show"
          @click.prevent="isStateEdit = false"
        />
      </form>

Purpose of this page

          In Remembering the Kanji, the Japanese characters are studied
          and reviewed from the keyword to the kanji. In this sight-reading
          section, you can test your memory the other way round, all the while
          seeing the characters in context.

With very basic grammar you can locate compound words made of two or
          more kanji. You may be able to guess the meaning of some words based
          on the meaning of the characters.

Resources

            Japanese text:
            Aozora Bunko.

            Guide to the Japanese Writing System
            by Jack Halpern

        <button class="btn btn-success" @click="onClickToEdit"
          >Enter more japanese text</button
        >

        Point at the colored kanji with the mouse or click/tap to reveal the
        keyword. To study the character, click (or
        tap) the kanji, and then click the "Study" link inside the tooltip.

        <cjk-lang-ja :html="transformJapaneseText"></cjk-lang-ja>

</template>

<template>

Kanji Recognition

        Copy and paste japanese text into the form below, then click "Show". The
        kanji for which you have flashcards will be hyperlinked to the
        Study pages, and a popup will reveal the Heisig keywords.

      <form>
        <textarea
          ref="input"
          v-model="japaneseText"
          class="w-full mb-4 p-2 min-h-[100px] border border-[#ddd] rounded text-lg"
        ></textarea>
        <input
          type="submit"
          class="btn btn-success"
          value="Show"
          @click.prevent="isStateEdit = false"
        />
      </form>

Purpose of this page

          In _Remembering the Kanji_, the Japanese characters are studied and
          reviewed _from the keyword to the kanji_. In this sight-reading
          section, you can test your memory the other way round, all the while
          seeing the characters _in context_.

With very basic grammar you can locate compound words made of two or
          more kanji. You may be able to guess the meaning of some words based
          on the meaning of the characters.

Resources

            Japanese text:
            Yomiuri Online,
            Old Stories of Japan,
            Aozora Bunko.

            Guide to the Japanese Writing System
            by Jack Halpern

        <button class="btn btn-success" @click="isStateEdit = true"
          >Enter more japanese text</button
        >

Point at the colored kanji with the mouse or click/tap to reveal the
        keyword. To study the character, click (or
        tap) the kanji, and then click the "Study" link inside the tooltip.

        <cjk-lang-ja :html="transformJapaneseText"></cjk-lang-ja>

</template>


image: local upload zone selection fix (#274)

Fixes #269

Signed-off-by: Abhishek Kumar <af012c8507429d6aba5b82a315e3a191d146c0de@gmail.com>
Signed-off-by: Rohit Yadav <902b9eb5dd62819678163bd5e00fbf0cbc7c264b@shapeblue.com>

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

<template>

     0">

      Do not close this form, file upload is in progress...

                Click or drag file to this area to upload

                    {{ opt.name || opt.description }}

                      {{ zone.name || zone.description }}

                  {{ opt.name || opt.description }}

                  {{ opt.name || opt.description }}

                  {{ opt.name || opt.description }}

                  {{ opt.name || opt.description }}

                  {{ opt.name || opt.description }}

                  {{ opt.name || opt.description }}

                  {{ opt.name || opt.description }}

                      {{ $t('isextractable') }}

                      {{ $t('passwordenabled') }}

                      {{ $t('isdynamicallyscalable') }}

                      {{ $t('sshkeyenabled') }}

                      {{ $t('isrouting') }}

                      {{ $t('ispublic') }}

                      {{ $t('requireshvm') }}

                      {{ $t('isfeatured') }}

          {{ this.$t('Cancel') }}
          {{ this.$t('OK') }}

</template>


scope popover

scope popover

<template>

    <slot name="prebutton" />
    <v-popover
      @hide="hide"
      @show="show"
      :offset="menuOffset"
      :placement="menuPlacement"
      trigger="manual"
      :open="isOpen"
      :delay="{ show: 0, hide: 0 }"
      popover-class="apos-popover"
    >

      <AposButton
        class="apos-context-menu__btn"
        @click="buttonClicked($event)"
        v-bind="button"
        :state="buttonState"
        ref="button"
      />
      <template #popover>

          <AposContextMenuTip
            :align="tipAlignment"
            :origin="menuOrigin"
          />

            <slot>

                <AposContextMenuItem
                  v-for="item in menu"
                  :key="item.action"
                  :menu-item="item"
                  @clicked="menuItemClicked"
                  :open="isOpen"
                />

            </slot>

      </template>
    </v-popover>

</template>

<template>

    <slot name="prebutton" />
    <v-popover
      ref="popover"
      @hide="hide"
      @show="show"
      :offset="menuOffset"
      :placement="menuPlacement"
      trigger="manual"
      :open="isOpen"
      :delay="{ show: 0, hide: 0 }"
    >

      <AposButton
        class="apos-context-menu__btn"
        @click="buttonClicked($event)"
        v-bind="button"
        :state="buttonState"
        ref="button"
      />
      <template #popover>

          <AposContextMenuTip
            :align="tipAlignment"
            :origin="menuOrigin"
          />

            <slot>

                <AposContextMenuItem
                  v-for="item in menu"
                  :key="item.action"
                  :menu-item="item"
                  @clicked="menuItemClicked"
                  :open="isOpen"
                />

            </slot>

      </template>
    </v-popover>

</template>


add jump to edit

add jump to edit

<template>

        <router-link :to="routeLink('prePage')" class="button">Previous</router-link>
        <router-link :to="routeLink('nextPage')" class="button">Next page</router-link>

            Starred
            Title
            Tags
            Categories
            Note
            Updated

            🌟

            {{ bookmark.title }}

                <router-link :to="{name: 'urls', query: {tag: tag.name} }"
                 class="tag is-info">{{ tag.name }}</router-link>

                <router-link :to="{name: 'urls', query: {category: category.name} }"
                 class="tag is-info">{{ category.name }}</router-link>

            {{ bookmark.note }}
            {{ bookmark.updated_at }}

        <router-link :to="routeLink('prePage')" class="button">Previous</router-link>
        <router-link :to="routeLink('nextPage')" class="button">Next page</router-link>

</template>


typo fix on dashboard

typo fix on dashboard

<template>
  <d-container fluid class="main-content-container px-4">

Insights

        <d-row>

          <d-col v-for="(record, idx) in highest_frame" :key="idx" lg="4" md="4" sm="6" class="mb-4">

            <d-card v-if="idx < highest_frame.length" class="card-small card-post card-post--1">

                <spinner style="padding: 1rem 0 1rem 0; position: relative; transform: translateY(-50%);"></spinner>

                <d-badge pill :class="['card-post__category', 'bg-' + themes[idx] ]">{{ highest[idx].ri_metric }} ({{ highest[idx].ri_field }})</d-badge>
                <insight-chart style="transform: translateX(-2rem)" :data="insights[highest[idx].rg_name][highest[idx].repo_git][highest[idx].ri_metric]" :url="highest[idx].repo_git" :color="colors[idx]"></insight-chart>

                    {{ getDirection(insights[highest[idx].rg_name][highest[idx].repo_git][highest[idx].ri_metric]) }}

              <d-card-body v-if="loadedInsights">

                  {{ highest[idx].repo_git.substr(19) }}

This repository had a sharp {{ getPhrase(insights[highest[idx].rg_name][highest[idx].repo_git][highest[idx].ri_metric]) }}

{{ timeframes[highest[idx].repo_git] }}

                  <d-col col sm="7" style="transform: translateX(-1rem) !important;">
                    <d-button size="sm" @click="onInspectInsight(insights[highest[idx].rg_name][highest[idx].repo_git][highest[idx].ri_metric])" style="color: white !important" class="d-flex btn-white ml-auto mr-auto ml-sm-auto mr-sm-0 mt-3 mt-sm-0">View Full Report →</d-button>
                  </d-col>

              </d-card-body>
            </d-card>
          </d-col>
        </d-row>

Top 5 Most Significant Anomalies In Your Repo Groups

          <d-row>
            <d-col v-if="!loadedInsights">
              <d-card>

                  <spinner></spinner>

              </d-card>
            </d-col>

            <d-col v-else v-for="(group, idx) in Object.keys(insights).slice(0,6)" :key="idx" lg="4" sm="12" class="mb-4">
              <d-card class="card-small card">

{{ group }}

                        {{ repo }}

                        <spark-chart :color="colors[idx]" :title="metric + ' (' + insights[group][repo][metric][0].ri_field + ')'" :url="repo" :data="insights[group][repo][metric]" style="max-height: 50px; padding-bottom: 0px; "/>

              </d-card>
            </d-col>
          </d-row>

  </d-container>
</template>

<template>
  <d-container fluid class="main-content-container px-4">

Insights

        <d-row>

          <d-col v-for="(record, idx) in highest_frame" :key="idx" lg="4" md="4" sm="6" class="mb-4">

            <d-card v-if="idx < highest_frame.length" class="card-small card-post card-post--1">

                <spinner style="padding: 1rem 0 1rem 0; position: relative; transform: translateY(-50%);"></spinner>

                <d-badge pill :class="['card-post__category', 'bg-' + themes[idx] ]">{{ highest[idx].ri_metric }} ({{ highest[idx].ri_field }})</d-badge>
                <insight-chart style="transform: translateX(-2rem)" :data="insights[highest[idx].rg_name][highest[idx].repo_git][highest[idx].ri_metric]" :url="highest[idx].repo_git" :color="colors[idx]"></insight-chart>

                    {{ getDirection(insights[highest[idx].rg_name][highest[idx].repo_git][highest[idx].ri_metric]) }}

              <d-card-body v-if="loadedInsights">

                  {{ highest[idx].repo_git.substr(19) }}

This repository had a sharp {{ getPhrase(insights[highest[idx].rg_name][highest[idx].repo_git][highest[idx].ri_metric]) }}

{{ timeframes[highest[idx].repo_git] }}

                  <d-col col sm="7" style="transform: translateX(-1rem) !important;">
                    <d-button size="sm" @click="onInspectInsight(insights[highest[idx].rg_name][highest[idx].repo_git][highest[idx].ri_metric])" style="color: white !important" class="d-flex btn-white ml-auto mr-auto ml-sm-auto mr-sm-0 mt-3 mt-sm-0">View Full Report →</d-button>
                  </d-col>

              </d-card-body>
            </d-card>
          </d-col>
        </d-row>

Top 5 Most Significant Anomolies In Your Repo Groups

          <d-row>
            <d-col v-if="!loadedInsights">
              <d-card>

                  <spinner></spinner>

              </d-card>
            </d-col>

            <d-col v-else v-for="(group, idx) in Object.keys(insights).slice(0,6)" :key="idx" lg="4" sm="12" class="mb-4">
              <d-card class="card-small card">

{{ group }}

                        {{ repo }}

                        <spark-chart :color="colors[idx]" :title="metric + ' (' + insights[group][repo][metric][0].ri_field + ')'" :url="repo" :data="insights[group][repo][metric]" style="max-height: 50px; padding-bottom: 0px; "/>

              </d-card>
            </d-col>
          </d-row>

  </d-container>
</template>


fix: va-input removable

fix: va-input removable

<template>
  <va-input-wrapper
    class="va-input"
    :disabled="disabled"
    :success="success"
    :messages="messages"
    :error="error"
    :error-messages="errorMessages"
    :errorCount="errorCount"
  >
    <slot name="prepend" slot="prepend"/>
    <div
      class="va-input__container"
      :class="{'va-input__container--textarea': isTextarea}"
      :style="containerStyles"
    >
      <div
        class="va-input__container__content-wrapper"
        :style="{ paddingTop: label ? '' : '0'}"
      >
        <label
          :style="labelStyles"
          aria-hidden="true"
          class="va-input__container__label"
        >
          {{ label }}
        </label>
        <textarea
          v-if="isTextarea"
          class="va-input__container__input"
          :style="textareaStyles"
          :aria-label="label"
          :placeholder="placeholder"
          :disabled="disabled"
          :readonly="readonly"
          :value="value"
          v-on="inputListeners"
          v-bind="$attrs"
        />
        <input
          v-else
          class="va-input__container__input"
          :style="{ paddingBottom: label ? '0.125rem' : '0.875rem' }"
          :aria-label="label"
          :type="type"
          :placeholder="placeholder"
          :disabled="disabled"
          :readonly="readonly"
          :value="value"
          v-on="inputListeners"
          v-bind="$attrs"
        />
      </div>
      <div
        v-if="success || error || $slots.append || (removable && hasContent)"
        class="va-input__container__icon-wrapper"
      >
        <va-icon
          v-if="success"
          class="va-input__container__icon"
          icon="fa fa-check"
          color="success"
        />
        <va-icon
          v-if="error"
          class="va-input__container__icon"
          icon="fa fa-exclamation-triangle"
          color="danger"
        />
        <slot name="append"/>
        <va-icon
          v-if="removable && hasContent"
          @click.native="clearContent()"
          class="va-input__container__close-icon"
          :color="error ? 'danger': 'gray'"
          icon="ion ion-md-close ion"
        />
      </div>
    </div>
  </va-input-wrapper>
</template>

<script>
import VaInputWrapper from '../va-input/VaInputWrapper'
import VaIcon from '../va-icon/VaIcon'
import {
  getHoverColor,
} from './../../../services/color-functions'

export default {
  name: 'va-input',
  extends: VaInputWrapper,
  components: { VaInputWrapper, VaIcon },
  props: {
    value: {},
    label: {
      type: String,
    },
    placeholder: {
      type: String,
    },
    type: {
      type: String,
      default: 'text',
    },
    disabled: {
      type: Boolean,
    },
    readonly: {
      type: Boolean,
    },
    removable: {
      type: Boolean,
    },
  },
  data () {
    return {
      isFocused: false,
    }
  },
  computed: {
    labelStyles () {
      return {
        color: this.error ? this.$themes.danger : '',
      }
    },
    containerStyles () {
      return {
        backgroundColor:
          this.error ? getHoverColor(this.$themes['danger'])
            : this.success ? getHoverColor(this.$themes['success']) : '#f5f8f9',
        borderColor:
          this.error ? this.$themes.danger
            : this.success ? this.$themes.success
              : this.isFocused ? this.$themes.dark : this.$themes.gray,
      }
    },
    textareaStyles () {
      return {
        paddingBottom: this.label ? '0.125rem' : '',
        marginTop: this.label ? '0.875rem' : '',
        paddingTop: this.label ? 0 : '',
        minHeight: this.label ? '1.5rem' : '2.25rem',
        marginBottom: 0,
      }
    },
    inputListeners () {
      // TODO Probably not the best idea to stick this in computed.
      return Object.assign(
        {},
        this.$listeners,
        {
          input: event => {
            this.$emit('input', event.target.value)
          },
          click: event => {
            this.$emit('click', event)
          },
          focus: event => {
            // eslint-disable-next-line vue/no-side-effects-in-computed-properties
            this.isFocused = true
            this.$emit('focus', event)
          },
          blur: event => {
            // eslint-disable-next-line vue/no-side-effects-in-computed-properties
            this.isFocused = false
            this.$emit('blur', event)
          },
          keyup: event => {
            this.$emit('keyup', event)
          },
          keydown: event => {
            this.$emit('keydown', event)
          },
        }
      )
    },
    hasContent () {
      return ![null, undefined, ''].includes(this.value)
    },
    isTextarea () {
      return this.type === 'textarea'
    },
  },
  methods: {
    clearContent () {
      this.$emit('input', '')
    },
  },
}
</script>

<style lang='scss'>
@import '../../vuestic-sass/resources/resources';

.va-input {
  &__container {
    display: flex;
    position: relative;
    width: 100%;
    min-height: 2.375rem;
    border-style: solid;
    border-width: 0 0 thin 0;
    border-top-left-radius: 0.5rem;
    border-top-right-radius: 0.5rem;

    &__content-wrapper {
      display: flex;
      align-items: flex-end;
      width: 100%;
      /*min-width: 100%;*/
    }

    &__icon-wrapper {
      display: flex;
      align-items: center;
      margin-right: 0.5rem;
    }

    &__close-icon {
      cursor: pointer;
      margin-left: 0.25rem;
    }

    &__label {
      position: absolute;
      bottom: 0.875rem;
      left: 0.5rem;
      margin-bottom: 0.5rem;
      max-width: calc(100% - 0.25rem);
      color: $vue-green;
      font-size: 0.625rem;
      letter-spacing: 0.0375rem;
      line-height: 1.2;
      font-weight: bold;
      text-transform: uppercase;
      @include va-ellipsis();
      transform-origin: top left;
    }

    &.va-input__container--textarea &__label {
      bottom: auto;
      top: 0.125rem;
    }

    &__input {
      width: 100%;
      height: 1.5rem;
      margin-bottom: 0.125rem;
      padding: 0.25rem 0.5rem;
      color: #34495e;
      background-color: transparent;
      border-style: none;
      outline: none;
      font-size: 1rem;
      font-family: $font-family-sans-serif;
      font-weight: normal;
      font-style: normal;
      font-stretch: normal;
      line-height: 1.5;
      letter-spacing: normal;

      &::placeholder {
        color: $brand-secondary;
      }

      &:placeholder-shown {
        padding-bottom: 0.875rem;
      }
    }

    &.va-input__container--textarea &__input {
      height: inherit;
    }
  }
}
</style>

<template>
  <va-input-wrapper
    class="va-input"
    :disabled="disabled"
    :success="success"
    :messages="messages"
    :error="error"
    :error-messages="errorMessages"
    :errorCount="errorCount"
  >
    <slot name="prepend" slot="prepend"/>
    <div
      class="va-input__container"
      :class="{'va-input__container--textarea': isTextarea}"
      :style="containerStyles"
    >
      <div
        class="va-input__container__content-wrapper"
        :style="{ paddingTop: label ? '' : '0'}"
      >
        <label
          :style="labelStyles"
          aria-hidden="true"
          class="va-input__container__label"
        >
          {{ label }}
        </label>
        <textarea
          v-if="isTextarea"
          class="va-input__container__input"
          :style="textareaStyles"
          :aria-label="label"
          :placeholder="placeholder"
          :disabled="disabled"
          :readonly="readonly"
          :value="value"
          v-on="inputListeners"
          v-bind="$attrs"
        />
        <input
          v-else
          class="va-input__container__input"
          :style="{ paddingBottom: label ? '0.125rem' : '0.875rem' }"
          :aria-label="label"
          :type="type"
          :placeholder="placeholder"
          :disabled="disabled"
          :readonly="readonly"
          :value="value"
          v-on="inputListeners"
          v-bind="$attrs"
        />
      </div>
      <div
        v-if="success || error || $slots.append || (removable && hasContent)"
        class="va-input__container__icon-wrapper"
      >
        <va-icon
          v-if="success"
          class="va-input__container__icon"
          icon="fa fa-check"
          color="success"
        />
        <va-icon
          v-if="error"
          class="va-input__container__icon"
          icon="fa fa-exclamation-triangle"
          color="danger"
        />
        <slot name="append"/>
        <va-icon
          v-if="removable && hasContent"
          @click.native="clearContent()"
          class="va-input__container__close-icon"
          :color="error ? 'danger': 'gray'"
          icon="ion ion-md-close ion"
        />
      </div>
    </div>
  </va-input-wrapper>
</template>

<script>
import VaInputWrapper from '../va-input/VaInputWrapper'
import VaIcon from '../va-icon/VaIcon'
import {
  getHoverColor,
} from './../../../services/color-functions'

export default {
  name: 'va-input',
  extends: VaInputWrapper,
  components: { VaInputWrapper, VaIcon },
  props: {
    value: {},
    label: {
      type: String,
    },
    placeholder: {
      type: String,
    },
    type: {
      type: String,
      default: 'text',
    },
    disabled: {
      type: Boolean,
    },
    readonly: {
      type: Boolean,
    },
    removable: {
      type: Boolean,
    },
  },
  data () {
    return {
      isFocused: false,
    }
  },
  computed: {
    labelStyles () {
      return {
        color: this.error ? this.$themes.danger : '',
      }
    },
    containerStyles () {
      return {
        backgroundColor:
          this.error ? getHoverColor(this.$themes['danger'])
            : this.success ? getHoverColor(this.$themes['success']) : '#f5f8f9',
        borderColor:
          this.error ? this.$themes.danger
            : this.success ? this.$themes.success
              : this.isFocused ? this.$themes.dark : this.$themes.gray,
      }
    },
    textareaStyles () {
      return {
        paddingBottom: this.label ? '0.125rem' : '',
        marginTop: this.label ? '0.875rem' : '',
        paddingTop: this.label ? 0 : '',
        minHeight: this.label ? '1.5rem' : '2.25rem',
        marginBottom: 0,
      }
    },
    inputListeners () {
      // TODO Probably not the best idea to stick this in computed.
      return Object.assign(
        {},
        this.$listeners,
        {
          input: event => {
            this.$emit('input', event.target.value)
          },
          click: event => {
            this.$emit('click', event)
          },
          focus: event => {
            // eslint-disable-next-line vue/no-side-effects-in-computed-properties
            this.isFocused = true
            this.$emit('focus', event)
          },
          blur: event => {
            // eslint-disable-next-line vue/no-side-effects-in-computed-properties
            this.isFocused = false
            this.$emit('blur', event)
          },
          keyup: event => {
            this.$emit('keyup', event)
          },
          keydown: event => {
            this.$emit('keydown', event)
          },
        }
      )
    },
    hasContent () {
      return [null, undefined, ''].includes(this.value)
    },
    isTextarea () {
      return this.type === 'textarea'
    },
  },
  methods: {
    clearContent () {
      this.$emit('input', '')
    },
  },
}
</script>

<style lang='scss'>
@import '../../vuestic-sass/resources/resources';

.va-input {
  &__container {
    display: flex;
    position: relative;
    width: 100%;
    min-height: 2.375rem;
    border-style: solid;
    border-width: 0 0 thin 0;
    border-top-left-radius: 0.5rem;
    border-top-right-radius: 0.5rem;

    &__content-wrapper {
      display: flex;
      align-items: flex-end;
      width: 100%;
      /*min-width: 100%;*/
    }

    &__icon-wrapper {
      display: flex;
      align-items: center;
      margin-right: 0.5rem;
    }

    &__close-icon {
      cursor: pointer;
      margin-left: 0.25rem;
    }

    &__label {
      position: absolute;
      bottom: 0.875rem;
      left: 0.5rem;
      margin-bottom: 0.5rem;
      max-width: calc(100% - 0.25rem);
      color: $vue-green;
      font-size: 0.625rem;
      letter-spacing: 0.0375rem;
      line-height: 1.2;
      font-weight: bold;
      text-transform: uppercase;
      @include va-ellipsis();
      transform-origin: top left;
    }

    &.va-input__container--textarea &__label {
      bottom: auto;
      top: 0.125rem;
    }

    &__input {
      width: 100%;
      height: 1.5rem;
      margin-bottom: 0.125rem;
      padding: 0.25rem 0.5rem;
      color: #34495e;
      background-color: transparent;
      border-style: none;
      outline: none;
      font-size: 1rem;
      font-family: $font-family-sans-serif;
      font-weight: normal;
      font-style: normal;
      font-stretch: normal;
      line-height: 1.5;
      letter-spacing: normal;

      &::placeholder {
        color: $brand-secondary;
      }

      &:placeholder-shown {
        padding-bottom: 0.875rem;
      }
    }

    &.va-input__container--textarea &__input {
      height: inherit;
    }
  }
}
</style>


remove redundant component render

remove redundant component render

<template>
  <div>
    <the-move-action class="window-action move-window-action" />
    <the-close-action class="window-action close-window-action" />
  </div>
</template>

<script lang="ts">
import Vue from 'vue';

import TheMoveAction from './TheMoveAction.vue';
import TheCloseAction from './TheCloseAction.vue';

export default Vue.extend({
  name: 'TheWindowActions',

  components: {
    TheMoveAction,
    TheCloseAction,
  },
});
</script>

<style lang="scss" scoped>
.window-action {
  top: 0;
  margin: 0;
  padding: 0;
  left: 5.5px;
  border: none;
  font-size: 15px;
  background: none;
  position: absolute;

  &.move-window-action {
    left: 24px;
  }

  &.close-window-action {
    left: 42px;
  }
}
</style>

<template>
  <div>
    <the-options-action class="window-action" />
    <the-move-action class="window-action move-window-action" />
    <the-close-action class="window-action close-window-action" />
  </div>
</template>

<script lang="ts">
import Vue from 'vue';

import TheMoveAction from './TheMoveAction.vue';
import TheCloseAction from './TheCloseAction.vue';

export default Vue.extend({
  name: 'TheWindowActions',

  components: {
    TheMoveAction,
    TheCloseAction,
  },
});
</script>

<style lang="scss" scoped>
.window-action {
  top: 0;
  margin: 0;
  padding: 0;
  left: 5.5px;
  border: none;
  font-size: 15px;
  background: none;
  position: absolute;

  &.move-window-action {
    left: 24px;
  }

  &.close-window-action {
    left: 42px;
  }
}
</style>


Ad展示优化

Ad展示优化

<template>

         腾讯云促销

        欢迎您，{{ nickname() }}

           界面设置

          密码修改

         退出登录

    <user-password ref="userPassword"></user-password>
    <depart-select ref="departSelect" :closable="true" title="部门切换"></depart-select>
    <setting-drawer ref="settingDrawer" :closable="true" title="系统设置"></setting-drawer>

</template>


ButtonTab: Fix eslint error close #164

ButtonTab: Fix eslint error close #164

<template>
  <a class="vux-button-tab-item" :class="class" href="javascript:" :style="style" @click="onClick">
    <slot></slot>
  </a>
</template>

<script>
export default {
  props: {
    selected: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    onClick: function () {
      this.$dispatch('on-item-click', this.$el.getAttribute('data-index'))
      this.selected = true
    }
  },
  events: {
    'on-item-click': function (dataIndex) {
      const domIndex = this.$el.getAttribute('data-index')
      this.selected = domIndex === dataIndex
      this.shouldRemoveBorder = (dataIndex - 1) === domIndex - 0
    }
  },
  computed: {
    class () {
      return {
        'vux-button-group-current': this.selected,
        'no-border-right': this.shouldRemoveBorder
      }
    },
    style () {
      if (this.$parent.height) {
        return {
          height: `${this.$parent.height}px`,
          lineHeight: `${this.$parent.height}px`
        }
      }
    }
  },
  data () {
    return {
      shouldRemoveBorder: false
    }
  }
}
</script>

<template>
  <a class="vux-button-tab-item" :class="class" href="javascript:" :style="style" @click="onClick">
    <slot></slot>
  </a>
</template>

<script>
export default {
  props: {
    selected: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    onClick: function () {
      this.$dispatch('on-item-click', this.$el.getAttribute('data-index'))
      this.selected = true
    }
  },
  events: {
    'on-item-click': function (dataIndex) {
      const domIndex = this.$el.getAttribute('data-index')
      this.selected = domIndex === dataIndex
      this.shouldRemoveBorder = (dataIndex - 1) === domIndex - 0
    }
  },
  computed: {
    class () {
      return {
        'vux-button-group-current': this.selected,
        'no-border-right': this.shouldRemoveBorder,
      }
    },
    style () {
      if (this.$parent.height) {
        return {
          height: `${this.$parent.height}px`,
          lineHeight: `${this.$parent.height}px`
        }
      }
    }
  },
  data () {
    return {
      shouldRemoveBorder: false
    }
  }
}
</script>


make badge styles more consistent

make badge styles more consistent

<template>

        <{{ instance.name }}>

        router-view{{ instance.matchedRouteSegment ? ': ' + instance.matchedRouteSegment : null }}

        fragment

        inactive

      <component-instance
        v-for="child in instance.children | orderBy 'inactive'"
        track-by="id"
        :instance="child"
        :depth="depth + 1">
      </component-instance>

</template>


fixing Vue template bugs

fixing Vue template bugs

<template>

            <video class="background"  v-if="backgroundShowOrHideVideo" autoplay loop muted >
                <source :src="'storage/'+media.src" :type="media.type">
            </video>

        <transition name="entry" appear mode="out-in">
            <component :is="activeComponent"></component>
        </transition>

</template>


add product dialog improvements

add product dialog improvements

<template>

    <AddNewButton label="Добавить продукт" @addNew="showAddProductPopup = true"/>
    <Popup v-if="showAddProductPopup" @okPressed="addProduct" @close="showAddProductPopup = false"
           buttonLabel="Добавить">

Добавьте продукт

        Категория

          <select v-model="categoryId" class="form-control">
            <option
              v-for="category in availableCategories"
              :value="category.id"
            >{{category.name}}
            </option>
          </select>

        Тип

          <select v-model="productTypeId" class="form-control">
            <option
              v-for="productType in availableProductTypes"
              :value="productType.id"
            >{{productType.name}}
            </option>
          </select>

        Упаковка

          <select v-model="packId" class="form-control">
            <option
              v-for="pack in packs"
              :value="pack.id"
            >{{pack.name}}
            </option>
          </select>

    </Popup>

</template>

<template>

    <AddNewButton label="Добавить продукт" @addNew="showAddProductPopup = true"/>
    <Popup v-if="showAddProductPopup" @okPressed="addProduct" @close="showAddProductPopup = false"
           buttonLabel="Добавить">

Добавьте продукт

        Категория

          <select v-model="categoryId" class="form-control">
            <option
              v-for="category in availableCategories"
              :value="category.id"
            >{{category.name}}
            </option>
          </select>

        Тип

          <select v-model="productTypeId" class="form-control">
            <option
              v-for="productType in productTypes"
              :value="productType.id"
            >{{productType.name}}
            </option>
          </select>

        Упаковка

          <select v-model="packId" class="form-control">
            <option
              v-for="pack in packs"
              :value="pack.id"
            >{{pack.name}}
            </option>
          </select>

    </Popup>

</template>


fix: hasquery to show default search button

<template>

    <btn
      @click="filterOpen=true"
      size="xs"
      :class="hasQuery?'btn-queried btn-info':'btn-secondary'"
      v-tooltip="hasQuery?$t('Click to edit Search Query'):''"
    >

            <i18n :path="'jobquery.title.'+qname"/>:
            {{query[qname]}}

      {{$t('search.ellipsis')}}
    </btn>

    <modal id="activityFilter" v-model="filterOpen" :title="$t('Search Activity')" size="lg" @hide="closing">

                  <i18n path="jobquery.title.jobFilter"/>

                <input
                  type="text"
                  name="jobFilter"
                  v-model="query.jobFilter"
                  autofocus="true"
                  class="form-control"
                  :placeholder="$t('jobquery.title.jobFilter')"
                >

                  <i18n path="jobquery.title.jobIdFilter"/>

                <input
                  type="text"
                  name="jobIdFilter"
                  v-model="query.jobIdFilter"
                  class="form-control"
                  :placeholder="$t( 'jobquery.title.jobIdFilter')"
                >

                  <i18n path="jobquery.title.userFilter"/>

                <input
                  type="text"
                  name="userFilter"
                  v-model="query.userFilter"
                  class="form-control"
                  :placeholder="$t( 'jobquery.title.userFilter')"
                >

                  <i18n path="jobquery.title.filter"/>

                <input
                  type="text"
                  name="execnodeFilter"
                  v-model="query.execnodeFilter"
                  class="form-control"
                  :placeholder="$t( 'jobquery.title.filter')"
                >

                  <i18n path="jobquery.title.titleFilter"/>

                <input
                  type="text"
                  name="titleFilter"
                  v-model="query.titleFilter"
                  class="form-control"
                  :placeholder="$t( 'jobquery.title.titleFilter')"
                >

                  <i18n path="jobquery.title.statFilter"/>

                <select
                  name="statFilter"
                  v-model="query.statFilter"
                  noSelection="['': 'Any']"
                  valueMessagePrefix="status.label"
                  class="form-control"
                >
                  <option value>Any</option>
                  <option>succeed</option>
                  <option>fail</option>
                  <option>cancel</option>
                </select>

                  <i18n path="jobquery.title.recentFilter"/>

                  <select name="recentFilter" v-model="query.recentFilter" class="form-control">
                    <option value>Any Time</option>
                    <option :value="val" v-for="(key,val) in recentDateFilters" :key="key">{{key}}</option>
                    <option value="-">Other...</option>
                  </select>

                <date-filter v-model="df.filter">
                  {{$t('jobquery.title.'+df.name)}}
                </date-filter>

      <template slot="footer">
        <btn @click="filterOpen=false">Cancel</btn>
        <btn @click="search">Search</btn>
        <btn @click="saveFilter">Save as a Filter</btn>
      </template>
    </modal>

</template>


Fix typo

Fix typo

<template>

      <form
        @submit.prevent="search"
        class="search-box">
        <input
          type="search"
          :placeholder="$tr('search')"
          v-model="searchQuery"
          class="search-input"
          ref="searchInput"
        >

        <ui-icon-button
          :ariaLabel="$tr('clear')"
          icon="clear"
          color="black"
          class="search-clear-button"
          :class="searchQuery === '' ? '' : 'search-clear-button-visble'"
          @click="searchQuery = ''"
          size="small"
        />

          <ui-icon-button
            :ariaLabel="$tr('search')"
            :icon="showDropdownSearchBox ? 'arrow_forward' : 'search'"
            type="secondary"
            color="white"
            @click="search"
            class="search-submit-button"
          />

      </form>

    <ui-icon-button
      v-show="showSearchToggleBtn"
      icon="search"
      type="primary"
      color="primary"
      @click="toggleDropdownSearchBox"
    />

</template>


:wheelchair: (a11y) Removes h2 tags in settings menu

Closes #43

<template>

      <router-link :to="{ name: item.name }">
        {{ item.label }}
        <feather-arrow-right />
      </router-link>

      Version{{ version }}

</template>


removed unused code from meetingroom

removed unused code from meetingroom

<template>

Meeting room 🤝

🧠Perfect for brainstorming and meeting clients

💺Capacity 10 seats

📽Projector with Chromecast

🎨Whiteboard

🎧Good for Podcasts

📍Downtown location

💞By renting our meeting room you are supporting community

          {{ orderPrices.meetingRoom }}€ / hour

      <ImageFrame v-bind:url="frame" :key="frame"></ImageFrame>

</template>


Details alliance

Details alliance

<template>

        <svg viewBox="0 0 100 100" class="exchange-icon animated pulse">
          <use xlink:href="#app-icon-arrow"></use>
        </svg>

            <svg viewBox="0 0 100 100" class="foods-icon animated pulse">
              <use xlink:href="#foods-icon-{{ alliance.product.icon }}"></use>
            </svg>

{{ alliance.quantity }}

{{ alliance.users.applicant.name.first }}

{{ alliance.users.giver.name.first }}

{{ alliance.product.name }}

Suivi de vos actions

    <template v-if="alliance.status == 'current'">

      <template v-if="alliance.type == 'applicant'">

        <template v-if="alliance.request.completed && !alliance.availability.completed">

            <fieldset class="step my-side animated">
              <legend>
                <svg viewBox="0 0 100 100" class="alliance-icon">
                  <use xlink:href="#app-icon-helmet"></use>
                </svg>
              </legend>

Ta requête à bien été envoyé à {{ alliance.users.giver.name.first }} le :

{{ allianceCreatedAt }}

            </fieldset>

        </template>

        <template v-if="alliance.request.completed && alliance.availability.completed && !alliance.exchange">

                  <fieldset class="step my-side animated">
                    <legend>
                      <svg viewBox="0 0 100 100" class="alliance-icon">
                        <use xlink:href="#app-icon-helmet"></use>
                      </svg>
                    </legend>

{{ alliance.users.giver.name.first }} est

                        disponible pour le créneau :

Entre {{ alliance.availability.timeStart }} et {{ alliance.availability.timeEnd }}

                      le {{ alliance.availability.date }}
                  </fieldset>

                  <fieldset class="step my-side animated">
                    <legend>
                      <svg viewBox="0 0 100 100" class="alliance-icon">
                        <use xlink:href="#app-icon-helmet"></use>
                      </svg>
                    </legend>

Tu es un sacré vénard ! {{ alliance.users.giver.name.first }}

                      est disponible pour le créneau:

Entre {{ alliance.request.timeStart }} et {{ alliance.request.timeEnd }}

                      {{ alliance.request.date }}
                  </fieldset>

                  Tu le trouveras à l'adresse suivante:

                    {{ foodkeeper.location.street }}

                  {{ foodkeeper.location.additional }}

                  {{ foodkeeper.location.zipcode }} {{ foodkeeper.location.city }}

                  Voici des informations complèmentaires:
                  {{ foodkeeper.location.infos }}

              <fieldset class="step user-side animated">
                <legend>
                  <svg viewBox="0 0 100 100" class="alliance-icon">
                    <use xlink:href="#app-icon-bugle"></use>
                  </svg>
                </legend>
                <form>

  Fichtre,

                  {{ alliance.users.giver.name.first }} n'est pas disponible
                    <template v-if="alliance.request.delayed">
 pour le créneau horaire que tu lui a indiqué</template>
                    <template v-else>maintenant</template>

Mais il te propose l'horaire suivant:

                    <input type="radio" id="date-1" class="filter" value="false" v-model="productType">

Entre {{ alliance.availability.timeStart }} et
                      {{ alliance.availability.timeEnd }}

                      le {{ alliance.availability.date }}

                </form>
              </fieldset>
              <fieldset class="step final-step animated">
                <form>
                  <svg viewBox="0 0 100 100" class="alliance-icon">
                    <use xlink:href="#app-icon-note"></use>
                  </svg>

Ce créneau te convient-il ?

Oui

Non

                </form>
              </fieldset>

        </template>

        <template v-if="alliance.request.completed && alliance.availability.completed && alliance.exchange">

            <fieldset class="step final-step animated">
                <svg viewBox="0 0 100 100" class="alliance-icon">
                  <use xlink:href="#app-icon-note"></use>
                </svg>

                  Qu'as tu pensé de cette alliance ?

                  Elle était :

                <select class="market-add-form-select" v-model="form.review">
                    <option value="0">Naze</option>
                    <option value="1">Bof</option>
                    <option value="2">Ça va</option>
                    <option value="3" selected>Passable</option>
                    <option value="4">Bien</option>
                    <option value="5">Très bien</option>

                </select>
            </fieldset>

Valider

        </template>

      </template>

      <template v-if="alliance.type == 'giver'">

        <template v-if="alliance.request.completed && !alliance.availability.completed">

            <fieldset class="step user-side animated">
              <legend>
                <svg viewBox="0 0 100 100" class="alliance-icon">
                  <use xlink:href="#app-icon-bugle"></use>
                </svg>
              </legend>
              <form>

Tu viens de recevoir une requête

                  {{ alliance.users.applicant.name.first }} demande ta denrée située

                  dans ton garde-manger

{{ foodkeeper.name }}

                  Pour la récupération de ta denrée,

                  {{ alliance.users.applicant.name.first }}
                  te propose le créneau suivant:

                    <input type="radio" id="date-1" class="filter" value="false" v-model="productType">

Entre {{ alliance.request.timeStart }} et {{ alliance.request.timeEnd }}

                      le {{ alliance.request.date }}

Es-tu disponible dès maintenant ?

Oui

Non

              </form>
            </fieldset>

        </template>

        <template v-if="alliance.request.completed && alliance.availability.completed && !alliance.exchange">
          <template v-if="alliance.availability.applicant || alliance.availability.giver">

              <fieldset class="step user-side animated">
                <legend>
                  <svg viewBox="0 0 100 100" class="alliance-icon">
                    <use xlink:href="#app-icon-bugle"></use>
                  </svg>
                </legend>
                <form>
                  As-tu donné la denrée desirée ?

Oui

Non

                </form>
              </fieldset>

          </template>
          <template v-else>

              <fieldset class="step final-step animated">
                <form>
                  <svg viewBox="0 0 100 100" class="alliance-icon">
                    <use xlink:href="#app-icon-note"></use>
                  </svg>

En attente de la confirmation de la disponibilité du demandeur...

                </form>
              </fieldset>

          </template>
        </template>

        <template v-if="alliance.request.completed && alliance.availability.completed && alliance.exchange">

            <fieldset class="step final-step animated">
              <form>
                <svg viewBox="0 0 100 100" class="alliance-icon">
                  <use xlink:href="#app-icon-note"></use>
                </svg>

                Ton allié ne t'a toujours pas évalué
 pour cet échange
              </form>
            </fieldset>

        </template>
      </template>
    </template>

    <template v-if="alliance.status == 'terminated'">

        <template v-if="alliance.type == 'applicant'">
          <fieldset class="step final-step animated">
            <form>
              <svg viewBox="0 0 100 100" class="alliance-icon">
                <use xlink:href="#app-icon-note"></use>
              </svg>

Hip Hip Hip Houra !

              Une étape de plus a été franchie dans la quête du Pain Perdu !
            </form>
          </fieldset>
        </template>
        <template v-else>
          <fieldset class="step final-step animated">
            <form>
              <svg viewBox="0 0 100 100" class="alliance-icon">
                <use xlink:href="#app-icon-note"></use>
              </svg>

Hip Hip Hip Houra !

              Une étape de plus a été franchie dans la quête du Pain Perdu !

            </form>
          </fieldset>

Voir l'avis obtenu

        </template>

    </template>

    <template v-if="alliance.status == 'abandoned'">

        <fieldset class="step final-step animated">
          <form>
            <svg viewBox="0 0 100 100" class="alliance-icon">
              <use xlink:href="#app-icon-note"></use>
            </svg>

Diantre,

            Cette alliance s'avère compliquée !

            Réessaye plus tard lorsque
 les conditions seront plus favorables !
          </form>
        </fieldset>

    </template>

    <slot-popup
      :alliance-id="$route.params.id"
      :update-alliance="updateCurrentAlliance">
    </slot-popup>
    <confirmation-popup
      :user-selection="userSelection"
      :update-alliance="updateCurrentAlliance">
    </confirmation-popup>

</template>

<template>

        <svg viewBox="0 0 100 100" class="exchange-icon animated pulse">
          <use xlink:href="#app-icon-arrow"></use>
        </svg>

            <svg viewBox="0 0 100 100" class="foods-icon animated pulse">
              <use xlink:href="#foods-icon-{{ alliance.product.icon }}"></use>
            </svg>

{{ alliance.quantity }}

{{ alliance.users.applicant.name.first }}

{{ alliance.users.giver.name.first }}

{{ alliance.product.name }}

    <template v-if="alliance.status == 'current'">

      <template v-if="alliance.type == 'applicant'">

        <template v-if="alliance.request.completed && !alliance.availability.completed">

            <fieldset class="step my-side animated">
              <legend>
                <svg viewBox="0 0 100 100" class="alliance-icon">
                  <use xlink:href="#app-icon-helmet"></use>
                </svg>
              </legend>

Ta requête à bien été envoyé à {{ alliance.users.giver.name.first }} le :

{{ allianceCreatedAt }}

            </fieldset>

        </template>

        <template v-if="alliance.request.completed && alliance.availability.completed && !alliance.exchange">

                  <fieldset class="step my-side animated">
                    <legend>
                      <svg viewBox="0 0 100 100" class="alliance-icon">
                        <use xlink:href="#app-icon-helmet"></use>
                      </svg>
                    </legend>

{{ alliance.users.giver.name.first }} est

                        disponible pour le créneau :

Entre {{ alliance.availability.timeStart }} et {{ alliance.availability.timeEnd }}

                      le {{ alliance.availability.date }}
                  </fieldset>

                  <fieldset class="step my-side animated">
                    <legend>
                      <svg viewBox="0 0 100 100" class="alliance-icon">
                        <use xlink:href="#app-icon-helmet"></use>
                      </svg>
                    </legend>

Tu es un sacré vénard ! {{ alliance.users.giver.name.first }}

                      est disponible pour le créneau:

Entre {{ alliance.request.timeStart }} et {{ alliance.request.timeEnd }}

                      {{ alliance.request.date }}
                  </fieldset>

                  Tu le trouveras à l'adresse suivante:

                    {{ foodkeeper.location.street }}

                  {{ foodkeeper.location.additional }}

                  {{ foodkeeper.location.zipcode }} {{ foodkeeper.location.city }}

                  Voici des informations complèmentaires:
                  {{ foodkeeper.location.infos }}

              <fieldset class="step user-side animated">
                <legend>
                  <svg viewBox="0 0 100 100" class="alliance-icon">
                    <use xlink:href="#app-icon-bugle"></use>
                  </svg>
                </legend>
                <form>

  Fichtre,

                  {{ alliance.users.giver.name.first }} n'est pas disponible
                    <template v-if="alliance.request.delayed">
 pour le créneau horaire que tu lui a indiqué</template>
                    <template v-else>maintenant</template>

Mais il te propose l'horaire suivant:

                    <input type="radio" id="date-1" class="filter" value="false" v-model="productType">

Entre {{ alliance.availability.timeStart }} et
                      {{ alliance.availability.timeEnd }}

                      le {{ alliance.availability.date }}

                </form>
              </fieldset>
              <fieldset class="step final-step animated">
                <form>
                  <svg viewBox="0 0 100 100" class="alliance-icon">
                    <use xlink:href="#app-icon-note"></use>
                  </svg>

Ce créneau te convient-il ?

Oui

Non

                </form>
              </fieldset>

        </template>

        <template v-if="alliance.request.completed && alliance.availability.completed && alliance.exchange">

            <fieldset class="step final-step animated">
                <svg viewBox="0 0 100 100" class="alliance-icon">
                  <use xlink:href="#app-icon-note"></use>
                </svg>

                  Qu'as tu pensé de cette alliance ?

                  Elle était :

                <select class="market-add-form-select" v-model="form.review">
                    <option value="0">Naze</option>
                    <option value="1">Bof</option>
                    <option value="2">Ça va</option>
                    <option value="3" selected>Passable</option>
                    <option value="4">Bien</option>
                    <option value="5">Très bien</option>

                </select>
            </fieldset>

Valider

        </template>

      </template>

      <template v-if="alliance.type == 'giver'">

        <template v-if="alliance.request.completed && !alliance.availability.completed">

            <fieldset class="step user-side animated">
              <legend>
                <svg viewBox="0 0 100 100" class="alliance-icon">
                  <use xlink:href="#app-icon-bugle"></use>
                </svg>
              </legend>
              <form>

Tu viens de recevoir une requête

                  {{ alliance.users.applicant.name.first }} demande ta denrée située

                  dans ton garde-manger

{{ foodkeeper.name }}

                  Pour la récupération de ta denrée,

                  {{ alliance.users.applicant.name.first }}
                  te propose le créneau suivant:

                    <input type="radio" id="date-1" class="filter" value="false" v-model="productType">

Entre {{ alliance.request.timeStart }} et {{ alliance.request.timeEnd }}

                      le {{ alliance.request.date }}

Es-tu disponible dès maintenant ?

Oui

Non

              </form>
            </fieldset>

        </template>

        <template v-if="alliance.request.completed && alliance.availability.completed && !alliance.exchange">
          <template v-if="alliance.availability.applicant || alliance.availability.giver">

              <fieldset class="step user-side animated">
                <legend>
                  <svg viewBox="0 0 100 100" class="alliance-icon">
                    <use xlink:href="#app-icon-bugle"></use>
                  </svg>
                </legend>
                <form>
                  As-tu donné la denrée desirée ?

Oui

Non

                </form>
              </fieldset>

          </template>
          <template v-else>

              <fieldset class="step final-step animated">
                <form>
                  <svg viewBox="0 0 100 100" class="alliance-icon">
                    <use xlink:href="#app-icon-note"></use>
                  </svg>

En attente de la confirmation de la disponibilité du demandeur...

                </form>
              </fieldset>

          </template>
        </template>

        <template v-if="alliance.request.completed && alliance.availability.completed && alliance.exchange">

            <fieldset class="step final-step animated">
              <form>
                <svg viewBox="0 0 100 100" class="alliance-icon">
                  <use xlink:href="#app-icon-note"></use>
                </svg>

Ton allié ne t'a toujours pas évalué
 pour cet échange

              </form>
            </fieldset>

        </template>
      </template>
    </template>

    <template v-if="alliance.status == 'terminated'">

        <template v-if="alliance.type == 'applicant'">
          <fieldset class="step final-step animated">
            <form>
              <svg viewBox="0 0 100 100" class="alliance-icon">
                <use xlink:href="#app-icon-note"></use>
              </svg>

Hip Hip Hip Houra !

              Une étape de plus a été franchie dans la quête du Pain Perdu !
            </form>
          </fieldset>
        </template>
        <template v-else>
          <fieldset class="step final-step animated">
            <form>
              <svg viewBox="0 0 100 100" class="alliance-icon">
                <use xlink:href="#app-icon-note"></use>
              </svg>

Hip Hip Hip Houra !

              Une étape de plus a été franchie dans la quête du Pain Perdu !

            </form>
          </fieldset>

Voir l'avis obtenu

        </template>

    </template>

    <template v-if="alliance.status == 'abandoned'">

        <fieldset class="step final-step animated">
          <form>
            <svg viewBox="0 0 100 100" class="alliance-icon">
              <use xlink:href="#app-icon-note"></use>
            </svg>

Diantre,

            Cette alliance s'avère compliquée !

            Réessaye plus tard lorsque
 les conditions seront plus favorables !
          </form>
        </fieldset>

    </template>

    <slot-popup
      :alliance-id="$route.params.id"
      :update-alliance="updateCurrentAlliance">
    </slot-popup>
    <confirmation-popup
      :user-selection="userSelection"
      :update-alliance="updateCurrentAlliance">
    </confirmation-popup>

</template>


fix: autocomplete null judge

fix: autocomplete null judge

<template>

      <template v-if="multiple">{{obj.title}}
        <input :disabled="disabled"
               type="text"
               class="h-autocomplete-input"
               @focus="focus"
               v-model="tempValue"
               @blur="blur"
               @paste="paste"
               @keyup="handle"
               @keypress.enter="enterHandle"
               :placeholder="showPlaceholder" />

      </template>
      <template v-if="!multiple">
        <input type="text"
               :disabled="disabled"
               class="h-autocomplete-input"
               @focus="focus"
               v-model="tempValue"
               @paste="paste"
               @blur="blur"
               @keyup="handle"
               @keypress.enter="enterHandle"
               :placeholder="showPlaceholder" />

      </template>

        <slot name="top" :results="results"></slot>

          <template v-else-if="!$scopedSlots.item">{{result.title}}</template>
          <slot v-else :item="result" name="item"></slot>

{{showEmptyContent}}

        <slot name="bottom" :results="results"></slot>

</template>


[fix] fix Search style bug

[fix] fix Search style bug

<template lang="html">

      <input type="search" name="" value="" v-model="inputText" @focus="closeIcon = true" :placeholder="placeholder">
      ✕

搜索

</template>

<template lang="html">

      <input type="text" name="" value="" v-model="inputText" @focus="closeIcon = true" :placeholder="placeholder">
      ×

搜索

</template>