Remove unused router prop

Remove unused router prop

<template>

  <div>

    <PageHeader
      :title="topic.title"
      :progress="calculateProgress"
      contentType="topic"
    />

    <TextTruncator
      v-if="topic.description"
      :text="topic.description"
      :maxHeight="90"
      :showTooltip="false"
      :showViewMore="true"
      dir="auto"
      class="page-description"
    />

    <ContentCardGroupGrid
      v-if="contents.length"
      :contents="contents"
      :genContentLink="genContentLink"
    />

  </div>

</template>

<script>

  import { mapState } from 'vuex';
  import { ContentNodeKinds } from 'kolibri.coreVue.vuex.constants';
  import TextTruncator from 'kolibri.coreVue.components.TextTruncator';
  import { PageNames } from '../constants';
  import PageHeader from './PageHeader';
  import ContentCardGroupGrid from './ContentCardGroupGrid';

  export default {
    name: 'TopicsPage',
    metaInfo() {
      let title;
      if (this.isRoot) {
        title = this.$tr('documentTitleForChannel', {
          channelTitle: this.channelTitle,
        });
      } else {
        title = this.$tr('documentTitleForTopic', {
          channelTitle: this.channelTitle,
          topicTitle: this.topic.title,
        });
      }
      return { title };
    },
    components: {
      PageHeader,
      ContentCardGroupGrid,
      TextTruncator,
    },
    computed: {
      ...mapState('topicsTree', ['channel', 'contents', 'isRoot', 'topic']),
      channelTitle() {
        return this.channel.title;
      },
      calculateProgress() {
        // calculate progress across all topics
        const contentsLength = this.contents.length;
        if (contentsLength !== 0) {
          const computedSum =
            this.contents.map(content => content.progress).reduce((acc, val) => acc + val) /
            contentsLength;
          return computedSum !== 0 ? computedSum : undefined;
        }

        return undefined;
      },
    },
    methods: {
      genContentLink(id, kind) {
        const routeName =
          kind === ContentNodeKinds.TOPIC ? PageNames.TOPICS_TOPIC : PageNames.TOPICS_CONTENT;
        return {
          name: routeName,
          params: { id },
        };
      },
    },
    $trs: {
      topics: 'Topics',
      navigate: 'Navigate content using headings',
      documentTitleForChannel: 'Topics - { channelTitle }',
      documentTitleForTopic: '{ topicTitle } - { channelTitle }',
    },
  };

</script>

<style lang="scss" scoped>

  .page-description {
    margin-top: 1em;
    margin-bottom: 1em;
    line-height: 1.5em;
  }

</style>

<template>

  <div>

    <PageHeader
      :title="topic.title"
      :progress="calculateProgress"
      contentType="topic"
    />

    <TextTruncator
      v-if="topic.description"
      :text="topic.description"
      :maxHeight="90"
      :showTooltip="false"
      :showViewMore="true"
      dir="auto"
      class="page-description"
    />

    <ContentCardGroupGrid
      v-if="contents.length"
      :contents="contents"
      :genContentLink="genContentLink"
    />

  </div>

</template>

<script>

  import { mapState } from 'vuex';
  import { ContentNodeKinds } from 'kolibri.coreVue.vuex.constants';
  import TextTruncator from 'kolibri.coreVue.components.TextTruncator';
  import { PageNames } from '../constants';
  import PageHeader from './PageHeader';
  import ContentCardGroupGrid from './ContentCardGroupGrid';

  export default {
    name: 'TopicsPage',
    metaInfo() {
      let title;
      if (this.isRoot) {
        title = this.$tr('documentTitleForChannel', {
          channelTitle: this.channelTitle,
        });
      } else {
        title = this.$tr('documentTitleForTopic', {
          channelTitle: this.channelTitle,
          topicTitle: this.topic.title,
        });
      }
      return { title };
    },
    components: {
      PageHeader,
      ContentCardGroupGrid,
      TextTruncator,
    },
    computed: {
      ...mapState('topicsTree', ['channel', 'contents', 'isRoot', 'topic']),
      channelId() {
        return this.channel.id;
      },
      channelTitle() {
        return this.channel.title;
      },
      calculateProgress() {
        // calculate progress across all topics
        const contentsLength = this.contents.length;
        if (contentsLength !== 0) {
          const computedSum =
            this.contents.map(content => content.progress).reduce((acc, val) => acc + val) /
            contentsLength;
          return computedSum !== 0 ? computedSum : undefined;
        }

        return undefined;
      },
    },
    methods: {
      genContentLink(id, kind) {
        if (kind === ContentNodeKinds.TOPIC) {
          return {
            name: PageNames.TOPICS_TOPIC,
            params: { channel_id: this.channelId, id },
          };
        }
        return {
          name: PageNames.TOPICS_CONTENT,
          params: { channel_id: this.channelId, id },
        };
      },
    },
    $trs: {
      topics: 'Topics',
      navigate: 'Navigate content using headings',
      documentTitleForChannel: 'Topics - { channelTitle }',
      documentTitleForTopic: '{ topicTitle } - { channelTitle }',
    },
  };

</script>

<style lang="scss" scoped>

  .page-description {
    margin-top: 1em;
    margin-bottom: 1em;
    line-height: 1.5em;
  }

</style>


feat(dev): Fix for broken dev example (#3057)

<template>

Chat with avatar

To mix messages with avatar and without avatar in the same thread, use a placeholder avatar image.

      <q-chat-message
        v-for="(msg, index) in messages"
        :key="index"
        :label="msg.label"
        :sent="msg.sent"
        :text-color="msg.textColor"
        :bg-color="msg.bgColor"
        :name="msg.name"
        :avatar="msg.avatar"
        :text="msg.text"
        :stamp="msg.stamp"
      />
      <q-chat-message
        name="Vladimir"
        avatar="/https://cdn.quasar-framework.org/img/boy-avatar.png"
      >
        <q-spinner-dots size="2rem" />
      </q-chat-message>

Chat using avatar slot

      <q-chat-message
        name="Vladimir"
        :text="['Use your own spacing or class q-message-avatar']"
      >
        <q-icon name="face" size="4em" slot="avatar"/>
      </q-chat-message>

Chat without avatar

      <q-chat-message
        v-for="(msg, index) in messages"
        :key="1000 + index"
        :label="msg.label"
        :sent="msg.sent"
        :text-color="msg.textColor"
        :bg-color="msg.bgColor"
        :name="msg.name"
        :text="msg.text"
        :stamp="msg.stamp"
      />
      <q-chat-message
        name="Vladimir"
      >
        <q-spinner-dots size="2rem" />
      </q-chat-message>

</template>


KIcon GroupEnrollPage

KIcon GroupEnrollPage

<template>

  <CoreBase
    :immersivePage="true"
    immersivePageIcon="arrow_back"
    :immersivePagePrimary="true"
    :primary="true"
    :toolbarTitle="currentGroup.name"
    :appBarTitle="currentGroup.name"
    :immersivePageRoute="$router.getRoute('GroupMembersPage')"
    :pageTitle="pageTitle"
  >
    <KPageContainer>

        {{ $tr('pageHeader', { className: currentGroup.name }) }}

      <form @submit.prevent="addSelectedUsersToGroup">

          <FilterTextbox
            v-model.trim="filterInput"
            :placeholder="$tr('searchForUser')"
            @input="pageNum = 1"
          />

{{ $tr('userTableLabel') }}

        <UserTable
          v-model="selectedUsers"
          :users="visibleFilteredUsers"
          :selectable="true"
          :emptyMessage="emptyMessage"
          :infoDescriptor="$tr('learnerGroups')"
        >
          <template v-slot:info="userRow">
            <TruncatedItemList :items="getGroupsForLearner(userRow.user.id)" />
          </template>
        </UserTable>

            {{ $tr('pagination', {
              visibleStartRange,
              visibleEndRange,
              numFilteredUsers
            }) }}

          <UiIconButton
            type="primary"
            :ariaLabel="$tr('previousResults')"
            :disabled="pageNum === 1"
            size="small"
            @click="goToPage(pageNum - 1)"
          >
            <KIcon
              icon="keyboard_arrow_left"
              style="top: 0; width: 24px; height 24px;"
            />
          </UiIconButton>
          <UiIconButton
            type="primary"
            :ariaLabel="$tr('nextResults')"
            :disabled="numPages === 0 || pageNum === numPages"
            size="small"
            @click="goToPage(pageNum + 1)"
          >
            <KIcon
              icon="keyboard_arrow_right"
              style="top: 0; width: 24px; height 24px;"
            />
          </UiIconButton>

          <KButton
            :text="coreString('confirmAction')"
            :primary="true"
            type="submit"
            :disabled="selectedUsers.length === 0"
          />

      </form>
    </KPageContainer>

  </CoreBase>

</template>

<template>

  <CoreBase
    :immersivePage="true"
    immersivePageIcon="arrow_back"
    :immersivePagePrimary="true"
    :primary="true"
    :toolbarTitle="currentGroup.name"
    :appBarTitle="currentGroup.name"
    :immersivePageRoute="$router.getRoute('GroupMembersPage')"
    :pageTitle="pageTitle"
  >
    <KPageContainer>

        {{ $tr('pageHeader', { className: currentGroup.name }) }}

      <form @submit.prevent="addSelectedUsersToGroup">

          <FilterTextbox
            v-model.trim="filterInput"
            :placeholder="$tr('searchForUser')"
            @input="pageNum = 1"
          />

{{ $tr('userTableLabel') }}

        <UserTable
          v-model="selectedUsers"
          :users="visibleFilteredUsers"
          :selectable="true"
          :emptyMessage="emptyMessage"
          :infoDescriptor="$tr('learnerGroups')"
        >
          <template v-slot:info="userRow">
            <TruncatedItemList :items="getGroupsForLearner(userRow.user.id)" />
          </template>
        </UserTable>

            {{ $tr('pagination', {
              visibleStartRange,
              visibleEndRange,
              numFilteredUsers
            }) }}

          <UiIconButton
            type="primary"
            :ariaLabel="$tr('previousResults')"
            :disabled="pageNum === 1"
            size="small"
            @click="goToPage(pageNum - 1)"
          >
            <mat-svg
              v-if="isRtl"
              name="chevron_right"
              category="navigation"
            />
            <mat-svg
              v-else
              name="chevron_left"
              category="navigation"
            />
          </UiIconButton>
          <UiIconButton
            type="primary"
            :ariaLabel="$tr('nextResults')"
            :disabled="numPages === 0 || pageNum === numPages"
            size="small"
            @click="goToPage(pageNum + 1)"
          >
            <mat-svg
              v-if="isRtl"
              name="chevron_left"
              category="navigation"
            />
            <mat-svg
              v-else
              name="chevron_right"
              category="navigation"
            />
          </UiIconButton>

          <KButton
            :text="coreString('confirmAction')"
            :primary="true"
            type="submit"
            :disabled="selectedUsers.length === 0"
          />

      </form>
    </KPageContainer>

  </CoreBase>

</template>


Add new internal icon 'close-circle' to docs (#2785)

To make custom icons work when using clearable autocomplete

<template>

                ionicons

                <button class="button is-dark">

                    Finish
                </button>
                <button class="button is-warning">

                    Finish
                </button>
                <button class="button is-warning">

                    Refresh
                </button>

                unicons

                <button class="button is-dark">

                    Finish
                </button>
                <button class="button is-warning">

                    Finish
                </button>
                <button class="button is-warning">

                    Refresh
                </button>

                Can also customize some properties of the default icon packs. In this example, default sizes for FontAwesome have been modified.

</template>


remove unused import

remove unused import

<template>

        {{ $tr('selectedLanguageLabel') }}

        {{ selectedLanguage }}

    <k-button
      v-for="language in buttonLanguages"
      class="language-list-button-option language-list-items"
      @click="switchLanguage(language.id)"
      :key="language.id"
      :raised="false"
      :text="language.lang_name"
    />

    <select
      @input="switchLanguage($event.target.value)"
      v-if="selectorLanguages.length"
      class="language-list-dropdown language-list-items">
      <option
        disabled
        selected
        hidden
      >
        {{ $tr('showMoreLanguagesSelector') }}
      </option>

      <option
        v-for="language in selectorLanguages"
        :key="language.id"
        :value="language.id"
        class="language-list-dropdown-option"
      >
        {{ language.lang_name }}
      </option>
    </select>

</template>


Handle the case where password is undefined

<template>

    <uw-card :loaded="isReady"
             :errored="isErrored"
             :errored-show="showError"
    >
      <template #card-heading>

          UW Medicine Account

      </template>
      <template #card-error>
        An error occurred and MyUW cannot load your information right now.
        In the meantime, try the
        UW Medicine Account page.
      </template>
      <template #card-body>

          This password is for UW Medicine applications
          like Epic, ORCA, MINDscape, AMC network, etc.

              Password expired on {{ toFriendlyDate(expiresMed) }}.

Change your password to regain access.

            Password expiration

            {{ toFriendlyDate(expiresMed) }}
            in {{ daysBeforeExpires }} days*

*Expiration date gets updated nightly.

            Change UW Medicine password

      </template>
    </uw-card>

</template>


patch

patch

<template>
    <div :class="[prefixClz, fixed ? `${prefixClz}-fixed` : '']">
        <div :class="[`${prefixClz}-header`]" v-if="hasSlot('header')">
            <slot name="header"></slot>
        </div>
        <div :class="[`${prefixClz}-body`, bodyClz]">
            <template v-if="fixed">
                <stick :class="[`${prefixClz}-left`]" v-if="hasSlot('left')">
                    <slot name="left"></slot>
                </stick>
                <div :class="[`${prefixClz}-main`]" v-if="hasSlot('default')">
                    <slot></slot>
                </div>
                <div :class="[`${prefixClz}-right`]" v-if="hasSlot('right')">
                    <slot name="right"></slot>
                </div>
            </template>
            <template v-else>
                <div :class="[`${prefixClz}-left`]" v-if="hasSlot('left')">
                    <slot name="left"></slot>
                </div>
                <div :class="[`${prefixClz}-main`]" v-if="hasSlot('default')">
                    <slot></slot>
                </div>
                <div :class="[`${prefixClz}-right`]" v-if="hasSlot('right')">
                    <slot name="right"></slot>
                </div>
            </template>
        </div>
        <div :class="[`${prefixClz}-footer`]" v-if="hasSlot('footer')">
            <slot name="footer"></slot>
        </div>
    </div>
</template>
<script>
  import { getScroll, getOffset } from '../../../utils'
  import Stick from '../../stick'
  const prefixClz = 'vvue-layout-type-holy-grail'
  export default {
    name: 'HolyGrail',
    components: { Stick },
    props: {
      fixed: {
        type: Boolean,
        default: false
      },
      bodyClz: {
        type: String,
        default: ''
      }
    },
    data: () => ({
      prefixClz: prefixClz,
    }),
    methods: {
      hasSlot(name) {
        return this.$slots[name].length > 0
      },
      handleScroll() {
        const header = document.querySelector(`.${prefixClz}-header`)
        const footer = document.querySelector(`.${prefixClz}-footer`)
        const leftStick = document.querySelector(`.${prefixClz}-left`)
        const absEle = document.querySelector(`.${prefixClz}-left > div`)
        const scrollTop = getScroll(window, true);
        const windowHeight = window.innerHeight

        const headerBelowTop = header.offsetHeight - scrollTop
        const footerBelowBottom = getOffset(footer).top - (windowHeight + scrollTop)

        if (headerBelowTop > 0 && footerBelowBottom > 0) { // only header
          leftStick.style.height = `calc(100vh - ${headerBelowTop}px)`
        }
        if (headerBelowTop < 0 && footerBelowBottom > 0) { // neither header nor footer
          leftStick.style.height = '100vh'
        }
        if (headerBelowTop < 0 && footerBelowBottom < 0) { // only footer
          leftStick.style.height = `calc(100vh + ${footerBelowBottom}px)`
        }
        if (headerBelowTop > 0 && footerBelowBottom < 0) { // both header and footer
          leftStick.style.height = `calc(100vh + ${footerBelowBottom}px) - ${headerBelowTop}px`
        }
        absEle.style.height = leftStick.offsetHeight // absEle 会脱离文档流 所以不能使用100%设置高度
      }
    },
    mounted() {
      if (this.fixed) {
        const leftStick = document.querySelector(`.${prefixClz}-left`)
        const leftSlot = document.querySelector(`.${prefixClz}-left > div`).firstChild
        leftSlot.style.height = '100%'
        leftStick.style.width = leftSlot.offsetWidth + 'px'
        window.addEventListener('scroll', this.handleScroll, false)
      }
    }
  }
</script>

<template>
    <div :class="[prefixClz, fixed ? `${prefixClz}-fixed` : '']">
        <div :class="[`${prefixClz}-header`]" v-if="hasSlot('header')">
            <slot name="header"></slot>
        </div>
        <div :class="[`${prefixClz}-body`, bodyClz]">
            <template v-if="fixed">
                <stick :class="[`${prefixClz}-left`]" v-if="hasSlot('left')">
                    <slot name="left"></slot>
                </stick>
                <div :class="[`${prefixClz}-main`]" v-if="hasSlot('default')">
                    <slot></slot>
                </div>
                <div :class="[`${prefixClz}-right`]" v-if="hasSlot('right')">
                    <slot name="right"></slot>
                </div>
            </template>
            <template v-else>
                <div :class="[`${prefixClz}-left`]" v-if="hasSlot('left')">
                    <slot name="left"></slot>
                </div>
                <div :class="[`${prefixClz}-main`]" v-if="hasSlot('default')">
                    <slot></slot>
                </div>
                <div :class="[`${prefixClz}-right`]" v-if="hasSlot('right')">
                    <slot name="right"></slot>
                </div>
            </template>
        </div>
        <div :class="[`${prefixClz}-footer`]" v-if="hasSlot('footer')">
            <slot name="footer"></slot>
        </div>
    </div>
</template>
<script>
  import { getScroll, getOffset } from '../../../utils'
  import Stick from '../../stick'
  const prefixClz = 'vvue-layout-type-holy-grail'
  export default {
    name: 'HolyGrail',
    components: { Stick },
    props: {
      fixed: {
        type: Boolean,
        default: false
      },
      bodyClz: {
        type: String,
        default: ''
      }
    },
    data: () => ({
      prefixClz: prefixClz,
    }),
    methods: {
      hasSlot(name) {
        return this.$slots[name].length > 0
      },
      handleScroll() {
        const header = document.querySelector(`.${prefixClz}-header`)
        const footer = document.querySelector(`.${prefixClz}-footer`)
        const leftStick = document.querySelector(`.${prefixClz}-left`)
        const absEle = document.querySelector(`.${prefixClz}-left > div`)
        const scrollTop = getScroll(window, true);
        const windowHeight = window.innerHeight

        const headerBelowTop = header.offsetHeight - scrollTop
        const footerBelowBottom = getOffset(footer).top - (windowHeight + scrollTop)

        if (headerBelowTop > 0 && footerBelowBottom > 0) { // only header
          leftStick.style.height = `calc(100vh - ${headerBelowTop}px)`
        }
        if (headerBelowTop < 0 && footerBelowBottom > 0) { // neither header nor footer
          leftStick.style.height = '100vh'
        }
        if (headerBelowTop < 0 && footerBelowBottom < 0) { // only footer
          leftStick.style.height = `calc(100vh + ${footerBelowBottom}px)`
        }
        if (headerBelowTop > 0 && footerBelowBottom < 0) { // both header and footer
          leftStick.style.height = `calc(100vh + ${footerBelowBottom}px) - ${headerBelowTop}px`
        }
        absEle.style.height = leftStick.style.maxHeight // absEle 会脱离文档流 所以不能使用100%设置高度
      }
    },
    mounted() {
      if (this.fixed) {
        const leftStick = document.querySelector(`.${prefixClz}-left`)
        const leftSlot = document.querySelector(`.${prefixClz}-left > div`).firstChild
        leftSlot.style.height = '100%'
        leftStick.style.width = leftSlot.offsetWidth + 'px'
        window.addEventListener('scroll', this.handleScroll, false)
      }
    }
  }
</script>


devop: add comments

devop: add comments

<template>

      <v-skeleton-loader width="150px" type="list-item" />
      <v-skeleton-loader
        v-for="idx in 3"
        :key="idx"
        class="mb-4"
        height="100px"
        type="image"
      />

        You are currently not staking any eth.

 0" class="pb-8">
        Pending

                  {{ pending.amount }} ETH

                  {{ '$' + pending.amountFiat }}

              <v-progress-circular
                size="18"
                width="2"
                color="primary"
                indeterminate
              />
              <v-icon class="ml-5" color="searchText" size="22">{{
                isExpanded(idx) ? 'mdi-chevron-up' : 'mdi-chevron-down'
              }}</v-icon>

More Info

              <v-progress-circular
                class="ml-4"
                size="18"
                width="2"
                color="primary"
                indeterminate
              />
              Sending

              <v-icon size="20" color="primary">mdi-check-circle</v-icon>
              Deposited

              <v-icon size="20" color="error">mdi-close-circle</v-icon>
              Failed

              View on Etherscan
                <v-icon color="primary" size="14">mdi-open-in-new</v-icon>
              View on EthVM
                <v-icon color="primary" size="14">mdi-open-in-new</v-icon>

                <v-progress-circular
                  size="18"
                  width="2"
                  color="primary"
                  indeterminate
                />
                Waiting for validator activation

              Estimated wait time: {{ pending.estimatedWaitTime }}

              Eth2 Beacon Chain transactions
                <v-icon color="primary" size="14">mdi-open-in-new</v-icon>

 0">
        Active

                {{ active.totalBalanceETH + ' ETH' }}

                {{ '$' + active.totalBalanceFiat }}

                Earned
                {{ active.earned + ' ETH' }}
                · Average APR {{ active.averageApr }}

          View Eth2 address
            <v-icon color="primary" size="14">mdi-open-in-new</v-icon>

</template>


name change

name change

<template>
  <div
    class="apos-primary-scrollbar apos-context-menu__dialog"
    :class="classes"
    role="dialog"
  >
    <AposContextMenuTip
      v-if="hasTip"
      :align="tipAlignment"
      :origin="menuOrigin"
      x-placement="bottom"
    />
    <div class="apos-context-menu__pane">
      <slot>
        <ul
          v-if="menu"
          class="apos-context-menu__items" role="menu"
        >
          <AposContextMenuItem
            v-for="item in menu"
            :key="item.action"
            :data-apos-test-context-menu-item="item.action"
            :menu-item="item"
            @clicked="menuItemClicked"
            :open="isOpen"
          />
        </ul>
      </slot>
    </div>
  </div>
</template>

<script>

export default {
  name: 'AposContextMenuDialog',
  props: {
    menuPlacement: {
      type: String,
      required: true
    },
    menu: {
      type: Array,
      default: null
    },
    classList: {
      type: String,
      default: ''
    },
    isOpen: {
      type: Boolean,
      default: false
    },
    modifiers: {
      type: Array,
      default() {
        return [];
      }
    },
    hasTip: {
      type: Boolean,
      default: true
    }
  },
  emits: [ 'item-clicked' ],
  data() {
    return {
    };
  },
  computed: {
    menuPositions () {
      return this.menuPlacement.split('-');
    },
    menuOrigin() {
      return this.menuPositions[0];
    },
    tipAlignment() {
      if (!this.menuPositions[1]) {
        return 'center';
      } else {
        return this.menuPositions[1];
      }
    },
    classes() {
      const classes = this.classList.split(' ');
      this.modifiers.forEach(c => {
        classes.push(`apos-context-menu__dialog--${c}`);
      });
      return classes.join(' ');
    }
  },
  methods: {
    menuItemClicked(action) {
      this.$emit('item-clicked', action);
    }
  }
};
</script>

<style lang="scss">

.apos-context-menu__dialog--unpadded > .apos-context-menu__pane {
  padding: 0;
}

.apos-context-menu__dialog--tb-padded > .apos-context-menu__pane {
  padding-top: 20px;
  padding-bottom: 20px;
}

.apos-context-menu__dialog {
  display: inline-block;
  color: var(--a-text-primary);
  transition: scale 0.15s ease, translatey 0.15s ease;
}

.apos-context-menu__inner {
  border-radius: var(--a-border-radius);
  box-shadow: var(--a-box-shadow);
  background-color: var(--a-background-primary);
  border: 1px solid var(--a-base-8);
}

.apos-context-menu__pane {
  @include type-base;
  padding: 20px;
  border: 1px solid var(--a-base-8);
  border-radius: var(--a-border-radius);
  box-shadow: var(--a-box-shadow);
  background-color: var(--a-background-primary);
}

.apos-context-menu__items {
  @include apos-list-reset();
  display: inline-block;
  list-style-type: none;
  width: max-content;
  margin: none;
  margin-block-start: 0;
  margin-block-end: 0;
  padding: 10px 0;
}

.apos-context-menu__dialog ::v-deep .apos-schema .apos-field {
  margin-bottom: 20px;
  .apos-field__help {
    margin-top: 5px;
  }
}

</style>

<template>
  <div
    class="apos-primary-scrollbar apos-context-menu__dialog"
    :class="classes"
    role="dialog"
  >
    <AposContextMenuTip
      v-if="hasTip"
      :align="tipAlignment"
      :origin="menuOrigin"
      x-placement="bottom"
    />
    <div class="apos-context-menu__pane">
      <slot>
        <ul
          v-if="menu"
          class="apos-context-menu__items" role="menu"
        >
          <AposContextMenuItem
            v-for="item in menu"
            :key="item.action"
            :data-apos-test="item.action"
            :menu-item="item"
            @clicked="menuItemClicked"
            :open="isOpen"
          />
        </ul>
      </slot>
    </div>
  </div>
</template>

<script>

export default {
  name: 'AposContextMenuDialog',
  props: {
    menuPlacement: {
      type: String,
      required: true
    },
    menu: {
      type: Array,
      default: null
    },
    classList: {
      type: String,
      default: ''
    },
    isOpen: {
      type: Boolean,
      default: false
    },
    modifiers: {
      type: Array,
      default() {
        return [];
      }
    },
    hasTip: {
      type: Boolean,
      default: true
    }
  },
  emits: [ 'item-clicked' ],
  data() {
    return {
    };
  },
  computed: {
    menuPositions () {
      return this.menuPlacement.split('-');
    },
    menuOrigin() {
      return this.menuPositions[0];
    },
    tipAlignment() {
      if (!this.menuPositions[1]) {
        return 'center';
      } else {
        return this.menuPositions[1];
      }
    },
    classes() {
      const classes = this.classList.split(' ');
      this.modifiers.forEach(c => {
        classes.push(`apos-context-menu__dialog--${c}`);
      });
      return classes.join(' ');
    }
  },
  methods: {
    menuItemClicked(action) {
      this.$emit('item-clicked', action);
    }
  }
};
</script>

<style lang="scss">

.apos-context-menu__dialog--unpadded > .apos-context-menu__pane {
  padding: 0;
}

.apos-context-menu__dialog--tb-padded > .apos-context-menu__pane {
  padding-top: 20px;
  padding-bottom: 20px;
}

.apos-context-menu__dialog {
  display: inline-block;
  color: var(--a-text-primary);
  transition: scale 0.15s ease, translatey 0.15s ease;
}

.apos-context-menu__inner {
  border-radius: var(--a-border-radius);
  box-shadow: var(--a-box-shadow);
  background-color: var(--a-background-primary);
  border: 1px solid var(--a-base-8);
}

.apos-context-menu__pane {
  @include type-base;
  padding: 20px;
  border: 1px solid var(--a-base-8);
  border-radius: var(--a-border-radius);
  box-shadow: var(--a-box-shadow);
  background-color: var(--a-background-primary);
}

.apos-context-menu__items {
  @include apos-list-reset();
  display: inline-block;
  list-style-type: none;
  width: max-content;
  margin: none;
  margin-block-start: 0;
  margin-block-end: 0;
  padding: 10px 0;
}

.apos-context-menu__dialog ::v-deep .apos-schema .apos-field {
  margin-bottom: 20px;
  .apos-field__help {
    margin-top: 5px;
  }
}

</style>


fix(timeline): time cursor spacing

fix(timeline): time cursor spacing

<template>

    <SplitPane
      save-id="timeline-left-main"
      :default-split="25"
      dragger-offset="before"
    >
      <template #left>

            <LayerItem
              v-for="layer of layers"
              :key="layer.id"
              :layer="layer"
              :hover="hoverLayerId === layer.id"
              class="flex-none"
              @mouseover.native="hoverLayerId = layer.id"
              @mouseout.native="hoverLayerId = null"
            />

      </template>

      <template #right>
        <SplitPane
          save-id="timeline-right"
          :default-split="70"
          :max="85"
          dragger-offset="after"
        >
          <template #left>

              <TimelineScrollbar
                :min.sync="minTime"
                :max.sync="maxTime"
                :start.sync="startTime"
                :end.sync="endTime"
                class="flex-none"
              />
              <TimelineView
                class="h-full"
              />

                  <VueIcon
                    icon="schedule"
                    class="w-3 h-3 opacity-50"
                  />

                    {{ formattedCursorTime }}

          </template>

          <template #right>
            <SelectedEventInspector />
          </template>
        </splitpane>
      </template>
    </SplitPane>

    <portal to="header-end">
      <VueDropdown>
        <template #trigger>
          <VueButton
            v-tooltip="'Select layers'"
            class="icon-button flat"
            icon-left="playlist_add"
          />
        </template>

            <VueSwitch
              v-for="layer of allLayers"
              :key="layer.id"
              :value="!isLayerHidden(layer)"
              class="extend-left px-2 py-1 hover:bg-green-100 dark-hover:bg-green-900"
              @update="value => setLayerHidden(layer, !value)"
            >
              {{ layer.label }}
            </VueSwitch>

      </VueDropdown>

      <VueButton
        v-tooltip="'Clear all timelines'"
        class="icon-button flat"
        icon-left="delete"
        @click="resetTimeline()"
      />
    </portal>

</template>


docs(NotificationsMenu): make outline style dependent upon unread msgs

<template>
  <app-menu
    key="notifications-menu"
    v-model="menu"
    :close-on-content-click="false"
    :max-width="maxWidth"
    bottom
    content-class="overflow-hidden"
    left
  >
    <template #activator="{ attrs, on }">
      <app-tooltip-btn
        path="notifications"
        v-bind="attrs"
        v-on="on"
      >
        <template #icon>
          <v-badge
            :value="unread.length"
            color="red"
            left
            overlap
          >
            <template #badge>
              {{ unread.length }}
            </template>

            <v-icon v-text="`$mdiBell${unread.length === 0 ? 'Outline' : ''}`" />
          </v-badge>
        </template>
      </app-tooltip-btn>
    </template>

    <v-toolbar
      :width="maxWidth"
      class="pr-5"
      flat
      short
    >
      <v-btn
        :disabled="archived ? unread.length < 1 : read.length < 1"
        class="px-2 ml-n1"
        small
        text
        @click="archived = !archived"
      >
        <i18n :path="archived ? 'unread' : 'read'">
          <template #number>
            <strong v-text="archived ? unread.length : read.length" />
          </template>
        </i18n>
      </v-btn>

      <v-spacer />

      <app-tooltip-btn
        v-if="marked"
        :disabled="done"
        :icon="marked.icon"
        :path="`marked-${marked.path}`"
        small
        @click="toggleAll"
      />
    </v-toolbar>

    <v-divider />

    <v-responsive
      class="overflow-y-scroll"
      max-height="320"
    >
      <div
        v-if="done"
        class="py-8 text-center text-subtitle-1"
      >
        <i18n
          path="done"
          tag="p"
        />

        <v-icon
          color="grey lighten-2"
          size="96"
        >
          $mdiVuetify
        </v-icon>
      </div>

      <template v-else>
        <v-list-item
          v-for="({ created_at, metadata, slug, title }) in filtered"
          :key="slug"
          :href="metadata.action"
          :ripple="false"
          target="_blank"
          @click="toggle(slug)"
        >
          <v-list-item-content>
            <div
              class="grey--text text--darken-1 text-caption font-weight-light text-uppercase"
              v-text="created_at"
            />

            <v-list-item-title
              class="text-subtitle-1"
              v-text="`${metadata.emoji} ${title}`"
            />
          </v-list-item-content>

          <v-list-item-action>
            <v-btn
              :ripple="false"
              icon
              @click.stop.prevent="toggle(slug)"
            >
              <v-icon v-text="marked.icon" />
            </v-btn>
          </v-list-item-action>
        </v-list-item>
      </template>
    </v-responsive>
  </app-menu>
</template>

<script>
  // Utilities
  import { formatDate } from '@/util/date.js'
  import { sync } from 'vuex-pathify'

  export default {
    name: 'NotificationsMenu',

    inject: ['theme'],

    data: () => ({
      archived: false,
      icons: {
        read: '$mdiEmailOpen',
        unread: '$mdiEmailMarkAsUnread',
      },
      menu: false,
    }),

    computed: {
      notifications: sync('messages/notifications'),
      snack: sync('snackbar/value'),
      snackbar: sync('snackbar/snackbar'),
      unotifications: sync('user/notifications'),
      done () {
        return this.filtered.length === 0
      },
      // What is ultimately iterated
      filtered () {
        return this.archived ? this.read : this.unread
      },
      // Map items to contain a viewed
      // property and format the date
      mapped () {
        return this.notifications.map(item => {
          return {
            ...item,
            created_at: formatDate(new Date(item.created_at)),
            viewed: this.unotifications.includes(item.slug),
          }
        })
      },
      marked () {
        const path = this.archived ? 'unread' : 'read'
        const icon = this.icons[path]

        if (!icon || !path) return null

        return { icon, path }
      },
      maxWidth () {
        return this.$vuetify.breakpoint.mobile ? 296 : 320
      },
      read () {
        return this.mapped.filter(n => n.viewed)
      },
      unread () {
        return this.mapped.filter(n => !n.viewed)
      },
    },

    methods: {
      toggle (slug) {
        this.unotifications = this.unotifications.includes(slug)
          ? this.unotifications.filter(n => n !== slug)
          : [...this.unotifications, slug]
      },
      toggleAll () {
        this.unotifications = !this.archived
          ? this.notifications.map(i => i.slug)
          : []
      },
    },
  }
</script>

<template>
  <app-menu
    key="notifications-menu"
    v-model="menu"
    :close-on-content-click="false"
    :max-width="maxWidth"
    bottom
    content-class="overflow-hidden"
    left
  >
    <template #activator="{ attrs, on }">
      <app-tooltip-btn
        path="notifications"
        v-bind="attrs"
        v-on="on"
      >
        <template #icon>
          <v-badge
            :value="unread.length"
            color="red"
            left
            overlap
          >
            <template #badge>
              {{ unread.length }}
            </template>

            <v-icon v-text="'$mdiBellOutline'" />
          </v-badge>
        </template>
      </app-tooltip-btn>
    </template>

    <v-toolbar
      :width="maxWidth"
      class="pr-5"
      flat
      short
    >
      <v-btn
        :disabled="archived ? unread.length < 1 : read.length < 1"
        class="px-2 ml-n1"
        small
        text
        @click="archived = !archived"
      >
        <i18n :path="archived ? 'unread' : 'read'">
          <template #number>
            <strong v-text="archived ? unread.length : read.length" />
          </template>
        </i18n>
      </v-btn>

      <v-spacer />

      <app-tooltip-btn
        v-if="marked"
        :disabled="done"
        :icon="marked.icon"
        :path="`marked-${marked.path}`"
        small
        @click="toggleAll"
      />
    </v-toolbar>

    <v-divider />

    <v-responsive
      class="overflow-y-scroll"
      max-height="320"
    >
      <div
        v-if="done"
        class="py-8 text-center text-subtitle-1"
      >
        <i18n
          path="done"
          tag="p"
        />

        <v-icon
          color="grey lighten-2"
          size="96"
        >
          $mdiVuetify
        </v-icon>
      </div>

      <template v-else>
        <v-list-item
          v-for="({ created_at, metadata, slug, title }) in filtered"
          :key="slug"
          :href="metadata.action"
          :ripple="false"
          target="_blank"
          @click="toggle(slug)"
        >
          <v-list-item-content>
            <div
              class="grey--text text--darken-1 text-caption font-weight-light text-uppercase"
              v-text="created_at"
            />

            <v-list-item-title
              class="text-subtitle-1"
              v-text="`${metadata.emoji} ${title}`"
            />
          </v-list-item-content>

          <v-list-item-action>
            <v-btn
              :ripple="false"
              icon
              @click.stop.prevent="toggle(slug)"
            >
              <v-icon v-text="marked.icon" />
            </v-btn>
          </v-list-item-action>
        </v-list-item>
      </template>
    </v-responsive>
  </app-menu>
</template>

<script>
  // Utilities
  import { formatDate } from '@/util/date.js'
  import { sync } from 'vuex-pathify'

  export default {
    name: 'NotificationsMenu',

    inject: ['theme'],

    data: () => ({
      archived: false,
      icons: {
        read: '$mdiEmailOpen',
        unread: '$mdiEmailMarkAsUnread',
      },
      menu: false,
    }),

    computed: {
      notifications: sync('messages/notifications'),
      snack: sync('snackbar/value'),
      snackbar: sync('snackbar/snackbar'),
      unotifications: sync('user/notifications'),
      done () {
        return this.filtered.length === 0
      },
      // What is ultimately iterated
      filtered () {
        return this.archived ? this.read : this.unread
      },
      // Map items to contain a viewed
      // property and format the date
      mapped () {
        return this.notifications.map(item => {
          return {
            ...item,
            created_at: formatDate(new Date(item.created_at)),
            viewed: this.unotifications.includes(item.slug),
          }
        })
      },
      marked () {
        const path = this.archived ? 'unread' : 'read'
        const icon = this.icons[path]

        if (!icon || !path) return null

        return { icon, path }
      },
      maxWidth () {
        return this.$vuetify.breakpoint.mobile ? 296 : 320
      },
      read () {
        return this.mapped.filter(n => n.viewed)
      },
      unread () {
        return this.mapped.filter(n => !n.viewed)
      },
    },

    methods: {
      toggle (slug) {
        this.unotifications = this.unotifications.includes(slug)
          ? this.unotifications.filter(n => n !== slug)
          : [...this.unotifications, slug]
      },
      toggleAll () {
        this.unotifications = !this.archived
          ? this.notifications.map(i => i.slug)
          : []
      },
    },
  }
</script>


Fix this manquant

Fix this manquant

<template>
  <ExternalIframe :src="deckPath"></ExternalIframe>
</template>

<script>
import externalIframe from "./ExternalIframe.vue";

export default {
  name: "RevealDeck",
  components: { externalIframe },
  props:{
      src: {
          required: true
      }
  },
  computed: {
      deckPath(){
          return `/cours/sources/revealjs/index.html?source=${this.src}`;
      }
  }
};
</script>

<template>
  <ExternalIframe :src="deckPath"></ExternalIframe>
</template>

<script>
import externalIframe from "./ExternalIframe.vue";

export default {
  name: "RevealDeck",
  components: { externalIframe },
  props:{
      src: {
          required: true
      }
  },
  computed: {
      deckPath(){
          return `/cours/sources/revealjs/index.html?source=${src}`;
      }
  }
};
</script>


chore(client): Improve emoji picker usability

<template>
<x-popup :source="source" ref="popup" @closed="() => { $emit('closed'); destroyDom(); }" v-hotkey.global="keymap">

			<button class="_button" v-for="(reaction, i) in rs" :key="reaction" @click="react(reaction)" :tabindex="i + 1" :title="reaction" v-particle><x-reaction-icon :reaction="reaction"/></button>

		<input class="text" v-model.trim="text" :placeholder="$t('enterEmoji')" @keyup.enter="reactText" @input="tryReactText" v-autocomplete="{ model: 'text' }">

</x-popup>
</template>

<template>
<x-popup :source="source" ref="popup" @closed="() => { $emit('closed'); destroyDom(); }" v-hotkey.global="keymap">

			<button class="_button" v-for="(reaction, i) in rs" :key="reaction" @click="react(reaction)" :tabindex="i + 1" :title="reaction" v-particle><x-reaction-icon :reaction="reaction"/></button>

		<input class="text" v-model="text" :placeholder="$t('enterEmoji')" @keyup.enter="reactText" @input="tryReactText" v-autocomplete="{ model: 'text' }">

</x-popup>
</template>


bug fix

bug fix

<template>

            <page-side-nav/>
            <page-user-nav/>

                    <template v-if="environment == 'STAGING' && id != null">
                        Delete
                        Restore
                    </template>

Consumer Message {{ message.is_deleted ? "(deleted)" : "" }}

Name

                        <input v-model="message.message_category" :disabled="id" type="email" class="form-control" id="email">

Languages

                        <message-item
                            v-for="(value, key) in message.languages"
                            v-if="value.selected"
                            v-bind:item="value"
                            v-bind:fieldsDisabled="fieldsDisabled"
                            v-bind:environment="environment"
                            v-bind:index="key"
                            v-bind:key="key">
                        </message-item>

                        <vue-ladda
                            type="submit"
                            class="btn btn-card"
                            data-style="zoom-in"
                            v-if="!fieldsDisabled"
                            v-on:click="saveMessageGroup()"
                            v-bind:loading="save_button_loading"
                            v-bind:class="{ 'btn-style-green': !message.is_deleted, 'btn-danger': message.is_deleted }">
                            Save consumer message
                        </vue-ladda>

                <input v-model="lang_search" placeholder="Search for a language" class="form-control" id="lang-search">

                    {{ value.language_id }}

                    Are you sure you want to delete this Consumer Message group and its associated languages? By doing so, the Consumer Message will be immediately removed from the staging policy table, and will be removed from the production policy table upon the next promotion to production.

                    Yes, delete this consumer message

                    Are you sure you want to restore this Consumer Message group and its associated languages? By doing so, the Consumer Message will be immediately restored on the staging policy table, and will be restored on the production policy table upon the next promotion to production.

                <vue-ladda
                    type="button"
                    class="btn btn-card btn-success"
                    data-style="zoom-in"
                    v-on:click="undeleteMessageGroup()"
                    v-bind:loading="undelete_button_loading">
                    Yes, restore this consumer message
                </vue-ladda>

</template>


fix: bug №103

fix: bug №103

<template>
  <div>
    <data-table-actions class="mb-4"/>
    <data-table-sorting-pagination class="mb-4"/>
    <data-table-filter class="mb-4"/>
    <data-table-infinite-scroll class="mb-4"/>
    <data-table-select class="mb-4"/>
    <data-table-server-pagination class="mb-4"/>
    <data-table-empty class="mb-4"/>
    <data-table-loading/>
  </div>
</template>

<script>
import DataTableActions from './scenarios/DataTableActions.vue'
import DataTableSortingPagination from './scenarios/DataTableSortingPagination.vue'
import DataTableFilter from './scenarios/DataTableFilter.vue'
import DataTableInfiniteScroll from './scenarios/DataTableInfiniteScroll.vue'
import DataTableSelect from './scenarios/DataTableSelect.vue'
import DataTableServerPagination from './scenarios/DataTableServerPagination.vue'
import DataTableEmpty from './scenarios/DataTableEmpty.vue'
import DataTableLoading from './scenarios/DataTableLoading.vue'

export default {
  components: {
    DataTableActions,
    DataTableSortingPagination,
    DataTableFilter,
    DataTableInfiniteScroll,
    DataTableSelect,
    DataTableServerPagination,
    DataTableEmpty,
    DataTableLoading,
  },
}
</script>

<style lang="scss">
</style>

<template>
  <div>
    <data-table-actions class="mb-2" style="maxWidth: 1200px" />
    <data-table-sorting-pagination class="mb-2" style="maxWidth: 1200px" />
    <data-table-filter class="mb-2" style="maxWidth: 1200px" />
    <data-table-infinite-scroll class="mb-2" style="maxWidth: 1200px" />
    <data-table-select class="mb-2" style="maxWidth: 1200px" />
    <data-table-server-pagination class="mb-2" style="maxWidth: 1200px" />
    <data-table-empty class="mb-2" style="maxWidth: 1200px" />
    <data-table-loading class="mb-2" style="maxWidth: 1200px" />
  </div>
</template>

<script>
import DataTableActions from './scenarios/DataTableActions.vue'
import DataTableSortingPagination from './scenarios/DataTableSortingPagination.vue'
import DataTableFilter from './scenarios/DataTableFilter.vue'
import DataTableInfiniteScroll from './scenarios/DataTableInfiniteScroll.vue'
import DataTableSelect from './scenarios/DataTableSelect.vue'
import DataTableServerPagination from './scenarios/DataTableServerPagination.vue'
import DataTableEmpty from './scenarios/DataTableEmpty.vue'
import DataTableLoading from './scenarios/DataTableLoading.vue'

export default {
  components: {
    DataTableActions,
    DataTableSortingPagination,
    DataTableFilter,
    DataTableInfiniteScroll,
    DataTableSelect,
    DataTableServerPagination,
    DataTableEmpty,
    DataTableLoading,
  },
}
</script>

<style lang="scss">
</style>


retrieve data in AZ order

retrieve data in AZ order

<template>

Add new Hops

        <v-alert v-if="!isAuthenticated" :value="true" color="info" class="mb-3">
            <v-btn to="/auth">
                <v-icon left>lock_open</v-icon>
                Authorize
            </v-btn>
            to add hops or
            <v-btn to="/" exact>Go to Catalogue</v-btn>
        </v-alert>

            <v-container fluid grid-list-lg class="pa-0 mb-3">
                <v-layout row wrap>
                    <v-flex d-flex md8>
                        <v-card>
                            <v-card-text>

                                <v-form v-model="isValid" ref="form">
                                    Common information
                                    <v-layout row wrap>
                                        <v-flex sm6>
                                            <v-text-field
                                                label="Name"
                                                v-model.trim="newHops.name"
                                                required
                                                placeholder="Cascade"
                                                :rules="nameRules"
                                            >
                                            </v-text-field>
                                        </v-flex>
                                        <v-flex sm6>
                                            <v-select
                                                label="Alias"
                                                tags
                                                chips
                                                appendIcon=""
                                                v-model="newHops.alias"
                                                hint="Duplicated values are not allowed"
                                            >
                                                <template slot="selection" slot-scope="data">
                                                    <input-chip
                                                        :item="data.item"
                                                        :onClose="removeAlias"
                                                        :selected="data.selected"
                                                    >
                                                    </input-chip>
                                                </template>
                                            </v-select>
                                        </v-flex>
                                    </v-layout>

                                    <v-layout row wrap>
                                        <v-flex sm6>
                                            <v-select
                                                :items="usageValues"
                                                v-model="newHops.usage"
                                                label="Usage"
                                                hint="Usage"
                                                persistentHint
                                                single-line
                                                bottom
                                            ></v-select>
                                        </v-flex>
                                        <v-flex sm6>
                                            <v-select
                                                :items="shelfLifeValues"
                                                v-model="newHops.shelfLife"
                                                hint="Shelf life"
                                                persistentHint
                                                placeholder="NA"
                                                single-line
                                                bottom
                                            ></v-select>
                                        </v-flex>
                                    </v-layout>

Aroma Profile

                                    <v-select
                                        label="Primary"
                                        chips
                                        tags
                                        :items="aromasProcessed"
                                        appendIcon=""
                                        prependIcon="looks_one"
                                        v-model="newHops.aroma.primary"
                                        autocomplete
                                        maxHeight="400"
                                    >
                                        <template slot="selection" slot-scope="data">
                                            <v-chip
                                                :key="JSON.stringify(data.item)"
                                                color="light-green"
                                            >
                                                {{ data.item }}
                                            </v-chip>
                                        </template>
                                    </v-select>
                                    <v-select
                                        label="Secondary"
                                        chips
                                        tags
                                        :items="aromasProcessed"
                                        appendIcon=""
                                        prependIcon="looks_two"
                                        v-model="newHops.aroma.secondary"
                                        autocomplete
                                        maxHeight="400"
                                    >
                                        <template slot="selection" slot-scope="data">
                                            <v-chip
                                                :key="JSON.stringify(data.item)"
                                                color="amber"
                                            >
                                                {{ data.item }}
                                            </v-chip>
                                        </template>
                                    </v-select>
                                    <v-select
                                        label="Extra"
                                        chips
                                        tags
                                        :items="aromasProcessed"
                                        appendIcon=""
                                        prependIcon="looks_3"
                                        v-model="newHops.aroma.extra"
                                        autocomplete
                                        maxHeight="400"
                                    ></v-select>

Chemistry

                                    Acid, %
                                    <v-layout row wrap>
                                        <v-flex md4>
                                            Alpha
                                            <v-layout column nowrap>
                                                <v-flex>
                                                    <v-text-field :rules="acidRules" label="min" required v-model.number="newHops.alpha.min" type="number"></v-text-field>
                                                </v-flex>
                                                <v-flex>
                                                    <v-text-field :rules="acidRules" label="max" required v-model.number="newHops.alpha.max" type="number"></v-text-field>
                                                </v-flex>
                                            </v-layout>
                                        </v-flex>

                                        <v-flex md4>
                                            Beta
                                            <v-layout column nowrap>
                                                <v-flex>
                                                    <v-text-field label="min" v-model.number="newHops.beta.min" type="number"></v-text-field>
                                                </v-flex>
                                                <v-flex>
                                                    <v-text-field label="max" v-model.number="newHops.beta.max" type="number"></v-text-field>
                                                </v-flex>
                                            </v-layout>
                                        </v-flex>

                                        <v-flex md4>
                                            Co-Humulone
                                            <v-layout column nowrap>
                                                <v-flex>
                                                    <v-text-field label="min" v-model.number="newHops.co.min" type="number"></v-text-field>
                                                </v-flex>
                                                <v-flex>
                                                    <v-text-field label="max" v-model.number="newHops.co.max" type="number"></v-text-field>
                                                </v-flex>
                                            </v-layout>
                                        </v-flex>
                                    </v-layout>

                                    Oil, ml/100g
                                    <v-layout row wrap>
                                        <v-flex md4>
                                            Total
                                            <v-layout column nowrap>
                                                <v-flex>
                                                    <v-text-field :rules="oilRules" label="min" v-model.number="newHops.oil.min" type="number"></v-text-field>
                                                </v-flex>
                                                <v-flex>
                                                    <v-text-field :rules="oilRules" label="max" v-model.number="newHops.oil.max" type="number"></v-text-field>
                                                </v-flex>
                                            </v-layout>
                                        </v-flex>

                                        <v-flex md2>
                                            Myrcene
                                            <v-layout column nowrap>
                                                <v-flex>
                                                    <v-text-field :rules="oilRules" label="min" v-model.number="newHops.myr.min" type="number"></v-text-field>
                                                </v-flex>
                                                <v-flex>
                                                    <v-text-field :rules="oilRules" label="max" v-model.number="newHops.myr.max" type="number"></v-text-field>
                                                </v-flex>
                                            </v-layout>
                                        </v-flex>

                                        <v-flex md2>
                                            Humulene
                                            <v-layout column nowrap>
                                                <v-flex>
                                                    <v-text-field :rules="oilRules" label="min" v-model.number="newHops.hum.min" type="number"></v-text-field>
                                                </v-flex>
                                                <v-flex>
                                                    <v-text-field :rules="oilRules" label="max" v-model.number="newHops.hum.max" type="number"></v-text-field>
                                                </v-flex>
                                            </v-layout>
                                        </v-flex>

                                        <v-flex md2>
                                            Caryophyllene
                                            <v-layout column nowrap>
                                                <v-flex>
                                                    <v-text-field :rules="oilRules" label="min" v-model.number="newHops.car.min" type="number"></v-text-field>
                                                </v-flex>
                                                <v-flex>
                                                    <v-text-field :rules="oilRules" label="max" v-model.number="newHops.car.max" type="number"></v-text-field>
                                                </v-flex>
                                            </v-layout>
                                        </v-flex>

                                        <v-flex md2>
                                            Farnesene
                                            <v-layout column nowrap>
                                                <v-flex>
                                                    <v-text-field :rules="oilRules" label="min" v-model.number="newHops.far.min" type="number"></v-text-field>
                                                </v-flex>
                                                <v-flex>
                                                    <v-text-field :rules="oilRules" label="max" v-model.number="newHops.far.max" type="number"></v-text-field>
                                                </v-flex>
                                            </v-layout>
                                        </v-flex>
                                    </v-layout>

                                    Supplementary information
                                    <v-select
                                        label="Countries of origin"
                                        chips
                                        multiple
                                        :items="flagsProcessed"
                                        appendIcon=""
                                        item-text="name"
                                        item-value="code"
                                        v-model="newHops.country"
                                        autocomplete
                                        maxHeight="400"
                                    >
                                        <template slot="selection" slot-scope="data">
                                            <v-chip
                                                close
                                                @input="removeFlag(data.item.code)"
                                                :selected="data.selected"
                                            >
                                                <v-avatar class="secondary">
                                                    {{ data.item.code.toUpperCase() }}
                                                </v-avatar>
                                                {{ data.item.name }}
                                            </v-chip>
                                        </template>
                                    </v-select>

                                    <v-select
                                        label="Most used in"
                                        multiple
                                        :items="stylesProcessed"
                                        appendIcon=""
                                        v-model="newHops.styles"
                                        autocomplete
                                        maxHeight="400"
                                    ></v-select>

                                    <v-text-field
                                        multi-line
                                        label="Description"
                                        v-model.trim="newHops.notes"
                                        hint="General notes and special observations"
                                        persistent-hint
                                    >
                                    </v-text-field>

                                    <v-alert :value="true" color="info" class="my-2" dismissible v-model="isDefaultPropsNotification">

                                            Some fields were changed to new hops defaults

                                        <v-btn color="secondary" outline @click="hideDefaultPropsNotification" class="ml-0">
                                            Don't show again
                                        </v-btn>
                                    </v-alert>

                                    <v-layout row wrap text-xs-center text-md-left>
                                        <v-flex>
                                            <v-btn color="primary" @click="addHops" :disabled="!isValid">
                                                <v-icon left v-text="isHopsUpdated ? 'mode_edit' : 'add'"></v-icon>

                                            </v-btn>

                                            <v-btn color="secondary" @click="clearFields">
                                                <v-icon left v-text="isHopsSelected ? 'select_all' : 'clear_all'"></v-icon>

                                            </v-btn>
                                        </v-flex>

                                        <v-flex text-md-right>
                                            <v-btn color="error" @click="removeHops" :disabled="!isHopsSelected">
                                                <v-icon left>delete</v-icon>
                                                Delete
                                            </v-btn>
                                        </v-flex>
                                    </v-layout>
                                </v-form>

                            </v-card-text>
                        </v-card>
                    </v-flex>

                    <v-flex d-flex md4>
                        <v-card class="grey lighten-4">
                            <v-card-text style="max-height: 80vh; overflow: auto;">

{{ JSON.stringify(transformHops(newHops), null, 2) }}

                            </v-card-text>
                        </v-card>
                    </v-flex>
                </v-layout>
            </v-container>

            <v-data-table
                class="elevation-1"
                hideActions
                v-bind:headers="headers"
                :items="hopsProcessed"
                item-key=".key"
            >
                <template slot="headerCell" slot-scope="props">
                    <v-tooltip top v-if="props.header.hint">
                        {{ props.header.text }}
                        {{ props.header.hint }}
                    </v-tooltip>

                        {{ props.header.text }}

                </template>
                <template slot="items" slot-scope="props">
                    <catalogue-item
                        :key="props.item.key"
                        :dbKey="props.item['.key']"
                        :isSelected="props.item.isSelected"
                        :name="props.item.name"
                        :alias="props.item.alias"
                        :country="props.item.country"
                        :usage="props.item.usage"
                        :shelfLife="props.item.shelfLife"
                        :alpha="props.item.alpha"
                        :beta="props.item.beta"
                        :co="props.item.co"
                        :oil="props.item.oil"
                        :myr="props.item.myr"
                        :hum="props.item.hum"
                        :car="props.item.car"
                        :far="props.item.far"
                        :aroma="props.item.aroma"
                        :notes="props.item.notes"
                        :styles="props.item.styles"
                        :onClick="handleHopsClick"
                        :ctx="props"
                    >
                    </catalogue-item>
                </template>
                <template slot="expand" slot-scope="props">
                    <v-card flat class="grey lighten-4">
                        <v-card-text class="px-4">
                            {{ props.item.notes }}
                        </v-card-text>
                    </v-card>
                </template>
            </v-data-table>

        <v-snackbar
            :timeout="notification.timeout"
            v-model="notification.show"
            top
        >

                {{ notification.text }}

            <v-btn dark :color="notification.btnColor" flat @click.native="notification.onAction">
                {{ notification.btnText }}
            </v-btn>
        </v-snackbar>

</template>


change document.qsa to this.$el.qsa

change document.qsa to this.$el.qsa

<template lang="html">

    <base-dialog>
      <form>
        name
        <input v-model="form.name"></input>
        <input v-model="form.id" type="hidden"></input>
        memo
        <textarea v-model="form.memo"></textarea>
        <form class="upload-form">
          <input type="file" name="file" class="upload-input" v-on:change="executeUpload">
        </form>

          hp
          <input v-model="form.hp"></input>
          maxhp
          <input v-model="form.max_hp"></input>
          mp
          <input v-model="form.mp"></input>
          maxmp
          <input v-model="form.max_mp"></input>
          move
          <input v-model="form.move"></input>
          protection
          <input v-model="form.protection"></input>

          x
          <input v-model="form.x"></input>
          y
          <input v-model="form.y"></input>

        <button type="submit" class="dialogButton" value="OK" v-on:click="onClickOKButton">OK</button>
        <button type="button" class="dialogButton" value="Cancel" v-on:click="dismiss">Cancel</button>
      </form>
    </base-dialog>

</template>


devop: 🔧 check if price and 24hr change are empty

<template>

    <app-table
      v-if="!isMobile"
      background
      full-width
      flat
      border-bottom
      class="mt-4 mb-4"
    >

            TOKEN
            PRICE
            MARKET CAP
            24H
            BALANCE

                <mew-token-container
                  :img="td.tokenImg"
                  size="20px"
                  class="mr-2"
                />
                {{ td.token }}

              {{ td.price }}
              / token

            {{ td.cap }}

{{ td.change }}%

                <v-icon small color="greenPrimary"> mdi-arrow-up-thick </v-icon>

{{ td.change }}%

                <v-icon small color="redPrimary"> mdi-arrow-down-thick </v-icon>

{{ td.balance[0] }}

{{ td.balance[1] }}

              <template v-if="td.callToAction">
                <mew-button
                  v-for="(button, idx) in td.callToAction"
                  :key="idx"
                  btn-style="outline"
                  btn-size="small"
                  @click.native="button.method(td)"
                >
                  {{ button.title }}
                </mew-button>
              </template>

    </app-table>

    <app-table
      v-for="(td, dataKey) in tableData"
      v-else
      :key="dataKey"
      class="mx-4 mt-2"
      full-width
      border-around
      padding-around
      flat
      round-corner
      mobile-background
    >

Token

          <mew-token-container :img="td.tokenImg" size="17px" class="mr-2" />
          {{ td.token }}

Price

{{ td.price }}

Market Cap

{{ td.cap }}

24H

{{ td.change }}%

            <v-icon v-if="td.status == '+'" small color="greenPrimary">
              mdi-arrow-up-thick
            </v-icon>
            <v-icon v-else small color="redPrimary">
              mdi-arrow-down-thick
            </v-icon>

Balance

          {{ td.balance[0] }} {{ td.balance[1] }}

        <template v-if="td.callToAction">
          <v-btn
            v-for="(button, idx) in td.callToAction"
            :key="idx"
            outlined
            color="greenPrimary"
            small
            depressed
            @click="button.method(td)"
          >

              {{ button.title }}

          </v-btn>
        </template>

    </app-table>

</template>


修复touch move事件上下滑动没有end导致意外更新diff的值

修复touch move事件上下滑动没有end导致意外更新diff的值

<template>
  <div class="enhanced-scroller-wrapper"
       :class="{ 'active-transition': activeTransition }"
       :style="{ transform: `translate3d(0, ${diff}px, 0)` }">
    <slot v-if="enabledTopAction"
          name="top-block"
          :state-text="topText">

        <slot name="top-default-block"
              :state="topState"
              :state-text="topText">
          {{ topText }}
        </slot>

    </slot>

      <slot></slot>

    <slot
      v-if="enabledBottomAction"
      name="bottom-block"
      :state-text="bottomText">

        <slot name="bottom-default-block" :state-text="bottomText">
          {{ bottomText }}
        </slot>

    </slot>

</template>


Implement Jochen's cool homepage

Implement Jochen's cool homepage

<template>

About Clash of Flags

                This project has been created by Simon Schneider, Philipp Schemel, Jochen Walther & Marc Vornetran for the "Games and Gaming" course at the Cooperative State University in Karlsruhe.

</template>


Restrict what toolbar options are displayed based on the tags allowed for that specific rich text field.

<template>

		<button
			type="button"
			class="richtext-toolbar__tooltip"
			:aria-label="item.label"
			:data-command-name="item.command || null"
		>
			<icon
				:name="item.icon"
				:width="14"
				:height="14"
				viewBox="0 0 14 14"
			/>
		</button>

			<component
				v-if="!Array.isArray(item.menu) && item.menu.component"
				ref="table"
				:is="item.menu.component"
			/>

				<button
					type="button" class="elem"
					:data-command-name="subItem.command || null"
					v-html="subItem.label"
				/>

</template>


Hide Delete button on self

Hide Delete button on self

<template>

{{ user.name }}

{{ user.email }}

          <button class="btn btn-blue btn-edit" @click="edit">
            {{ isCurrentUser ? 'Update Profile' : 'Edit' }}
          </button>
          <button v-if="!isCurrentUser" class="btn btn-red btn-delete" @click="del">Delete</button>

</template>

<template>

{{ user.name }}

{{ user.email }}

          <button class="btn btn-blue btn-edit" @click="edit">
            {{ isCurrentUser ? 'Update Profile' : 'Edit' }}
          </button>
          <button class="btn btn-red btn-delete" @click="del">Delete</button>

</template>


devop: 🔧 add modal for the verified address

<template>

          <v-menu offset-y>
            <template #activator="{ on }">

                  MY Personal Account

                <v-icon class="white--text ml-2" small dense>
                  mdi-menu-down
                </v-icon>

            </template>
            <v-list width="232px">
              <v-list-item class="cursor-pointer" @click="refresh">
                <v-icon color="textDark" class="mr-3">mdi-refresh</v-icon>
                <v-list-item-title> Refresh Balance</v-list-item-title>
              </v-list-item>
              <v-list-item class="cursor-pointer" @click="openPaperWallet">
                <v-icon color="textDark" class="mr-3">mdi-printer</v-icon>
                <v-list-item-title>View paper wallet</v-list-item-title>
              </v-list-item>
              <v-list-item
                v-if="isHardware && canDisplayAddress"
                class="cursor-pointer"
                @click="viewAddressOnDevice"
              >
                <mew-icon
                  :icon-name="iconIdentifier"
                  :img-height="24"
                  class="mr-3"
                />
                <v-list-item-title
                  >View address on {{ walletName }}</v-list-item-title
                >
              </v-list-item>
              <v-divider class="mx-5 my-4"></v-divider>
              <v-list-item
                v-if="canSwitch"
                class="cursor-pointer"
                @click="openChangeAddress"
              >
                <v-icon color="textDark" class="mr-3"
                  >mdi-account-box-multiple</v-icon
                >
                <v-list-item-title>Switch Account</v-list-item-title>
              </v-list-item>
              <v-list-item class="cursor-pointer" @click="openLogout">
                <v-icon color="textDark" class="mr-3">mdi-logout</v-icon>
                <v-list-item-title>Logout</v-list-item-title>
              </v-list-item>
            </v-list>
          </v-menu>

            <v-tooltip top content-class="tooltip-inner">
              <template #activator="{ on }">

                  {{ addrFirstSix }}
                  <v-icon class="info-container--addr pt-1"
                    >mdi-dots-horizontal</v-icon
                  >

                  {{ addrlastFour }}

              </template>
              {{
                getChecksumAddressString
              }}
            </v-tooltip>

        ${{ totalWalletBalance }}
        {{
          network.type.currencyName
        }}

            {{ walletChainBalance }} {{ network.type.currencyName }}

 0" class="info-container--text">
            and {{ nonChainTokensCount }} Tokens

          <v-btn
            class="info-container--action-btn mr-2 px-0"
            fab
            depressed
            color="white"
            @click="openQR = true"
            ><v-icon class="info-container--icon" size="18px"
              >mdi-qrcode</v-icon
            ></v-btn
          >

          <v-btn
            class="info-container--action-btn px-0"
            depressed
            fab
            color="white"
            @click="copyAddress"
            ><v-icon class="info-container--icon" small
              >mdi-content-copy</v-icon
            ></v-btn
          >

    <balance-address-paper-wallet
      :open="showPaperWallet"
      :close="closePaperWallet"
      @close="closePaperWallet"
    />
    <app-modal
      :show="openQR"
      :close="closeQR"
      :has-buttons="false"
      width="408px"
    >
      <template #dialogBody>
        <app-addr-qr />
      </template>
    </app-modal>
    <module-access-wallet-hardware
      v-if="showHardware"
      :open="showChangeAddress"
      :close="closeChangeAddress"
      :switch-address="!!instance.path"
    />
    <module-access-wallet-software
      v-else
      :open="showChangeAddress"
      :close="closeChangeAddress"
      :switch-address="!!instance.path"
      :wallet-type="identifier"
    />

    <mew-popup
      max-width="400px"
      hide-close-btn
      :show="showLogout"
      :title="$t('interface.menu.logout')"
      :left-btn="{ text: 'Cancel', method: closeLogout, color: 'basic' }"
      :right-btn="{
        text: 'Log out',
        color: 'error',
        method: onLogout,
        enabled: true
      }"
    />
    <mew-popup
      max-width="515px"
      :show="showVerify"
      :title="verifyAddressTitle"
      :has-buttons="false"
      :has-body-content="true"
    >

          {{ verifyAddressBody }}

            ACCOUNT ADDRESS

            {{ getChecksumAddressString }}

    </mew-popup>

</template>

<template>

          <v-menu offset-y>
            <template #activator="{ on }">

                  MY Personal Account

                <v-icon class="white--text ml-2" small dense>
                  mdi-menu-down
                </v-icon>

            </template>
            <v-list dense>
              <v-list-item class="cursor-pointer" @click="refresh">
                <v-list-item-icon
                  ><v-icon color="textDark"
                    >mdi-refresh</v-icon
                  ></v-list-item-icon
                >
                <v-list-item-title>Refresh Balance</v-list-item-title>
              </v-list-item>
              <v-list-item class="cursor-pointer" @click="openPaperWallet">
                <v-list-item-icon
                  ><v-icon color="textDark"
                    >mdi-printer</v-icon
                  ></v-list-item-icon
                >
                <v-list-item-title>View paper wallet</v-list-item-title>
              </v-list-item>
              <v-list-item
                v-if="isHardware && canDisplayAddress"
                class="cursor-pointer"
                @click="viewAddressOnDevice"
              >
                <v-list-item-icon
                  ><mew-icon :icon-name="iconIdentifier" :img-height="24"
                /></v-list-item-icon>
                <v-list-item-title
                  >View address on {{ walletName }}</v-list-item-title
                >
              </v-list-item>
              <v-divider></v-divider>
              <v-list-item
                v-if="canSwitch"
                class="cursor-pointer"
                @click="openChangeAddress"
              >
                <v-list-item-icon
                  ><v-icon color="textDark"
                    >mdi-account-box-multiple</v-icon
                  ></v-list-item-icon
                >
                <v-list-item-title>Switch Account</v-list-item-title>
              </v-list-item>
              <v-list-item class="cursor-pointer" @click="openLogout">
                <v-list-item-icon
                  ><v-icon color="textDark"
                    >mdi-logout</v-icon
                  ></v-list-item-icon
                >
                <v-list-item-title>Logout</v-list-item-title>
              </v-list-item>
            </v-list>
          </v-menu>

            <v-tooltip top content-class="tooltip-inner">
              <template #activator="{ on }">

                  {{ addrFirstSix }}
                  <v-icon class="info-container--addr pt-1"
                    >mdi-dots-horizontal</v-icon
                  >

                  {{ addrlastFour }}

              </template>
              {{
                getChecksumAddressString
              }}
            </v-tooltip>

        ${{ totalWalletBalance }}
        {{
          network.type.currencyName
        }}

            {{ walletChainBalance }} {{ network.type.currencyName }}

 0" class="info-container--text">
            and {{ nonChainTokensCount }} Tokens

          <v-btn
            class="info-container--action-btn mr-2 px-0"
            fab
            depressed
            color="white"
            @click="openQR = true"
            ><v-icon class="info-container--icon" size="18px"
              >mdi-qrcode</v-icon
            ></v-btn
          >

          <v-btn
            class="info-container--action-btn px-0"
            depressed
            fab
            color="white"
            @click="copyAddress"
            ><v-icon class="info-container--icon" small
              >mdi-content-copy</v-icon
            ></v-btn
          >

    <balance-address-paper-wallet
      :open="showPaperWallet"
      :close="closePaperWallet"
      @close="closePaperWallet"
    />
    <app-modal
      :show="openQR"
      :close="closeQR"
      :has-buttons="false"
      width="408px"
    >
      <template #dialogBody>
        <app-addr-qr />
      </template>
    </app-modal>
    <module-access-wallet-hardware
      v-if="showHardware"
      :open="showChangeAddress"
      :close="closeChangeAddress"
      :switch-address="!!instance.path"
    />
    <module-access-wallet-software
      v-else
      :open="showChangeAddress"
      :close="closeChangeAddress"
      :switch-address="!!instance.path"
      :wallet-type="identifier"
    />

    <mew-popup
      max-width="400px"
      hide-close-btn
      :show="showLogout"
      :title="$t('interface.menu.logout')"
      :left-btn="{ text: 'Cancel', method: closeLogout, color: 'basic' }"
      :right-btn="{
        text: 'Log out',
        color: 'error',
        method: onLogout,
        enabled: true
      }"
    ></mew-popup>

</template>


Minor: fix wording

Minor: fix wording

<template>
    <client-form
        submit-button-text="Neuen Klienten erstellen"
        :initial-client="{}"
        @submit="handleSubmit"
    />
</template>

<script>
'use strict';

import ClientForm from './ClientForm.vue';
export default {
    name: 'ClientCreate',
    components: {
        ClientForm,
    },
    data: function () {
        return {
        };
    },
    computed: {
        currentUser() {
            return this.$store.getters['security/currentUser'];
        },
        initialClient() {
            return this.currentUser.client;
        },
    },
    async created() {
    },
    methods: {
        async handleSubmit(payload) {
            const client = await this.$store.dispatch('client/create', payload);
            if (client) {
                const message = `Der Klient "${client.name}" wurde erfolgreich erstellt.`;
                this.$bvToast.toast(message, {
                    title: 'Klient erstellt',
                    toaster: 'b-toaster-top-right',
                    autoHideDelay: 10000,
                    appendToast: true,
                    solid: true,
                });
            } else {
                this.$bvToast.toast('Upps! :-(', {
                    title: 'Klient erstellen fehlgeschlagen',
                    toaster: 'b-toaster-top-right',
                    autoHideDelay: 10000,
                    variant: 'danger',
                    appendToast: true,
                    solid: true,
                });
            }
        },
    },
};
</script>

<style scoped lang="scss">
</style>

<template>
    <client-form
        submit-button-text="Neuen Benutzer erstellen"
        :initial-client="{}"
        @submit="handleSubmit"
    />
</template>

<script>
'use strict';

import ClientForm from './ClientForm.vue';
export default {
    name: 'ClientCreate',
    components: {
        ClientForm,
    },
    data: function () {
        return {
        };
    },
    computed: {
        currentUser() {
            return this.$store.getters['security/currentUser'];
        },
        initialClient() {
            return this.currentUser.client;
        },
    },
    async created() {
    },
    methods: {
        async handleSubmit(payload) {
            const client = await this.$store.dispatch('client/create', payload);
            if (client) {
                const message = `Der Klient "${client.name}" wurde erfolgreich erstellt.`;
                this.$bvToast.toast(message, {
                    title: 'Klient erstellt',
                    toaster: 'b-toaster-top-right',
                    autoHideDelay: 10000,
                    appendToast: true,
                    solid: true,
                });
            } else {
                this.$bvToast.toast('Upps! :-(', {
                    title: 'Klient erstellen fehlgeschlagen',
                    toaster: 'b-toaster-top-right',
                    autoHideDelay: 10000,
                    variant: 'danger',
                    appendToast: true,
                    solid: true,
                });
            }
        },
    },
};
</script>

<style scoped lang="scss">
</style>


default to poloniex slug

default to poloniex slug

<template lang='jade'>
div
  div
    label(for='exchange').wrapper Exchange:
    .custom-select.button
      select(v-model='exchange')
        option(v-for='(market, e) in exchanges') {{ e }}
  div
    label(for='currency') Market:
    .custom-select.button
      select(v-model='market')
        option(v-for='market in markets') {{ market }}
</template>

<script>

import _ from 'lodash'
import markets from './markets'
import rangePicker from './rangepicker.vue'
import rangeCreator from './rangecreator.vue'

export default {
  props: ['has'],
  data: () => {
    return {
      exchanges: markets,

      // defaults:
      exchange: 'poloniex',
      currency: 'BTC',
      asset: 'ETH',
      market: 'USDT/BTC'
    };
  },

  created: function() {
    this.emitConfig();
  },
  computed: {
    markets: function() {
      return this.exchanges[ this.exchange ];
    },
    currency: function() {
      return _.first(this.market.split('/'));
    },
    asset: function() {
      return _.last(this.market.split('/'));
    },
    watchConfig: function() {
      return {
        watch: {
          exchange: this.exchange,
          currency: this.currency,
          asset: this.asset
        }
      }
    }
  },

  watch: {
    currency: function() { this.emitConfig() },
    market: function() { this.emitConfig() }
  },

  methods: {
    emitConfig: function() {
      this.$emit('market', this.watchConfig);
    }
  }
}
</script>
</style>

<template lang='jade'>
div
  div
    label(for='exchange').wrapper Exchange:
    .custom-select.button
      select(v-model='exchange')
        option(v-for='(market, e) in exchanges') {{ e }}
  div
    label(for='currency') Market:
    .custom-select.button
      select(v-model='market')
        option(v-for='market in markets') {{ market }}
</template>

<script>

import _ from 'lodash'
import markets from './markets'
import rangePicker from './rangepicker.vue'
import rangeCreator from './rangecreator.vue'

export default {
  props: ['has'],
  data: () => {
    return {
      exchanges: markets,

      exchange: 'Poloniex',
      currency: 'BTC',
      asset: 'ETH',
      market: 'USDT/BTC'
    };
  },

  created: function() {
    this.emitConfig();
  },
  computed: {
    markets: function() {
      return this.exchanges[ this.exchange ];
    },
    currency: function() {
      return _.first(this.market.split('/'));
    },
    asset: function() {
      return _.last(this.market.split('/'));
    },
    watchConfig: function() {
      return {
        watch: {
          exchange: this.exchange,
          currency: this.currency,
          asset: this.asset
        }
      }
    }
  },

  watch: {
    currency: function() { this.emitConfig() },
    market: function() { this.emitConfig() }
  },

  methods: {
    emitConfig: function() {
      this.$emit('market', this.watchConfig);
    }
  }
}
</script>
</style>


remove irrelevant resize button

remove irrelevant resize button

<template>

What do you want to know?

          <input type="text" v-model="inputText" @keyup.enter="lookUp()" class="lookup_input" placeholder="Type in your word ...">
          <button @click="lookUp()" class="lookup_button hvr-sweep-to-right">Search</button>

Oops, something went wrong with the dictionary.

            {{this.errorMessage}}

      <Explanations v-if="inputText" v-bind:explanation="this.explanation" v-on:followUp="followUp" v-bind:class="{hide:spinner}"></Explanations>

</template>

<template>

What do you want to know? <button @click="resize()">Resize</button>

          <input type="text" v-model="inputText" @keyup.enter="lookUp()" class="lookup_input" placeholder="Type in your word ...">
          <button @click="lookUp()" class="lookup_button hvr-sweep-to-right">Search</button>

Oops, something went wrong with the dictionary.

            {{this.errorMessage}}

      <Explanations v-if="inputText" v-bind:explanation="this.explanation" v-on:followUp="followUp" v-bind:class="{hide:spinner}"></Explanations>

</template>