fix(admin): fix cannot fetch role list when edit user

<template>
    <el-dialog :title="title" :visible.sync="dialogFormVisible">
        <el-form ref="form" :rules="userRules" label-width="120px" :model="user">
            <el-form-item label="Account" required>
                <el-input v-model="user.username"></el-input>
            </el-form-item>
            <el-form-item label="Email">
                <el-input v-model="user.email"></el-input>
            </el-form-item>
            <el-form-item label="Nick">
                <el-input v-model="user.nick"></el-input>
            </el-form-item>
            <el-form-item label="Password">
                <el-input type="password" v-model="user.password"></el-input>
            </el-form-item>
            <el-form-item label="Confirm Password" prop="confirmPass">
                <el-input type="password" v-model="user.confirm_password"></el-input>
            </el-form-item>
            <el-form-item label="School">
                <el-input v-model="user.school"></el-input>
            </el-form-item>
            <el-form-item label="Locale">
                <el-input v-model="user.locale"></el-input>
            </el-form-item>
            <el-form-item label="User Status">
                <el-select v-model="user.status">
                    <el-option v-for="item in options" :key="item.value" :label="item.label"
                               :value="item.value"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="Roles">
                <el-transfer v-model="user.roles_edit"
                             :data="roles"
                             :titles="['Available Roles', 'Current Roles']"
                ></el-transfer>
            </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
            <el-button @click="dialogFormVisible = false">Cancel</el-button>
            <el-button type="primary" @click="save(user)">Save</el-button>
        </div>
    </el-dialog>
</template>

<script>

    export default {
        data() {
            let self = this;
            let confirmPassword = (rule, value, callback) => {
                if (self.user.password || self.user.confirm_password) {
                    if (self.user.password !== self.user.confirm_password) {
                        callback(new Error('Password is not equal'));
                    }
                } else {
                    callback();
                }
            };
            return {
                dialogFormVisible: false,
                user: {},
                options: [
                    {
                        value: 0,
                        label: 'Active',
                    }, {
                        value: 1,
                        label: 'Inactive',
                    }
                ],
                roles: [],
                userRules: {
                    confirmPass: [
                        {
                            validator: confirmPassword,
                            trigger: 'blur'
                        },
                    ]
                },
                title: 'Add User',
            }
        },
        methods: {
            save(item) {
                let self = this;
                if (item.id) {
                    this.$http.put('admin/users/' + item.id, item)
                        .then(function (resp) {
                            self.$message.success('Save success!');
                            self.dialogFormVisible = false;
                            self.$bus.emit('reload-users');
                        }).catch(function (resp) {
                        self.$message.error('Save failed!');
                    });
                } else {
                    this.$http.post('admin/users', item)
                        .then(function (resp) {
                            self.$message.success('Save success!');
                            self.dialogFormVisible = false;
                            self.$bus.emit('reload-users');
                        }).catch(function (resp) {
                        self.$message.error('Save failed!');
                    })
                }
            },
            loadRoles() {
                let self = this;
                this.$http.get('/admin/roles').then(function (res) {
                    let data = [];
                    res.data.data.forEach((item) => {
                        data.push({
                            key: item.id,
                            label: item.name
                        });
                    });
                    self.roles = data;
                })
            }
        },
        created() {
            let self = this;
            this.$bus.on('edit-user', function (user) {
                self.user = JSON.parse(JSON.stringify(user));
                if (user.id) {
                    self.title = 'Edit User';
                }
                self.dialogFormVisible = true;
            });

            this.loadRoles();
        }
    }
</script>

<template>
    <el-dialog :title="title" :visible.sync="dialogFormVisible">
        <el-form ref="form" :rules="userRules" label-width="120px" :model="user">
            <el-form-item label="Account" required >
                <el-input v-model="user.username"></el-input>
            </el-form-item>
            <el-form-item label="Email">
                <el-input v-model="user.email"></el-input>
            </el-form-item>
            <el-form-item label="Nick">
                <el-input v-model="user.nick"></el-input>
            </el-form-item>
            <el-form-item label="Password">
                <el-input type="password" v-model="user.password"></el-input>
            </el-form-item>
            <el-form-item label="Confirm Password" prop="confirmPass">
                <el-input type="password" v-model="user.confirm_password"></el-input>
            </el-form-item>
            <el-form-item label="School">
                <el-input v-model="user.school"></el-input>
            </el-form-item>
            <el-form-item label="Locale">
                <el-input v-model="user.locale"></el-input>
            </el-form-item>
            <el-form-item label="User Status" >
                <el-select v-model="user.status">
                    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="Roles">
                <el-transfer v-model="user.roles_edit"
                             :data="roles"
                             :titles="['Available Roles', 'Current Roles']"
                ></el-transfer>
            </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
            <el-button @click="dialogFormVisible = false">Cancel</el-button>
            <el-button type="primary" @click="save(user)">Save</el-button>
        </div>
    </el-dialog>
</template>

<script>

    export default {
        data(){
            let self = this;
            let confirmPassword = (rule, value, callback) => {
                if (self.user.password || self.user.confirm_password) {
                    if (self.user.password !== self.user.confirm_password) {
                        callback(new Error('Password is not equal'));
                    }
                } else {
                    callback();
                }
            };
            return {
                dialogFormVisible: false,
                user:{},
                options: [
                    {
                        value: 0,
                        label: 'Active',
                    }, {
                        value: 1,
                        label: 'Inactive',
                    }
                ],
                roles: [],
                userRules: {
                    confirmPass: [
                        {
                            validator: confirmPassword,
                            trigger: 'blur'
                        },
                    ]
                },
                title: 'Add User',
            }
        },
        methods: {
            save(item) {
                let self = this;
                if (item.id) {
                    this.$http.put('admin/users/' + item.id, item)
                        .then(function (resp) {
                            self.$message.success('Save success!');
                            self.dialogFormVisible = false;
                            self.$bus.emit('reload-users');
                        }).catch(function (resp) {
                            self.$message.error('Save failed!');
                        });
                } else {
                    this.$http.post('admin/users', item)
                        .then(function (resp) {
                            self.$message.success('Save success!');
                            self.dialogFormVisible = false;
                            self.$bus.emit('reload-users');
                        }).catch(function (resp) {
                            self.$message.error('Save failed!');
                        })
                }
            },
            loadRoles() {
                this.$http.get('/admin/roles').then(function(res){
                    let data = [];

                    for(let index = 0; index < res.data.data.length; index++) {
                        let item = res.data.data[index];
                        data.push({
                            key: item.id,
                            label: item.name
                        });
                    }
                    self.roles = data;
                })
            }
        },
        created() {
            let self = this;
            this.$bus.on('edit-user', function(user){
                self.user = JSON.parse(JSON.stringify(user));
                if (user.id) {
                    self.title = 'Edit User';
                }
                self.dialogFormVisible = true;
            });

            this.loadRoles();
        }
    }
</script>


speed is not good

speed is not good

<template>

取消

确定

{{year}}

{{year}}

{{month}}

{{month}}

{{day}}

{{day}}

</template>


fix: 修复页面切换后 textarea 组件 auto-height 失效的问题

<template>
  <uni-resize-sensor @animationstart.once="update">

  </uni-resize-sensor>
</template>

<script>
export default {
  name: 'ResizeSensor',
  props: {
    initial: {
      type: [Boolean, String],
      default: false
    }
  },
  data: function () {
    return {
      size: {
        width: -1,
        height: -1
      }
    }
  },
  watch: {
    size: {
      deep: true,
      handler: function (size) {
        this.$emit('resize', Object.assign({}, size))
      }
    }
  },
  mounted: function () {
    if (this.initial === true) {
      this.$nextTick(this.update)
    }

    if (this.$el.offsetParent !== this.$el.parentNode) {
      this.$el.parentNode.style.position = 'relative'
    }

    if (!('AnimationEvent' in window)) {
      this.reset()
    }
  },
  methods: {
    reset: function () {
      var expand = this.$el.firstChild
      var shrink = this.$el.lastChild
      expand.scrollLeft = 100000
      expand.scrollTop = 100000
      shrink.scrollLeft = 100000
      shrink.scrollTop = 100000
    },
    update: function () {
      this.size.width = this.$el.offsetWidth
      this.size.height = this.$el.offsetHeight
      this.reset()
    }
  },
  render: function (create) {
    return create('uni-resize-sensor', {
      on: {
        '~animationstart': this.update
      }
    }, [
      create('div', {
        on: {
          scroll: this.update
        }
      }, [
        create('div')
      ]),
      create('div', {
        on: {
          scroll: this.update
        }
      }, [
        create('div')
      ])
    ])
  }
}

</script>

<style>
@keyframes once-show {
  from {
    top: 0;
  }
}
uni-resize-sensor,
uni-resize-sensor > div {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
}
uni-resize-sensor {
  display: block;
  z-index: -1;
  visibility: hidden;
  animation: once-show 1ms;
}
uni-resize-sensor > div > div {
  position: absolute;
  left: 0;
  top: 0;
}
uni-resize-sensor > div:first-child > div {
  width: 100000px;
  height: 100000px;
}
uni-resize-sensor > div:last-child > div {
  width: 200%;
  height: 200%;
}
</style>


修改侧边栏设置url

修改侧边栏设置url

<template>

        <el-tooltip effect="dark" :content="isMini ? '展开菜单' : '折叠菜单'" placement="right" :disabled="!isMini">

            {{isMini ? '展开菜单' : '折叠菜单'}}

        </el-tooltip>

        <el-tooltip effect="dark" content="创建资源" placement="right" :disabled="!isMini">
          <router-link to="/resource/create" class="nav-link create-resource ls-nav-link">

            创建资源
          </router-link>
        </el-tooltip>

        <el-tooltip effect="dark" content="资源市场" placement="right" :disabled="!isMini">
          <router-link to="/" class="nav-link ls-nav-link">

            资源市场
          </router-link>
        </el-tooltip>

        <el-tooltip effect="dark" content="我的资源库" placement="right" :disabled="!isMini">
          <router-link to="/resource/list" class="nav-link ls-nav-link">

            我的资源库
          </router-link>
        </el-tooltip>

            节点
            <el-tooltip effect="dark" content="创建节点" placement="right" :disabled="!isMini">
              <router-link to="/node/create" class="nav-link ls-nav-link create-node-btn">

              </router-link>
            </el-tooltip>

            <router-link :to="'/node/'+node.nodeId" class="nav-link mnl-nav-link" :title="node.nodeName">
              {{node.nodeName}}
            </router-link>

        <el-tooltip effect="dark" content="设置" placement="right" :disabled="!isMini">
          <router-link to="/setting" class="nav-link ls-nav-link">

            设置
          </router-link>

        </el-tooltip>

</template>

<template>

        <el-tooltip effect="dark" :content="isMini ? '展开菜单' : '折叠菜单'" placement="right" :disabled="!isMini">

            {{isMini ? '展开菜单' : '折叠菜单'}}

        </el-tooltip>

        <el-tooltip effect="dark" content="创建资源" placement="right" :disabled="!isMini">
          <router-link to="/resource/create" class="nav-link create-resource ls-nav-link">

            创建资源
          </router-link>
        </el-tooltip>

        <el-tooltip effect="dark" content="资源市场" placement="right" :disabled="!isMini">
          <router-link to="/" class="nav-link ls-nav-link">

            资源市场
          </router-link>
        </el-tooltip>

        <el-tooltip effect="dark" content="我的资源库" placement="right" :disabled="!isMini">
          <router-link to="/resource/list" class="nav-link ls-nav-link">

            我的资源库
          </router-link>
        </el-tooltip>

            节点
            <el-tooltip effect="dark" content="创建节点" placement="right" :disabled="!isMini">
              <router-link to="/node/create" class="nav-link ls-nav-link create-node-btn">

              </router-link>
            </el-tooltip>

            <router-link :to="'/node/'+node.nodeId" class="nav-link mnl-nav-link" :title="node.nodeName">
              {{node.nodeName}}
            </router-link>

        <el-tooltip effect="dark" content="设置" placement="right" :disabled="!isMini">
          <a class="nav-link ls-nav-link" :href="`//${targetHostname}/user/profile`" target="_blank">

            设置

        </el-tooltip>

</template>


Replace previous state when commitment has been deleted.

<template>
    <v-layout row justify-center>
        <v-dialog v-model="dialog" scrollable persistent max-width="400px">
            <v-card>
                <v-card-title>
                    {{$t("pages:detailCommitment.deleteDialog.title")}}
                </v-card-title>
                <v-divider></v-divider>
                <v-card-text>

                </v-card-text>
                <v-divider></v-divider>
                <v-card-actions>
                    <v-spacer></v-spacer>
                    <v-btn color="primary" flat @click.native="$emit('close-dialog')" :disabled="running">
                        {{$t("common:button.abort")}}
                    </v-btn>
                    <v-btn color="primary" @click.native="deleteCommitment()"
                           :loading="running" :disabled="running">
                        {{$t("pages:detailCommitment.deleteDialog.deleteCommitmentButton")}}
                    </v-btn>
                </v-card-actions>
            </v-card>
        </v-dialog>
        <v-snackbar top v-model="showError" color="error" :timeout="0">{{$t("common:error.unknown")}}
            <v-btn dark flat @click="showError = false">{{$t("common:button.close")}}</v-btn>
        </v-snackbar>
    </v-layout>
</template>


stash

stash

<template>
  <btn type="primary" @click="click" :disabled="isDisabled">
    <slot></slot>
  </btn>
  <req v-ref:req :url="url" :method="method"></req>
</template>

<script>

  import Btn from 'vux/components/x-button'
  import Req from './Req.vue';
  var _ = require('underscore');

  export default {
    name: 'AjaxBtn',
    props: {
      url: {
        type: String,
        required: true
      },
      method: {
        type: String,
        default: 'get'
      },
      data: {
        type: Object,
        default: function(){
          return {};
        }
      }
    },
    components: {
      Btn, Req
    },
    data: function () {
      return {
        isDisabled:false,
        loading: {
          show: false
        }
      };

    },
    methods: {

      click(){

        var _this = this;

        if(this.isDisabled) return;

        var data = this.data;

        var params = {};
        if (!this.$dispatch('before', params)) return;

        data = _.extend(data, params);

        this.isDisabled = true;
        this.$refs.req.send(data,function(res){
          _this.isDisabled = false;
          return _this.$dispatch('after', res);
        });

        return true;

      }

    },
    events: {
    }

  }

</script>

<style>
</style>

<template>
  <btn type="primary" @click="click" :disabled="isDisabled">
    <slot></slot>
  </btn>
  <req v-ref:req :url="url" :method="method"></req>
</template>

<script>

  import Btn from 'vux/components/button'
  import Req from './Req.vue';
  var _ = require('underscore');

  export default {
    name: 'AjaxBtn',
    props: {
      url: {
        type: String,
        required: true
      },
      method: {
        type: String,
        default: 'get'
      },
      data: {
        type: Object,
        default: function(){
          return {};
        }
      }
    },
    components: {
      Btn, Req
    },
    data: function () {
      return {
        isDisabled:false,
        loading: {
          show: false
        }
      };

    },
    methods: {

      click(){

        var _this = this;

        if(this.isDisabled) return;

        var data = this.data;

        var params = {};
        if (!this.$dispatch('before', params)) return;

        data = _.extend(data, params);

        this.isDisabled = true;
        this.$refs.req.send(data,function(res){
          _this.isDisabled = false;
          return _this.$dispatch('after', res);
        });

        return true;

      }

    },
    events: {
    }

  }

</script>

<style>
</style>


update

update

<template>

        2015-07
        2015-04

                {{tab}}

                        <input v-model="search" type="text" placeholder="Search..." debounce="300">

                <item
                    v-for="item in items"
                    :item="item"
                ></item>

</template>


updated to process NTU modules and exam duration

<template>

      {{ module.code }}
      {{ module.title }}
      {{ module.credit }}
      {{ readableDateTime }}
({{ readableDuration }})

        <button class="action__button" @click="deleteModule(module)">
          <svg><use xlink:href="#delete"/></svg>
        </button>
        <button class="action__button"
            @click="setIsPainting()"
            :class="toggleClass(isChoosingColor, 'action__button')">
          <svg><use xlink:href="#paint"/></svg>
        </button>
        <button class="action__button"
            @click="toggleInfo()"
            :class="toggleClass(showMoreInfo, 'action__button')">
          <svg><use xlink:href="#info"/></svg>
        </button>
        <mod-change-color @click="setIsPainting()"
        v-if="isChoosingColor" :module="module" transition="color"></mod-change-color>

Description:

{{ module.description }}

Availability:

{{ module.availability }}

Remarks:

{{ module.remarks }}

None

Prerequisite:

{{ module.prerequisite }}

None

Preclusion:

{{ module.preclusion }}

None

</template>

<template>

      {{ module.code }}
      {{ module.title }}
      {{ module.credit }}
      {{ readableDateTime }}

        <button class="action__button" @click="deleteModule(module)">
          <svg><use xlink:href="#delete"/></svg>
        </button>
        <button class="action__button"
            @click="setIsPainting()"
            :class="toggleClass(isChoosingColor, 'action__button')">
          <svg><use xlink:href="#paint"/></svg>
        </button>
        <button class="action__button"
            @click="toggleInfo()"
            :class="toggleClass(showMoreInfo, 'action__button')">
          <svg><use xlink:href="#info"/></svg>
        </button>
        <mod-change-color @click="setIsPainting()"
        v-if="isChoosingColor" :module="module" transition="color"></mod-change-color>

Description:

{{ module.description }}

Availability:

{{ module.availability }}

Remarks:

{{ module.remarks }}

None

Prerequisite:

{{ module.prerequisite }}

None

Preclusion:

{{ module.preclusion }}

None

</template>


deprecate

deprecate

<template>
    <v-container v-if="pokemonHide == false">
        <v-layout row wrap class="details">
                <v-flex xs12 md8>

{{pokemonData.id}} {{pokemonData.name | capitalize}}

The {{getGenera()}}

                        <v-chip v-for="pokemonDetail in pokemonDetails.types" v-bind:key="pokemonDetail.id">{{pokemonDetail.type.name | capitalize}} Type</v-chip>

                </v-flex>
                <v-flex xs12 md2>

                </v-flex>
        </v-layout>
        <v-layout row wrap>
                <v-flex xs12>

Flavour Text

                            <v-btn dark v-for="version in versions.results" v-bind:key="version.name" v-on:click="changeVersion(version.name)" v-bind:class="[version.name, btnClass]">{{version.name | capitalize}}</v-btn>

{{getFlavourText(version)}}

Base Stats

{{pokemonDetail.stat.name | capitalize }} : {{pokemonDetail.base_stat}}

Base Experience: {{pokemonDetails.base_experience}}

                </v-flex>
        </v-layout>
    </v-container>
</template>


add qsData

add qsData

<template>

    < 返回

{{item.title}}

      404 Not Found

</template>


Fix date issues in new event card

Fix date issues in new event card

<template>

{{calendar_event.title | truncate(33)}}

{{venue_info.name}}<ii-location iconColor="#B7B09C" width="12" height="12" />

{{when_date}}

{{when_time}}

{{calendar_event.brief_description | truncate(90)}}

            More Info
            <ii-calendar iconColor="#fff" width="17" height="17" class="ii-calendar"/>Add to Calendar

iCal

Outlook

Google Cal

</template>


Fix bug

Fix bug

<template>
<div class="mkw-messaging">
	<mk-widget-container :show-header="props.design == 0">
		<template slot="header">%fa:comments%%i18n:@title%</template>

		<mk-messaging ref="index" compact @navigate="navigate"/>
	</mk-widget-container>
</div>
</template>

<script lang="ts">
import define from '../../../common/define-widget';
import MkMessagingRoomWindow from '../components/messaging-room-window.vue';

export default define({
	name: 'messaging',
	props: () => ({
		design: 0
	})
}).extend({
	methods: {
		navigate(user) {
			(this as any).os.new(MkMessagingRoomWindow, {
				user: user
			});
		},
		func() {
			if (this.props.design == 1) {
				this.props.design = 0;
			} else {
				this.props.design++;
			}
		}
	}
});
</script>

<style lang="stylus" scoped>
.mkw-messaging
	.mk-messaging
		max-height 250px
		overflow auto

</style>

<template>
<div class="mkw-messaging">
	<mk-widget-container :show-header="props.design == 0">
		<template slot="header">%fa:comments%%i18n:@title%</template>

		<mk-messaging ref="index" compact @navigate="navigate"/>
	</mk-widget-container>
</div>
</template>

<script lang="ts">
import define from '../../../common/define-widget';
import MkMessagingRoomWindow from '../components/messaging-room-window.vue';

export default define({
	name: 'messaging',
	props: () => ({
		design: 0
	})
}).extend({
	methods: {
		navigate(user) {
			(this as any).os.new(MkMessagingRoomWindow, {
				user: user
			});
		},
		func() {
			if (this.props.design == 1) {
				this.props.design = 0;
			} else {
				this.props.design++;
			}
		}
	}
});
</script>

<style lang="stylus" scoped>
.mkw-messaging
	> .mk-messaging
		max-height 250px
		overflow auto

</style>


Added source service on autocomplete

Added source service on autocomplete

<template>
  <q-search v-model="selection">
    <q-autocomplete @search="onSearch" @selected="onSelected" />
  </q-search>
</template>

<script>
import _ from 'lodash'
import { QSearch, QAutocomplete } from 'quasar'

export default {
  name: 'k-autocomplete',
  components: {
    QSearch,
    QAutocomplete
  },
  props: {
    services: {
      type: Array,
      required: true
    },
    processResults: {
      type: Function
    }
  },
  data () {
    return {
      selection: null
    }
  },
  methods: {
    onSearch (pattern, done) {
      // Perform request for partial match to all registered services
      const requests = this.services.map(item => {
        const service = this.$api.getService(item.service)
        // build the query using given templet if any
        let query = Object.assign({}, item.baseQuery)
        // Then add partial match
        // We don't use set by dot here because Mongo queries on nested fields
        // require the key to contain the path and not nested objects
        //_.set(query, item.field, { $search: pattern })
        query[item.field] = { $search: pattern }
        return service.find({ query })
      })
      Promise.all(requests).then(responses => {
        let results = []
        for (let i = 0; i < responses.length; i++) {
          const response = responses[i]
          const item = this.services[i]
          if (response.total > 0) {
            response.data.forEach(result => {
              Object.assign(result, {
                label: _.get(result, item.field),
                value: _.get(result, item.field),
                service: item.service
              })
              // If this type of item has an icon
              if (item.iconField) {
                // Use object icon if provided, otherwise service-level icon
                result.icon = _.get(result, item.iconField) || item.icon
              } else {
                // Use service-level icon
                result.icon = item.icon
              }
              results.push(result)
            })
          }
        }
        if (this.processResults) {
          this.processResults(pattern, results)
        }
        done(results)
      })
    },
    onSelected (item) {
      this.$emit('item-selected', item)
    }
  }
}
</script>

<template>
  <q-search v-model="selection">
    <q-autocomplete @search="onSearch" @selected="onSelected" />
  </q-search>
</template>

<script>
import _ from 'lodash'
import { QSearch, QAutocomplete } from 'quasar'

export default {
  name: 'k-autocomplete',
  components: {
    QSearch,
    QAutocomplete
  },
  props: {
    services: {
      type: Array,
      required: true
    },
    processResults: {
      type: Function
    }
  },
  data () {
    return {
      selection: null
    }
  },
  methods: {
    onSearch (pattern, done) {
      // Perform request for partial match to all registered services
      const requests = this.services.map(item => {
        const service = this.$api.getService(item.service)
        // build the query using given templet if any
        let query = Object.assign({}, item.baseQuery)
        // Then add partial match
        // We don't use set by dot here because Mongo queries on nested fields
        // require the key to contain the path and not nested objects
        //_.set(query, item.field, { $search: pattern })
        query[item.field] = { $search: pattern }
        return service.find({ query })
      })
      Promise.all(requests).then(responses => {
        let results = []
        for (let i = 0; i < responses.length; i++) {
          const response = responses[i]
          const service = this.services[i]
          if (response.total > 0) {
            response.data.forEach(result => {
              Object.assign(result, {
                label: _.get(result, service.field),
                value: _.get(result, service.field)
              })
              // If this type of item has an icon
              if (service.iconField) {
                // Use object icon if provided, otherwise service-level icon
                result.icon = _.get(result, service.iconField) || service.icon
              } else {
                // Use service-level icon
                result.icon = service.icon
              }
              results.push(result)
            })
          }
        }
        if (this.processResults) {
          this.processResults(pattern, results)
        }
        done(results)
      })
    },
    onSelected (item) {
      this.$emit('item-selected', item)
    }
  }
}
</script>


school updates

school updates

<template>

 0">
                <svg class="icon icon-school"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-school"></use></svg>

Your ELEMENTARY school 1">s {{ elementary.length > 1 ? 'are' : 'is' }}

                <template v-for="(item, index) in elementary">

{{item.name.toUpperCase()}}

{{item.grade_level}}

                        {{item.address}}

{{ item.distance | distance }}

                </template>

 0">
                    <svg class="icon icon-school"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-school"></use></svg>

Your MIDDLE school 1">s {{ middle.length > 1 ? 'are' : 'is' }}

                    <template v-for="(item, index) in middle">

{{item.name.toUpperCase()}}

{{item.grade_level}}

                            {{item.address}}

{{ item.distance | distance }}

                    </template>

 0">
                    <svg class="icon icon-school"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-school"></use></svg>

Your HIGH school 1">s {{ high.length > 1 ? 'are' : 'is' }}

                    <template v-for="(item, index) in high">

{{item.name.toUpperCase()}}

{{item.grade_level}}

                            {{item.address}}

{{ item.distance | distance }}

                    </template>

                <svg class="icon icon-bus"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-bus"></use></svg>

Your Transportation Zone is

{{zone}}

Magnet Schools

                        School
                        Address
                        Grades
                        Distance

                            {{item.name}}{{ item.num | getAsterik }}

                                    {{item.address}}, {{item.city}}

                          {{item.grade_level}}

                            {{ item.distance | distance }}

                Transportation eligibility is determined by the transportation zone in which you live. The county is divided into three transportation zones: violet, blue and green. Magnet schools are assigned a zone to serve with transportation. If the distance
                is to the magnet greater than 5 miles, you may be assigned to a shuttle stop location. Some programs (*) provide county-wide transportation, meaning that regardless of your zone, you would receive transportation. For more information please
                contact Charlotte-Mecklenburg School Transportation Services at (980) 343-6715.

For more information, please visit:

Charlotte-Mecklenburg Schools

</template>

<template>

 0">
                <svg class="icon icon-school"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-school"></use></svg>

Your ELEMENTARY school is

{{resultsElementary[0].name.toUpperCase()}}

                        {{resultsElementary[0].address}}

{{ resultsElementary[0].dist | distance }}

 0">
                    <svg class="icon icon-school"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-school"></use></svg>

Your MIDDLE school is

{{resultsMiddle[0].name.toUpperCase()}}

                            {{resultsMiddle[0].address}}

{{ resultsMiddle[0].dist | distance }}

 0">
                    <svg class="icon icon-school"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-school"></use></svg>

Your HIGH school is

{{resultsHigh[0].name.toUpperCase()}}

                            {{resultsHigh[0].address}}

{{ resultsHigh[0].dist | distance }}

 0">
                <svg class="icon icon-bus"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-bus"></use></svg>

Your Transportation Zone is

{{tmpTransportationZone[0].choicezn.toUpperCase()}}

Magnet Schools

                        School
                        Address
                        Distance

                            {{item.schlname}}{{ item.schl | getAsterik }}

                                    {{item.address}}, {{item.city}}

                            {{ item.distance | distance }}

                Transportation eligibility is determined by the transportation zone in which you live. The county is divided into three transportation zones: violet, blue and green. Magnet schools are assigned a zone to serve with transportation. If the distance
                is to the magnet greater than 5 miles, you may be assigned to a shuttle stop location. Some programs (*) provide county-wide transportation, meaning that regardless of your zone, you would receive transportation. For more information please
                contact Charlotte-Mecklenburg School Transportation Services at (980) 343-6715.

For more information, please visit:

Charlotte-Mecklenburg Schools

</template>


repopulate AposSchema when the schema itself changes, prevents crashes when switching panes

<!--
  AposSchema takes an array of fields with their values, renders their inputs, and emits their `input` events
-->
<template>
  <div class="apos-schema">
    <div
      v-for="field in schema" :key="field.name"
      :data-apos-field="field.name"
    >
      <component
        v-show="displayComponent(field.name)"
        v-model="fieldState[field.name]"
        :following-values="followingValues[field.name]"
        :is="fieldComponentMap[field.type]"
        :field="fields[field.name].field"
        :modifiers="fields[field.name].modifiers"
        :display-options="displayOptions"
        :trigger-validation="triggerValidation"
        :server-error="fields[field.name].serverError"
        :doc-id="docId"
        :ref="field.name"
      />
    </div>
  </div>
</template>

<script>
import { detectFieldChange } from 'Modules/@apostrophecms/schema/lib/detectChange';

export default {
  name: 'AposSchema',
  props: {
    value: {
      type: Object,
      required: true
    },
    schema: {
      type: Array,
      required: true
    },
    currentFields: {
      type: Array,
      default() {
        return [];
      }
    },
    followingValues: {
      type: Object,
      default() {
        return {};
      }
    },
    modifiers: {
      type: Array,
      default() {
        return [];
      }
    },
    triggerValidation: Boolean,
    utilityRail: Boolean,
    docId: {
      type: String,
      default() {
        return null;
      }
    },
    serverErrors: {
      type: Object,
      default() {
        return null;
      }
    },
    displayOptions: {
      type: Object,
      default() {
        return {};
      }
    }
  },
  emits: [ 'input', 'reset' ],
  data() {
    return {
      schemaReady: false,
      next: {
        hasErrors: false,
        data: {}
      },
      fieldState: {},
      fieldComponentMap: window.apos.schema.components.fields || {}
    };
  },
  computed: {
    fields() {
      const fields = {};
      this.schema.forEach(item => {
        fields[item.name] = {};
        fields[item.name].field = item;
        fields[item.name].value = {
          data: this.value[item.name]
        };
        fields[item.name].serverError = this.serverErrors && this.serverErrors[item.name];
        fields[item.name].modifiers = this.modifiers;
      });
      return fields;
    }
  },
  watch: {
    fieldState: {
      deep: true,
      handler() {
        this.updateNextAndEmit();
      }
    },
    schema() {
      this.populateDocData();
    },
    value: {
      deep: true,
      handler(newVal, oldVal) {
        // The doc might be swapped out completely in cases such as the media
        // library editor. Repopulate the fields if that happens.
        if (
          // If the fieldState had been cleared and there's new populated data
          (!this.fieldState._id && newVal.data._id) ||
          // or if there *is* active fieldState, but the new data is a new doc
          (this.fieldState._id && newVal.data._id !== this.fieldState._id.data)
        ) {
          // repopulate the schema.
          this.populateDocData();
        }
      }
    }
  },
  created() {
    this.populateDocData();
  },
  methods: {
    populateDocData() {
      this.schemaReady = false;
      const next = {
        hasErrors: false,
        data: {}
      };

      const fieldState = {};

      // Though not in the schema, keep track of the _id field.
      if (this.value.data._id) {
        next.data._id = this.value.data._id;
        fieldState._id = { data: this.value.data._id };
      }

      this.schema.forEach(field => {
        const value = this.value.data[field.name];
        fieldState[field.name] = {
          error: false,
          data: (value === undefined) ? field.def : value
        };
        next.data[field.name] = fieldState[field.name].data;
      });
      this.next = next;
      this.fieldState = fieldState;

      // Wait until the next tick so the parent editor component is done
      // updating. This is only really a concern in editors that can swap
      // the active doc/object without unmounting AposSchema.
      this.$nextTick(() => {
        this.schemaReady = true;
        // Signal that the schema data is ready to be tracked.
        this.$emit('reset');
      });
    },
    updateNextAndEmit() {
      if (!this.schemaReady) {
        return;
      }

      const oldHasErrors = this.next.hasErrors;
      this.next.hasErrors = false;
      let changeFound = false;

      this.schema.forEach(field => {
        if (this.fieldState[field.name].error) {
          this.next.hasErrors = true;
        }
        if (
          this.fieldState[field.name].data !== undefined &&
          detectFieldChange(field, this.next.data[field.name], this.fieldState[field.name].data)
        ) {
          changeFound = true;
          this.next.data[field.name] = this.fieldState[field.name].data;
        } else {
          this.next.data[field.name] = this.value.data[field.name];
        }
      });
      if (oldHasErrors !== this.next.hasErrors) {
        // Otherwise the save button may never unlock
        changeFound = true;
      }

      if (changeFound) {
        // ... removes need for deep watch at parent level
        this.$emit('input', { ...this.next });
      }
    },
    displayComponent(fieldName) {
      return this.currentFields.length ? this.currentFields.includes(fieldName) : true;
    },
    scrollFieldIntoView(fieldName) {
      // The refs for a name are an array if that ref was assigned
      // in a v-for. We know there is only one in this case
      // https://forum.vuejs.org/t/this-refs-theid-returns-an-array/31995/9
      this.$refs[fieldName][0].$el.scrollIntoView();
    }
  }
};
</script>

<style lang="scss" scoped>
  .apos-field {
    .apos-schema /deep/ & {
      margin-bottom: $spacing-triple;
      &.apos-field--micro {
        margin-bottom: $spacing-double;
      }
    }

    .apos-schema /deep/ .apos-toolbar & {
      margin-bottom: 0;
    }
  }
</style>

<!--
  AposSchema takes an array of fields with their values, renders their inputs, and emits their `input` events
-->
<template>
  <div class="apos-schema">
    <div
      v-for="field in schema" :key="field.name"
      :data-apos-field="field.name"
    >
      <component
        v-show="displayComponent(field.name)"
        v-model="fieldState[field.name]"
        :following-values="followingValues[field.name]"
        :is="fieldComponentMap[field.type]"
        :field="fields[field.name].field"
        :modifiers="fields[field.name].modifiers"
        :display-options="displayOptions"
        :trigger-validation="triggerValidation"
        :server-error="fields[field.name].serverError"
        :doc-id="docId"
        :ref="field.name"
      />
    </div>
  </div>
</template>

<script>
import { detectFieldChange } from 'Modules/@apostrophecms/schema/lib/detectChange';

export default {
  name: 'AposSchema',
  props: {
    value: {
      type: Object,
      required: true
    },
    schema: {
      type: Array,
      required: true
    },
    currentFields: {
      type: Array,
      default() {
        return [];
      }
    },
    followingValues: {
      type: Object,
      default() {
        return {};
      }
    },
    modifiers: {
      type: Array,
      default() {
        return [];
      }
    },
    triggerValidation: Boolean,
    utilityRail: Boolean,
    docId: {
      type: String,
      default() {
        return null;
      }
    },
    serverErrors: {
      type: Object,
      default() {
        return null;
      }
    },
    displayOptions: {
      type: Object,
      default() {
        return {};
      }
    }
  },
  emits: [ 'input', 'reset' ],
  data() {
    return {
      schemaReady: false,
      next: {
        hasErrors: false,
        data: {}
      },
      fieldState: {},
      fieldComponentMap: window.apos.schema.components.fields || {}
    };
  },
  computed: {
    fields() {
      const fields = {};
      this.schema.forEach(item => {
        fields[item.name] = {};
        fields[item.name].field = item;
        fields[item.name].value = {
          data: this.value[item.name]
        };
        fields[item.name].serverError = this.serverErrors && this.serverErrors[item.name];
        fields[item.name].modifiers = this.modifiers;
      });
      return fields;
    }
  },
  watch: {
    fieldState: {
      deep: true,
      handler() {
        this.updateNextAndEmit();
      }
    },
    value: {
      deep: true,
      handler(newVal, oldVal) {
        // The doc might be swapped out completely in cases such as the media
        // library editor. Repopulate the fields if that happens.
        if (
          // If the fieldState had been cleared and there's new populated data
          (!this.fieldState._id && newVal.data._id) ||
          // or if there *is* active fieldState, but the new data is a new doc
          (this.fieldState._id && newVal.data._id !== this.fieldState._id.data)
        ) {
          // repopulate the schema.
          this.populateDocData();
        }
      }
    }
  },
  created() {
    this.populateDocData();
  },
  methods: {
    populateDocData() {
      this.schemaReady = false;
      const next = {
        hasErrors: false,
        data: {}
      };

      const fieldState = {};

      // Though not in the schema, keep track of the _id field.
      if (this.value.data._id) {
        next.data._id = this.value.data._id;
        fieldState._id = { data: this.value.data._id };
      }

      this.schema.forEach(field => {
        const value = this.value.data[field.name];
        fieldState[field.name] = {
          error: false,
          data: (value === undefined) ? field.def : value
        };
        next.data[field.name] = fieldState[field.name].data;
      });
      this.next = next;
      this.fieldState = fieldState;

      // Wait until the next tick so the parent editor component is done
      // updating. This is only really a concern in editors that can swap
      // the active doc/object without unmounting AposSchema.
      this.$nextTick(() => {
        this.schemaReady = true;
        // Signal that the schema data is ready to be tracked.
        this.$emit('reset');
      });
    },
    updateNextAndEmit() {
      if (!this.schemaReady) {
        return;
      }

      const oldHasErrors = this.next.hasErrors;
      this.next.hasErrors = false;
      let changeFound = false;

      this.schema.forEach(field => {
        if (this.fieldState[field.name].error) {
          this.next.hasErrors = true;
        }
        if (
          this.fieldState[field.name].data !== undefined &&
          detectFieldChange(field, this.next.data[field.name], this.fieldState[field.name].data)
        ) {
          changeFound = true;
          this.next.data[field.name] = this.fieldState[field.name].data;
        } else {
          this.next.data[field.name] = this.value.data[field.name];
        }
      });
      if (oldHasErrors !== this.next.hasErrors) {
        // Otherwise the save button may never unlock
        changeFound = true;
      }

      if (changeFound) {
        // ... removes need for deep watch at parent level
        this.$emit('input', { ...this.next });
      }
    },
    displayComponent(fieldName) {
      return this.currentFields.length ? this.currentFields.includes(fieldName) : true;
    },
    scrollFieldIntoView(fieldName) {
      // The refs for a name are an array if that ref was assigned
      // in a v-for. We know there is only one in this case
      // https://forum.vuejs.org/t/this-refs-theid-returns-an-array/31995/9
      this.$refs[fieldName][0].$el.scrollIntoView();
    }
  }
};
</script>

<style lang="scss" scoped>
  .apos-field {
    .apos-schema /deep/ & {
      margin-bottom: $spacing-triple;
      &.apos-field--micro {
        margin-bottom: $spacing-double;
      }
    }

    .apos-schema /deep/ .apos-toolbar & {
      margin-bottom: 0;
    }
  }
</style>


Add task status icons

Add task status icons

<template>

      <mat-svg
        v-if="!taskHasFailed"
        category="action"
        name="autorenew"
        class="inprogress"
      />
      <mat-svg
        v-else
        category="alert"
        name="error"
        class="error"
      />

        {{ stageText }}

      <ui-progress-linear
        class="progress-linear"
        :progress="formattedPercentage"
        :type="progressBarType"
        color="primary"
      />

      {{ progressMessage }}

      <k-button
        :text="status==='COMPLETED' ? $tr('close') : $tr('cancel')"
        :primary="false"
        :raised="false"
        @click="cancelTaskHandler()"
      />

</template>

<template>

        {{ stageText }}

      <ui-progress-linear
        class="progress-linear"
        :progress="formattedPercentage"
        :type="progressBarType"
        color="primary"
      />

      {{ progressMessage }}

      <k-button
        :text="status==='COMPLETED' ? $tr('close') : $tr('cancel')"
        :primary="false"
        :raised="false"
        @click="cancelTaskHandler()"
      />

</template>


Add validation rules to threshold field

Add validation rules to threshold field

<template>

            <fieldset>
                <legend></legend>
            </fieldset>

                        <control-group labelMessageKey="perfTest.config.agent" ref="agentCountControlGroup">
                            <input-append name="agentCount" ref="agentCount"
                                          v-model="test.agentCount"
                                          @validationResult="$refs.agentCountControlGroup.handleError($event)"
                                          :validationRules="agentCountValidationRules"
                                          errStyle="width: 145px; word-break: break-all; white-space: normal;"
                                          appendPrefix="perfTest.config.max"
                                          :append="maxAgentCount"
                                          message="perfTest.config.agent">
                            </input-append>
                        </control-group>

                        <control-group ref="regionControlGroup" labelMessageKey="perfTest.config.region" labelHelpMessageKey="perfTest.config.region" labelStyle="margin-left: -50px; width: 80px;">
                            <select2 name="region" ref="region" v-model="test.region" @change="changeMaxAgentCount" class="pull-right required" customStyle="width: 110px;"
                                     :validationRules="{ required: true }" @validationResult="$refs.regionControlGroup.handleError($event)">
                                <option v-for="region in ngrinder.config.visibleRegions" :value="region" :selected="region === test.region" v-text="region"></option>
                            </select2>
                        </control-group>

                <control-group labelMessageKey="perfTest.config.vuserPerAgent" ref="vuserPerAgentControlGroup" dataStep="5" :dataIntro="i18n('intro.config.basic.vuser')">
                    <input-append name="vuserPerAgent" ref="vuserPerAgent"
                                  v-model="test.vuserPerAgent"
                                  @validationResult="$refs.vuserPerAgentControlGroup.handleError($event)"
                                  :validationRules="{ required: true, max_value: config.maxVuserPerAgent, min_value: 1 }"
                                  @change="changeVuserPerAgent"
                                  errStyle="margin: 0; width: 140px;"
                                  appendPrefix="perfTest.config.max"
                                  :append="config.maxVuserPerAgent"
                                  message="perfTest.config.vuserPerAgent">
                    </input-append>

                    <transition name="fade">

                            <input-prepend name="processes" v-model="test.processes"
                                           @change="changeProcessThreadCount"
                                           message="perfTest.config.process" extraCss="control-group">
                            </input-prepend>
                            <input-prepend name="threads" v-model="test.threads"
                                           @change="changeProcessThreadCount"
                                           message="perfTest.config.thread" extraCss="control-group">
                            </input-prepend>

                    </transition>
                </control-group>

                <control-group labelMessageKey="perfTest.config.script" ref="scriptNameControlGroup">
                    <select2 v-model="test.scriptName" name="scriptName" ref="scriptName" customStyle="width: 275px;" :option="{placeholder: i18n('perfTest.config.scriptInput')}"
                             :validationRules="{ required: true, scriptValidation: true }" @validationResult="$refs.scriptNameControlGroup.handleError($event)" errStyle="position: absolute;">
                        <option value=""></option>
                        <option v-for="script in scripts" :data-validate="script.validated" v-text="script.pathInShort" :value="script.path"></option>
                    </select2>
                    <input type="hidden" name="scriptRevision" :value="test.scriptRevision">
                    <button class="btn btn-mini btn-info pull-right btn-script-revision" type="button">
                        R

                    </button>
                </control-group>

                <control-group labelMessageKey="perfTest.config.scriptResources">

                </control-group>

                <control-group labelMessageKey="perfTest.config.targetHost">

                    <input type="hidden" name="targetHosts" :value="targetHost.join(',')">
                </control-group>

                    <control-group :class="{error: errors.has('duration')}" :radio="{radioValue: 'D', checked: test.threshold === 'D'}" v-model="test.threshold"
                                   ref="thresholdControlGroup" labelMessageKey="perfTest.config.duration" name="threshold" id="duration">
                        <select class="select-item" id="select_hour" v-model="duration.hour" @change="changeDuration(true)">
                            <option v-for="(v, h) in 8" :value="h" v-text="h"></option>
                        </select> :
                        <select class="select-item" id="select_min" v-model="duration.min" @change="changeDuration(true)">
                            <option v-for="(v, m) in 60" :value="m" v-text="m < 10 ? `0${m}` : m"></option>
                        </select> :
                        <select class="select-item" id="select_sec" v-model="duration.sec" @change="changeDuration(true)">
                            <option v-for="(v, s) in 60" :value="s" v-text="s < 10 ? `0${s}` : s"></option>
                        </select>
                        HH:MM:SS
                        <input v-validate="{min_value: test.threshold === 'D' ? 1 : 0}" type="hidden" name="duration" v-model="durationMilliSeconds"/>
                        <vue-slider ref="durationSlider" @callback="changeDurationSlider" v-model="durationSeconds" width="278" :max="28799" tooltip="none"></vue-slider>

                    </control-group>

                    <control-group :radio="{radioValue: 'R', checked: test.threshold === 'R'}" v-model="test.threshold" labelMessageKey="perfTest.config.runCount" ref="runCountControlGroup" name="threshold" id="runCount">
                        <input-append name="runCount" ref="runCount"
                                      appendPrefix="perfTest.config.max"
                                      :append="config.maxRunCount"
                                      @validationResult="$refs.runCountControlGroup.handleError($event)"
                                      :validationRules="{required: true, max_value: config.maxRunCount, min_value: test.threshold === 'R' ? 1 : 0}"
                                      v-model="test.runCount"
                                      @focus="test.threshold = 'R'"
                                      message="perfTest.config.runCount">
                        </input-append>
                    </control-group>

                <transition name="fade">

                                <control-group name="samplingInterval" labelMessageKey="perfTest.config.samplingInterval">
                                    <select class="select-item" id="sampling_interval"
                                            name="samplingInterval" v-model="test.samplingInterval">
                                        <option v-for="interval in samplingIntervals" :value="interval" v-text="interval"></option>
                                    </select>
                                </control-group>

                                <control-group name="ignoreSampleCount" ref="ignoreSampleCountControlGroup" labelStyle="width: 150px;" labelMessageKey="perfTest.config.ignoreSampleCount">
                                    <input-popover v-model="test.ignoreSampleCount"
                                                   ref="ignoreSampleCount"
                                                   @validationResult="$refs.ignoreSampleCountControlGroup.handleError($event)"
                                                   :validationRules="{ numeric: true }"
                                                   dataPlacement="top"
                                                   errStyle="margin-left: -120px;"
                                                   name="ignoreSampleCount"
                                                   message="perfTest.config.ignoreSampleCount" extraCss="input-mini">
                                    </input-popover>
                                </control-group>

                                <control-group name="safeDistribution" labelMessageKey="perfTest.config.safeDistribution" labelHelpMessageKey="perfTest.config.safeDistribution">
                                    <input type="checkbox" name="safeDistribution" :checked="test.safeDistribution">
                                </control-group>

                                <control-group name="param" labelMessageKey="perfTest.config.param" controlsStyle="margin-left: 85px;"
                                               labelStyle="width: 70px;" ref="paramControlGroup">
                                    <input-popover name="param"
                                                   ref="param"
                                                   @validationResult="$refs.paramControlGroup.handleError($event)"
                                                   :validationRules="{ regex: /^[a-zA-Z0-9_\.,\|=]{0,50}$/ }"
                                                   dataPlacement="top"
                                                   v-model="test.param"
                                                   message="perfTest.config.param"
                                                   customStyle="width: 125px;">
                                    </input-popover>
                                </control-group>

                </transition>

        <ramp-up ref="rampUp" :test="test" :rampUpTypes="config.rampUpTypes"></ramp-up>
        <host-modal ref="addHostModal" @add-host="addHost"></host-modal>
        <target-host-info-modal ref="targetHostInfoModal" :ip="targetHostIp"></target-host-info-modal>

</template>

<template>

            <fieldset>
                <legend></legend>
            </fieldset>

                        <control-group labelMessageKey="perfTest.config.agent" ref="agentCountControlGroup">
                            <input-append name="agentCount" ref="agentCount"
                                          v-model="test.agentCount"
                                          @validationResult="$refs.agentCountControlGroup.handleError($event)"
                                          :validationRules="agentCountValidationRules"
                                          errStyle="width: 145px; word-break: break-all; white-space: normal;"
                                          appendPrefix="perfTest.config.max"
                                          :append="maxAgentCount"
                                          message="perfTest.config.agent">
                            </input-append>
                        </control-group>

                        <control-group ref="regionControlGroup" labelMessageKey="perfTest.config.region" labelHelpMessageKey="perfTest.config.region" labelStyle="margin-left: -50px; width: 80px;">
                            <select2 name="region" ref="region" v-model="test.region" @change="changeMaxAgentCount" class="pull-right required" customStyle="width: 110px;"
                                     :validationRules="{ required: true }" @validationResult="$refs.regionControlGroup.handleError($event)">
                                <option v-for="region in ngrinder.config.visibleRegions" :value="region" :selected="region === test.region" v-text="region"></option>
                            </select2>
                        </control-group>

                <control-group labelMessageKey="perfTest.config.vuserPerAgent" ref="vuserPerAgentControlGroup" dataStep="5" :dataIntro="i18n('intro.config.basic.vuser')">
                    <input-append name="vuserPerAgent" ref="vuserPerAgent"
                                  v-model="test.vuserPerAgent"
                                  @validationResult="$refs.vuserPerAgentControlGroup.handleError($event)"
                                  :validationRules="{ required: true, max_value: config.maxVuserPerAgent, min_value: 1 }"
                                  @change="changeVuserPerAgent"
                                  errStyle="margin: 0; width: 140px;"
                                  appendPrefix="perfTest.config.max"
                                  :append="config.maxVuserPerAgent"
                                  message="perfTest.config.vuserPerAgent">
                    </input-append>

                    <transition name="fade">

                            <input-prepend name="processes" v-model="test.processes"
                                           @change="changeProcessThreadCount"
                                           message="perfTest.config.process" extraCss="control-group">
                            </input-prepend>
                            <input-prepend name="threads" v-model="test.threads"
                                           @change="changeProcessThreadCount"
                                           message="perfTest.config.thread" extraCss="control-group">
                            </input-prepend>

                    </transition>
                </control-group>

                <control-group labelMessageKey="perfTest.config.script" ref="scriptNameControlGroup">
                    <select2 v-model="test.scriptName" name="scriptName" ref="scriptName" customStyle="width: 275px;" :option="{placeholder: i18n('perfTest.config.scriptInput')}"
                             :validationRules="{ required: true, scriptValidation: true }" @validationResult="$refs.scriptNameControlGroup.handleError($event)" errStyle="position: absolute;">
                        <option value=""></option>
                        <option v-for="script in scripts" :data-validate="script.validated" v-text="script.pathInShort" :value="script.path"></option>
                    </select2>
                    <input type="hidden" name="scriptRevision" :value="test.scriptRevision">
                    <button class="btn btn-mini btn-info pull-right btn-script-revision" type="button">
                        R

                    </button>
                </control-group>

                <control-group labelMessageKey="perfTest.config.scriptResources">

                </control-group>

                <control-group labelMessageKey="perfTest.config.targetHost">

                    <input type="hidden" name="targetHosts" :value="targetHost.join(',')">
                </control-group>

                    <control-group :radio="{radioValue: 'D', checked: test.threshold === 'D'}" v-model="test.threshold" labelMessageKey="perfTest.config.duration" name="threshold" id="duration">
                        <select class="select-item" id="select_hour" v-model="duration.hour" @change="changeDuration(true)">
                            <option v-for="(v, h) in 8" :value="h" v-text="h"></option>
                        </select> :
                        <select class="select-item" id="select_min" v-model="duration.min" @change="changeDuration(true)">
                            <option v-for="(v, m) in 60" :value="m" v-text="m < 10 ? `0${m}` : m"></option>
                        </select> :
                        <select class="select-item" id="select_sec" v-model="duration.sec" @change="changeDuration(true)">
                            <option v-for="(v, s) in 60" :value="s" v-text="s < 10 ? `0${s}` : s"></option>
                        </select>
                        HH:MM:SS
                        <input type="hidden" name="duration" :value="durationSeconds * 1000"/>
                        <input type="hidden" name="durationHour" value="0"/>
                        <vue-slider ref="durationSlider" @callback="changeDurationSlider" v-model="durationSeconds" width="278" :max="28799" tooltip="none"></vue-slider>
                    </control-group>

                    <control-group :radio="{radioValue: 'R', checked: test.threshold === 'R'}" v-model="test.threshold" labelMessageKey="perfTest.config.runCount" ref="runCountControlGroup" name="threshold" id="runCount">
                        <input-append name="runCount" ref="runCount"
                                      appendPrefix="perfTest.config.max"
                                      :append="config.maxRunCount"
                                      @validationResult="$refs.runCountControlGroup.handleError($event)"
                                      :validationRules="{ required: true, max_value: config.maxRunCount, min_value: 0 }"
                                      v-model="test.runCount"
                                      @focus="test.threshold = 'R'"
                                      message="perfTest.config.runCount">
                        </input-append>
                    </control-group>

                <transition name="fade">

                                <control-group name="samplingInterval" labelMessageKey="perfTest.config.samplingInterval">
                                    <select class="select-item" id="sampling_interval"
                                            name="samplingInterval" v-model="test.samplingInterval">
                                        <option v-for="interval in samplingIntervals" :value="interval" v-text="interval"></option>
                                    </select>
                                </control-group>

                                <control-group name="ignoreSampleCount" ref="ignoreSampleCountControlGroup" labelStyle="width: 150px;" labelMessageKey="perfTest.config.ignoreSampleCount">
                                    <input-popover v-model="test.ignoreSampleCount"
                                                   ref="ignoreSampleCount"
                                                   @validationResult="$refs.ignoreSampleCountControlGroup.handleError($event)"
                                                   :validationRules="{ numeric: true }"
                                                   dataPlacement="top"
                                                   errStyle="margin-left: -120px;"
                                                   name="ignoreSampleCount"
                                                   message="perfTest.config.ignoreSampleCount" extraCss="input-mini">
                                    </input-popover>
                                </control-group>

                                <control-group name="safeDistribution" labelMessageKey="perfTest.config.safeDistribution" labelHelpMessageKey="perfTest.config.safeDistribution">
                                    <input type="checkbox" name="safeDistribution" :checked="test.safeDistribution">
                                </control-group>

                                <control-group name="param" labelMessageKey="perfTest.config.param" controlsStyle="margin-left: 85px;"
                                               labelStyle="width: 70px;" ref="paramControlGroup">
                                    <input-popover name="param"
                                                   ref="param"
                                                   @validationResult="$refs.paramControlGroup.handleError($event)"
                                                   :validationRules="{ regex: /^[a-zA-Z0-9_\.,\|=]{0,50}$/ }"
                                                   dataPlacement="top"
                                                   v-model="test.param"
                                                   message="perfTest.config.param"
                                                   customStyle="width: 125px;">
                                    </input-popover>
                                </control-group>

                </transition>

        <ramp-up ref="rampUp" :test="test" :rampUpTypes="config.rampUpTypes"></ramp-up>
        <host-modal ref="addHostModal" @add-host="addHost"></host-modal>
        <target-host-info-modal ref="targetHostInfoModal" :ip="targetHostIp"></target-host-info-modal>

</template>


to vue file

to vue file

<template>
    <div>
    </div>
</template>
<script>
    export default{
        data(){
            return{
                msg:'hello vue'
            }
        },
        components:{
            'other-component':OtherComponent,
            HeaderComponent,
        }
    }
</script>
<style>

</style>


fix sprite sheet bug

fix sprite sheet bug

<template>

    <md-layout flex="100" style="padding: 2%; padding-top: 0px;">
      <md-layout flex="100">
        <md-input-container>
          HERO
          <md-input v-model="hero" v-bind:readonly="isFindingAvatar"></md-input>
        </md-input-container>
      </md-layout>
      <md-layout md-align="center">
        <md-button class="md-raised md-primary large-button" v-on:click.native="find" v-bind:disabled="isFindingAvatar">
          {{ !isFindingAvatar ? 'Start Battle' : 'Battle in progress'}}
        </md-button>
      </md-layout>
      <md-layout>
        <md-input-container flex="100">
          ENEMY
          <md-input v-model="enemy" v-bind:readonly="isFindingAvatar"></md-input>
        </md-input-container>
      </md-layout>
    </md-layout>

</template>


change twitter username

change twitter username

<template lang="html">

      <cn-button></cn-button>

👊🏼 {{joke}} 👊🏼

      <cn-loading></cn-loading>

    <cn-share></cn-share>

</template>


Add key on Tabs (on v-for)

Add key on Tabs (on v-for)

<template>

            <i :class="[`fa fa-${(typeof item.icon === 'string') ? item.icon : item.icon.name}`]">

          {{ item.label }}

</template>


fix params

fix params

<template>

      <textarea class="editor-input" :id="'editor-' + $index">{{ tab.content }}</textarea>

        {{{ tab.html }}}

</template>


12 PM is 1200

12 PM is 1200

<template>

      <input type='text' id='tj-datetime-input' class='' v-model='date' :name='name' v-on:click='toggleCal' autocomplete='off'  />

              <button class='nav-l' v-on:click='leftYear'><</button>
              {{year}}
              <button class='nav-r' v-on:click='rightYear' >></button>

              <button class='nav-l' v-on:click='leftMonth'><</button>
              {{month}}
              <button class='nav-r' v-on:click='rightMonth' v-on:mousedown=''>></button>

            {{port}}

            {{port}}

{{hour}}

{{h}}

            :

{{minute}}

{{m}}

            :

{{period}}

        <button v-on:click='setDate' class='okButton'>OK</button>

</template>


#13 fix Changing from AM to PM bug

#13 fix Changing from AM to PM bug

<template>

      <input type='text' id='tj-datetime-input' :value="date"  :name='name' v-on:click='toggleCal' autocomplete='off'  />

              <button type='button' class='nav-l' v-on:click='leftYear'><</button>
              {{year}}
              <button type='button' class='nav-r' v-on:click='rightYear' >></button>

              <button type='button' class='nav-l' v-on:click='leftMonth'><</button>
              {{month}}
              <button type='button' class='nav-r' v-on:click='rightMonth' v-on:mousedown=''>></button>

            {{port}}

                {{day}}

{{hour}}

{{h}}

            :

{{minute}}

{{m}}

            :

{{period}}

        <button type='button' v-on:click='setDate' class='okButton'>OK</button>

</template>


fix #5373 bulk delete shouldnt select run later executions

<template>

                 0 && pagination.total > pagination.max" class="text-muted">
                  {{pagination.offset+1}}
                  -

                  {{pagination.offset+reports.length}}

                of

                  <span class="summary-count" :class="{ 'text-primary': pagination.total < 1, 'text-info': pagination.total > 0 }" v-if="pagination.total>=0">
                    {{pagination.total}}

                  {{$tc('execution',pagination.total>0?pagination.total:0)}}

          <activity-filter v-model="query" :event-bus="eventBus" :opts="filterOpts" v-if="showFilters"></activity-filter>

              <input type=checkbox id=auto-refresh v-model=autorefresh />
              {{$t('Auto refresh')}}

            0 && showBulkDelete">

                  <i18n path="bulk.selected.count">
                    {{bulkSelectedIds.length}}
                  </i18n>

                      <i18n path="select.all"/>

                      <i18n path="select.none"/>

                  <btn size="xs" type="danger" class="btn-fill"
                        :disabled="bulkSelectedIds.length<1"
                        @click="showBulkEditConfirm=true">
                      <i18n path="delete.selected.executions"/>
                  </btn>

                      <i18n path="cancel.bulk.delete"/>

              <btn size="xs" type="secondary" v-if="auth.deleteExec && !bulkEditMode" @click="bulkEditMode=true">
                  {{$t('bulk.delete')}}
              </btn>

    <modal  v-model="showBulkEditCleanSelections" id="cleanselections" :title="$t('Clear bulk selection')">

      <i18n tag="p" path="clearselected.confirm.text">
        {{bulkSelectedIds.length}}
      </i18n>

        <btn data-dismiss="modal" @click="showBulkEditCleanSelections=false">{{$t('cancel')}}</btn>
        <button type="submit"
                class="btn btn-default  "
                data-dismiss="modal"
                @click="bulkEditDeselectAll">
            {{$t('Only shown executions')}}
        </button>
        <button class="btn btn-danger "
                data-dismiss="modal"
                @click="bulkEditDeselectAllPages">
            {{$t('all')}}
        </button>

    </modal>

    <modal v-model="showBulkEditConfirm" id="bulkexecdelete" :title="$t('Bulk Delete Executions')">
      <i18n tag="p" path="delete.confirm.text">
        {{bulkSelectedIds.length}}
        {{$tc('execution',bulkSelectedIds.length)}}
      </i18n>

          <btn @click="showBulkEditConfirm=false">
              {{$t('cancel')}}
          </btn>
          <btn type="danger"
                @click="performBulkDelete"
                data-dismiss="modal">
              {{$t('Delete Selected')}}
          </btn>

    </modal>

    <modal v-model="showBulkEditResults" id="bulkexecdeleteresult" :title="$t('Bulk Delete Executions: Results')" >

                        {{$t('Requesting bulk delete, please wait.')}}

 0"
                        class="text-info">

                        <i18n path="bulkresult.attempted.text" tag="p" >
                          {{bulkEditResults.requestCount}}
                        </i18n>

 0"
                        class="text-success">

                        <i18n path="bulkresult.success.text" tag="p" >
                          {{bulkEditResults.successCount}}
                        </i18n>

 0"
                            class="text-warning">

                        <i18n path="bulkresult.failed.text" tag="p" >
                          {{bulkEditResults.failedCount}}
                        </i18n>

 0">

{{message}}

{{bulkEditError}}

                <btn @click="showBulkEditResults=false">{{$t('close')}}</btn>

    </modal>

0" class="running-executions">

                <input
                type="checkbox"
                name="bulk_edit"
                :value="exec.id"
                v-model="bulkSelectedIds"
                :disabled="exec.status==='running' || exec.status==='scheduled'"
                class="_defaultInput"/>

                            {{exec.dateStarted.date | moment(momentJobFormat)}}

                            {{exec.dateStarted.date | moment('calendar',null)}}

                            {{exec.dateStarted.date | moment('from','now')}}

                      <progress-bar v-if="exec.status === 'scheduled'" :value="100" striped  type="default" label :label-text="$t('job.execution.starting.0',[runningStartedDisplay(exec.dateStarted.date)])" ></progress-bar>
                      <progress-bar v-else-if="exec.job && exec.job.averageDuration" :value="jobDurationPercentage(exec)" striped active type="info" label min-width></progress-bar>
                      <progress-bar v-else-if="exec.dateStarted.date" :value="100" striped active type="info" label :label-text="$t('running')" ></progress-bar>

                    <i18n path="by" default="by"/>
                    {{exec.user}}

                    {{exec.job.name}}

                          {{key}}
                          {{value}}

                    {{exec.description}}

                    #{{exec.id}}

0">

                {{ $tc('info.newexecutions.since.0', sincecount) }}

 0">

                <input
                type="checkbox"
                name="bulk_edit"
                :value="rpt.executionId"
                v-model="bulkSelectedIds"
                class="_defaultInput"/>

                        {{rpt.dateCompleted | moment(momentJobFormat)}}

                        {{rpt.dateCompleted | moment('calendar',null)}}

                        {{rpt.dateCompleted | moment('from','now')}}

                0">{{rpt.node.failed}} {{$t('failed')}}
                0">{{rpt.node.succeeded}} {{$t('ok')}}

                {{rpt.duration | duration('humanize',false)}}

                <i18n path="by" default="by"/>
                {{rpt.user}}

                    {{rpt.jobName}}

                    {{rpt.executionString}}

                    {{$t('Referenced')}}

                      {{$t('job.has.been.deleted.0',[rpt.jobName])}}

                    {{rpt.execution.status}}

                        {{key}}:
                        {{value}}

                {{rpt.execution.argString}}

                #{{rpt.executionId}}

    <div v-if="reports.length < 1 " class="loading-area">

          {{$t('results.empty.text')}}

        <div class="loading-text" v-if="loading && lastDate<0">

          {{$t('Loading...')}}

          {{$t('error.message.0',[loadError])}}

    <offset-pagination
          :pagination="pagination"
          @change="changePageOffset($event)"
          :disabled="loading"
          :showPrefix="false"
        >
        </offset-pagination>

</template>

<template>

                 0 && pagination.total > pagination.max" class="text-muted">
                  {{pagination.offset+1}}
                  -

                  {{pagination.offset+reports.length}}

                of

                  <span class="summary-count" :class="{ 'text-primary': pagination.total < 1, 'text-info': pagination.total > 0 }" v-if="pagination.total>=0">
                    {{pagination.total}}

                  {{$tc('execution',pagination.total>0?pagination.total:0)}}

          <activity-filter v-model="query" :event-bus="eventBus" :opts="filterOpts" v-if="showFilters"></activity-filter>

              <input type=checkbox id=auto-refresh v-model=autorefresh />
              {{$t('Auto refresh')}}

            0 && showBulkDelete">

                  <i18n path="bulk.selected.count">
                    {{bulkSelectedIds.length}}
                  </i18n>

                      <i18n path="select.all"/>

                      <i18n path="select.none"/>

                  <btn size="xs" type="danger" class="btn-fill"
                        :disabled="bulkSelectedIds.length<1"
                        @click="showBulkEditConfirm=true">
                      <i18n path="delete.selected.executions"/>
                  </btn>

                      <i18n path="cancel.bulk.delete"/>

              <btn size="xs" type="secondary" v-if="auth.deleteExec && !bulkEditMode" @click="bulkEditMode=true">
                  {{$t('bulk.delete')}}
              </btn>

    <modal  v-model="showBulkEditCleanSelections" id="cleanselections" :title="$t('Clear bulk selection')">

      <i18n tag="p" path="clearselected.confirm.text">
        {{bulkSelectedIds.length}}
      </i18n>

        <btn data-dismiss="modal" @click="showBulkEditCleanSelections=false">{{$t('cancel')}}</btn>
        <button type="submit"
                class="btn btn-default  "
                data-dismiss="modal"
                @click="bulkEditDeselectAll">
            {{$t('Only shown executions')}}
        </button>
        <button class="btn btn-danger "
                data-dismiss="modal"
                @click="bulkEditDeselectAllPages">
            {{$t('all')}}
        </button>

    </modal>

    <modal v-model="showBulkEditConfirm" id="bulkexecdelete" :title="$t('Bulk Delete Executions')">
      <i18n tag="p" path="delete.confirm.text">
        {{bulkSelectedIds.length}}
        {{$tc('execution',bulkSelectedIds.length)}}
      </i18n>

          <btn @click="showBulkEditConfirm=false">
              {{$t('cancel')}}
          </btn>
          <btn type="danger"
                @click="performBulkDelete"
                data-dismiss="modal">
              {{$t('Delete Selected')}}
          </btn>

    </modal>

    <modal v-model="showBulkEditResults" id="bulkexecdeleteresult" :title="$t('Bulk Delete Executions: Results')" >

                        {{$t('Requesting bulk delete, please wait.')}}

 0"
                        class="text-info">

                        <i18n path="bulkresult.attempted.text" tag="p" >
                          {{bulkEditResults.requestCount}}
                        </i18n>

 0"
                        class="text-success">

                        <i18n path="bulkresult.success.text" tag="p" >
                          {{bulkEditResults.successCount}}
                        </i18n>

 0"
                            class="text-warning">

                        <i18n path="bulkresult.failed.text" tag="p" >
                          {{bulkEditResults.failedCount}}
                        </i18n>

 0">

{{message}}

{{bulkEditError}}

                <btn @click="showBulkEditResults=false">{{$t('close')}}</btn>

    </modal>

0" class="running-executions">

                <input
                type="checkbox"
                name="bulk_edit"
                :value="exec.id"
                v-model="bulkSelectedIds"
                :disabled="exec.status==='running'"
                class="_defaultInput"/>

                            {{exec.dateStarted.date | moment(momentJobFormat)}}

                            {{exec.dateStarted.date | moment('calendar',null)}}

                            {{exec.dateStarted.date | moment('from','now')}}

                      <progress-bar v-if="exec.status === 'scheduled'" :value="100" striped  type="default" label :label-text="$t('job.execution.starting.0',[runningStartedDisplay(exec.dateStarted.date)])" ></progress-bar>
                      <progress-bar v-else-if="exec.job && exec.job.averageDuration" :value="jobDurationPercentage(exec)" striped active type="info" label min-width></progress-bar>
                      <progress-bar v-else-if="exec.dateStarted.date" :value="100" striped active type="info" label :label-text="$t('running')" ></progress-bar>

                    <i18n path="by" default="by"/>
                    {{exec.user}}

                    {{exec.job.name}}

                          {{key}}
                          {{value}}

                    {{exec.description}}

                    #{{exec.id}}

0">

                {{ $tc('info.newexecutions.since.0', sincecount) }}

 0">

                <input
                type="checkbox"
                name="bulk_edit"
                :value="rpt.executionId"
                v-model="bulkSelectedIds"
                class="_defaultInput"/>

                        {{rpt.dateCompleted | moment(momentJobFormat)}}

                        {{rpt.dateCompleted | moment('calendar',null)}}

                        {{rpt.dateCompleted | moment('from','now')}}

                0">{{rpt.node.failed}} {{$t('failed')}}
                0">{{rpt.node.succeeded}} {{$t('ok')}}

                {{rpt.duration | duration('humanize',false)}}

                <i18n path="by" default="by"/>
                {{rpt.user}}

                    {{rpt.jobName}}

                    {{rpt.executionString}}

                    {{$t('Referenced')}}

                      {{$t('job.has.been.deleted.0',[rpt.jobName])}}

                    {{rpt.execution.status}}

                        {{key}}:
                        {{value}}

                {{rpt.execution.argString}}

                #{{rpt.executionId}}

    <div v-if="reports.length < 1 " class="loading-area">

          {{$t('results.empty.text')}}

        <div class="loading-text" v-if="loading && lastDate<0">

          {{$t('Loading...')}}

          {{$t('error.message.0',[loadError])}}

    <offset-pagination
          :pagination="pagination"
          @change="changePageOffset($event)"
          :disabled="loading"
          :showPrefix="false"
        >
        </offset-pagination>

</template>


Refactored list

Refactored list

<template>
  <v-app id="chat" :dark="dark" toolbar footer>

    <v-navigation-drawer persistent v-model="drawer" disable-route-watcher fixed>
      <v-subheader class="mt-3 grey--text text--darken-1">Settings</v-subheader>
        <v-divider></v-divider>
      <v-list dense>

        <v-list-tile v-for="item in listItems" :key="item.title" @click.stop="item.click()"
        v-if="item.show()">
          <v-list-tile-action>
            <v-icon>{{item.icon}}</v-icon>
          </v-list-tile-action>
            <v-list-tile-content>
              {{item.title}}
            </v-list-tile-content>
        </v-list-tile>
      </v-list>
    </v-navigation-drawer>

    <v-dialog v-model="share" lazy absolute>
      <v-card>
        <v-card-title>

Share Chat Link

        </v-card-title>
        <v-card-text>

            {{url}}

        </v-card-text>
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn class="blue--text darken-1" flat="flat" @click.native="share = false">Close</v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <v-toolbar fixed>
      <v-toolbar-side-icon @click.stop="drawer = !drawer"></v-toolbar-side-icon>
      <v-toolbar-title>Mon Chat{{chatID ? ' - ' + chatID : ''}}</v-toolbar-title>
    </v-toolbar>

      <v-container fluid>
        <router-view></router-view>
      </v-container>

    <v-footer fixed>
      Jase Pellerin 2017
    </v-footer>
  </v-app>
</template>

<template>
  <v-app id="chat" :dark="dark" toolbar footer>

    <v-navigation-drawer persistent v-model="drawer" disable-route-watcher fixed>
      <v-list dense>
        <v-subheader class="mt-3 grey--text text--darken-1">Settings</v-subheader>

        <v-list-tile @click.stop="share = !share" v-if="chatID">
          <v-list-tile-action>
            <v-icon>link</v-icon>
          </v-list-tile-action>
          <v-list-tile-content>
            Share chat link
          </v-list-tile-content>
        </v-list-tile>
        <v-spacer> </v-spacer>
        <v-divider></v-divider>

        <v-list-tile @click.stop="dark = !dark">
          <v-list-tile-action>
            <v-icon>lightbulb_outline</v-icon>
          </v-list-tile-action>
          <v-list-tile-content>
            {{dark ? 'Light Mode' : 'Dark Mode'}}
          </v-list-tile-content>
        </v-list-tile>

        <v-list-tile @click.stop="chatSelect()" v-if="chatID">
          <v-list-tile-action>
            <v-icon>compare_arrows</v-icon>
          </v-list-tile-action>
          <v-list-tile-content>
            Change Chatroom
          </v-list-tile-content>
        </v-list-tile>

        <v-list-tile @click.stop="logOut()" v-if="username">
          <v-list-tile-action>
            <v-icon>power_settings_new</v-icon>
          </v-list-tile-action>
          <v-list-tile-content>
            Logout
          </v-list-tile-content>
        </v-list-tile>
      </v-list>
    </v-navigation-drawer>

    <v-dialog v-model="share" lazy absolute>
      <v-card>
        <v-card-title>

Share Chat Link

        </v-card-title>
        <v-card-text>

            {{url}}

        </v-card-text>
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn class="blue--text darken-1" flat="flat" @click.native="share = false">Close</v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <v-toolbar fixed>
      <v-toolbar-side-icon @click.stop="drawer = !drawer"></v-toolbar-side-icon>
      <v-toolbar-title>Mon Chat{{chatID ? ' - ' + chatID : ''}}</v-toolbar-title>
    </v-toolbar>

      <v-container fluid>
        <router-view></router-view>
      </v-container>

    <v-footer fixed>
      Jase Pellerin 2017
    </v-footer>
  </v-app>
</template>


remove unnecessary comment

remove unnecessary comment

<template>

      <v-form @submit.prevent="testConnection">
        <v-text-field id="host"
                      :rules="[hostValid]"
                      v-model="elasticsearchHost"
                      append-icon="mdi-close"
                      autofocus
                      label="Host"
                      title="Host"
                      type="text"
                      @click:append="resetElasticsearchHost"
                      @keyup.ctrl.enter="connect"
                      @keyup.esc="resetElasticsearchHost"/>

          <v-btn id="test_connection"
                 :color="testConnectionColor"
                 :disabled="hostValid !== true"
                 :loading="testLoading"
                 class="mr-2 mt-2"
                 type="submit">
            Test connection
          </v-btn>

          <v-btn id="connect"
                 :color="connectColor"
                 :disabled="hostValid !== true"
                 :loading="connectLoading"
                 class="mt-2"
                 type="button"
                 @click.native="connect">Connect
          </v-btn>

      </v-form>

To connect with credentials use http://username:password@host syntax. Don't encode special
        characters in the password!

      <v-alert :value="true" type="error">
        Could not connect. Please make sure that

Your cluster is reachable via {{ elasticsearchHost }}

You added the correct settings to your elasticsearch.yml and restarted your cluster

          {{ errorMessage }}

      </v-alert>

</template>


Preferences Styling

Preferences Styling

<template>

Settings

info_outline

Plex Client Polling Interval

                <form action="#" style="margin-top: -15px">

                        <v-range v-model="clientpollinterval" :min="100" :max="10000"></v-range>

                </form>

                <input class="center" id="clientpollinginterval" type="number" step="10" v-model="clientpollinterval">

info_outline

Sync Flexibility

                <form action="#" style="margin-top: -15px">

                        <v-range v-model="syncflexability" :min="500" :max="10000"></v-range>

                </form>

                <input class="center" id="syncflexability" type="number" step="10" v-model="syncflexability">

info_outline

Syncing Method

            <form action="#">

                    <input name="syncModeInputs" id="CLEANSEEK" value="cleanseek" v-model="syncmode" type="radio" />
                    Clean Seek

                    <input name="syncModeInputs" id="SKIPAHEAD" value="skipahead" v-model="syncmode" type="radio" />
                    Skip Ahead

            </form>

</template>


refactor(modal): update example

refactor(modal): update example

<template>

    <cdr-text
      tag="h2"
      modifier="heading-600 heading-700@md heading-700@lg"
    >
      Modal
    </cdr-text>

    <cdr-modal
      label="label text is title or aria"
      :opened="opened"
      @closed="closed"
      wrapper-class="wrapper-test-class"
      overlay-class="overlay-test-class"
      :show-title="showTitle"
      :size="size"
      data-backstop="modal-large"
    >
      <template slot="title">
        <cdr-text
          tag="h1"
          modifier="heading-600"
        >
          Added to Cart (is a common label) and let's make this longer so it
        </cdr-text>
      </template>

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet dictum ipsum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam non urna sit amet dolor euismod consequat vitae non nunc. Nullam vulputate enim ac pharetra sagittis. Curabitur volutpat, metus eu euismod finibus, neque turpis viverra dolor, at ornare justo libero a arcu. Suspendisse nec lectus id leo aliquam posuere id eu mauris. Aenean fermentum justo ex, vel sagittis nulla efficitur nec. Mauris aliquet urna id felis maximus, et molestie erat bibendum. Donec dolor purus, iaculis vitae tellus at, iaculis facilisis nibh. Pellentesque at ex sit amet eros elementum iaculis quis ut justo. Pellentesque consequat in sapien ac blandit. Donec ullamcorper lacus sed interdum auctor.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet dictum ipsum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam non urna sit amet dolor euismod consequat vitae non nunc. Nullam vulputate enim ac pharetra sagittis. Curabitur volutpat, metus eu euismod finibus, neque turpis viverra dolor, at ornare justo libero a arcu. Suspendisse nec lectus id leo aliquam posuere id eu mauris. Aenean fermentum justo ex, vel sagittis nulla efficitur nec. Mauris aliquet urna id felis maximus, et molestie erat bibendum. Donec dolor purus, iaculis vitae tellus at, iaculis facilisis nibh. Pellentesque at ex sit amet eros elementum iaculis quis ut justo. Pellentesque consequat in sapien ac blandit. Donec ullamcorper lacus sed interdum auctor.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet dictum ipsum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam non urna sit amet dolor euismod consequat vitae non nunc. Nullam vulputate enim ac pharetra sagittis. Curabitur volutpat, metus eu euismod finibus, neque turpis viverra dolor, at ornare justo libero a arcu. Suspendisse nec lectus id leo aliquam posuere id eu mauris. Aenean fermentum justo ex, vel sagittis nulla efficitur nec. Mauris aliquet urna id felis maximus, et molestie erat bibendum. Donec dolor purus, iaculis vitae tellus at, iaculis facilisis nibh. Pellentesque at ex sit amet eros elementum iaculis quis ut justo. Pellentesque consequat in sapien ac blandit. Donec ullamcorper lacus sed interdum auctor.

    </cdr-modal>

    <cdr-button
      @click="opened = true"
      aria-haspopup="dialog"
    >Open modal
    </cdr-button>

    <cdr-text
      modifier="heading-400"
      class="cdr-pt-space-one-x"
    >
      Size
    </cdr-text>

    <cdr-radio
      name="modal-width"
      custom-value="medium"
      v-model="size"
    >Medium
    </cdr-radio>

    <cdr-radio
      name="modal-width"
      custom-value="large"
      v-model="size"
    >Large
    </cdr-radio>

    <cdr-text
      modifier="heading-400"
      class="cdr-pt-space-one-x"
    >
      Content Length
    </cdr-text>

    <cdr-radio
      name="modal-content-length"
      custom-value="short"
      v-model="contentLength"
    >Short
    </cdr-radio>

    <cdr-radio
      name="modal-content-length"
      custom-value="long"
      v-model="contentLength"
    >Long
    </cdr-radio>

    <cdr-text
      modifier="heading-400"
      class="cdr-pt-space-one-x"
    >
      Show Title
    </cdr-text>

    <cdr-radio
      name="modal-show-title"
      :custom-value="true"
      v-model="showTitle"
    >True
    </cdr-radio>

    <cdr-radio
      name="modal-show-title"
      :custom-value="false"
      v-model="showTitle"
    >False
    </cdr-radio>

</template>

<template>

    <cdr-text
      tag="h2"
      modifier="heading-600 heading-700@md heading-700@lg"
    >
      Modal
    </cdr-text>

    <cdr-modal
      label="label text is title or aria"
      :opened="large"
      @closed="closed"
      wrapper-class="wrapper-test-class"
      overlay-class="overlay-test-class"
      size="large"
      data-backstop="modal-large"
    >
      <template slot="title">
        <cdr-text
          tag="h1"
          modifier="heading-600"
        >
          Added to Cart (is a common label) and let's make this longer so it
        </cdr-text>
      </template>

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet dictum ipsum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam non urna sit amet dolor euismod consequat vitae non nunc. Nullam vulputate enim ac pharetra sagittis. Curabitur volutpat, metus eu euismod finibus, neque turpis viverra dolor, at ornare justo libero a arcu. Suspendisse nec lectus id leo aliquam posuere id eu mauris. Aenean fermentum justo ex, vel sagittis nulla efficitur nec. Mauris aliquet urna id felis maximus, et molestie erat bibendum. Donec dolor purus, iaculis vitae tellus at, iaculis facilisis nibh. Pellentesque at ex sit amet eros elementum iaculis quis ut justo. Pellentesque consequat in sapien ac blandit. Donec ullamcorper lacus sed interdum auctor.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet dictum ipsum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam non urna sit amet dolor euismod consequat vitae non nunc. Nullam vulputate enim ac pharetra sagittis. Curabitur volutpat, metus eu euismod finibus, neque turpis viverra dolor, at ornare justo libero a arcu. Suspendisse nec lectus id leo aliquam posuere id eu mauris. Aenean fermentum justo ex, vel sagittis nulla efficitur nec. Mauris aliquet urna id felis maximus, et molestie erat bibendum. Donec dolor purus, iaculis vitae tellus at, iaculis facilisis nibh. Pellentesque at ex sit amet eros elementum iaculis quis ut justo. Pellentesque consequat in sapien ac blandit. Donec ullamcorper lacus sed interdum auctor.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet dictum ipsum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam non urna sit amet dolor euismod consequat vitae non nunc. Nullam vulputate enim ac pharetra sagittis. Curabitur volutpat, metus eu euismod finibus, neque turpis viverra dolor, at ornare justo libero a arcu. Suspendisse nec lectus id leo aliquam posuere id eu mauris. Aenean fermentum justo ex, vel sagittis nulla efficitur nec. Mauris aliquet urna id felis maximus, et molestie erat bibendum. Donec dolor purus, iaculis vitae tellus at, iaculis facilisis nibh. Pellentesque at ex sit amet eros elementum iaculis quis ut justo. Pellentesque consequat in sapien ac blandit. Donec ullamcorper lacus sed interdum auctor.

    </cdr-modal>

    <cdr-button
      @click="large = true"
    >Toggle Modal
    </cdr-button>

</template>