Sidebar: fix missing arg for contact support

<script lang="coffee">
import AppConfig      from '@/shared/services/app_config'
import Session        from '@/shared/services/session'
import Records        from '@/shared/services/records'
import EventBus       from '@/shared/services/event_bus'
import AbilityService from '@/shared/services/ability_service'
import LmoUrlService  from '@/shared/services/lmo_url_service'
import InboxService   from '@/shared/services/inbox_service'

import { isUndefined, sortBy, filter, find, head, each, uniq, map, sum, compact,
         concat, intersection, difference, orderBy } from 'lodash'

export default
  data: ->
    organization: null
    open: false
    group: null
    version: AppConfig.version
    tree: []
    myGroups: []
    otherGroups: []
    organizations: []
    unreadCounts: {}
    expandedGroupIds: []
    openGroups: []
    unreadDirectThreadsCount: 0

  created: ->
    EventBus.$on 'toggleSidebar', => @open = !@open

    EventBus.$on 'currentComponent', (data) =>
      @group = data.group
      if @group
        @organization = data.group.parentOrSelf()
        @expandedGroupIds = [@organization.id]
      else
        @organization = null

    @watchRecords
      collections: ['groups', 'memberships', 'discussions']
      query: (store) =>
        @unreadDirectThreadsCount =
          Records.discussions.collection.chain().
                  find({groupId: null}).
                  where((thread) -> thread.isUnread()).data().length
        @updateGroups()

    EventBus.$on 'signedIn', (user) =>
      @fetchData()
      @openIfPinned()

    @fetchData() if Session.isSignedIn()

  mounted: ->
    @openIfPinned()

  watch:
    organization: 'updateGroups'

    open: (val) ->
      EventBus.$emit("sidebarOpen", val)

  methods:
    memberGroups: (group) ->
      group.subgroups().filter (g) -> !g.archivedAt && g.membershipFor(Session.user())

    openIfPinned: ->
      @open = !!Session.isSignedIn() && !!Session.user().experiences['sidebar'] && @$vuetify.breakpoint.lgAndUp

    fetchData: ->
      Records.users.fetchGroups().then =>
        if @$router.history.current.path == "/dashboard" && Session.user().groups().length == 1
          @$router.replace("/g/#{Session.user().groups()[0].key}")
        if @$router.history.current.path == "/dashboard" && Session.user().groups().length == 0
          if AppConfig.features.app.subscriptions
            @$router.replace("/try")
          else
            @$router.replace("/g/new")

      InboxService.load()

    goToGroup: (group) ->
      @$router.push @urlFor(group)

    updateGroups: ->
      @organizations = compact(Session.user().parentGroups().concat(Session.user().orphanParents())) || []
      @openCounts = {}
      @closedCounts = {}
      @openGroups = []
      Session.user().groups().forEach (group) =>
        @openCounts[group.id] = filter(group.discussions(), (discussion) -> discussion.isUnread()).length
      Session.user().parentGroups().forEach (group) =>
        if @organization && @organization.id == group.parentOrSelf().id
          @openGroups[group.id] = true
        @closedCounts[group.id] = @openCounts[group.id] + sum(map(@memberGroups(group), (subgroup) => @openCounts[subgroup.id]))

    unreadThreadCount: ->
      InboxService.unreadCount()

    canViewPublicGroups: -> AbilityService.canViewPublicGroups()
    setProfilePicture: -> EventBus.$emit 'openModal', {component: 'ChangePictureForm'}

  computed:
    isSignedIn: -> Session.isSignedIn()
    showHelp: -> AppConfig.features.app.help_link
    user: -> Session.user()
    activeGroup: -> if @group then [@group.id] else []
    logoUrl: -> AppConfig.theme.app_logo_src
    showContact: -> AppConfig.features.app.show_contact
    canStartGroups: -> AbilityService.canStartGroups()
    canStartDemo: -> AppConfig.features.app.demos
    showTemplateGallery: -> AppConfig.features.app.template_gallery
    showExploreGroups: -> AppConfig.features.app.explore_public_groups
    needProfilePicture: ->
      Session.isSignedIn() && @user && !@user.avatarUrl && !@user.hasExperienced('changePicture')

</script>

<template lang="pug">
v-navigation-drawer.sidenav-left.lmo-no-print(app v-model="open")
  template(v-slot:prepend)
  template(v-slot:append)
    v-layout.mx-10.my-2(column align-center style="max-height: 64px")
      v-img(:src="logoUrl")

  v-list-group.sidebar__user-dropdown
    template(v-slot:activator)
      v-list-item-icon.mr-2
        user-avatar(:user="user")
      v-list-item-content
        v-list-item-title {{user.name}}
        v-list-item-subtitle {{user.email}}
    user-dropdown
  template(v-if="needProfilePicture")
    v-divider
    v-list-item.sidebar__list-item-button--recent(@click="setProfilePicture" color="warning")
      v-list-item-icon
        v-icon mdi-emoticon-outline
      v-list-item-content
        v-list-item-title(v-t="'profile_page.incomplete_profile'")
        v-list-item-subtitle(v-t="'profile_page.set_your_profile_picture'")
  v-divider

  v-list-item.sidebar__list-item-button--recent(dense to="/dashboard")
    v-list-item-title(v-t="'dashboard_page.aria_label'")
  v-list-item(dense to="/inbox")
    v-list-item-title(v-t="{ path: 'sidebar.unread_threads', args: { count: unreadThreadCount() } }")
  v-list-item.sidebar__list-item-button--private(dense to="/threads/direct")
    v-list-item-title
      span(v-t="'sidebar.invite_only_threads'")
      span(v-if="unreadDirectThreadsCount > 0")
        space
        span ({{unreadDirectThreadsCount}})
  v-list-item.sidebar__list-item-button--start-thread(dense to="/d/new")
    v-list-item-title(v-t="'sidebar.start_thread'")
    v-list-item-icon
      v-icon mdi-plus
  v-list-item(dense to="/tasks")
    v-list-item-title(v-t="'tasks.tasks'")
  v-divider

  v-list.sidebar__groups(dense)
    template(v-for="parentGroup in organizations")
      template(v-if="memberGroups(parentGroup).length")
        v-list-group(v-model="openGroups[parentGroup.id]"  @click="goToGroup(parentGroup)")
          template(v-slot:activator)
            v-list-item-avatar(aria-hidden="true")
              group-avatar(:group="parentGroup")
            v-list-item-content
              v-list-item-title
                span {{parentGroup.name}}
                template(v-if="closedCounts[parentGroup.id]")
                  |
                  span ({{closedCounts[parentGroup.id]}})
          v-list-item(:to="urlFor(parentGroup)+'?subgroups=none'")
            v-list-item-content
              v-list-item-title
                span {{parentGroup.name}}
                template(v-if='openCounts[parentGroup.id]')
                  |
                  span ({{openCounts[parentGroup.id]}})
          v-list-item(v-for="group in memberGroups(parentGroup)", :key="group.id", :to="urlFor(group)")
            v-list-item-content
              v-list-item-title
                span {{group.name}}
                template(v-if='openCounts[group.id]')
                  |
                  span ({{openCounts[group.id]}})
      template(v-else)
        v-list-item(:to="urlFor(parentGroup)")
          v-list-item-avatar
            group-avatar(:group="parentGroup")
          v-list-item-content
            v-list-item-title
              span {{parentGroup.name}}
              template(v-if='openCounts[parentGroup.id]')
                |
                span ({{openCounts[parentGroup.id]}})

    v-list-item.sidebar__list-item-button--start-group(v-if="canStartGroups" to="/g/new")
      v-list-item-avatar
        v-icon(tile) mdi-plus
      v-list-item-title(v-t="'group_form.new_group'")
  v-divider
  v-list-item.sidebar__list-item-button--start-group(v-if="canStartDemo" to="/demo" dense)
    v-list-item-title(v-t="'templates.demo_group'")
    v-list-item-icon
      v-icon mdi-car-convertible
  v-list-item(v-if="showHelp", href="https://help.loomio.com" target="_blank" dense)
    v-list-item-title(v-t="'common.help_and_guides'")
    v-list-item-icon
      v-icon mdi-book-open-page-variant
  v-list-item.sidebar__list-item-button--example-templates(v-if="showTemplateGallery" to="/templates" dense)
    v-list-item-title(v-t="'sidebar.examples_and_templates'")
    v-list-item-icon
      v-icon mdi-lightbulb-on
  v-list-item(dense to="/explore" v-if="showExploreGroups")
    v-list-item-title(v-t="'sidebar.explore_groups'")
    v-list-item-icon
      v-icon mdi-map-search
  v-list-item(v-if="showContact" to="/contact" dense)
    v-list-item-title(v-t="'user_dropdown.contact_support'")
    v-list-item-icon
      v-icon mdi-face-agent
</template>
<style lang="sass">
.sidenav-left
  .v-avatar.v-list-item__avatar
    margin-right: 8px
  .v-list-group .v-list-group__header .v-list-item__icon.v-list-group__header__append-icon
    min-width: 0
  .v-list-item__icon.v-list-group__header__append-icon
    min-width: 32px
  .v-list-item__icon.v-list-group__header__append-icon
    margin-left: 0 !important
</style>

<script lang="coffee">
import AppConfig      from '@/shared/services/app_config'
import Session        from '@/shared/services/session'
import Records        from '@/shared/services/records'
import EventBus       from '@/shared/services/event_bus'
import AbilityService from '@/shared/services/ability_service'
import LmoUrlService  from '@/shared/services/lmo_url_service'
import InboxService   from '@/shared/services/inbox_service'

import { isUndefined, sortBy, filter, find, head, each, uniq, map, sum, compact,
         concat, intersection, difference, orderBy } from 'lodash'

export default
  data: ->
    organization: null
    open: false
    group: null
    version: AppConfig.version
    tree: []
    myGroups: []
    otherGroups: []
    organizations: []
    unreadCounts: {}
    expandedGroupIds: []
    openGroups: []
    unreadDirectThreadsCount: 0

  created: ->
    EventBus.$on 'toggleSidebar', => @open = !@open

    EventBus.$on 'currentComponent', (data) =>
      @group = data.group
      if @group
        @organization = data.group.parentOrSelf()
        @expandedGroupIds = [@organization.id]
      else
        @organization = null

    @watchRecords
      collections: ['groups', 'memberships', 'discussions']
      query: (store) =>
        @unreadDirectThreadsCount =
          Records.discussions.collection.chain().
                  find({groupId: null}).
                  where((thread) -> thread.isUnread()).data().length
        @updateGroups()

    EventBus.$on 'signedIn', (user) =>
      @fetchData()
      @openIfPinned()

    @fetchData() if Session.isSignedIn()

  mounted: ->
    @openIfPinned()

  watch:
    organization: 'updateGroups'

    open: (val) ->
      EventBus.$emit("sidebarOpen", val)

  methods:
    memberGroups: (group) ->
      group.subgroups().filter (g) -> !g.archivedAt && g.membershipFor(Session.user())

    openIfPinned: ->
      @open = !!Session.isSignedIn() && !!Session.user().experiences['sidebar'] && @$vuetify.breakpoint.lgAndUp

    fetchData: ->
      Records.users.fetchGroups().then =>
        if @$router.history.current.path == "/dashboard" && Session.user().groups().length == 1
          @$router.replace("/g/#{Session.user().groups()[0].key}")
        if @$router.history.current.path == "/dashboard" && Session.user().groups().length == 0
          if AppConfig.features.app.subscriptions
            @$router.replace("/try")
          else
            @$router.replace("/g/new")

      InboxService.load()

    goToGroup: (group) ->
      @$router.push @urlFor(group)

    updateGroups: ->
      @organizations = compact(Session.user().parentGroups().concat(Session.user().orphanParents())) || []
      @openCounts = {}
      @closedCounts = {}
      @openGroups = []
      Session.user().groups().forEach (group) =>
        @openCounts[group.id] = filter(group.discussions(), (discussion) -> discussion.isUnread()).length
      Session.user().parentGroups().forEach (group) =>
        if @organization && @organization.id == group.parentOrSelf().id
          @openGroups[group.id] = true
        @closedCounts[group.id] = @openCounts[group.id] + sum(map(@memberGroups(group), (subgroup) => @openCounts[subgroup.id]))

    unreadThreadCount: ->
      InboxService.unreadCount()

    canViewPublicGroups: -> AbilityService.canViewPublicGroups()
    setProfilePicture: -> EventBus.$emit 'openModal', {component: 'ChangePictureForm'}

  computed:
    isSignedIn: -> Session.isSignedIn()
    showHelp: -> AppConfig.features.app.help_link
    user: -> Session.user()
    activeGroup: -> if @group then [@group.id] else []
    logoUrl: -> AppConfig.theme.app_logo_src
    showContact: -> AppConfig.features.app.show_contact
    canStartGroups: -> AbilityService.canStartGroups()
    canStartDemo: -> AppConfig.features.app.demos
    showTemplateGallery: -> AppConfig.features.app.template_gallery
    showExploreGroups: -> AppConfig.features.app.explore_public_groups
    needProfilePicture: ->
      Session.isSignedIn() && @user && !@user.avatarUrl && !@user.hasExperienced('changePicture')

</script>

<template lang="pug">
v-navigation-drawer.sidenav-left.lmo-no-print(app v-model="open")
  template(v-slot:prepend)
  template(v-slot:append)
    v-layout.mx-10.my-2(column align-center style="max-height: 64px")
      v-img(:src="logoUrl")

  v-list-group.sidebar__user-dropdown
    template(v-slot:activator)
      v-list-item-icon.mr-2
        user-avatar(:user="user")
      v-list-item-content
        v-list-item-title {{user.name}}
        v-list-item-subtitle {{user.email}}
    user-dropdown
  template(v-if="needProfilePicture")
    v-divider
    v-list-item.sidebar__list-item-button--recent(@click="setProfilePicture" color="warning")
      v-list-item-icon
        v-icon mdi-emoticon-outline
      v-list-item-content
        v-list-item-title(v-t="'profile_page.incomplete_profile'")
        v-list-item-subtitle(v-t="'profile_page.set_your_profile_picture'")
  v-divider

  v-list-item.sidebar__list-item-button--recent(dense to="/dashboard")
    v-list-item-title(v-t="'dashboard_page.aria_label'")
  v-list-item(dense to="/inbox")
    v-list-item-title(v-t="{ path: 'sidebar.unread_threads', args: { count: unreadThreadCount() } }")
  v-list-item.sidebar__list-item-button--private(dense to="/threads/direct")
    v-list-item-title
      span(v-t="'sidebar.invite_only_threads'")
      span(v-if="unreadDirectThreadsCount > 0")
        space
        span ({{unreadDirectThreadsCount}})
  v-list-item.sidebar__list-item-button--start-thread(dense to="/d/new")
    v-list-item-title(v-t="'sidebar.start_thread'")
    v-list-item-icon
      v-icon mdi-plus
  v-list-item(dense to="/tasks")
    v-list-item-title(v-t="'tasks.tasks'")
  v-divider

  v-list.sidebar__groups(dense)
    template(v-for="parentGroup in organizations")
      template(v-if="memberGroups(parentGroup).length")
        v-list-group(v-model="openGroups[parentGroup.id]"  @click="goToGroup(parentGroup)")
          template(v-slot:activator)
            v-list-item-avatar(aria-hidden="true")
              group-avatar(:group="parentGroup")
            v-list-item-content
              v-list-item-title
                span {{parentGroup.name}}
                template(v-if="closedCounts[parentGroup.id]")
                  |
                  span ({{closedCounts[parentGroup.id]}})
          v-list-item(:to="urlFor(parentGroup)+'?subgroups=none'")
            v-list-item-content
              v-list-item-title
                span {{parentGroup.name}}
                template(v-if='openCounts[parentGroup.id]')
                  |
                  span ({{openCounts[parentGroup.id]}})
          v-list-item(v-for="group in memberGroups(parentGroup)", :key="group.id", :to="urlFor(group)")
            v-list-item-content
              v-list-item-title
                span {{group.name}}
                template(v-if='openCounts[group.id]')
                  |
                  span ({{openCounts[group.id]}})
      template(v-else)
        v-list-item(:to="urlFor(parentGroup)")
          v-list-item-avatar
            group-avatar(:group="parentGroup")
          v-list-item-content
            v-list-item-title
              span {{parentGroup.name}}
              template(v-if='openCounts[parentGroup.id]')
                |
                span ({{openCounts[parentGroup.id]}})

    v-list-item.sidebar__list-item-button--start-group(v-if="canStartGroups" to="/g/new")
      v-list-item-avatar
        v-icon(tile) mdi-plus
      v-list-item-title(v-t="'group_form.new_group'")
  v-divider
  v-list-item.sidebar__list-item-button--start-group(v-if="canStartDemo" to="/demo" dense)
    v-list-item-title(v-t="'templates.demo_group'")
    v-list-item-icon
      v-icon mdi-car-convertible
  v-list-item(v-if="showHelp", href="https://help.loomio.com" target="_blank" dense)
    v-list-item-title(v-t="'common.help_and_guides'")
    v-list-item-icon
      v-icon mdi-book-open-page-variant
  v-list-item.sidebar__list-item-button--example-templates(v-if="showTemplateGallery" to="/templates" dense)
    v-list-item-title(v-t="'sidebar.examples_and_templates'")
    v-list-item-icon
      v-icon mdi-lightbulb-on
  v-list-item(dense to="/explore" v-if="showExploreGroups")
    v-list-item-title(v-t="'sidebar.explore_groups'")
    v-list-item-icon
      v-icon mdi-map-search
  v-list-item(v-if="showContact" to="/contact" dense)
    v-list-item-title(v-t="{path: 'user_dropdown.contact_support', args: {site_name: siteName}}")
    v-list-item-icon
      v-icon mdi-face-agent
</template>
<style lang="sass">
.sidenav-left
  .v-avatar.v-list-item__avatar
    margin-right: 8px
  .v-list-group .v-list-group__header .v-list-item__icon.v-list-group__header__append-icon
    min-width: 0
  .v-list-item__icon.v-list-group__header__append-icon
    min-width: 32px
  .v-list-item__icon.v-list-group__header__append-icon
    margin-left: 0 !important
</style>


Adds the z index as 1 for the navigation bar

<template>

                Begin

Home

Source

Tasks

Create Task

Register

Login

                        {{ $root.user.name }}

{{ $root.user.name }}

{{ $root.user.email }}

                                                Profile

Account Settings

Sign Out

</template>


Fixed link for hlt_client

Fixed link for hlt_client

<template>

      <Message :message="message.content" :type="message.type"></Message>

PLAY A HALITE AI BOT

You can either submit a bot to have it start playing games, or you can preview a bot by uploading a replay file that was generated offline.

            <Upload :logged-in="loggedIn"></Upload>

You can also submit a bot via our Halite Client Tool

            <visualizer-container></visualizer-container>

      <bot-upload :user="user" :bot-file="botFile" :bots-list="botsList"  v-if="currentView='botUpload'"
        :enableMessage="enableMessage"
        :disableMessage="disableMessage"></bot-upload>

</template>


Update message ids to be more descriptive/semantic

<template>

  <form
    class="search-box"
    @submit.prevent="search"
    @keydown.esc.prevent="handleEscKey">

      {{ $tr('search') }}
      <input
        v-model="searchQuery"
        id="searchfield"
        type="search"
        class="search-input"
        ref="searchInput"
        :placeholder="$tr('search')"
      >

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

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

  </form>

</template>


[fleet] fix performance graph

[fleet] fix performance graph

GitOrigin-RevId: 32758694b1ad015516d5e5b17d535bd7f5439bfb

<template>

    <el-row>
      <el-col :span="16">
        <el-form :inline="true" size="small">
          <el-form-item label="Server">
            <el-input
                data-lpignore="true"
                placeholder="Enter the aggregated stats server URL..."
                v-model="chartSettings.serverUrl"/>
          </el-form-item>

          <el-form-item label="Machine">
            <el-cascader
                v-model="chartSettings.selectedMachine"
                :show-all-levels="false"
                :props='{"label": "name", value: "name", checkStrictly: true, emitPath: false}'
                :options="machines"/>
          </el-form-item>

          <el-form-item>
            <el-button title="Updated automatically, but you can force data reloading"
                       type="primary"
                       icon="el-icon-refresh"
                       :loading="isFetching"
                       @click="loadData"/>
          </el-form-item>
        </el-form>
      </el-col>
      <el-col :span="8">

          <el-checkbox size="small" v-model="chartSettings.showScrollbarXPreview">Show horizontal scrollbar preview</el-checkbox>

      </el-col>
    </el-row>

Aggregated

    <el-tabs value="date" size="small">
      <el-tab-pane v-for='item in [
          {name: "By Date", order: "date"},
          {name: "By Build", order: "buildNumber"}
          ]' :key="item.order" :label="item.name" :name="item.order" lazy>
        <keep-alive>

            <el-form v-if="item.order === 'date'" :inline="true" size="small">
              <el-form-item label="Granularity">
                <el-select v-model="chartSettings.granularity" data-lpignore="true" filterable>
                  <el-option v-for='name in ["as is", "2 hour", "day", "week", "month"]' :key="name" :label="name" :value="name"/>
                </el-select>
              </el-form-item>
              <el-form-item label="Period">
                <el-select v-model="timeRange" data-lpignore="true" filterable>
                  <el-option v-for='item in timeRanges' :key="item.k" :label="item.l" :value="item.k"/>
                </el-select>
              </el-form-item>
            </el-form>

            <el-row :gutter="5">
              <el-col :span="12">
                <el-card shadow="never" :body-style="{ padding: '0px' }">
                  <LineChartComponent type="duration" :order="item.order" :dataRequest="dataRequest" :timeRange="timeRange"
                                      :metrics='["prepareAppInitActivities.run frontend"]'
                                      :chartSettings="chartSettings"/>
                </el-card>
              </el-col>
              <el-col :span="12">
                <el-card shadow="never" :body-style="{ padding: '0px' }">
                  <LineChartComponent type="duration" :order="item.order" :dataRequest="dataRequest" :timeRange="timeRange"
                                      :metrics='["prepareAppInitActivities.start main frontend"]'
                                      :chartSettings="chartSettings"/>
                </el-card>
              </el-col>
            </el-row>

            <el-row :gutter="5">
              <el-col :span="12">
                <el-card shadow="never" :body-style="{ padding: '0px' }">
                  <LineChartComponent type="duration" :order="item.order" :dataRequest="dataRequest" :timeRange="timeRange"
                                      :metrics='["prepareAppInitActivities.uiRoot.s"]'
                                      :chartSettings="chartSettings"/>
                </el-card>
              </el-col>
              <el-col :span="12">
                <el-card shadow="never" :body-style="{ padding: '0px' }">
                  <LineChartComponent type="duration" :order="item.order" :dataRequest="dataRequest" :timeRange="timeRange"
                                      :metrics='["prepareAppInitActivities.start app"]'
                                      :chartSettings="chartSettings"/>
                </el-card>
              </el-col>
            </el-row>

        </keep-alive>
      </el-tab-pane>
    </el-tabs>

</template>

<template>

    <el-row>
      <el-col :span="16">
        <el-form :inline="true" size="small">
          <el-form-item label="Server">
            <el-input
                data-lpignore="true"
                placeholder="Enter the aggregated stats server URL..."
                v-model="chartSettings.serverUrl"/>
          </el-form-item>

          <el-form-item label="Machine">
            <el-cascader
                v-model="chartSettings.selectedMachine"
                :show-all-levels="false"
                :props='{"label": "name", value: "name", checkStrictly: true, emitPath: false}'
                :options="machines"/>
          </el-form-item>

          <el-form-item>
            <el-button title="Updated automatically, but you can force data reloading"
                       type="primary"
                       icon="el-icon-refresh"
                       :loading="isFetching"
                       @click="loadData"/>
          </el-form-item>
        </el-form>
      </el-col>
      <el-col :span="8">

          <el-checkbox size="small" v-model="chartSettings.showScrollbarXPreview">Show horizontal scrollbar preview</el-checkbox>

      </el-col>
    </el-row>

Aggregated

    <el-tabs value="date" size="small">
      <el-tab-pane v-for='item in [
          {name: "By Date", order: "date"},
          {name: "By Build", order: "buildNumber"}
          ]' :key="item.order" :label="item.name" :name="item.order" lazy>
        <keep-alive>

            <el-form v-if="item.order === 'date'" :inline="true" size="small">
              <el-form-item label="Granularity">
                <el-select v-model="chartSettings.granularity" data-lpignore="true" filterable>
                  <el-option v-for='name in ["as is", "2 hour", "day", "week", "month"]' :key="name" :label="name" :value="name"/>
                </el-select>
              </el-form-item>
              <el-form-item label="Period">
                <el-select v-model="timeRange" data-lpignore="true" filterable>
                  <el-option v-for='item in timeRanges' :key="item.k" :label="item.l" :value="item.k"/>
                </el-select>
              </el-form-item>
            </el-form>

            <el-row :gutter="5">
              <el-col :span="12">
                <el-card shadow="never" :body-style="{ padding: '0px' }">
                  <LineChartComponent type="duration" :order="item.order" :dataRequest="dataRequest" :timeRange="timeRange"
                                      :metrics='["prepareAppInitActivities.run frontend"]'
                                      :chartSettings="chartSettings"/>
                </el-card>
              </el-col>
              <el-col :span="12">
                <el-card shadow="never" :body-style="{ padding: '0px' }">
                  <LineChartComponent type="duration" :order="item.order" :dataRequest="dataRequest" :timeRange="timeRange"
                                      :metrics='["prepareAppInitActivities.start main frontend"]'
                                      :chartSettings="chartSettings"/>
                </el-card>
              </el-col>
            </el-row>

            <el-row :gutter="5">
              <el-col :span="12">
                <el-card shadow="never" :body-style="{ padding: '0px' }">
                  <LineChartComponent type="duration" :order="item.order" :dataRequest="dataRequest" :timeRange="timeRange"
                                      :metrics='["prepareAppInitActivities.uiRoot.s"]'
                                      :chartSettings="chartSettings"/>
                </el-card>
              </el-col>
              <el-col :span="12">
                <el-card shadow="never" :body-style="{ padding: '0px' }">
                  <LineChartComponent type="duration" :order="item.order" :dataRequest="dataRequest" :timeRange="timeRange"
                                      :metrics='["prepareAppInitActivities.start app.duration"]'
                                      :chartSettings="chartSettings"/>
                </el-card>
              </el-col>
            </el-row>

        </keep-alive>
      </el-tab-pane>
    </el-tabs>

</template>


Add OtherDecisions and OtherDevelopment Law as OtherDecisionsGeneral to DecisionSpecificFields

<template>

Ειδικά πεδία {{ selected | getSpecialFieldsTranslator}}

    <normative></normative>

    <circular></circular>

    <appointment></appointment>

    <award></award>

    <legislative-decree></legislative-decree>

    <other-decisions-general></other-decisions-general>

</template>

<template>

Ειδικά πεδία {{ selected | getSpecialFieldsTranslator}}

    <normative></normative>

    <circular></circular>

    <appointment></appointment>

    <award></award>

    <legislative-decree></legislative-decree>

</template>


Allow to use auto height/width for thumbnail widget

<template functional>
<img
  class="thumbnail-picture"
  :style="{
    width: props.width,
    height: props.height
  }"
  v-lazy="'/api/pictures/' + props.type + '/preview-files/' + props.previewFileId + '.png'"
  :key="props.previewFileId"
  v-bind="data.attrs"
  v-if="props.previewFileId"
/>
<span
  :class="{
    'thumbnail-picture': true,
    'thumbnail-empty': true
  }"
  :style="{
    width: props.width,
    height: props.emptyHeight ? props.emptyHeight : props.height,
  }"
  v-bind="data.attrs"
  v-else>
</span>
</template>

<script>
export default {
  name: 'light-entity-thumbnail',
  functional: true,

  props: {
    previewFileId: {
      default: '',
      type: String
    },
    width: {
      default: '150px',
      type: String
    },
    height: {
      default: '50px',
      type: String
    },
    emptyHeight: {
      type: String
    },
    type: {
      default: 'thumbnails',
      type: String
    }
  }
}
</script>

<style lang="scss">
.dark .thumbnail-picture {
  background-color: $dark-grey-lighter;
  border-color: $dark-grey-light;
}

span.thumbnail-empty {
  background: $white-grey;
  display: block;
  margin: 0;
}
</style>

<template functional>
<img
  class="thumbnail-picture"
  :style="{
    width: props.width + 'px',
    height: props.height + 'px'
  }"
  v-lazy="'/api/pictures/' + props.type + '/preview-files/' + props.previewFileId + '.png'"
  :key="props.previewFileId"
  v-bind="data.attrs"
  v-if="props.previewFileId"
/>
<span
  :class="{
    'thumbnail-picture': true,
    'thumbnail-empty': true
  }"
  :style="{
    width: props.width + 'px',
    height: props.height + 'px',
  }"
  v-bind="data.attrs"
  v-else>
</span>
</template>

<script>
export default {
  name: 'light-entity-thumbnail',
  functional: true,

  props: {
    previewFileId: {
      default: '',
      type: String
    },
    width: {
      default: 150,
      type: Number
    },
    height: {
      default: 50,
      type: Number
    },
    type: {
      default: 'thumbnails',
      type: String
    }
  }
}
</script>

<style lang="scss">
.dark .thumbnail-picture {
  background-color: $dark-grey-lighter;
  border-color: $dark-grey-light;
}

span.thumbnail-empty {
  background: $white-grey;
  display: block;
  margin: 0;
}
</style>


Change user image.

Change user image.

<template>
    <v-card id="welcome-profile-image-container">

            <slot name="header"></slot>

        <v-card-text class="mobile-dialog-content" v-if="hideCropImageDialog">

                <input type="file" accept="image/*" style="display: none" ref="openFileDialog"
                       @change="handleImageChange"/>
                <v-btn id="change-image-button" color="primary" @click="openUploadImage">
                    {{$t("common:button.changeImage")}}
                </v-btn>

                <slot name="description">{{$t("dialog:welcome.stepProfileImage.description")}}</slot>

        </v-card-text>
        <v-divider v-if="hideCropImageDialog"></v-divider>
        <v-card-actions v-if="hideCropImageDialog">
            <slot name="footer">
                <v-spacer></v-spacer>
                <v-btn color="primary" text @click="$emit('close-dialog')">
                    {{$t("common:button.later")}}
                </v-btn>
                <v-btn color="primary" @click="$emit('next')" :disabled="loading">
                    {{$t("common:button.next")}}
                </v-btn>
            </slot>
        </v-card-actions>
        <crop-image v-if="!hideCropImageDialog" :initial-image="imageToUpload"
                    :action-label="$t('common:button.changeImage')"
                    :upload-running="uploadImageRunning" :aspect-ratio="1"
                    @close="hideCropImageDialog = true" @action="uploadImage">
        </crop-image>
        <v-snackbar top v-model="showError" color="error" :timeout="0">{{$t("common:error.unknown")}}
            <v-btn dark text @click="showError = false">{{$t("common:button.close")}}</v-btn>
        </v-snackbar>
    </v-card>
</template>


update: 优化 ECharts 示例

update: 优化 ECharts 示例

<template>
    <div class="container">
        <view class="page-section-title" style="display: block;">
            <text>这是uni-app集成mpvue-echarts的图表示例，mpvue-echarts组件的用法参考：</text>
            <text class="navigate" @tap="goBrowser" selectable>https://github.com/F-loat/mpvue-echarts</text>
        </view>
        <view class="canvasView">
            <view class="title">饼图示例</view>
            <button type="primary" size="mini" @click="updatePie">修改饼状图数据</button>
            <mpvue-echarts :echarts="echarts" :onInit="pieInit" canvasId="pie" ref="pieChart" />
        </view>
        <view class="canvasView">
            <view class="title">折线图示例</view>
            <mpvue-echarts :echarts="echarts" :onInit="lineInit" canvasId="line" ref="lineChart" />
        </view>
    </div>
</template>

<script>
    import * as echarts from '../../../components/echarts/echarts.simple.min.js';
    import mpvueEcharts from '../../../components/mpvue-echarts/src/echarts.vue';

    let pieOption = {
        animation: false,
        backgroundColor: '#F8F8F8',
        color: ['#37A2DA', '#32C5E9', '#67E0E3', '#91F2DE', '#FFDB5C', '#FF9F7F'],
        series: [{
            label: {
                normal: {
                    fontSize: 14
                }
            },
            type: 'pie',
            center: ['50%', '50%'],
            radius: [0, '60%'],
            data: [{
                value: 55,
                name: '北京'
            }, {
                value: 38,
                name: '上海'
            }, {
                value: 20,
                name: '广州'
            }, {
                value: 10,
                name: '杭州'
            }],
            itemStyle: {
                emphasis: {
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowColor: 'rgba(0, 2, 2, 0.3)'
                }
            }
        }]
    };

    let lineOption = {
        animation: false,
        color: ['#37A2DA', '#9FE6B8'],
        grid: {
            x: 35,
            x2: 10,
            y: 30,
            y2: 25
        },
        calculable: false,
        xAxis: [{
            type: 'category',
            data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
        }],
        yAxis: [{
            type: 'value',
            splitArea: {
                show: true
            }
        }],
        series: [{
            name: '蒸发量',
            type: 'line',
            data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
        }, {
            name: '降水量',
            type: 'line',
            data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
        }]
    };

    export default {
        data() {
            return {
                echarts: echarts,
                updateStatus: false
            }
        },
        methods: {
            goBrowser() {
                // #ifdef APP-PLUS
                plus.runtime.openURL('https://github.com/F-loat/mpvue-echarts');
                // #endif
                // #ifdef MP-WEIXIN
                uni.showModal({
                    content: '请复制链接在浏览器里打开',
                    showCancel: false
                })
                // #endif
            },
            updatePie() {
                // 参考 mpvue-charts 的懒加载示例
                // https://github.com/F-loat/mpvue-echarts/blob/master/examples/lazyLoad.vue

                if (this.updateStatus) {
                    return;
                }
                pieOption.series[0].data.push({
                    value: 20,
                    name: '武汉'
                });
                this.$refs.pieChart.init();
            },
            pieInit(canvas, width, height) {
                let pieChart = echarts.init(canvas, null, {
                    width: width,
                    height: height
                })
                canvas.setChart(pieChart)

                pieChart.setOption(pieOption)
                return pieChart
            },
            lineInit(canvas, width, height) {
                let lineChart = echarts.init(canvas, null, {
                    width: width,
                    height: height
                })
                canvas.setChart(lineChart)

                lineChart.setOption(lineOption)
                return lineChart
            }
        },
        components: {
            mpvueEcharts
        }
    }
</script>

<style>
    page,
    view {
        display: flex;
        /* uni-app默认使用flex布局。因为flex布局有利于跨更多平台，尤其是采用原生渲染的平台。如不了解flex布局，请参考http://www.w3.org/TR/css3-flexbox/。若不需要flex布局可删除本行*/
    }

    page {
        min-height: 100%;
    }

    .title {
        margin-left: 30upx;
        color: #8f8f94;
    }

    .container {
        padding-bottom: 30upx;
        box-sizing: border-box;
    }

    .container,
    .canvasView {
        flex: 1;
        flex-direction: column;
    }

    .navigate {
        color: #007AFF;
    }
</style>

<template>
	<div class="container">
		<view class="page-section-title" style="display: block;">
			<text>这是uni-app集成mpvue-echarts的图表示例，mpvue-echarts组件的用法参考：</text>
			<text class="navigate" @tap="goBrowser" selectable>https://github.com/F-loat/mpvue-echarts</text>
		</view>
		<view class="canvasView">
			<view class="title">饼图示例</view>
			<mpvue-echarts :echarts="echarts" :onInit="pieInit" canvasId="pie" />
		</view>
		<view class="canvasView">
			<view class="title">折线图示例</view>
			<mpvue-echarts :echarts="echarts" :onInit="lineInit" canvasId="line" />
		</view>
	</div>
</template>

<script>
	import * as echarts from '../../../components/echarts/echarts.simple.min.js';
	import mpvueEcharts from '../../../components/mpvue-echarts/src/echarts.vue';

	function getPieOption() {
		return {
			animation: false,
			backgroundColor: '#F8F8F8',
			color: ['#37A2DA', '#32C5E9', '#67E0E3', '#91F2DE', '#FFDB5C', '#FF9F7F'],
			series: [{
				label: {
					normal: {
						fontSize: 14
					}
				},
				type: 'pie',
				center: ['50%', '50%'],
				radius: [0, '60%'],
				data: [{
					value: 55,
					name: '北京'
				}, {
					value: 20,
					name: '武汉'
				}, {
					value: 10,
					name: '杭州'
				}, {
					value: 20,
					name: '广州'
				}, {
					value: 38,
					name: '上海'
				}],
				itemStyle: {
					emphasis: {
						shadowBlur: 10,
						shadowOffsetX: 0,
						shadowColor: 'rgba(0, 2, 2, 0.3)'
					}
				}
			}]
		}
	}

	function getLineOption() {
		return {
			animation: false,
			color: ['#37A2DA', '#9FE6B8'],
			legend: {
				data: ['蒸发量', '降水量']
			},
			grid: {
				x: 35,
				x2: 10,
				y: 30,
				y2: 25
			},
			calculable: false,
			xAxis: [{
				type: 'category',
				data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
			}],
			yAxis: [{
				type: 'value',
				splitArea: {
					show: true
				}
			}],
			series: [{
				name: '蒸发量',
				type: 'line',
				data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
			}, {
				name: '降水量',
				type: 'line',
				data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
			}]
		}
	}

	export default {
		data() {
			return {
				echarts,
				pieInit: function (canvas, width, height) {
					let pieChart = echarts.init(canvas, null, {
						width: width,
						height: height
					})
					canvas.setChart(pieChart)

					pieChart.setOption(getPieOption())
					return pieChart
				},
				lineInit: function (canvas, width, height) {
					let lineChart = echarts.init(canvas, null, {
						width: width,
						height: height
					})
					canvas.setChart(lineChart)

					lineChart.setOption(getLineOption())
					return lineChart
				}
			}
		},
		methods: {
			goBrowser() {
				// #ifdef APP-PLUS
				plus.runtime.openURL("https://github.com/F-loat/mpvue-echarts");
				// #endif
				// #ifdef MP-WEIXIN
				uni.showModal({
					content:"请复制链接在浏览器里打开",
					showCancel:false
				})
				// #endif
			}
		},
		components: {
			mpvueEcharts
		}
	}
</script>

<style>
	page,
	view {
		display: flex;
		/* uni-app默认使用flex布局。因为flex布局有利于跨更多平台，尤其是采用原生渲染的平台。如不了解flex布局，请参考http://www.w3.org/TR/css3-flexbox/。若不需要flex布局可删除本行*/
	}

	page {
		min-height: 100%;
	}

	.title {
		margin-left: 30upx;
		color: #8f8f94;
	}

	.container {
		padding-bottom: 30upx;
		box-sizing: border-box;
	}

	.container,
	.canvasView {
		flex: 1;
		flex-direction: column;
	}

	.navigate {
		color: #007AFF;
	}
</style>


Removed now unused component

Removed now unused component

<template lang="pug">
  v-dialog(v-model='show', persistent, max-width='650', @keydown.esc='hide()')
    v-card
      v-card-title.headline Add «{{ title }}» to
      v-card-text
        v-layout(row, wrap)
          template(v-for='i in 5')
            v-flex(v-if='i < 4', xs4)
              v-checkbox.option(
                color='orange',
                v-model='selected',
                :value='options[i - 1].value',
                :label='options[i - 1].label'
              )
            v-flex.checkbox-container(v-else, xs6)
              v-checkbox.option(
                color='orange',
                v-model='selected',
                :value='options[i - 1].value',
                :label='options[i - 1].label'
              )
      v-card-actions
        v-spacer
        v-btn.blue--text.darken-1(text, @click='add()') Add
        v-btn.blue--text.darken-1(text, @click='hide()') Close
</template>

<script>
export default {
  data () {
    return {
      selected: [],
      options: [{
        label: 'Watch list',
        value: 'watchList'
      }, {
        label: 'Watching',
        value: 'watching'
      }, {
        label: 'Seen',
        value: 'seen'
      }, {
        label: 'On Hold',
        value: 'onHold'
      }, {
        label: 'Dropped',
        value: 'dropped'
      }]
    }
  },
  methods: {
    hide () {
      this.$store.commit('setAddToChoice', false)
    },
    add () {
      this.selected.forEach((listName) => {
        this.$store.dispatch('watchLists/updateList', {
          listName,
          entry: this.title
        })
      })

      this.hide()
    }
  },
  computed: {
    show: {
      get () {
        return this.$store.state.addToChoice.show
      },
      set (bool) {
        this.$store.commit('setAddToChoice', bool)
      }
    },
    title () {
      return this.$store.state.addToChoice.title
    }
  }
}
</script>

<style lang="stylus" scoped>
  .option
    width 60%
    margin-left 35%
</style>


remove href props, not needed

remove href props, not needed

<template>

{{ displayText }}

        <login-modal></login-modal>

Device Owner

{{ fullname }}

{{ username }}

{{ kind }}

            Logout

</template>


Fixes broken background color.

Fixes broken background color.

<template>
  <uw-card v-if="showOutageCard" :loaded="true" class="myuw-outage">
    <template #card-heading>

        Limited data due to technical difficulties

    </template>
    <template #card-body>

            We are aware of the issue and working on it. Please try again later.

        Things you might be looking for:

          Canvas LMS

          Catalyst Web Tools

          Student Registration

          Student Class Schedule

          Student Tuition Statement

          Time Schedule

          MyPlan

          My Class Instructor Resources

          GradePage

          Panopto Lecture Capture

          UW Professional & Continuing Education

          Workday

          MyFinancial.desktop

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


Load maps first in Home

Load maps first in Home

<template>
<section class="page page--welcome">
  <Welcome />
  <RecentSection class="section" v-if="isSectionActive('RecentSection') && hasRecentContent" @sectionChange="changeSection"/>
  <TagsSection class="section tags-section" v-if="isSectionActive('TagsSection')" @sectionChange="changeSection"/>
  <MapsSection class="section" />
  <DatasetsSection class="section section--noBorder" />
  <QuotaSection></QuotaSection>
</section>
</template>

<script>
import Welcome from './WelcomeSection/Welcome.vue';
import TagsSection from './TagsSection/TagsSection.vue';
import RecentSection from './RecentSection/RecentSection.vue';
import MapsSection from './MapsSection/MapsSection.vue';
import DatasetsSection from './DatasetsSection/DatasetsSection.vue';
import QuotaSection from './QuotaSection/QuotaSection.vue';
import { sendMetric, MetricsTypes } from 'new-dashboard/core/metrics';

export default {
  name: 'Home',
  components: {
    Welcome,
    TagsSection,
    RecentSection,
    MapsSection,
    DatasetsSection,
    QuotaSection
  },
  beforeMount () {
    this.$store.dispatch('recentContent/fetchContent');
  },
  created () {
    this.$store.dispatch('maps/resetFilters');
    this.$store.dispatch('datasets/resetFilters');

    if (this.isFirstTimeViewingDashboard) {
      sendMetric(MetricsTypes.VISITED_PRIVATE_PAGE, { page: 'dashboard' });
    }
  },
  data () {
    return {
      activeSection: 'RecentSection'
    };
  },
  computed: {
    hasRecentContent () {
      return this.$store.getters['recentContent/hasRecentContent'] ||
        this.$store.state.recentContent.isFetching;
    },
    isFirstTimeViewingDashboard () {
      return this.$store.state.config.isFirstTimeViewingDashboard;
    }
  },
  methods: {
    isSectionActive (activeSection) {
      return activeSection === this.activeSection;
    },
    changeSection (nextActiveSection) {
      this.activeSection = nextActiveSection;
    }
  }
};
</script>

<style scoped lang="scss">
@import 'stylesheets/new-dashboard/variables';

.page--welcome {
  padding: 64px 0 0;
}

.tags-section {
  padding-bottom: 104px;
}
</style>

<template>
<section class="page page--welcome">
  <Welcome />
  <RecentSection class="section" v-if="isSectionActive('RecentSection') && hasRecentContent" @sectionChange="changeSection"/>
  <TagsSection class="section tags-section" v-if="isSectionActive('TagsSection')" @sectionChange="changeSection"/>
  <MapsSection class="section" />
  <DatasetsSection class="section section--noBorder" />
  <QuotaSection></QuotaSection>
</section>
</template>

<script>
import Welcome from './WelcomeSection/Welcome.vue';
import TagsSection from './TagsSection/TagsSection.vue';
import RecentSection from './RecentSection/RecentSection.vue';
import MapsSection from './MapsSection/MapsSection.vue';
import DatasetsSection from './DatasetsSection/DatasetsSection.vue';
import QuotaSection from './QuotaSection/QuotaSection.vue';
import { sendMetric, MetricsTypes } from 'new-dashboard/core/metrics';

export default {
  name: 'Home',
  components: {
    Welcome,
    TagsSection,
    RecentSection,
    MapsSection,
    DatasetsSection,
    QuotaSection
  },
  beforeMount () {
    this.$store.dispatch('recentContent/fetchContent');
  },
  created () {
    this.$store.dispatch('datasets/resetFilters');
    this.$store.dispatch('maps/resetFilters');

    if (this.isFirstTimeViewingDashboard) {
      sendMetric(MetricsTypes.VISITED_PRIVATE_PAGE, { page: 'dashboard' });
    }
  },
  data () {
    return {
      activeSection: 'RecentSection'
    };
  },
  computed: {
    hasRecentContent () {
      return this.$store.getters['recentContent/hasRecentContent'] ||
        this.$store.state.recentContent.isFetching;
    },
    isFirstTimeViewingDashboard () {
      return this.$store.state.config.isFirstTimeViewingDashboard;
    }
  },
  methods: {
    isSectionActive (activeSection) {
      return activeSection === this.activeSection;
    },
    changeSection (nextActiveSection) {
      this.activeSection = nextActiveSection;
    }
  }
};
</script>

<style scoped lang="scss">
@import 'stylesheets/new-dashboard/variables';

.page--welcome {
  padding: 64px 0 0;
}

.tags-section {
  padding-bottom: 104px;
}
</style>


Move up/down/delete buttons.

Move up/down/delete buttons.

<template>

Niveaus

                <level-details v-for="(level, index) in rubric.levels" :has-new="!!newLevel" :selected-level="selectedLevel" :rubric="rubric" :level="level" tag="li" :key="`level_${index}`" @change="onLevelChange" @level-move-up="moveLevelUp" @level-move-down="moveLevelDown" @level-selected="selectLevel" @level-default="setDefault" @level-remove="showRemoveLevelDialog"></level-details>

                    <button class="btn-level-add" @click.stop="createNewLevel"> Niveau toevoegen</button>

                <level-details v-else :selected-level="newLevel" :has-new="true" :is-new="true" :rubric="rubric" :level="newLevel" tag="li" :key="`level_${rubric.levels.length}`" @new-level-added="addLevel" @new-level-canceled="cancelLevel" @level-default="setDefault"></level-details>

Niveau '{{ removingLevel.title }}' verwijderen?

                    <button class="btn-dialog-remove btn-ok" ref="btn-remove-level" @click.stop="removeLevel(removingLevel)">Verwijder</button>
                    <button class="btn-dialog-remove btn-cancel" @click.stop="hideRemoveLevelDialog">Annuleer</button>

</template>


changing URL and copy for PCE not current state.

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

U-Pass Membership

    </template>
    <template #card-error>
      An error occurred and MyUW cannot load your U-PASS status right now. In the meantime,
      you may check out the
      U-PASS page.
    </template>
    <template #card-body>
      <uw-card-status>
        <template #status-label>Status</template>
        <template #status-value>
          {{ isCurrent ? 'Current' : 'Not current' }}
        </template>
      </uw-card-status>

          U-PASS not working?

          U-PASS not working?

          What is the U-PASS?

            Some employees automatically qualify for a

              subsidized U-PASS.
            If you do not qualify, you can purchase a quarterly or annual U-PASS
            through your campus transportation office.

              If you are registered for a quarter, your U-PASS will work one week
              before the quarter starts.

              If you

                purchase
              a U-PASS for a quarter, your U-PASS will work one week before the quarter starts.

            Summer U-PASS Use

            Unless you are registered for summer quarter, your U-PASS will not
            work during summer quarter. Check your

              campus transportation office for summer transit options.

              What is the U-PASS?

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

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

U-Pass Membership

    </template>
    <template #card-error>
      An error occurred and MyUW cannot load your U-PASS status right now. In the meantime,
      you may check out the
      U-PASS page.
    </template>
    <template #card-body>
      <uw-card-status>
        <template #status-label>Status</template>
        <template #status-value>
          {{ isCurrent ? 'Current' : 'Not current' }}
        </template>
      </uw-card-status>

          U-PASS not working?

          U-PASS not working?

          What is the U-PASS?

            Some employees automatically qualify for a

              subsidized U-PASS.
            If you do not qualify, you can purchase a quarterly or annual U-PASS
            through your campus transportation office.

              If you are registered for a quarter, your U-PASS will work one week
              before the quarter starts.

              If you

                purchase

              a U-PASS for a quarter, your U-PASS will work one week before the quarter starts.

            Summer U-PASS Use

            Unless you are registered for summer quarter, your U-PASS will not
            work during summer quarter. Check your

              campus transportation office
             for summer transit options.

              What is the U-PASS?

              Purchasing a U-PASS

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


Don't capture pointer events on the select component caret

<template>

    <input
      @click="active ? false : open()"
      @focus="open"
      @blur="close"
      @keydown.space="active ? false : open()"
      @keydown.enter.prevent="active ? select('enter') : open()"
      @keydown.esc="close"
      @keydown.up.prevent="active ? up() : open()"
      @keydown.down.prevent="active ? down() : open()"
      v-model="valueText"
      class="select"
      :id="id"
      :tabindex="disabled ? -1 : 0"
      role="listbox"
      :placeholder="placeholder"
      :readonly="!hasFilter || readonly || !active"
      :disabled="disabled"
    >

      <option
        v-for="(option, index) in list"
        :key="option.id"
        :data-id="option.id"
        class="input-select-option"
        :class="{ 'selected': index === i}"
        role="option"
        :disabled="option.disabled"
      >
        {{ option.text }}
      </option>

        No matches

</template>


New website (#416)

New website (#416)

* new website ui: visuallizer page

* new website: replay heading

* add video image, add post game dashboard

* update new website: add some graph images. real graph will be added soon

* update new website: add button login in mobile

* new website: update hover state for footer and header navigators

* new website: hide post game dashboard content by default

* new website: add version in post game dashboard

* CSS fix for header and submit bot button

* Minor margin adjustment

* Added deployment files

* Updated remote deploy

* Added more deployment fixes

* Updated deployment scripts

* Fixed up deployments

* Fixed up docs

* Add header menu selected in different sections.

* Halite promo website (#269)

* Added base site

* Fixed up assets

* Fixed more assets

* Adding missing pages

* Updated Home page to use new template

* Updated config to point to staging

* Add forum item in header navigation and adjust elements in footer

* Move halite tv from html to vue

* ignore yarn

* fix a bug

* add baseurl

* Move halitetv from html to vue (#276)

* Move halite tv from html to vue

* fix a bug

* fix conflict

* remove the duplicate script

* Move user avatar outside and to the right

* Add a popup for the nav

* change HaliteTV component to Visualizer

* Add Player stats with faked data since api server was down

* update tab pane of player stats

* Update: rename visuallizer -> old visualizer

* Fix header layout after login

* Add some sections in home page

* Add some sections in home page (#293)

* player stats: display real data

* add player detail pane

* change player detail component name

* remove debug

* Player Stats & Player detail panes (#298)

* player stats: display real data

* add player detail pane

* change player detail component name

* remove debug

* Update home page sections

* add replay panel

* add player chart

* update gemfile & remove unused code

* move d3 package to the right place

* make the player stats works

* implement video controller actions

* Update home page and set up individual hackathon page

* visualizer page: video player

* remove comment

* Fix replay controller bugs

* Revert "Fix replay controller bugs"

This reverts commit b4223777397cfd1ce4d231a3fa9ae00bd3c6f9ce.

* Revert "Revert "Fix replay controller bugs""

This reverts commit e30d5777ee7677c47a99fef23dbe7e5be049d5e9.

* revert package-lock.json

* add play page

* line chart

* fix

* add player name

* update game time & fix name overflow

* Update copy of player detail pane.

* prevent dragging result the decimal frame number

* add start frame and end frame for frame slider

* add space to player name, reduce player name size, remove version number in the play name

* Modify global layout and add Teko font

* Modify global layout and add Teko font (#324)

* update tier

* Uppercase the header nav

* update the player tier badge and color

* Update the font of header elements

* Update selected object, change the player color to match the players in the video

* Add selected object component, update player chart information

* Object properties (#331)

* update tier

* Uppercase the header nav

* update the player tier badge and color

* Update selected object, change the player color to match the players in the video

* Add selected object component, update player chart information

* upload replay

* add upload replay feature

* update style

* fix merge bug

* Move the header nav to left

* fix merge bug (#342)

* Move the header nav to left (#343)

* fix some font bugs and change texts

* add a link from the footer

* Render map detail

* Render map detail

* update arrow animation

* remove logs

* update sections of homepage for beta

* Revert "update sections of homepage for beta"

This reverts commit 8d2f04dc2e440dc6113d17046b0bafd147355667.

* update sections of homepage for beta

* Fix commented out section in Home.vue

* Minor css change for login button

* Adding reddit widget

* Update play layout

* Add the upload state

* reverse the comment block for testing

* update width of page content (#358)

* Play flow page (#357)

* Update play layout

* Add the upload state

* reverse the comment block for testing

* add hackathon page

* fix conflict

* Update play flow layout

* Fix home page

* Update log in message style

* Update log in message style (#371)

* update notification color and font (#370)

* update width of page content

* update subcopy line align

* implement play flow: bot upload state

* Show the right avatar in post game dashboard

* implement play flow: bot upload state

* Play flow: Upload state error message

* update map stats color

* Put in fake IDs for hackathon

* remove comment, add cancel action

* implement play flow: bot upload state

* Play flow: Upload state error message

* fix merge

* remove console log

* Fix create account redirect

* Merge branch 'new-website' into play-flow (#377)

* Adding css file for associate page

* Add todo comment

* Play flow (#383)

* Update Play Flow

* Hackathon Individual: how to join and leaderboard

* add utils functions

* Update Play Flow

* Hackathon Individual: how to join and leaderboard

* add utils functions

* Update leaderboard table

* Link up buttons in home page

* Update play flow, automatically get bot compilation status

* remove comment

* Create account page: frontend

* Create Account: update form

* Uncomment redirect in associate

* Add leaderboard filter and pagination component (#402)

* add base leaderboard UI

* Add page component(not finish)

* Make sure leaderboard links work in hackathon

* add global alert, create account fields

* Update adding hackathon

* rollback the comment code

* Update anchor link

* Update anchor

* redirect to play page when click on “submit a bot“ in user profile bar

<template>

view profile

edit profile

sign out

                Submit a Bot

                            <img class="icon" :src="`${baseUrl}/assets/images/temp/submit-bot.png`"/>

SUBMIT A BOT

Drop a .bot file here to upload

SELECT FILE

</template>


Fix typo

Fix typo


Fix compatibility with UWC

Fix compatibility with UWC

<template>
    <div>
        <v-row class="equal-height-row">
            <v-col>
                <switch-datasets-card
                    :selected-assays="this.$store.getters.getSelectedAssays"
                    :active-assay="this.$store.getters.getActiveAssay"
                    v-on:deselect-assay="onDeselectAssay"
                    v-on:activate-assay="onActivateAssay"
                    v-on:assay-selection-in-progress="onAssaySelection"
                    style="min-height: 100%;">
                </switch-datasets-card>
            </v-col>
            <v-col>
                <experiment-summary-card
                    v-if="!datasetSelectionInProgress"
                    style="min-height: 100%;"
                    :disabled="$store.getters.getSelectedAssays.some(el => el.progress !== 1)"
                    :activeAssay="$store.getters.getActiveAssay"
                    v-on:update-search-settings="onUpdateSearchSettings">
                </experiment-summary-card>
                <load-datasets-card
                    v-else
                    :selected-assays="this.$store.getters.getSelectedAssays"
                    :stored-assays="this.$store.getters.getStoredAssays"
                    v-on:create-assay="onCreateAssay"
                    style="min-height: 100%;"
                    id="analysis-add-dataset-card">
                </load-datasets-card>
            </v-col>
        </v-row>
        <single-dataset-visualizations-card id="visualizations-card"
            :dataRepository="this.$store.getters.getActiveAssay ? this.$store.getters.getActiveAssay.dataRepository : null"
            :analysisInProgress="$store.getters.datasetsInProgress > 0">
        </single-dataset-visualizations-card>
        <functional-summary-card style="margin-top: 12px;"
            :dataRepository="this.$store.getters.getActiveAssay ? this.$store.getters.getActiveAssay.dataRepository : null"
            :analysisInProgress="$store.getters.datasetsInProgress > 0"
            :selected-taxon-id="$store.getters.getSelectedTaxonId">
        </functional-summary-card>
    </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import {Prop, Watch} from "vue-property-decorator";
import FunctionalSummaryCard from "unipept-web-components/src/components/analysis/functional/FunctionalSummaryCard.vue";
import SingleDatasetVisualizationsCard from "unipept-web-components/src/components/visualizations/SingleDatasetVisualizationsCard.vue";
import LoadDatasetsCard from "./../dataset/LoadDatasetsCard.vue";
import SwitchDatasetsCard from "./../dataset/SwitchDatasetsCard.vue";
import ExperimentSummaryCard from "unipept-web-components/src/components/analysis/statistics/ExperimentSummaryCard.vue";
import PeptideContainer from "unipept-web-components/src/logic/data-management/PeptideContainer";
import Assay from "unipept-web-components/src/logic/data-management/assay/Assay";

@Component({
    components: {
        FunctionalSummaryCard,
        SingleDatasetVisualizationsCard,
        LoadDatasetsCard,
        SwitchDatasetsCard,
        ExperimentSummaryCard
    },
    computed: {
        selectedDatasets: {
            get() {
                return this.$store.getters.selectedDatasets;
            }
        }
    }
})
export default class AnalysisPage extends Vue {
    private datasetSelectionInProgress: boolean = false;
    private eventListeners: {type: string, listener: any}[] = [];

    created() {
        for (let assay of this.$store.getters.getSelectedAssays) {
            this.$store.dispatch('processAssay', assay);
        }
    }

    private onDeselectAssay(assay: Assay) {
        this.$store.dispatch("deselectAssay", assay);
    }

    private onActivateAssay(assay: Assay) {
        this.$store.dispatch("setActiveAssay", assay);
    }

    private onCreateAssay(assay: Assay) {
        this.$store.dispatch("processAssay", assay);
    }

    private onAssaySelection(status: boolean) {
        this.datasetSelectionInProgress = status;
    }

    private onUpdateSearchSettings(settings: MPAConfig) {
        // We need to reprocess all assays with the new search settings.
        this.$store.dispatch("updateSearchSettings", settings);

    }
}
</script>

<style>
    #analysis-add-dataset-card::before {
        content:"\A";
        border-top: 24px solid transparent;
        border-bottom: 24px solid transparent;
        border-right: 24px solid #2196F3;
        z-index: 5;
        position: absolute;
        left: -24px;
    }

    #analysis-add-dataset-card {
        border-top-left-radius: 0px;
    }
</style>

<template>
    <div>
        <v-row class="equal-height-row">
            <v-col>
                <switch-datasets-card
                    :selected-assays="this.$store.getters.getSelectedAssays"
                    :active-assay="this.$store.getters.getActiveAssay"
                    v-on:deselect-assay="onDeselectAssay"
                    v-on:activate-assay="onActivateAssay"
                    v-on:assay-selection-in-progress="onAssaySelection"
                    style="min-height: 100%;">
                </switch-datasets-card>
            </v-col>
            <v-col>
                <experiment-summary-card
                    v-if="!datasetSelectionInProgress"
                    style="min-height: 100%;"
                    :disabled="$store.getters.getSelectedAssays.some(el => el.progress !== 1)"
                    :activeAssay="$store.getters.getActiveAssay"
                    v-on:update-search-settings="onUpdateSearchSettings">
                </experiment-summary-card>
                <load-datasets-card
                    v-else
                    :selected-assays="this.$store.getters.getSelectedAssays"
                    :stored-assays="this.$store.getters.getStoredAssays"
                    v-on:create-assay="onCreateAssay"
                    style="min-height: 100%;"
                    id="analysis-add-dataset-card">
                </load-datasets-card>
            </v-col>
        </v-row>
        <single-dataset-visualizations-card id="visualizations-card" :dataRepository="this.$store.getters.getActiveAssay ? this.$store.getters.getActiveAssay.dataRepository : null" :analysisInProgress="$store.getters.datasetsInProgress > 0"></single-dataset-visualizations-card>
        <functional-summary-card style="margin-top: 12px;" :dataRepository="this.$store.getters.getActiveAssay ? this.$store.getters.getActiveAssay.dataRepository : null" :analysisInProgress="$store.getters.datasetsInProgress > 0"></functional-summary-card>
    </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import {Prop, Watch} from "vue-property-decorator";
import FunctionalSummaryCard from "unipept-web-components/src/components/analysis/functional/FunctionalSummaryCard.vue";
import SingleDatasetVisualizationsCard from "unipept-web-components/src/components/visualizations/SingleDatasetVisualizationsCard.vue";
import LoadDatasetsCard from "./../dataset/LoadDatasetsCard.vue";
import SwitchDatasetsCard from "./../dataset/SwitchDatasetsCard.vue";
import ExperimentSummaryCard from "unipept-web-components/src/components/analysis/statistics/ExperimentSummaryCard.vue";
import PeptideContainer from "unipept-web-components/src/logic/data-management/PeptideContainer";
import Assay from "unipept-web-components/src/logic/data-management/assay/Assay";

@Component({
    components: {
        FunctionalSummaryCard,
        SingleDatasetVisualizationsCard,
        LoadDatasetsCard,
        SwitchDatasetsCard,
        ExperimentSummaryCard
    },
    computed: {
        selectedDatasets: {
            get() {
                return this.$store.getters.selectedDatasets;
            }
        }
    }
})
export default class AnalysisPage extends Vue {
    private datasetSelectionInProgress: boolean = false;
    private eventListeners: {type: string, listener: any}[] = [];

    created() {
        for (let assay of this.$store.getters.getSelectedAssays) {
            this.$store.dispatch('processAssay', assay);
        }
    }

    private onDeselectAssay(assay: Assay) {
        this.$store.dispatch("deselectAssay", assay);
    }

    private onActivateAssay(assay: Assay) {
        this.$store.dispatch("setActiveAssay", assay);
    }

    private onCreateAssay(assay: Assay) {
        this.$store.dispatch("processAssay", assay);
    }

    private onAssaySelection(status: boolean) {
        this.datasetSelectionInProgress = status;
    }

    private onUpdateSearchSettings(settings: MPAConfig) {
        // We need to reprocess all assays with the new search settings.
        this.$store.dispatch("updateSearchSettings", settings);

    }
}
</script>

<style>
    #analysis-add-dataset-card::before {
        content:"\A";
        border-top: 24px solid transparent;
        border-bottom: 24px solid transparent;
        border-right: 24px solid #2196F3;
        z-index: 5;
        position: absolute;
        left: -24px;
    }

    #analysis-add-dataset-card {
        border-top-left-radius: 0px;
    }
</style>


Clean user detail

Clean user detail

<template>

 {{ $t('sidebar.user.title')}} >

        <el-form :model="userForm" :rules="rules" ref="userForm">
          <el-form-item prop="email">
            <el-input placeholder="Email" v-model="userForm.email"></el-input>
          </el-form-item>
          <el-form-item prop="password">
            <el-input type="password" placeholder="Heslo" v-model="userForm.password"></el-input>
          </el-form-item>
          <el-button @click="signIn" class="full-width-btn" type="primary">{{ $t('sidebar.user.buttons.login') }}</el-button>

 - {{ $t('sidebar.user.misc.or') }} -

          <el-button @click="register" class="full-width-btn" type="primary"> {{ $t('sidebar.user.buttons.registration') }} </el-button>
        </el-form>

        <el-button @click="signOut" class="full-width-btn" type="primary">{{ $t('sidebar.user.buttons.logout') }}</el-button>

 Adresy

            <el-button id="add-address-btn" type="primary" class="full-width-btn" @click="isAddingAddress = !isAddingAddress">

                Přidat adresu

                Skrýt

            </el-button>

              <address-form @added="isAddingAddress = false"></address-form>

            <address-card v-for="address in addresses" :key="address.id" :address="address"></address-card>

</template>

<template>

 {{ $t('sidebar.user.title')}} >

        <el-form :model="userForm" :rules="rules" ref="userForm">
          <el-form-item prop="email">
            <el-input placeholder="Email" v-model="userForm.email"></el-input>
          </el-form-item>
          <el-form-item prop="password">
            <el-input type="password" placeholder="Heslo" v-model="userForm.password"></el-input>
          </el-form-item>
          <el-button @click="signIn" class="full-width-btn" type="primary">{{ $t('sidebar.user.buttons.login') }}</el-button>

 - {{ $t('sidebar.user.misc.or') }} -

          <el-button @click="register" class="full-width-btn" type="primary"> {{ $t('sidebar.user.buttons.registration') }} </el-button>
        </el-form>

        <el-button @click="signOut" class="full-width-btn" type="primary">{{ $t('sidebar.user.buttons.logout') }}</el-button>

 Detail

                {{ $t('sidebar.user.form.name') }}

                <el-input @change="userDetailTouched = true" name="name" v-model="user.name"></el-input>

                {{ $t('sidebar.user.form.surname') }}

                <el-input @blur="userDetailTouched = true" name="surname" v-model="user.surname"></el-input>

            <el-button v-if="userDetailTouched" @click="updateUserDetail" class="full-width-btn mt-2" type="primary">
              {{ $t('sidebar.user.buttons.saveChanges') }}
            </el-button>

 Adresy

            <el-button id="add-address-btn" type="primary" class="full-width-btn" @click="isAddingAddress = !isAddingAddress">

                Přidat adresu

                Skrýt

            </el-button>

              <address-form @added="isAddingAddress = false"></address-form>

            <address-card v-for="address in addresses" :key="address.id" :address="address"></address-card>

</template>


表記を合わせる

表記を合わせる

<template>

1 件見つかりました。本当に登録しますか？

                タイトル: {{ this.items[0].title }}
                巻号: {{ this.items[0].volume }}
                著者等: {{ this.items[0].authors }}

</template>

<template>

一件見つかりました。本当に登録しますか？

                タイトル: {{ this.items[0].title }}
                巻号: {{ this.items[0].volume }}
                著者等: {{ this.items[0].authors }}

</template>


Extract inline styling into the stylesheet

<template>

        <router-link to="/" class="vertical-align-child navbar-buttons">

        </router-link>

          <button class="button-dropdown button-group-margin vertical-align-child navbar-buttons" id="manage-file">

Manage

          </button>

            <input
              v-model="fileFormat"
              placeholder="File format"
              class="file-format-input-box"
            />
            <button v-on:click="updateParent('pages')" data-format="pages">Pages</button>
            <button v-on:click="updateParent('slides')" data-format="slides">Slides</button>
            <button v-on:click="updateParent('html')" data-format="html">HTML</button>

        <button class="navbar-buttons" id="button-editor"
                v-on:click="updateParent('editor')"
        >
        edit
        </button>
        <button class="navbar-buttons" id="button-split-screen"
                v-on:click="updateParent('split')"
        >

        </button>
        <button class="navbar-buttons" id="button-viewer"
                v-on:click="updateParent('viewer')"
        >
        remove_red_eye
        </button>

</template>

<template>

        <router-link to="/" class="vertical-align-child navbar-buttons">

        </router-link>

          <button class="button-dropdown button-group-margin vertical-align-child navbar-buttons" id="manage-file">

Manage

          </button>

            <input
              v-model="fileFormat"
              placeholder="File format"
              style="width: 100%;
              box-sizing: border-box;
              font-size: 1em;
              padding: 10px;
              padding-left: 10px;
              padding-right: 2px;"
            />
            <button v-on:click="updateParent('pages')" data-format="pages">Pages</button>
            <button v-on:click="updateParent('slides')" data-format="slides">Slides</button>
            <button v-on:click="updateParent('html')" data-format="html">HTML</button>

        <button class="navbar-buttons" id="button-editor"
                v-on:click="updateParent('editor')"
        >
        edit
        </button>
        <button class="navbar-buttons" id="button-split-screen"
                v-on:click="updateParent('split')"
        >

        </button>
        <button class="navbar-buttons" id="button-viewer"
                v-on:click="updateParent('viewer')"
        >
        remove_red_eye
        </button>

</template>


modify views product

modify views product

<template>

{{ product.name }}

¥ {{ product.cost }}

加入购物车

产品介绍

</template>


Make property name more descriptive

Make property name more descriptive

<template>

Add Tracker

                        <button @click="step2">+</button>

Choose Currency

                        <form action="javascript:void(0);">
                            <tracker-add-select
                                    :coin-list="coinList"
                                    :valid="selectedCoinValid"
                                    @on-change="handleCurrencySelect"
                                    @clear-error="handleCurrencyClearError"
                                    >
                            </tracker-add-select>

                                <button class="btn btn-info tracker-create" type="submit" @click="stepComplete">Create</button>

                        </form>

Choose Source

Success

</template>

<template>

Add Tracker

                        <button @click="step2">+</button>

Choose Currency

                        <form action="javascript:void(0);">
                            <tracker-add-select
                                    :coin-list="coinList"
                                    :valid="selectedCoinValid"
                                    @on-change="handleCurrencySelect"
                                    @clear-error="handleClearError"
                                    >
                            </tracker-add-select>

                                <button class="btn btn-info tracker-create" type="submit" @click="stepComplete">Create</button>

                        </form>

Choose Source

Success

</template>


#2593 (desktop) (#3518)

#2593 (desktop) (#3518)

<template>

				<mk-user-name :user="u"/>[x]

			{{ $t('add-visible-user') }}

 0 && $store.state.settings.suggestRecentHashtags">
			{{ $t('recent-tags') }}:
			#{{ tag }}

{{ $t('local-only-message') }}

		<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('annotations')" v-autocomplete="'cw'">

			<textarea :class="{ with: (files.length != 0 || poll) }"
				ref="text" v-model="text" :disabled="posting"
				@keydown="onKeydown" @paste="onPaste" :placeholder="placeholder"
				v-autocomplete="'text'"
			></textarea>
			<button class="emoji" @click="emoji" ref="emoji">
				<fa :icon="['far', 'laugh']"/>
			</button>

				<x-draggable :list="files" :options="{ animation: 150 }">

						<div class="img" :style="{ backgroundImage: `url(${file.thumbnailUrl})` }" :title="file.name">

				</x-draggable>

{{ 4 - files.length }}/4

			<mk-poll-editor v-if="poll" ref="poll" @destroyed="poll = false" @updated="onPollUpdate()"/>

	<mk-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/>
	<button class="upload" :title="$t('attach-media-from-local')" @click="chooseFile"><fa icon="upload"/></button>
	<button class="drive" :title="$t('attach-media-from-drive')" @click="chooseFileFromDrive"><fa icon="cloud"/></button>
	<button class="kao" :title="$t('insert-a-kao')" @click="kao"><fa :icon="['far', 'smile']"/></button>
	<button class="poll" :title="$t('create-poll')" @click="poll = !poll"><fa icon="chart-pie"/></button>
	<button class="cw" :title="$t('hide-contents')" @click="useCw = !useCw"><fa :icon="['far', 'eye-slash']"/></button>
	<button class="geo" :title="$t('attach-location-information')" @click="geo ? removeGeo() : setGeo()"><fa icon="map-marker-alt"/></button>
	<button class="visibility" :title="$t('visibility')" @click="setVisibility" ref="visibilityButton">
		<fa icon="globe"/>
		<fa icon="home"/>
		<fa icon="unlock"/>
		<fa icon="envelope"/>
		<fa icon="lock"/>
	</button>

 maxNoteTextLength }">{{ maxNoteTextLength - trimmedLength(text) }}

	<button :class="{ posting }" class="submit" :disabled="!canPost" @click="post">
		{{ posting ? $t('posting') : submitText }}<mk-ellipsis v-if="posting"/>
	</button>
	<input ref="file" type="file" multiple="multiple" tabindex="-1" @change="onChangeFile"/>

</template>

<template>

				<mk-user-name :user="u"/>[x]

			{{ $t('add-visible-user') }}

 0 && $store.state.settings.suggestRecentHashtags">
			{{ $t('recent-tags') }}:
			#{{ tag }}

{{ $t('local-only-message') }}

		<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('annotations')" v-autocomplete="'cw'">

			<textarea :class="{ with: (files.length != 0 || poll) }"
				ref="text" v-model="text" :disabled="posting"
				@keydown="onKeydown" @paste="onPaste" :placeholder="placeholder"
				v-autocomplete="'text'"
			></textarea>
			<button class="emoji" @click="emoji" ref="emoji">
				<fa :icon="['far', 'laugh']"/>
			</button>

				<x-draggable :list="files" :options="{ animation: 150 }">

						<div class="img" :style="{ backgroundImage: `url(${file.thumbnailUrl})` }" :title="file.name">

				</x-draggable>

{{ 4 - files.length }}/4

			<mk-poll-editor v-if="poll" ref="poll" @destroyed="poll = false" @updated="saveDraft()"/>

	<mk-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/>
	<button class="upload" :title="$t('attach-media-from-local')" @click="chooseFile"><fa icon="upload"/></button>
	<button class="drive" :title="$t('attach-media-from-drive')" @click="chooseFileFromDrive"><fa icon="cloud"/></button>
	<button class="kao" :title="$t('insert-a-kao')" @click="kao"><fa :icon="['far', 'smile']"/></button>
	<button class="poll" :title="$t('create-poll')" @click="poll = !poll"><fa icon="chart-pie"/></button>
	<button class="cw" :title="$t('hide-contents')" @click="useCw = !useCw"><fa :icon="['far', 'eye-slash']"/></button>
	<button class="geo" :title="$t('attach-location-information')" @click="geo ? removeGeo() : setGeo()"><fa icon="map-marker-alt"/></button>
	<button class="visibility" :title="$t('visibility')" @click="setVisibility" ref="visibilityButton">
		<fa icon="globe"/>
		<fa icon="home"/>
		<fa icon="unlock"/>
		<fa icon="envelope"/>
		<fa icon="lock"/>
	</button>

 maxNoteTextLength }">{{ maxNoteTextLength - trimmedLength(text) }}

	<button :class="{ posting }" class="submit" :disabled="!canPost" @click="post">
		{{ posting ? $t('posting') : submitText }}<mk-ellipsis v-if="posting"/>
	</button>
	<input ref="file" type="file" multiple="multiple" tabindex="-1" @change="onChangeFile"/>

</template>


增加wall的click效果

增加wall的click效果

<template>

        <button
          class="btn-floating btn-large waves-effect waves-light tooltipped"
          data-position="right" data-delay="0" data-tooltip="选择模式"
          :class="mode === 'select' ? 'purple' : 'white'"
          @click="mode = 'select'"
        >

        </button>

        <button
          class="btn-floating btn-large waves-effect waves-light tooltipped"
          data-position="right" data-delay="0" data-tooltip="画墙模式"
          :class="mode === 'wall' ? 'yellow darken-2' : 'white'"
          @click="mode = 'wall'"
        >

        </button>

        <button
          class="btn-floating btn-large waves-effect waves-light tooltipped"
          data-position="right" data-delay="0" data-tooltip="画门模式"
          :class="mode === 'door' ? 'green' : 'white'"
          @click="mode = 'door'"
        >

        </button>

        <button
          class="btn-floating btn-large waves-effect waves-light tooltipped"
          data-position="right" data-delay="0" data-tooltip="画窗模式"
          :class="mode === 'window' ? 'blue' : 'white'"
          @click="mode = 'window'"
        >

        </button>

    {{'x=' + mousePos.x + ', y=' + mousePos.y}}
    <button
      class="btn-large waves-effect waves-light red tooltipped"
      data-position="right" data-delay="0" data-tooltip="加载背景"
      @click="loadBackgroundImg"
    >

    </button>

  <input
    id="blueprint-edit-panel__background-input"
    type="file"
    @change="onBackgroundImgChange"
  />

</template>


[ux] Make text area extensible

[ux] Make text area extensible

<template>

  {{ label }}

    <textarea
      ref="input"
      class="input"
      :class="'input ' + inputClass"
      :placeholder="placeholder"
      :type="type"
      :value="value"
      @input="updateValue"
      @keyup.enter="emitEnter"
      @keyup="emitKeyup"
    />

</template>