diff --git a/src/web/app/common/-tags/uploader.tag b/src/web/app/common/-tags/uploader.tag deleted file mode 100644 index 519b063fac..0000000000 --- a/src/web/app/common/-tags/uploader.tag +++ /dev/null @@ -1,199 +0,0 @@ -<mk-uploader> - <ol v-if="uploads.length > 0"> - <li each={ uploads }> - <div class="img" style="background-image: url({ img })"></div> - <p class="name">%fa:spinner .pulse%{ name }</p> - <p class="status"><span class="initing" v-if="progress == undefined">%i18n:common.tags.mk-uploader.waiting%<mk-ellipsis/></span><span class="kb" v-if="progress != undefined">{ String(Math.floor(progress.value / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }<i>KB</i> / { String(Math.floor(progress.max / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }<i>KB</i></span><span class="percentage" v-if="progress != undefined">{ Math.floor((progress.value / progress.max) * 100) }</span></p> - <progress v-if="progress != undefined && progress.value != progress.max" value={ progress.value } max={ progress.max }></progress> - <div class="progress initing" v-if="progress == undefined"></div> - <div class="progress waiting" v-if="progress != undefined && progress.value == progress.max"></div> - </li> - </ol> - <style lang="stylus" scoped> - :scope - display block - overflow auto - - &:empty - display none - - > ol - display block - margin 0 - padding 0 - list-style none - - > li - display block - margin 8px 0 0 0 - padding 0 - height 36px - box-shadow 0 -1px 0 rgba($theme-color, 0.1) - border-top solid 8px transparent - - &:first-child - margin 0 - box-shadow none - border-top none - - > .img - display block - position absolute - top 0 - left 0 - width 36px - height 36px - background-size cover - background-position center center - - > .name - display block - position absolute - top 0 - left 44px - margin 0 - padding 0 - max-width 256px - font-size 0.8em - color rgba($theme-color, 0.7) - white-space nowrap - text-overflow ellipsis - overflow hidden - - > [data-fa] - margin-right 4px - - > .status - display block - position absolute - top 0 - right 0 - margin 0 - padding 0 - font-size 0.8em - - > .initing - color rgba($theme-color, 0.5) - - > .kb - color rgba($theme-color, 0.5) - - > .percentage - display inline-block - width 48px - text-align right - - color rgba($theme-color, 0.7) - - &:after - content '%' - - > progress - display block - position absolute - bottom 0 - right 0 - margin 0 - width calc(100% - 44px) - height 8px - background transparent - border none - border-radius 4px - overflow hidden - - &::-webkit-progress-value - background $theme-color - - &::-webkit-progress-bar - background rgba($theme-color, 0.1) - - > .progress - display block - position absolute - bottom 0 - right 0 - margin 0 - width calc(100% - 44px) - height 8px - border none - border-radius 4px - background linear-gradient( - 45deg, - lighten($theme-color, 30%) 25%, - $theme-color 25%, - $theme-color 50%, - lighten($theme-color, 30%) 50%, - lighten($theme-color, 30%) 75%, - $theme-color 75%, - $theme-color - ) - background-size 32px 32px - animation bg 1.5s linear infinite - - &.initing - opacity 0.3 - - @keyframes bg - from {background-position: 0 0;} - to {background-position: -64px 32px;} - - </style> - <script lang="typescript"> - this.mixin('i'); - - this.uploads = []; - - this.upload = (file, folder) => { - if (folder && typeof folder == 'object') folder = folder.id; - - const id = Math.random(); - - const ctx = { - id: id, - name: file.name || 'untitled', - progress: undefined - }; - - this.uploads.push(ctx); - this.$emit('change-uploads', this.uploads); - this.update(); - - const reader = new FileReader(); - reader.onload = e => { - ctx.img = e.target.result; - this.update(); - }; - reader.readAsDataURL(file); - - const data = new FormData(); - data.append('i', this.I.token); - data.append('file', file); - - if (folder) data.append('folder_id', folder); - - const xhr = new XMLHttpRequest(); - xhr.open('POST', _API_URL_ + '/drive/files/create', true); - xhr.onload = e => { - const driveFile = JSON.parse(e.target.response); - - this.$emit('uploaded', driveFile); - - this.uploads = this.uploads.filter(x => x.id != id); - this.$emit('change-uploads', this.uploads); - - this.update(); - }; - - xhr.upload.onprogress = e => { - if (e.lengthComputable) { - if (ctx.progress == undefined) ctx.progress = {}; - ctx.progress.max = e.total; - ctx.progress.value = e.loaded; - this.update(); - } - }; - - xhr.send(data); - }; - </script> -</mk-uploader> diff --git a/src/web/app/common/views/components/uploader.vue b/src/web/app/common/views/components/uploader.vue new file mode 100644 index 0000000000..1239bec55f --- /dev/null +++ b/src/web/app/common/views/components/uploader.vue @@ -0,0 +1,207 @@ +<template> +<div class="mk-uploader"> + <ol v-if="uploads.length > 0"> + <li v-for="ctx in uploads" :key="ctx.id"> + <div class="img" :style="{ backgroundImage: `url(${ ctx.img })` }"></div> + <p class="name">%fa:spinner .pulse%{{ ctx.name }}</p> + <p class="status"> + <span class="initing" v-if="ctx.progress == undefined">%i18n:common.tags.mk-uploader.waiting%<mk-ellipsis/></span> + <span class="kb" v-if="ctx.progress != undefined">{{ String(Math.floor(ctx.progress.value / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }}<i>KB</i> / {{ String(Math.floor(ctx.progress.max / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }<i>KB</i></span> + <span class="percentage" v-if="ctx.progress != undefined">{{ Math.floor((ctx.progress.value / ctx.progress.max) * 100) }}</span> + </p> + <progress v-if="ctx.progress != undefined && ctx.progress.value != ctx.progress.max" :value="ctx.progress.value" :max="ctx.progress.max"></progress> + <div class="progress initing" v-if="ctx.progress == undefined"></div> + <div class="progress waiting" v-if="ctx.progress != undefined && ctx.progress.value == ctx.progress.max"></div> + </li> + </ol> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; +export default Vue.extend({ + data() { + return { + uploads: [] + }; + }, + methods: { + upload(file, folder) { + if (folder && typeof folder == 'object') folder = folder.id; + + const id = Math.random(); + + const ctx = { + id: id, + name: file.name || 'untitled', + progress: undefined + }; + + this.uploads.push(ctx); + this.$emit('change', this.uploads); + + const reader = new FileReader(); + reader.onload = e => { + ctx.img = e.target.result; + }; + reader.readAsDataURL(file); + + const data = new FormData(); + data.append('i', this.$root.$data.os.i.token); + data.append('file', file); + + if (folder) data.append('folder_id', folder); + + const xhr = new XMLHttpRequest(); + xhr.open('POST', _API_URL_ + '/drive/files/create', true); + xhr.onload = e => { + const driveFile = JSON.parse(e.target.response); + + this.$emit('uploaded', driveFile); + + this.uploads = this.uploads.filter(x => x.id != id); + this.$emit('change', this.uploads); + }; + + xhr.upload.onprogress = e => { + if (e.lengthComputable) { + if (ctx.progress == undefined) ctx.progress = {}; + ctx.progress.max = e.total; + ctx.progress.value = e.loaded; + } + }; + + xhr.send(data); + } + } +}); +</script> + +<style lang="stylus" scoped> +.mk-uploader + overflow auto + + &:empty + display none + + > ol + display block + margin 0 + padding 0 + list-style none + + > li + display block + margin 8px 0 0 0 + padding 0 + height 36px + box-shadow 0 -1px 0 rgba($theme-color, 0.1) + border-top solid 8px transparent + + &:first-child + margin 0 + box-shadow none + border-top none + + > .img + display block + position absolute + top 0 + left 0 + width 36px + height 36px + background-size cover + background-position center center + + > .name + display block + position absolute + top 0 + left 44px + margin 0 + padding 0 + max-width 256px + font-size 0.8em + color rgba($theme-color, 0.7) + white-space nowrap + text-overflow ellipsis + overflow hidden + + > [data-fa] + margin-right 4px + + > .status + display block + position absolute + top 0 + right 0 + margin 0 + padding 0 + font-size 0.8em + + > .initing + color rgba($theme-color, 0.5) + + > .kb + color rgba($theme-color, 0.5) + + > .percentage + display inline-block + width 48px + text-align right + + color rgba($theme-color, 0.7) + + &:after + content '%' + + > progress + display block + position absolute + bottom 0 + right 0 + margin 0 + width calc(100% - 44px) + height 8px + background transparent + border none + border-radius 4px + overflow hidden + + &::-webkit-progress-value + background $theme-color + + &::-webkit-progress-bar + background rgba($theme-color, 0.1) + + > .progress + display block + position absolute + bottom 0 + right 0 + margin 0 + width calc(100% - 44px) + height 8px + border none + border-radius 4px + background linear-gradient( + 45deg, + lighten($theme-color, 30%) 25%, + $theme-color 25%, + $theme-color 50%, + lighten($theme-color, 30%) 50%, + lighten($theme-color, 30%) 75%, + $theme-color 75%, + $theme-color + ) + background-size 32px 32px + animation bg 1.5s linear infinite + + &.initing + opacity 0.3 + + @keyframes bg + from {background-position: 0 0;} + to {background-position: -64px 32px;} + +</style>