don't know where should call these 2 methods yet. Temporally call them here

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/christianmemije/kolibri-exercise-perseus-plugin.git/'


add team opgg

add team opgg

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/chypriote/france-v2.git/'


修改It'sMe页面

修改It'sMe页面

error: pathspec 'src/views/ItsMe/ItsMe.vue' did not match any file(s) known to git


add Profile.vue file to set about me, finsh this layout

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/joriscai/myblog-vue.git/'


translate guide/i18n

translate guide/i18n

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/iview/iview-doc.git/'


rename title-sub-tech

rename title-sub-tech

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/l10178/grapes.git/'


Write user show component

Write user show component

<template>

{{ user.username }}

{{ user.fullName }}

{{ user.email }}

{{ user.bio }}

Roles

              {{ project.role }} of
              <router-link v-bind:to="'/projects/' + project.project">
                {{ project.project }}
              </router-link>

Recent Activity

TODO

      <loading-spinner></loading-spinner>

</template>

error: pathspec 'client/src/components/Users/Show.vue' did not match any file(s) known to git


update hoem content

update hoem content

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/CHCP/toolmaker-web.git/'


index redirect

index redirect

error: pathspec 'virtdata-docsys/src/main/node/docsys/pages/_.vue' did not match any file(s) known to git


Inspection under way!

Inspection under way!

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/NathanielDavid/Sumie.git/'


minicart promisePrice style

minicart promisePrice style

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/NewDadaFE/newdada-daojia.git/'


test getComponentRect

test getComponentRect

<template>

            <text class="info">Width: {{size.width}}</text>
            <text class="info">Height: {{size.height}}</text>
            <text class="info">Top: {{size.top}}</text>
            <text class="info">Bottom: {{size.bottom}}</text>
            <text class="info">Left: {{size.left}}</text>
            <text class="info">Right: {{size.right}}</text>

        <text class="info btn" @click='click()'>{{this.tip}}</text>

</template>

error: pathspec 'WeexPractice/src/dom.vue' did not match any file(s) known to git


1.1.3

<template>

        <modal-tag  v-if="showModal" @close="showModal = false" :my-tag="selectTag" ></modal-tag>

</template>

error: pathspec 'example/snippet/vue/component.vue' did not match any file(s) known to git


[UPD] add checkboard

[UPD] add checkboard

error: pathspec 'src/components/common/Checkboard.vue' did not match any file(s) known to git


Two basic notifications

Two basic notifications

<template>
  <div class="notification">
  </div>
</template>

<script>
import EventBus from 'src/event-bus/event-bus'

export default {
  name: 'notification',
  data () {
    return {
      notifications: [
        {
          type: 'info',
          message: 'Product has been added to the cart!',
          action1: { label: 'OK', action: 'close' }
        },
        {
          type: 'info',
          message: 'Product has been added to the cart!',
          action1: { label: 'OK', action: 'close' }
        }
      ]
    }
  },
  created () {
    EventBus.$on('notification', data => {
      this.notifications.push(data)
    })
  },
  methods: {
    action (action, id) {
      switch (action) {
        case 'close':
          this.notifications.splice(id, 1)
      }
    }
  }
}
</script>

<template>
  <div class="notification">
  </div>
</template>

<script>
import EventBus from 'src/event-bus/event-bus'

export default {
  name: 'notification',
  data () {
    return {
      notifications: [
        {
          type: 'info',
          message: 'Product has been added to the cart!',
          action1: { label: 'OK', action: 'close' }
        }
      ]
    }
  },
  created () {
    EventBus.$on('notification', data => {
      this.notifications.push(data)
    })
  },
  methods: {
    action (action, id) {
      switch (action) {
        case 'close':
          this.notifications.splice(id, 1)
      }
    }
  }
}
</script>


Simplified RequestBarComponent css.

Simplified RequestBarComponent css.

Removed a lot of redundant code. Should look pretty much the same as before.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/codeweavers/Consign.git/'


#115 - The VueJs form passes the response and error to the callback to external processing

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AlexandreBERGIA/LivrOr_V4.git/'


mdRating

mdRating

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/jaceks-iRonin/vue-material-test.git/'


change brand message

change brand message


#115 - Update the new submit button class for browser testing purposes


remove v-html & use vdom instead

remove v-html & use vdom instead

<script>
import { escape } from 'underscore';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import FileIcon from '../../../vue_shared/components/file_icon.vue';
import ChangedFileIcon from '../changed_file_icon.vue';

const MAX_PATH_LENGTH = 60;

export default {
  components: {
    ChangedFileIcon,
    FileIcon,
  },
  props: {
    file: {
      type: Object,
      required: true,
    },
    focused: {
      type: Boolean,
      required: true,
    },
    searchText: {
      type: String,
      required: true,
    },
    index: {
      type: Number,
      required: true,
    },
  },
  computed: {
    pathWithEllipsis() {
      return this.file.path.length < MAX_PATH_LENGTH || !addEllipsis
        ? this.file.path
        : `...${this.file.path.substr(this.file.path.length - MAX_PATH_LENGTH)}`;
    },
    nameSearchTextOccurences() {
      return fuzzaldrinPlus.match(this.file.name, this.searchText);
    },
    pathSearchTextOccurences() {
      return fuzzaldrinPlus.match(this.pathWithEllipsis, this.searchText);
    },
  },
  methods: {
    clickRow() {
      this.$emit('click', this.file);
    },
    mouseOverRow() {
      this.$emit('mouseover', this.index);
    },
  },
};
</script>

<template>
  <a
    href="#"
    class="diff-changed-file"
    :class="{
      'is-focused': focused,
    }"
    @click.prevent="clickRow"
    @mouseover="mouseOverRow"
  >
    <file-icon
      :file-name="file.name"
      :size="16"
      css-classes="diff-file-changed-icon append-right-8"
    />
    <span class="diff-changed-file-content append-right-8">
      <strong
        class="diff-changed-file-name"
      >
        <span
          v-for="(char, index) in file.name.split('')"
          :key="index + char"
          :class="{
            highlighted: nameSearchTextOccurences.indexOf(index) >= 0,
          }"
          v-text="char"
        >
        </span>
      </strong>
      <span
        class="diff-changed-file-path prepend-top-5"
      >
        <span
          v-for="(char, index) in pathWithEllipsis.split('')"
          :key="index + char"
          :class="{
            highlighted: pathSearchTextOccurences.indexOf(index) >= 0,
          }"
          v-text="char"
        >
        </span>
      </span>
    </span>
    <span
      v-if="file.changed || file.tempFile"
      class="diff-changed-stats"
    >
      <changed-file-icon
        :file="file"
      />
    </span>
  </a>
</template>

<script>
import { escape } from 'underscore';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import FileIcon from '../../../vue_shared/components/file_icon.vue';
import ChangedFileIcon from '../changed_file_icon.vue';

const MAX_PATH_LENGTH = 60;

export default {
  components: {
    ChangedFileIcon,
    FileIcon,
  },
  props: {
    file: {
      type: Object,
      required: true,
    },
    focused: {
      type: Boolean,
      required: true,
    },
    searchText: {
      type: String,
      required: true,
    },
    index: {
      type: Number,
      required: true,
    },
  },
  methods: {
    clickRow() {
      this.$emit('click', this.file);
    },
    mouseOverRow() {
      this.$emit('mouseover', this.index);
    },
    highlightText(text, addEllipsis) {
      const escapedText = escape(text);
      const maxText =
        escapedText.length < MAX_PATH_LENGTH || !addEllipsis
          ? escapedText
          : `...${escapedText.substr(escapedText.length - MAX_PATH_LENGTH)}`;
      const occurrences = fuzzaldrinPlus.match(maxText, this.searchText);

      return maxText
        .split('')
        .map(
          (char, i) =>
            `<span class="${occurrences.indexOf(i) >= 0 ? 'highlighted' : ''}">${char}</span>`,
        )
        .join('');
    },
  },
};
</script>

<template>
  <a
    href="#"
    class="diff-changed-file"
    :class="{
      'is-focused': focused,
    }"
    @click.prevent="clickRow"
    @mouseover="mouseOverRow"
  >
    <file-icon
      :file-name="file.name"
      :size="16"
      css-classes="diff-file-changed-icon append-right-8"
    />
    <span class="diff-changed-file-content append-right-8">
      <strong
        class="diff-changed-file-name"
        v-html="highlightText(file.name, false)"
      >
      </strong>
      <span
        class="diff-changed-file-path prepend-top-5"
        v-html="highlightText(file.path, true)"
      >
      </span>
    </span>
    <span
      v-if="file.changed || file.tempFile"
      class="diff-changed-stats"
    >
      <changed-file-icon
        :file="file"
      />
    </span>
  </a>
</template>


add simple auth component for logging into keycloak

<template>

      <button type="button" class="btn btn-light" @click="keyCloakLogin()">Log in</button>

Logged in ({{ keycloak.tokenParsed.name }})

</template>

error: pathspec 'frontend/src/common/components/Auth.vue' did not match any file(s) known to git


update site meta settings

update site meta settings

<template>

{{ 'Meta' | trans }}

            <button class="uk-button uk-button-primary" type="submit">{{ 'Save' | trans }}</button>

            {{ 'Description' | trans }}

                <textarea id="form-meta-description" class="uk-form-width-large" rows="5" v-model="config.meta.description"></textarea>

            {{ 'Image' | trans }}

                <input-image :source.sync="config.meta.image"></input-image>

            Facebook

                <input id="form-meta-facebook" type="text" class="uk-form-width-large" placeholder="app_id" v-model="config.meta.facebook"></input>

            Twitter

                <input id="form-meta-twitter" type="text" class="uk-form-width-large" placeholder="@username" v-model="config.meta.twitter"></input>

</template>

<template>

{{ 'Meta' | trans }}

            <button class="uk-button uk-button-primary" type="submit">{{ 'Save' | trans }}</button>

            {{ 'Description' | trans }}

                <textarea id="form-meta-description" class="uk-form-width-large" rows="5" v-model="config.meta.description"></textarea>

            {{ 'Image' | trans }}

                <input-image :source.sync="config.meta.image"></input-image>

            {{ 'Facebook ID' | trans }}

                <input id="form-meta-facebook" type="text" class="uk-form-width-large" v-model="config.meta.fb_id"></input>

            {{ 'Twitter Site' | trans }}

                <input id="form-meta-twitter" type="text" class="uk-form-width-large" v-model="config.meta.twitter"></input>

</template>


Added assumed classnames for perseus Attempted cleanup of template fixes https://github.com/learningequality/kolibri/issues/1553

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/christianmemije/kolibri-exercise-perseus-plugin.git/'


timeline demo

timeline demo

<template>

		<timeline>
			<timeline-item>

【广东】 广州市 已发出

2016-04-17 12:00:00

			</timeline-item>
			<timeline-item>

 申通快递员 广东广州 收件员 xxx 已揽件

2016-04-16 10:23:00

			</timeline-item>
			<timeline-item>

 商家正在通知快递公司揽件

2016-04-15 9:00:00

			</timeline-item>
		</timeline>

</template>

error: pathspec 'src/demos/Timeline.vue' did not match any file(s) known to git


Add height to demo container

Add height to demo container

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/praneetloke/vue-material.git/'


添加DataRender

添加DataRender

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/www295686243/LavaCms.git/'


adjust text color

adjust text color

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/stefanjudis/stefan-judis-website.git/'


[ci skip] Remove usage of global scope and remove dom querying from issue note form

<template>

      This comment has changed since you started editing, please review the
      updated comment
        to ensure information is not lost.

    <form class="edit-note common-note-form">
      <markdown-field
        :markdown-preview-url="markdownPreviewUrl"
        :markdown-docs="markdownDocsUrl"
        :addSpacingClasses="false">
        <textarea
          id="note-body"
          name="note[note]"
          class="note-textarea js-gfm-input js-autosize markdown-area js-note-text"
          data-supports-slash-commands="true"
          data-supports-quick-actions="true"
          aria-label="Description"
          v-model="note"
          ref="textarea"
          slot="textarea"
          placeholder="Write a comment or drag your files here..."
          @keydown.meta.enter="handleUpdate"
          @keydown.up="editMyLastNote"
          @keydown.esc="cancelHandler(true)">
        </textarea>
      </markdown-field>

        <button
          @click="handleUpdate"
          type="button"
          class="btn btn-nr btn-save">
          {{saveButtonTitle}}
        </button>
        <button
          @click="cancelHandler"
          class="btn btn-nr btn-cancel note-edit-cancel"
          type="button">
          Cancel
        </button>

    </form>

</template>

<template>

      This comment has changed since you started editing, please review the
      updated comment
        to ensure information is not lost.

    <form class="edit-note common-note-form">
      <markdown-field
        :markdown-preview-url="markdownPreviewUrl"
        :markdown-docs="markdownDocsUrl"
        :addSpacingClasses="false">
        <textarea
          id="note-body"
          name="note[note]"
          class="note-textarea js-gfm-input js-autosize markdown-area js-note-text"
          data-supports-slash-commands="true"
          data-supports-quick-actions="true"
          aria-label="Description"
          v-model="note"
          ref="textarea"
          slot="textarea"
          placeholder="Write a comment or drag your files here..."
          @keydown.meta.enter="handleUpdate"
          @keydown.up="editMyLastNote"
          @keydown.esc="cancelHandler(true)">
        </textarea>
      </markdown-field>

        <button
          @click="handleUpdate"
          type="button"
          class="btn btn-nr btn-save">
          {{saveButtonTitle}}
        </button>
        <button
          @click="cancelHandler()"
          class="btn btn-nr btn-cancel note-edit-cancel"
          type="button">
          Cancel
        </button>

    </form>

</template>


add layout container

add layout container

<template lang="pug">
  .c-container(:class="classNames")
    slot
</template>

<script>
export default {
  name: 'c-container',
  props: {
    size: String,
    align: String
  },
  computed: {
    classNames () {
      const classNames = []
      if (this.size) classNames.push(`is-${this.size}`)
      if (this.align) classNames.push(`is-${this.align}`)
      return classNames
    }
  }
}
</script>

error: pathspec 'src/components/grid/container.vue' did not match any file(s) known to git


Social Medias display

Social Medias display

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/chypriote/france-v2.git/'


add message alert for mail testing result

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/notadd/administration.git/'


Fixed Web IDE live preview not hot reloading

<template>

    <template v-if="showPreview">
      <navigator
        :manager="manager"
      />

    </template>

        {{ s__('IDE|Live Preview') }}

        {{ s__('IDE|Preview your web application using Web IDE client-side evaluation.') }}

        {{ s__('IDE|Get started with Live Preview') }}

    <loading-icon
      v-else
      size="2"
      class="align-self-center mt-auto mb-auto"
    />

</template>


Removes parse, Adds conditional output for price

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/NathanielDavid/Sumie.git/'


update button

update button

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/TuhuFE/wepy.git/'


Reroute to workout if already logged in.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Joneteus/Mentulapp.git/'


fix laggy updates on done

fix laggy updates on done

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/aligerum/clockwork.git/'


using graphql query for extension page to get list of extensions


do not refresh page while addon status changed


Added OxyRating simple vue rating module using stars.

<template>
  <div class="rating-indicator">
    <i v-for="(_, index) in totalStart" :class="iconForStar(index)">
    </i>
  </div>
</template>

<script>
const numberStars = 5

export default {
  props: {
    editable: {
      type: Boolean,
      required: false,
      default: false
    },
    rating: {
      type: Number,
      required: true
    }
  },
  data () {
    return {
      totalStart: numberStars
    }
  },

  methods: {
    iconForStar: function (index) {
      let v = (this.rating - 1.0) - index
      console.debug(index, v, this.rating)
      if (v >= -0.3) {
        return 'ion-ios-star'
      } else if (v >= -0.5) {
        return 'ion-ios-star-half'
      }
      return 'ion-ios-star-outline'
    }
  }
}
</script>

<style>
  .rating-indicator {
    font-size: 2rem;
    color: #888;
    display: inline-block;
    text-align: center;
  }
</style>

error: pathspec 'src/components/UIComponents/OxyRating.vue' did not match any file(s) known to git


add github link

add github link

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/l10178/grapes.git/'


Avoid to do the same exam twice

Avoid to do the same exam twice

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/JimmehCai/VTIC.git/'


Better fix for menu opening after selection issue

This works because when the mouse clicks an item, `md-autocomplete`
loses focus so we can disable renderFilteredList() until the element is
focused again. However, with keyboard selection, the input remains
focused so we only disable it for one input event, therefore allowing
the input still to be modified.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/jaceks-iRonin/vue-material-test.git/'


[#157] Microcart / parse updated qty to integer instead of string

<template>

{{ product.name }}

{{ product.sku }}

Qty
          {{ product.quantity }}

            <input class="h6" type="number" v-model.number="qty">

          $ {{ product.price }}

<edit-button class="c-darkgray" />

<remove-button class="c-darkgray" />

</template>

<template>

{{ product.name }}

{{ product.sku }}

Qty
          {{ product.quantity }}

            <input class="h6" type="number" v-model="qty">

          $ {{ product.price }}

<edit-button class="c-darkgray" />

<remove-button class="c-darkgray" />

</template>


add uploads

add uploads

error: pathspec 'src/components/DataCards-Upload.vue' did not match any file(s) known to git


修复alert选中tag

修复alert选中tag

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/wuazhu/chinapost.git/'


Improve versatility of suggested component links

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/mplusmuseum/mplusmuseum-stories.git/'


实现 菜单交互 点击激活连接页面，菜单隐藏

实现 菜单交互 点击激活连接页面，菜单隐藏

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/aligger/vue-meizhi.git/'


Fix expiration

Fix expiration

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/ICJIA/icjia-gata.git/'


Complete basic function

Complete basic function

<template>

        <input @keyup.enter="addTodoItem"
               v-model="newTodoItem"
               type="text"
               class="form-control"
               placeholder="Input new TODO item">

                      <button type="button" class="btn btn-default" aria-label="Add new todo item">

        </button>

      Todo Items{{todoItems.length}}

      {{item}}

      Done Items{{doneItems.length}}

      {{item}}

</template>

<template>

        <input type="text" class="form-control" placeholder="Input new TODO item">

            <button type="button" class="btn btn-default" aria-label="Add">

            </button>

          Todo Items

      Dapibus ac facilisis in
      Morbi leo risus
      Porta ac consectetur ac
      Vestibulum at eros

          Done Items

      Dapibus ac facilisis in
      Morbi leo risus
      Porta ac consectetur ac
      Vestibulum at eros

</template>


Add close event on tab

Add close event on tab

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/praneetloke/vue-material.git/'


Fix for color and size selection

Fix for color and size selection

<template>
  <div id="Category">
    Core Category
  </div>
</template>

<script>
import builder from 'bodybuilder'

import { breadCrumbRoutes } from '@vue-storefront/store/helpers'
import config from 'config'
import Sidebar from 'core/components/blocks/Category/Sidebar.vue'
import ProductListing from 'core/components/ProductListing.vue'
import Breadcrumbs from 'core/components/Breadcrumbs.vue'
import { optionLabel } from '@vue-storefront/store/modules/attribute/helpers'
import EventBus from 'core/plugins/event-bus'
import Composite from 'core/mixins/composite'
import _ from 'lodash'
import i18n from 'core/lib/i18n'

function filterChanged (filterOption) { // slection of product variant on product page
  if (this.filters.chosen[filterOption.attribute_code] && ((_.toString(filterOption.id) === _.toString(this.filters.chosen[filterOption.attribute_code].id)) || filterOption.id === this.filters.chosen[filterOption.attribute_code].id)) { // for price filter it's a string
    delete this.filters.chosen[filterOption.attribute_code]
  } else {
    this.filters.chosen[filterOption.attribute_code] = filterOption
  }

  let filterQr = baseFilterQuery(config.products.defaultFilters, this.$store.state.category.current)

  let attrFilterBuilder = (filterQr, attrPostfix = '') => {
    for (let code of Object.keys(this.filters.chosen)) {
      const filter = this.filters.chosen[code]

      if (filter.attribute_code !== 'price') {
        filterQr = filterQr.andFilter('match', filter.attribute_code + attrPostfix, filter.id)
      } else { // multi should be possible filter here?
        const rangeqr = {}
        if (filter.from) {
          rangeqr['gte'] = filter.from
        }
        if (filter.to) {
          rangeqr['lte'] = filter.to
        }
        filterQr = filterQr.andFilter('range', filter.attribute_code, rangeqr)
      }
    }
    return filterQr
  }
  filterQr = filterQr.orFilter('bool', (b) => attrFilterBuilder(b).filter('match', 'type_id', 'simple'))
    .orFilter('bool', (b) => attrFilterBuilder(b, '_options').filter('match', 'type_id', 'configurable'))

  const fsC = Object.assign({}, this.filters.chosen) // create a copy because it will be used asynchronously (take a look below)
  filterData({ populateAggregations: false, searchProductQuery: filterQr, store: this.$store, route: this.$route, current: this.pagination.current, perPage: this.pagination.perPage, filters: config.products.defaultFilters }).then((res) => {
    EventBus.$emit('product-after-configured', { configuration: fsC })
  }) // because already aggregated
}

function baseFilterQuery (filters, parentCategory) { // TODO add aggregation of color_options and size_options fields
  let searchProductQuery = builder().query('range', 'price', { 'gt': 0 }).andFilter('range', 'visibility', { 'gte': 3, 'lte': 4 }/** Magento visibility in search & categories */)

  // add filters to query
  for (let attrToFilter of filters) {
    if (attrToFilter !== 'price') {
      searchProductQuery = searchProductQuery.aggregation('terms', attrToFilter)
      searchProductQuery = searchProductQuery.aggregation('terms', attrToFilter + '_options')
    } else {
      searchProductQuery = searchProductQuery.aggregation('terms', attrToFilter)
      searchProductQuery.aggregation('range', 'price', {
        ranges: [
          { from: 0, to: 50 },
          { from: 50, to: 100 },
          { from: 100, to: 150 },
          { from: 150 }
        ]
      })
    }
  }

  let childCats = [parentCategory.id]
  if (parentCategory.children_data) {
    let recurCatFinderBuilder = (category) => {
      if (!category) {
        return
      }

      if (!category.children_data) {
        return
      }

      for (let sc of category.children_data) {
        if (sc && sc.id) {
          childCats.push(sc.id)
        }
        recurCatFinderBuilder(sc)
      }
    }
    recurCatFinderBuilder(parentCategory)
  }
  searchProductQuery = searchProductQuery.filter('terms', 'category.category_id', childCats)
  return searchProductQuery
}

// TODO: Refactor - move this function to the Vuex store
function filterData ({ populateAggregations = false, filters = [], searchProductQuery, store, route, current = 0, perPage = 50, includeFields = null, excludeFields = null }) {
  if (config.entities.twoStageCaching && config.entities.optimize && !global.$VS.isSSR && !global.$VS.twoStageCachingDisabled) { // only client side, only when two stage caching enabled
    includeFields = config.entities.productListWithChildren.includeFields // we need configurable_children for filters to work
    excludeFields = config.entities.productListWithChildren.excludeFields
    console.log('Using two stage caching for performance optimization - executing first stage product pre-fetching')
  } else {
    if (global.$VS.twoStageCachingDisabled) {
      console.log('Two stage caching is disabled runtime because of no performance gain')
    } else {
      console.log('Two stage caching is disabled by the config')
    }
  }
  let t0 = new Date().getTime()
  let precachedQuery = searchProductQuery.build()
  let productPromise = store.dispatch('product/list', {
    query: precachedQuery,
    start: current,
    size: perPage,
    excludeFields: excludeFields,
    includeFields: includeFields
  }).then(function (res) {
    let t1 = new Date().getTime()
    global.$VS.twoStageCachingDelta1 = t1 - t0

    let subloaders = []
    if (!res || (res.noresults)) {
      EventBus.$emit('notification', {
        type: 'warning',
        message: i18n.t('No products synchronized for this category. Please come back while online!'),
        action1: { label: 'OK', action: 'close' }
      })
      store.dispatch('product/reset')
      store.state.product.list = { items: [] } // no products to show TODO: refactor to store.state.category.reset() and store.state.product.reset()
      // store.state.category.filters = { color: [], size: [], price: [] }
    } else {
      if (populateAggregations === true) { // populate filter aggregates
        for (let attrToFilter of filters) { // fill out the filter options
          store.state.category.filters.available[attrToFilter] = []

          let uniqueFilterValues = new Set()
          if (attrToFilter !== 'price') {
            if (res.aggregations['agg_terms_' + attrToFilter]) {
              let buckets = res.aggregations['agg_terms_' + attrToFilter].buckets
              if (res.aggregations['agg_terms_' + attrToFilter + '_options']) {
                buckets = buckets.concat(res.aggregations['agg_terms_' + attrToFilter + '_options'].buckets)
              }

              for (let option of buckets) {
                uniqueFilterValues.add(_.toString(option.key))
              }
            }

            for (let key of uniqueFilterValues.values()) {
              const label = optionLabel(store.state.attribute, { attributeKey: attrToFilter, optionId: key })
              if (_.trim(label) !== '') { // is there any situation when label could be empty and we should still support it?
                store.state.category.filters.available[attrToFilter].push({
                  id: key,
                  label: label
                })
              }
            }
          } else { // special case is range filter for prices
            if (res.aggregations['agg_range_' + attrToFilter]) {
              let index = 0
              let count = res.aggregations['agg_range_' + attrToFilter].buckets.length
              for (let option of res.aggregations['agg_range_' + attrToFilter].buckets) {
                store.state.category.filters.available[attrToFilter].push({
                  id: option.key,
                  from: option.from,
                  to: option.to,
                  label: (index === 0 || (index === count - 1)) ? (option.to ? '< $' + option.to : '> $' + option.from) : '$' + option.from + (option.to ? ' - ' + option.to : '')// TODO: add better way for formatting, extract currency sign
                })
                index++
              }
            }
          }
        }
      }
    }
    return subloaders
  }).catch((err) => {
    console.info(err)
    EventBus.$emit('notification', {
      type: 'warning',
      message: i18n.t('No products synchronized for this category. Please come back while online!'),
      action1: { label: 'OK', action: 'close' }
    })
  })

  if (config.entities.twoStageCaching && config.entities.optimize && !global.$VS.isSSR && !global.$VS.twoStageCachingDisabled) { // second stage - request for caching entities
    console.log('Using two stage caching for performance optimization - executing second stage product caching') // TODO: in this case we can pre-fetch products in advance getting more products than set by pageSize
    store.dispatch('product/list', {
      query: precachedQuery,
      start: current,
      size: perPage,
      excludeFields: null,
      includeFields: null,
      updateState: false // not update the product listing - this request is only for caching
    }).catch((err) => {
      console.info("Problem with second stage caching - couldn't store the data")
      console.info(err)
    }).then((res) => {
      let t2 = new Date().getTime()
      global.$VS.twoStageCachingDelta2 = t2 - t0
      console.log('Using two stage caching for performance optimization - Time comparison stage1 vs stage2', global.$VS.twoStageCachingDelta1, global.$VS.twoStageCachingDelta2)
      if (global.$VS.twoStageCachingDelta1 > global.$VS.twoStageCachingDelta2) { // two stage caching is not making any good
        global.$VS.twoStageCachingDisabled = true
        console.log('Disabling two stage caching')
      }
    })
  }
  return productPromise
}

export default {
  name: 'Category',
  metaInfo () {
    return {
      title: this.$route.meta.title || this.categoryName,
      meta: this.$route.meta.description ? [{vmid: 'description', description: this.$route.meta.description}] : []
    }
  },
  mixins: [Composite],
  methods: {
    onFilterChanged (filterData) {
      (filterChanged.bind(this))(filterData)
    },
    fetchData ({ store, route }) {
      let self = this
      let searchProductQuery = baseFilterQuery(config.products.defaultFilters, store.state.category.current)

      if (self.category) { // fill breadcrumb data - TODO: extract it to a helper to be used on product page
        this.$bus.$emit('current-category-changed', store.state.category.current_path)
        store.dispatch('attribute/list', { // load filter attributes for this specific category
          filterValues: config.products.defaultFilters// TODO: assign specific filters/ attribute codes dynamicaly to specific categories
        })
      }
      return filterData({ searchProductQuery: searchProductQuery, populateAggregations: true, store: store, route: route, current: self.pagination.current, perPage: self.pagination.perPage, filters: config.products.defaultFilters })
    },
    validateRoute ({store, route}) {
      let self = this
      if (store == null) {
        store = self.$store
      }
      if (route == null) {
        route = self.$route
      }
      let slug = route.params.slug
      this.filters.chosen = {} // reset selected filters
      this.$bus.$emit('filter-reset')

      store.dispatch('category/single', { key: 'slug', value: slug }).then((category) => {
        store.state.category.breadcrumbs.routes = breadCrumbRoutes(store.state.category.current_path)

        if (!self.category) {
          self.$router.push('/')
        } else {
          self.fetchData({store: store, route: route})
          EventBus.$emitFilter('category-after-load', { store: store, route: route })
        }
      })
    }
  },
  watch: {
    '$route': 'validateRoute'
  },
  asyncData ({ store, route }) { // this is for SSR purposes to prefetch data
    return new Promise((resolve, reject) => {
      console.log('Entering asyncData for Category root ' + new Date())
      const defaultFilters = config.products.defaultFilters
      store.dispatch('category/list', { includeFields: config.entities.optimize && global.$VS.isSSR ? config.entities.category.includeFields : null }).then((categories) => {
        store.dispatch('attribute/list', { // load filter attributes for this specific category
          filterValues: defaultFilters, // TODO: assign specific filters/ attribute codes dynamicaly to specific categories
          includeFields: config.entities.optimize && global.$VS.isSSR ? config.entities.attribute.includeFields : null
        }).then((attrs) => {
          store.dispatch('category/single', { key: 'slug', value: route.params.slug }).then((parentCategory) => {
            filterData({ searchProductQuery: baseFilterQuery(defaultFilters, parentCategory), populateAggregations: true, store: store, route: route, current: 0, perPage: 50, filters: defaultFilters, includeFields: config.entities.optimize && global.$VS.isSSR ? config.entities.productList.includeFields : null, excludeFields: config.entities.optimize && global.$VS.isSSR ? config.entities.productList.excludeFields : null }).then((subloaders) => {
              Promise.all(subloaders).then((results) => {
                store.state.category.breadcrumbs.routes = breadCrumbRoutes(store.state.category.current_path)

                EventBus.$emitFilter('category-after-load', { store: store, route: route }).then((results) => {
                  return resolve()
                }).catch((err) => {
                  console.error(err)
                  return resolve()
                })
              })
            })
          }).catch(err => {
            console.error(err)
            return reject(Error(err))
          })
        })
      })
    })
  },
  beforeMount () {
    this.$bus.$on('filter-changed-category', this.onFilterChanged)
  },
  beforeDestroy () {
    this.$bus.$off('filter-changed-category', this.onFilterChanged)
  },
  computed: {
    products () {
      return this.$store.state.product.list.items
    },
    productsCounter () {
      return this.$store.state.product.list.items.length
    },
    isCategoryEmpty () {
      return (!(this.$store.state.product.list.items) || this.$store.state.product.list.items.length === 0)
    },
    category () {
      return this.$store.state.category.current
    },
    categoryName () {
      return this.$store.state.category.current ? this.$store.state.category.current.name : ''
    },
    categoryId () {
      return this.$store.state.category.current ? this.$store.state.category.current.id : ''
    },
    filters () {
      return this.$store.state.category.filters
    },
    breadcrumbs () {
      return this.$store.state.category.breadcrumbs
    }

  },
  data () {
    return {
      pagination: {
        perPage: 50,
        current: 0,
        enabled: false
      }
    }
  },
  components: {
    ProductListing,
    Breadcrumbs,
    Sidebar
  }
}
</script>

<template>
  <div id="Category">
    Core Category
  </div>
</template>

<script>
import builder from 'bodybuilder'

import { breadCrumbRoutes } from '@vue-storefront/store/helpers'
import config from 'config'
import Sidebar from 'core/components/blocks/Category/Sidebar.vue'
import ProductListing from 'core/components/ProductListing.vue'
import Breadcrumbs from 'core/components/Breadcrumbs.vue'
import { optionLabel } from '@vue-storefront/store/modules/attribute/helpers'
import EventBus from 'core/plugins/event-bus'
import Composite from 'core/mixins/composite'
import _ from 'lodash'
import i18n from 'core/lib/i18n'

function filterChanged (filterOption) { // slection of product variant on product page
  if (this.filters.chosen[filterOption.attribute_code] && ((_.toString(filterOption.id) === _.toString(this.filters.chosen[filterOption.attribute_code].id)) || filterOption.id === this.filters.chosen[filterOption.attribute_code].id)) { // for price filter it's a string
    delete this.filters.chosen[filterOption.attribute_code]
  } else {
    this.filters.chosen[filterOption.attribute_code] = filterOption
  }

  let filterQr = baseFilterQuery(config.products.defaultFilters, this.$store.state.category.current)

  let attrFilterBuilder = (filterQr, attrPostfix = '') => {
    for (let code of Object.keys(this.filters.chosen)) {
      const filter = this.filters.chosen[code]

      if (filter.attribute_code !== 'price') {
        filterQr = filterQr.andFilter('match', filter.attribute_code + attrPostfix, filter.id)
      } else { // multi should be possible filter here?
        const rangeqr = {}
        if (filter.from) {
          rangeqr['gte'] = filter.from
        }
        if (filter.to) {
          rangeqr['lte'] = filter.to
        }
        filterQr = filterQr.andFilter('range', filter.attribute_code, rangeqr)
      }
    }
    return filterQr
  }
  filterQr = filterQr.orFilter('bool', (b) => attrFilterBuilder(b).filter('match', 'type_id', 'simple'))
    .orFilter('bool', (b) => attrFilterBuilder(b, '_options').filter('match', 'type_id', 'configurable'))

  const fsC = Object.assign({}, this.filters.chosen) // create a copy because it will be used asynchronously (take a look below)
  filterData({ populateAggregations: false, searchProductQuery: filterQr, store: this.$store, route: this.$route, current: this.pagination.current, perPage: this.pagination.perPage, filters: config.products.defaultFilters }).then((res) => {
    EventBus.$emit('product-after-configured', { configuration: fsC })
  }) // because already aggregated
}

function baseFilterQuery (filters, parentCategory) { // TODO add aggregation of color_options and size_options fields
  let searchProductQuery = builder().query('range', 'price', { 'gt': 0 }).andFilter('range', 'visibility', { 'gte': 3, 'lte': 4 }/** Magento visibility in search & categories */)

  // add filters to query
  for (let attrToFilter of filters) {
    if (attrToFilter !== 'price') {
      searchProductQuery = searchProductQuery.aggregation('terms', attrToFilter)
      searchProductQuery = searchProductQuery.aggregation('terms', attrToFilter + '_options')
    } else {
      searchProductQuery = searchProductQuery.aggregation('terms', attrToFilter)
      searchProductQuery.aggregation('range', 'price', {
        ranges: [
          { from: 0, to: 50 },
          { from: 50, to: 100 },
          { from: 100, to: 150 },
          { from: 150 }
        ]
      })
    }
  }

  let childCats = [parentCategory.id]
  if (parentCategory.children_data) {
    let recurCatFinderBuilder = (category) => {
      if (!category) {
        return
      }

      if (!category.children_data) {
        return
      }

      for (let sc of category.children_data) {
        if (sc && sc.id) {
          childCats.push(sc.id)
        }
        recurCatFinderBuilder(sc)
      }
    }
    recurCatFinderBuilder(parentCategory)
  }
  searchProductQuery = searchProductQuery.filter('terms', 'category.category_id', childCats)
  return searchProductQuery
}

// TODO: Refactor - move this function to the Vuex store
function filterData ({ populateAggregations = false, filters = [], searchProductQuery, store, route, current = 0, perPage = 50, includeFields = null, excludeFields = null }) {
  if (config.entities.twoStageCaching && config.entities.optimize && !global.$VS.isSSR && !global.$VS.twoStageCachingDisabled) { // only client side, only when two stage caching enabled
    includeFields = config.entities.productListWithChildren.includeFields // we need configurable_children for filters to work
    excludeFields = config.entities.productListWithChildren.excludeFields
    console.log('Using two stage caching for performance optimization - executing first stage product pre-fetching')
  } else {
    if (global.$VS.twoStageCachingDisabled) {
      console.log('Two stage caching is disabled runtime because of no performance gain')
    } else {
      console.log('Two stage caching is disabled by the config')
    }
  }
  let t0 = new Date().getTime()
  let precachedQuery = searchProductQuery.build()
  let productPromise = store.dispatch('product/list', {
    query: precachedQuery,
    start: current,
    size: perPage,
    excludeFields: excludeFields,
    includeFields: includeFields
  }).then(function (res) {
    let t1 = new Date().getTime()
    global.$VS.twoStageCachingDelta1 = t1 - t0

    let subloaders = []
    if (!res || (res.noresults)) {
      EventBus.$emit('notification', {
        type: 'warning',
        message: i18n.t('No products synchronized for this category. Please come back while online!'),
        action1: { label: 'OK', action: 'close' }
      })
      store.dispatch('product/reset')
      store.state.product.list = { items: [] } // no products to show TODO: refactor to store.state.category.reset() and store.state.product.reset()
      // store.state.category.filters = { color: [], size: [], price: [] }
    } else {
      if (populateAggregations === true) { // populate filter aggregates
        for (let attrToFilter of filters) { // fill out the filter options
          store.state.category.filters.available[attrToFilter] = []

          let uniqueFilterValues = new Set()
          if (attrToFilter !== 'price') {
            if (res.aggregations['agg_terms_' + attrToFilter]) {
              let buckets = res.aggregations['agg_terms_' + attrToFilter].buckets
              if (res.aggregations['agg_terms_' + attrToFilter + '_options']) {
                buckets = buckets.concat(res.aggregations['agg_terms_' + attrToFilter + '_options'].buckets)
              }

              for (let option of buckets) {
                uniqueFilterValues.add(_.toString(option.key))
              }
            }

            for (let key of uniqueFilterValues.values()) {
              const label = optionLabel(store.state.attribute, { attributeKey: attrToFilter, optionId: key })
              if (_.trim(label) !== '') { // is there any situation when label could be empty and we should still support it?
                store.state.category.filters.available[attrToFilter].push({
                  id: key,
                  label: label
                })
              }
            }
          } else { // special case is range filter for prices
            if (res.aggregations['agg_range_' + attrToFilter]) {
              let index = 0
              let count = res.aggregations['agg_range_' + attrToFilter].buckets.length
              for (let option of res.aggregations['agg_range_' + attrToFilter].buckets) {
                store.state.category.filters.available[attrToFilter].push({
                  id: option.key,
                  from: option.from,
                  to: option.to,
                  label: (index === 0 || (index === count - 1)) ? (option.to ? '< $' + option.to : '> $' + option.from) : '$' + option.from + (option.to ? ' - ' + option.to : '')// TODO: add better way for formatting, extract currency sign
                })
                index++
              }
            }
          }
        }
      }
    }
    return subloaders
  }).catch((err) => {
    console.info(err)
    EventBus.$emit('notification', {
      type: 'warning',
      message: i18n.t('No products synchronized for this category. Please come back while online!'),
      action1: { label: 'OK', action: 'close' }
    })
  })

  if (config.entities.twoStageCaching && config.entities.optimize && !global.$VS.isSSR && !global.$VS.twoStageCachingDisabled) { // second stage - request for caching entities
    console.log('Using two stage caching for performance optimization - executing second stage product caching') // TODO: in this case we can pre-fetch products in advance getting more products than set by pageSize
    store.dispatch('product/list', {
      query: precachedQuery,
      start: current,
      size: perPage,
      excludeFields: null,
      includeFields: null
    }).catch((err) => {
      console.info("Problem with second stage caching - couldn't store the data")
      console.info(err)
    }).then((res) => {
      let t2 = new Date().getTime()
      global.$VS.twoStageCachingDelta2 = t2 - t0
      console.log('Using two stage caching for performance optimization - Time comparison stage1 vs stage2', global.$VS.twoStageCachingDelta1, global.$VS.twoStageCachingDelta2)
      if (global.$VS.twoStageCachingDelta1 > global.$VS.twoStageCachingDelta2) { // two stage caching is not making any good
        global.$VS.twoStageCachingDisabled = true
        console.log('Disabling two stage caching')
      }
    })
  }
  return productPromise
}

export default {
  name: 'Category',
  metaInfo () {
    return {
      title: this.$route.meta.title || this.categoryName,
      meta: this.$route.meta.description ? [{vmid: 'description', description: this.$route.meta.description}] : []
    }
  },
  mixins: [Composite],
  methods: {
    onFilterChanged (filterData) {
      (filterChanged.bind(this))(filterData)
    },
    fetchData ({ store, route }) {
      let self = this
      let searchProductQuery = baseFilterQuery(config.products.defaultFilters, store.state.category.current)

      if (self.category) { // fill breadcrumb data - TODO: extract it to a helper to be used on product page
        this.$bus.$emit('current-category-changed', store.state.category.current_path)
        store.dispatch('attribute/list', { // load filter attributes for this specific category
          filterValues: config.products.defaultFilters// TODO: assign specific filters/ attribute codes dynamicaly to specific categories
        })
      }
      return filterData({ searchProductQuery: searchProductQuery, populateAggregations: true, store: store, route: route, current: self.pagination.current, perPage: self.pagination.perPage, filters: config.products.defaultFilters })
    },
    validateRoute ({store, route}) {
      let self = this
      if (store == null) {
        store = self.$store
      }
      if (route == null) {
        route = self.$route
      }
      let slug = route.params.slug
      this.filters.chosen = {} // reset selected filters
      this.$bus.$emit('filter-reset')

      store.dispatch('category/single', { key: 'slug', value: slug }).then((category) => {
        store.state.category.breadcrumbs.routes = breadCrumbRoutes(store.state.category.current_path)

        if (!self.category) {
          self.$router.push('/')
        } else {
          self.fetchData({store: store, route: route})
          EventBus.$emitFilter('category-after-load', { store: store, route: route })
        }
      })
    }
  },
  watch: {
    '$route': 'validateRoute'
  },
  asyncData ({ store, route }) { // this is for SSR purposes to prefetch data
    return new Promise((resolve, reject) => {
      console.log('Entering asyncData for Category root ' + new Date())
      const defaultFilters = config.products.defaultFilters
      store.dispatch('category/list', { includeFields: config.entities.optimize && global.$VS.isSSR ? config.entities.category.includeFields : null }).then((categories) => {
        store.dispatch('attribute/list', { // load filter attributes for this specific category
          filterValues: defaultFilters, // TODO: assign specific filters/ attribute codes dynamicaly to specific categories
          includeFields: config.entities.optimize && global.$VS.isSSR ? config.entities.attribute.includeFields : null
        }).then((attrs) => {
          store.dispatch('category/single', { key: 'slug', value: route.params.slug }).then((parentCategory) => {
            filterData({ searchProductQuery: baseFilterQuery(defaultFilters, parentCategory), populateAggregations: true, store: store, route: route, current: 0, perPage: 50, filters: defaultFilters, includeFields: config.entities.optimize && global.$VS.isSSR ? config.entities.productList.includeFields : null, excludeFields: config.entities.optimize && global.$VS.isSSR ? config.entities.productList.excludeFields : null }).then((subloaders) => {
              Promise.all(subloaders).then((results) => {
                store.state.category.breadcrumbs.routes = breadCrumbRoutes(store.state.category.current_path)

                EventBus.$emitFilter('category-after-load', { store: store, route: route }).then((results) => {
                  return resolve()
                }).catch((err) => {
                  console.error(err)
                  return resolve()
                })
              })
            })
          }).catch(err => {
            console.error(err)
            return reject(Error(err))
          })
        })
      })
    })
  },
  beforeMount () {
    this.$bus.$on('filter-changed-category', this.onFilterChanged)
  },
  beforeDestroy () {
    this.$bus.$off('filter-changed-category', this.onFilterChanged)
  },
  computed: {
    products () {
      return this.$store.state.product.list.items
    },
    productsCounter () {
      return this.$store.state.product.list.items.length
    },
    isCategoryEmpty () {
      return (!(this.$store.state.product.list.items) || this.$store.state.product.list.items.length === 0)
    },
    category () {
      return this.$store.state.category.current
    },
    categoryName () {
      return this.$store.state.category.current ? this.$store.state.category.current.name : ''
    },
    categoryId () {
      return this.$store.state.category.current ? this.$store.state.category.current.id : ''
    },
    filters () {
      return this.$store.state.category.filters
    },
    breadcrumbs () {
      return this.$store.state.category.breadcrumbs
    }

  },
  data () {
    return {
      pagination: {
        perPage: 50,
        current: 0,
        enabled: false
      }
    }
  },
  components: {
    ProductListing,
    Breadcrumbs,
    Sidebar
  }
}
</script>


Auto focus on the main input field

Auto focus on the main input field

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/zephraph/jeeves.git/'


Quick fix

Quick fix

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/JosefFriedrich-nodejs/baldr.git/'


Lie le premier champd de saisie de date à l'identifiant HTML

<template>
  <div>
    <input
      type="number"
      autofocus
      v-bind:id="firstId"
      ref="day"
      aria-label="Jour"
      v-model="day"
      placeholder="23"
      v-select-on-click
      min=1
      max=31 />
      /
    <input
      type="number"
      ref="month"
      aria-label="Mois"
      v-model="month"
      placeholder="02"
      v-select-on-click
      min=1
      max=12 />
      /
    <input
      type="number"
      ref="year"
      aria-label="Année"
      v-model="year"
      placeholder="1973"
      v-select-on-click
      min="1900"
      max="2020">
  </div>
</template>

<script>
import moment from 'moment'
import _ from 'lodash'

function stateManager(current, next) {
  if ((current.element === 'day' && current.length === 0 && next.element === 'day' && next.length === 1) ||
      (current.element === 'day' && current.length === 1 && next.element === 'day' && next.length === 2) ||
      (current.element === 'day' && current.length === 2 && next.element === 'month' && next.length === 1) ||
      (current.element === 'month' && current.length === 1 && next.element === 'month' && next.length === 2) ||
      (current.element === 'month' && current.length === 2 && next.element === 'year' && next.length === 1) ||
      (current.element === 'year' && current.length === 1 && next.element === 'year' && next.length === 2)) {
    return next
  } else {
    return false
  }
}

export default {
  name: 'InputDate',
  props: {
    id: String,
    value: Date,
  },
  data: function() {
    return {
      currentState: this.value ? 0 : { element: 'day', length: 0 },
      day: this.value && moment(this.value).format('DD'),
      month: this.value && moment(this.value).format('MM'),
      year: this.value && moment(this.value).format('YYYY'),
    }
  },
  computed: {
    auto: function() {
      return Boolean(this.currentState)
    },
    date: function() {
      return `${this.year}-${this.month && _.padStart(this.month, 2, '0')}-${this.day && _.padStart(this.day, 2, '0')}`
    },
    firstId: function() {
      const uniqueFieldName = 'id.' + Math.random().toString(36).slice(2)
      return this.id || uniqueFieldName
    }
  },
  methods: {
    emit: function($event) {
      var value = new Date($event.target.value)
      if (value) {
        this.$emit('input', value)
      }
    },
    update: function(name) {
      this.currentState = stateManager(this.currentState, { element: name, length: this[name] && this[name].length || 0 })

      const dt = moment(this.date, 'YYYY-MM-DD', true)
      if (dt.isValid()) {
        this.$emit('input', dt.toDate())
      } else {
        this.$emit('input', undefined)
      }
    }
  },
  watch: {
    day: function(to) {
      if (to && to.length == 2 && this.auto) {
        this.$refs.month.focus()
      }
      this.update('day')
    },
    month: function(to) {
      if (to && to.length == 2 && this.auto) {
        this.$refs.year.focus()
      }
      this.update('month')
    },
    year: function(to) {
      if (to && to.length == 4 && this.auto) {
        this.$refs.year.focus()
      }
      this.update('year')
    },
  }
}
</script>

<style scoped lang="css">
div {
  align-items: center;
  display: flex;
  flex-direction: row;
}
input {
  width: 5em;
}
</style>

<template>
  <div>
    <input
      type="number"
      autofocus
      ref="day"
      aria-label="Jour"
      v-model="day"
      placeholder="23"
      v-select-on-click
      min=1
      max=31 />
      /
    <input
      type="number"
      ref="month"
      aria-label="Mois"
      v-model="month"
      placeholder="02"
      v-select-on-click
      min=1
      max=12 />
      /
    <input
      type="number"
      ref="year"
      aria-label="Année"
      v-model="year"
      placeholder="1973"
      v-select-on-click
      min="1900"
      max="2020">
  </div>
</template>

<script>
import moment from 'moment'
import _ from 'lodash'

function stateManager(current, next) {
  if ((current.element === 'day' && current.length === 0 && next.element === 'day' && next.length === 1) ||
      (current.element === 'day' && current.length === 1 && next.element === 'day' && next.length === 2) ||
      (current.element === 'day' && current.length === 2 && next.element === 'month' && next.length === 1) ||
      (current.element === 'month' && current.length === 1 && next.element === 'month' && next.length === 2) ||
      (current.element === 'month' && current.length === 2 && next.element === 'year' && next.length === 1) ||
      (current.element === 'year' && current.length === 1 && next.element === 'year' && next.length === 2)) {
    return next
  } else {
    return false
  }
}

export default {
  name: 'InputDate',
  props: {
    value: Date,
  },
  data: function() {
    return {
      currentState: this.value ? 0 : { element: 'day', length: 0 },
      day: this.value && moment(this.value).format('DD'),
      month: this.value && moment(this.value).format('MM'),
      year: this.value && moment(this.value).format('YYYY'),
    }
  },
  computed: {
    auto: function() {
      return Boolean(this.currentState)
    },
    date: function() {
      return `${this.year}-${this.month && _.padStart(this.month, 2, '0')}-${this.day && _.padStart(this.day, 2, '0')}`
    }
  },
  methods: {
    emit: function($event) {
      var value = new Date($event.target.value)
      if (value) {
        this.$emit('input', value)
      }
    },
    update: function(name) {
      this.currentState = stateManager(this.currentState, { element: name, length: this[name] && this[name].length || 0 })

      const dt = moment(this.date, 'YYYY-MM-DD', true)
      if (dt.isValid()) {
        this.$emit('input', dt.toDate())
      } else {
        this.$emit('input', undefined)
      }
    }
  },
  watch: {
    day: function(to) {
      if (to && to.length == 2 && this.auto) {
        this.$refs.month.focus()
      }
      this.update('day')
    },
    month: function(to) {
      if (to && to.length == 2 && this.auto) {
        this.$refs.year.focus()
      }
      this.update('month')
    },
    year: function(to) {
      if (to && to.length == 4 && this.auto) {
        this.$refs.year.focus()
      }
      this.update('year')
    },
  }
}
</script>

<style scoped lang="css">
div {
  align-items: center;
  display: flex;
  flex-direction: row;
}
input {
  width: 5em;
}
</style>


Updating coordinates of the Marker on drag

<template>
  <div style="display: none">
    <!-- slot for custom marker -->
    <slot name="marker"/>
    <!-- slot for popup -->
    <slot />
  </div>
</template>

<script>
  import baseMixin from '../../lib/mixin'

  const markerEvents = {
    drag: 'drag',
    dragstart: 'dragstart',
    dragend: 'dragend'
  }

  export default {
    name: 'MapMarker',
    mixins: [baseMixin],
    props: {
      // mapbox marker options
      offset: {
        type: [Object, Array],
        default: () => [0, 0]
      },
      coordinates: {
        type: Array,
        required: true
      },
      color: {
        type: String
      },
      anchor: {
        type: String,
        default: 'center'
      },
      draggable: {
        type: Boolean,
        default: false
      }
    },

    data() {
      return {
        initial: true,
        marker: undefined
      }
    },

    watch: {
      coordinates(lngLat) {
        if (this.initial) return
        this.marker.setLngLat(lngLat)
      },
      draggable(next, prev) {
        if (this.initial) return
        this.marker.setDraggable(next)
      }
    },

    mounted() {
      this.$_checkMapTree()
    },

    beforeDestroy() {
      if (this.map !== undefined && this.marker !== undefined) {
        this.marker.remove()
      }
    },

    methods: {
      $_deferredMount(payload) {
        if (!this.marker) {
          const markerOptions = {
            ...this._props
          }
          if (this.$slots.marker) {
            markerOptions.element = this.$slots.marker[0].elm
          }
          this.marker = new this.mapbox.Marker(markerOptions)
        }

        this.map = payload.map
        this.$_addMarker()

        this.marker.on('dragend', event => {
          let newCoordinates
          if (this.coordinates instanceof Array) {
            newCoordinates = [event.target._lngLat.lng, event.target._lngLat.lat]
          } else {
            newCoordinates = event.target._lngLat
          }
          this.$emit('update:coordinates', newCoordinates)
        })

        const eventNames = Object.keys(markerEvents)
        const eventsToListen = Object.keys(this.$options._parentListeners)
        .filter(eventName =>
          eventNames.indexOf(eventName) !== -1
        )

        this.$_bindEvents(eventsToListen)

        this.initial = false
        payload.component.$off('load', this.$_deferredMount)
      },
      $_addMarker() {
        this.marker
          .setLngLat(this.coordinates)
          .addTo(this.map)

        this.$_emitMapEvent('added', { marker: this.marker })
      },

      remove() {
        this.$_emitMapEvent('removed', { marker: this.marker })
        return this.marker.remove()
      },

      togglePopup() {
        return this.marker.togglePopup()
      }
    }
  }
</script>

<template>
  <div style="display: none">
    <!-- slot for custom marker -->
    <slot name="marker"/>
    <!-- slot for popup -->
    <slot />
  </div>
</template>

<script>
  import baseMixin from '../../lib/mixin'

  export default {
    name: 'MapMarker',
    mixins: [baseMixin],
    props: {
      // mapbox marker options
      offset: {
        type: [Object, Array],
        default: () => [0, 0]
      },
      coordinates: {
        type: Array,
        required: true
      },
      color: {
        type: String
      },
      anchor: {
        type: String,
        default: 'center'
      },
      draggable: {
        type: Boolean,
        default: false
      }
    },

    data() {
      return {
        initial: true,
        marker: undefined
      }
    },

    watch: {
      coordinates(lngLat) {
        if (this.initial) return
        this.marker.setLngLat(lngLat)
      },
      draggable(next, prev) {
        if (this.initial) return
        this.marker.setDraggable(next)
      }
    },

    mounted() {
      this.$_checkMapTree()
    },

    beforeDestroy() {
      if (this.map !== undefined && this.marker !== undefined) {
        this.marker.remove()
      }
    },

    methods: {
      $_deferredMount(payload) {
        if (!this.marker) {
          const markerOptions = {
            ...this._props
          }
          if (this.$slots.marker) {
            markerOptions.element = this.$slots.marker[0].elm
          }
          this.marker = new this.mapbox.Marker(markerOptions)
        }

        this.map = payload.map
        this.$_addMarker()
        this.initial = false
        payload.component.$off('load', this.$_deferredMount)
      },
      $_addMarker() {
        this.marker
          .setLngLat(this.coordinates)
          .addTo(this.map)

        this.$_emitMapEvent('added', { marker: this.marker })
      },

      remove() {
        this.$_emitMapEvent('removed', { marker: this.marker })
        return this.marker.remove()
      },

      togglePopup() {
        return this.marker.togglePopup()
      }
    }
  }
</script>


Add themes to playground

Add themes to playground


add page

add page

<template>

home {{ test }}

</template>

error: pathspec 'view/src/js/app/home/index.vue' did not match any file(s) known to git


feat: Added a form-radio component

feat: Added a form-radio component

<template>
  <label class="form-radio" v-for="option in options" v-bind="$attrs">
    <input
        @change="$emit('input', $event.target.value)"
        :checked="value"
        :value="option.key || option.label || option"
        type="radio"
    >
    <i class="form-icon"></i> {{ option.label || option }}
  </label>
</template>

<script>
export default {
  props: {options: Array, value: [String, Number]}
}
</script>

error: pathspec 'resources/vue/components/formelements/form-radio.vue' did not match any file(s) known to git


Clear Camera search on clear from.

Clear Camera search on clear from.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-admin.git/'


Fix money filter falsely showing change

Fix money filter falsely showing change

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/PayBreak/basket.git/'


Update cloudradioo subnav

Update cloudradioo subnav

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/devfake/cloudradioo-app.git/'


Fix instant slides

Fix instant slides


ratingselect完成

ratingselect完成

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/zhou1178539345/vue-element.git/'


Event based success issue #1

Event based success issue #1

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/gstjohn/vue-stripe.git/'


app-tooltip component powered by tippy.js

<template>

      <icon name="ellipsis-h"></icon>

      Empty

</template>

error: pathspec 'frontend/src/components/AppTooltip.vue' did not match any file(s) known to git


Fix when no songs

Fix when no songs

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/stefanjarina/tab-tracker.git/'


Ensure does not fail for activities without organization

<template>

             {{ activity.created_at | timeago }}

                            {{actor.first_name}} {{actor.last_name}}<span v-if="$index < activity.aggregaterActors.length - 2">,
                            {{ _('and') }}

                        {{ activity.aggregatedLabel }}

                        {{ activity.organization.name }}
                        {{activity.actor.first_name}} {{activity.actor.last_name}}
                        {{ activity.label }}

                    {{ activity.related_to }}

                <dataset-card v-if="activity.related_to_kind === 'Dataset'" datasetid="{{ activity.related_to_id }}"></dataset-card>
                <organization-card v-if="activity.related_to_kind === 'Organization'" orgid="{{ activity.related_to_id }}"></organization-card>
                <reuse-card v-if="activity.related_to_kind === 'Reuse'" reuseid="{{ activity.related_to_id }}"></reuse-card>
                <user-card v-if="activity.related_to_kind === 'User'" userid="{{ activity.related_to_id }}"></user-card>

</template>


Fix link

Fix link


Fix lost title.

Fix lost title.

<template>

{{ $route.meta.label[language] }}

        <div class="image" :style="{ 'background-image': `url(${news.meta.image})` }">

{{ news.title }}

          {{ new Date(news.date).toLocaleDateString() }}

{{ `${news.content.substring(0, 50)}...` }}

          <router-link :to="`/culture/news/${news._id}`" class="button">
            閱讀全文

          </router-link>

</template>

<template>

      <div class="image" :style="{ 'background-image': `url(${news.meta.image})` }">

{{ news.title }}

        {{ new Date(news.date).toLocaleDateString() }}

{{ `${news.content.substring(0, 50)}...` }}

        <router-link :to="`/culture/news/${news._id}`" class="button">
          閱讀全文

        </router-link>

</template>


small cleanup in new chart

small cleanup in new chart

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/doce-org/web-doce-io.git/'


update

update

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/iview/iview-doc.git/'


init setting

init setting

<template>

</template>
<style>

</style>
<script>
  export default {
    name: 'setting'
  }
</script>

error: pathspec 'src/components/setting.vue' did not match any file(s) known to git


fix(MdChips): make chip allow spaces (#1211)

trim input value while inserting

fix #1207

<template>
  <md-field class="md-chips" :class="[$mdActiveTheme, chipsClasses]">
    <slot v-if="!mdStatic" />

    <md-chip
      v-for="(chip, key) in value"
      :key="key"
      :md-deletable="!mdStatic"
      :md-clickable="!mdStatic"
      @keydown.enter="$emit('md-click', chip, key)"
      @click.native="$emit('md-click', chip, key)"
      @md-delete.stop="removeChip(chip)">
      <slot name="md-chip" :chip="chip" v-if="$scopedSlots['md-chip']">{{ chip }}</slot>
      <template v-else>{{ chip }}</template>
    </md-chip>

    <md-input
      ref="input"
      v-model="inputValue"
      v-if="!mdStatic && modelRespectLimit"
      :type="mdInputType"
      :id="id"
      :placeholder="mdPlaceholder"
      @keydown.enter="insertChip"
      @keydown.8="handleBackRemove">
    </md-input>
  </md-field>
</template>

<script>
  import MdComponent from 'core/MdComponent'
  import MdField from 'components/MdField/MdField'
  import MdInput from 'components/MdField/MdInput/MdInput'
  import MdUuid from 'core/utils/MdUuid'
  import MdPropValidator from 'core/utils/MdPropValidator'

  export default new MdComponent({
    name: 'MdChips',
    components: {
      MdField,
      MdInput
    },
    props: {
      value: Array,
      id: {
        type: [String, Number],
        default: () => 'md-chips-' + MdUuid()
      },
      mdInputType: {
        type: [String, Number],
        ...MdPropValidator('md-input-type', ['email', 'number', 'password', 'search', 'tel', 'text', 'url'])
      },
      mdPlaceholder: [String, Number],
      mdStatic: Boolean,
      mdLimit: Number
    },
    data: () => ({
      inputValue: ''
    }),
    computed: {
      chipsClasses () {
        return {
          'md-has-value': this.value && this.value.length
        }
      },

      modelRespectLimit () {
        return !this.mdLimit || this.value.length < this.mdLimit
      }
    },
    methods: {
      insertChip () {
        let value = this.inputValue.trim()
        if (
          !value ||
          this.value.includes(value) ||
          !this.modelRespectLimit
        ) {
          return
        }
        this.value.push(value)
        this.$emit('input', this.value)
        this.$emit('md-insert', value)
        this.inputValue = ''
      },
      removeChip (chip) {
        const index = this.value.indexOf(chip)

        this.value.splice(index, 1)
        this.$emit('input', this.value)
        this.$emit('md-delete', chip, index)
        this.$nextTick(() => this.$refs.input.$el.focus())
      },
      handleBackRemove () {
        if (!this.inputValue) {
          this.removeChip(this.value[this.value.length - 1])
        }
      }
    }
  })
</script>

<style lang="scss">
  @import "~components/MdAnimation/variables";

  .md-chips.md-field {
    padding-top: 12px;
    flex-wrap: wrap;

    &.md-has-value {
      label {
        top: -6px;
      }
    }

    .md-chip {
      margin-bottom: 4px;

      &:last-of-type {
        margin-right: 8px;
      }
    }

    .md-input {
      min-width: 128px;
    }
  }
</style>

<template>
  <md-field class="md-chips" :class="[$mdActiveTheme, chipsClasses]">
    <slot v-if="!mdStatic" />

    <md-chip
      v-for="(chip, key) in value"
      :key="key"
      :md-deletable="!mdStatic"
      :md-clickable="!mdStatic"
      @keydown.enter="$emit('md-click', chip, key)"
      @click.native="$emit('md-click', chip, key)"
      @md-delete.stop="removeChip(chip)">
      <slot name="md-chip" :chip="chip" v-if="$scopedSlots['md-chip']">{{ chip }}</slot>
      <template v-else>{{ chip }}</template>
    </md-chip>

    <md-input
      ref="input"
      v-model.trim="inputValue"
      v-if="!mdStatic && modelRespectLimit"
      :type="mdInputType"
      :id="id"
      :placeholder="mdPlaceholder"
      @keydown.enter="insertChip"
      @keydown.8="handleBackRemove">
    </md-input>
  </md-field>
</template>

<script>
  import MdComponent from 'core/MdComponent'
  import MdField from 'components/MdField/MdField'
  import MdInput from 'components/MdField/MdInput/MdInput'
  import MdUuid from 'core/utils/MdUuid'
  import MdPropValidator from 'core/utils/MdPropValidator'

  export default new MdComponent({
    name: 'MdChips',
    components: {
      MdField,
      MdInput
    },
    props: {
      value: Array,
      id: {
        type: [String, Number],
        default: () => 'md-chips-' + MdUuid()
      },
      mdInputType: {
        type: [String, Number],
        ...MdPropValidator('md-input-type', ['email', 'number', 'password', 'search', 'tel', 'text', 'url'])
      },
      mdPlaceholder: [String, Number],
      mdStatic: Boolean,
      mdLimit: Number
    },
    data: () => ({
      inputValue: ''
    }),
    computed: {
      chipsClasses () {
        return {
          'md-has-value': this.value && this.value.length
        }
      },

      modelRespectLimit () {
        return !this.mdLimit || this.value.length < this.mdLimit
      }
    },
    methods: {
      insertChip ({ target }) {
        if (
          !this.inputValue ||
          this.value.includes(this.inputValue) ||
          !this.modelRespectLimit
        ) {
          return
        }
        this.value.push(this.inputValue)
        this.$emit('input', this.value)
        this.$emit('md-insert', this.inputValue)
        this.inputValue = ''
      },
      removeChip (chip) {
        const index = this.value.indexOf(chip)

        this.value.splice(index, 1)
        this.$emit('input', this.value)
        this.$emit('md-delete', chip, index)
        this.$nextTick(() => this.$refs.input.$el.focus())
      },
      handleBackRemove () {
        if (!this.inputValue) {
          this.removeChip(this.value[this.value.length - 1])
        }
      }
    }
  })
</script>

<style lang="scss">
  @import "~components/MdAnimation/variables";

  .md-chips.md-field {
    padding-top: 12px;
    flex-wrap: wrap;

    &.md-has-value {
      label {
        top: -6px;
      }
    }

    .md-chip {
      margin-bottom: 4px;

      &:last-of-type {
        margin-right: 8px;
      }
    }

    .md-input {
      min-width: 128px;
    }
  }
</style>


update label styles

update label styles

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/mubaidr/gh-pages.git/'


add item create handle code

add item create handle code

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/notadd/administration.git/'


Add page/_id.vue

Add page/_id.vue

<template>

Articles tagged with: {{ tag }}

    <ArticlesList :all-articles="taggedArticles"
                  :start-page="startPage"
                  :root-segment="rootSegment"
    />

</template>

error: pathspec 'pages/tags/_tag/page/_id.vue' did not match any file(s) known to git


Repare "jump" effect in sidebar

Repare "jump" effect in sidebar

<template>

        <search-icon class="p15 icon hidden-md" />
        <wishlist-icon class="p15 icon hidden-md" />
        <account-icon class="p15 icon hidden-md" />

        close

            <router-link class="block px25 py20 c-darkgray no-underline" to="/" exact>
              {{ $t('Home') }}
            </router-link>

 0 || category.children_data.length > 0"
          >
            <router-link
              class="px25 py20 c-darkgray no-underline col-xs"
              :to="{ name: 'category', params: { id: category.id, slug: category.slug }}"
            >
              {{ category.name }}
            </router-link>

            <router-link class="block px25 py20 brdr-bottom brdr-c-alto c-darkgray no-underline" to="/magazine" exact>
              {{ $t('Magazine') }}
            </router-link>

            <router-link class="block px25 py20 brdr-bottom brdr-c-alto c-darkgray no-underline" to="/sale" exact>
              {{ $t('Sale') }}
            </router-link>

            <router-link class="block px25 py20 brdr-bottom brdr-c-alto c-darkgray no-underline" to="/order-tracking" exact>
              {{ $t('Track my order') }}
            </router-link>

            <router-link v-if="currentUser" class="block px25 py20 c-darkgray no-underline col-xs" to="/my-account" exact>
              {{ $t('My account') }}
            </router-link>

              {{ $t('My account') }}

</template>


add dinner component

add dinner component

<template>
  <md-list class="md-double-line">
    <md-list-item v-for="dinner in dinners">
      <md-avatar>

      </md-avatar>

      {{dinner.name}}
      {{dinner.description}}

      <md-button>
        ${{dinner.price}}
      </md-button>

    </md-list-item>
  </md-list>
</template>

error: pathspec 'projects/day5/rest/src/components/dinner.vue' did not match any file(s) known to git


Add blog post stub.

Add blog post stub.

<template>

Blog Post

This is a blog post page.

    <nuxt-link to="/">
      Home
    </nuxt-link>

</template>

error: pathspec 'pages/blog/_slug.vue' did not match any file(s) known to git


Make send grab the contents of editor

Make send grab the contents of editor

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/ynagasaki/uwt-gui.git/'


fixed undefined variable after variable name change

<template>

          <icon
            :size="16"
            name="go-back"
          />

        <button
          type="button"
          class="ide-sidebar-link js-ide-edit-mode"
          :class="{
            active: currentActivityView === $options.activityBarViews.edit
          }"
          @click.prevent="updateActivityBarView($options.activityBarViews.edit)"
          :aria-label="s__('IDE|Edit mode')"
        >
          <icon
            name="code"
          />
        </button>

        <button
          type="button"
          class="ide-sidebar-link js-ide-review-mode"
          :class="{
            active: currentActivityView === $options.activityBarViews.review
          }"
          @click.prevent="updateActivityBarView($options.activityBarViews.review)"
        >
          <icon
            name="file-modified"
          />
        </button>

        <button
          type="button"
          class="ide-sidebar-link js-ide-commit-mode"
          :class="{
            active: currentActivityView === $options.activityBarViews.commit
          }"
          @click.prevent="updateActivityBarView($options.activityBarViews.commit)"
          :aria-label="s__('IDE|Commit mode')"
        >
          <icon
            name="commit"
          />
        </button>

</template>

<template>

          <icon
            :size="16"
            name="go-back"
          />

        <button
          type="button"
          class="ide-sidebar-link js-ide-edit-mode"
          :class="{
            active: currentActivityView === $options.activityBarViews.edit
          }"
          @click.prevent="updateActivityBarView($options.activityBarViews.edit)"
          :aria-label="s__('IDE|Edit mode')"
        >
          <icon
            name="code"
          />
        </button>

        <button
          type="button"
          class="ide-sidebar-link js-ide-review-mode"
          :class="{
            active: currentActivityView === $options.ActivityBarViews.review
          }"
          @click.prevent="updateActivityBarView($options.ActivityBarViews.review)"
        >
          <icon
            name="file-modified"
          />
        </button>

        <button
          type="button"
          class="ide-sidebar-link js-ide-commit-mode"
          :class="{
            active: currentActivityView === $options.activityBarViews.commit
          }"
          @click.prevent="updateActivityBarView($options.activityBarViews.commit)"
          :aria-label="s__('IDE|Commit mode')"
        >
          <icon
            name="commit"
          />
        </button>

</template>


fix[tags-view]: fixed contexrmenu bug on firefox

<template>

    <scroll-pane class='tags-view-wrapper' ref='scrollPane'>
      <router-link ref='tag' class="tags-view-item" :class="isActive(tag)?'active':''" v-for="tag in Array.from(visitedViews)"
        :to="tag.path" :key="tag.path" @contextmenu.prevent.native="openMenu(tag,$event)">
        {{generateTitle(tag.title)}}

      </router-link>
    </scroll-pane>

Close

Close Others

Close All

</template>