diff options
author | Johannes Zellner <johannes@cloudron.io> | 2018-05-17 14:59:45 +0200 |
---|---|---|
committer | Johannes Zellner <johannes@cloudron.io> | 2018-05-17 14:59:45 +0200 |
commit | d0803a0432f50d6d32b498d50f37f4325984e85c (patch) | |
tree | dc295cae5976db802ada47ff7dc003a014e4249b | |
parent | c248373641e65b585e0029176a608d6f4160642d (diff) | |
download | Surfer-d0803a0432f50d6d32b498d50f37f4325984e85c.tar.gz Surfer-d0803a0432f50d6d32b498d50f37f4325984e85c.tar.zst Surfer-d0803a0432f50d6d32b498d50f37f4325984e85c.zip |
Show upload progress
-rw-r--r-- | frontend/css/style.css | 2 | ||||
-rw-r--r-- | frontend/index.html | 62 | ||||
-rw-r--r-- | frontend/js/app.js | 57 |
3 files changed, 64 insertions, 57 deletions
diff --git a/frontend/css/style.css b/frontend/css/style.css index 5c9236b..45fce56 100644 --- a/frontend/css/style.css +++ b/frontend/css/style.css | |||
@@ -23,7 +23,7 @@ body { | |||
23 | .el-footer { | 23 | .el-footer { |
24 | padding: 3px 20px; | 24 | padding: 3px 20px; |
25 | font-size: 14px; | 25 | font-size: 14px; |
26 | text-align: center; | 26 | height: 38px !important; |
27 | } | 27 | } |
28 | 28 | ||
29 | a { | 29 | a { |
diff --git a/frontend/index.html b/frontend/index.html index 2e2e5e3..15e5d98 100644 --- a/frontend/index.html +++ b/frontend/index.html | |||
@@ -70,47 +70,43 @@ | |||
70 | </el-header> | 70 | </el-header> |
71 | <el-main> | 71 | <el-main> |
72 | 72 | ||
73 | <!-- <div class="container" v-show="uploadStatus.busy" v-cloak> | ||
74 | <div class="row"> | ||
75 | <div class="col-lg-12"> | ||
76 | <p>Uploading... ({{ uploadStatus.done }} / {{ uploadStatus.count }}) </p> | ||
77 | <center> | ||
78 | <div class="progress"> | ||
79 | <div class="progress-bar progress-bar-striped" role="progressbar" v-bind:style="{ width: uploadStatus.percentDone + '%' }"> | ||
80 | <span class="sr-only">{{ uploadStatus.percentDone }}% Complete</span> | ||
81 | </div> | ||
82 | </div> | ||
83 | </center> | ||
84 | </div> | ||
85 | </div> | ||
86 | </div> --> | ||
87 | |||
88 | <div v-show="busy"> | 73 | <div v-show="busy"> |
89 | <center><h1><i class="el-icon-loading"></i></h1></center> | 74 | <center><h1><i class="el-icon-loading"></i></h1></center> |
90 | </div> | 75 | </div> |
91 | 76 | ||
92 | <div v-show="!busy && session.valid" v-cloak> | 77 | <div v-show="!busy && session.valid" v-cloak> |
93 | <el-table :data="entries" style="width: 100%" height="100%" empty-text="Folder is emtpy" :default-sort="{ prop: 'filePath', order: 'descending' }" @row-click="open"> | 78 | <center> |
94 | <el-table-column prop="previewUrl" label="Type" width="100px" sortable> | 79 | <el-table :data="entries" style="max-width: 1280px;width: 100%" height="100%" empty-text="Folder is emtpy" :default-sort="{ prop: 'filePath', order: 'descending' }" @row-click="open"> |
95 | <template slot-scope="scope"> | 80 | <el-table-column prop="previewUrl" label="Type" width="100px" sortable> |
96 | <img v-bind:src="scope.row.previewUrl" height="48px" width="48px"/> | 81 | <template slot-scope="scope"> |
97 | </template> | 82 | <img v-bind:src="scope.row.previewUrl" height="48px" width="48px"/> |
98 | </el-table-column> | 83 | </template> |
99 | <el-table-column prop="filePath" label="Name" sortable></el-table-column> | 84 | </el-table-column> |
100 | <el-table-column prop="size" label="Size" width="150px" sortable :formatter="prettyFileSize"></el-table-column> | 85 | <el-table-column prop="filePath" label="Name" sortable></el-table-column> |
101 | <el-table-column prop="mtime" label="Modified" width="150px" sortable :formatter="prettyDate"></el-table-column> | 86 | <el-table-column prop="size" label="Size" width="150px" sortable :formatter="prettyFileSize"></el-table-column> |
102 | <el-table-column label="Actions" align="right" width="200px" class-name="list-actions"> | 87 | <el-table-column prop="mtime" label="Modified" width="150px" sortable :formatter="prettyDate"></el-table-column> |
103 | <template slot-scope="scope"> | 88 | <el-table-column label="Actions" align="right" width="200px" class-name="list-actions"> |
104 | <el-button size="small" icon="el-icon-download" circle v-show="scope.row.isFile" @click.stop="onDownload(scope.row)"></el-button> | 89 | <template slot-scope="scope"> |
105 | <el-button size="small" icon="el-icon-edit" circle @click.stop="onRename(scope.row)"></el-button> | 90 | <el-button size="small" icon="el-icon-download" circle v-show="scope.row.isFile" @click.stop="onDownload(scope.row)"></el-button> |
106 | <el-button size="small" icon="el-icon-delete" circle @click.stop="onDelete(scope.row)"></el-button> | 91 | <el-button size="small" icon="el-icon-edit" circle @click.stop="onRename(scope.row)"></el-button> |
107 | </template> | 92 | <el-button size="small" icon="el-icon-delete" circle @click.stop="onDelete(scope.row)"></el-button> |
108 | </el-table-column> | 93 | </template> |
109 | </el-table> | 94 | </el-table-column> |
95 | </el-table> | ||
96 | </center> | ||
110 | </div> | 97 | </div> |
111 | 98 | ||
112 | </el-main> | 99 | </el-main> |
113 | <el-footer style="height: 24px">Built by the <a href="https://cloudron.io" target="_blank">Cloudron.io</a> team. <a href="https://git.cloudron.io/cloudron/surfer" target="_blank">Get the code</a></el-footer> | 100 | <el-footer v-show="uploadStatus.busy"> |
101 | <el-row> | ||
102 | <el-col :span="4"> | ||
103 | Uploading files ({{ uploadStatus.done }} / {{ uploadStatus.count }}) | ||
104 | </el-col> | ||
105 | <el-col :span="20"> | ||
106 | <el-progress :text-inside="true" :stroke-width="18" :percentage="uploadStatus.percentDone"></el-progress> | ||
107 | </el-col> | ||
108 | </el-row> | ||
109 | </el-footer> | ||
114 | </el-container> | 110 | </el-container> |
115 | 111 | ||
116 | </div> | 112 | </div> |
diff --git a/frontend/js/app.js b/frontend/js/app.js index d659b18..1500457 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js | |||
@@ -1,6 +1,23 @@ | |||
1 | (function () { | 1 | (function () { |
2 | 'use strict'; | 2 | 'use strict'; |
3 | 3 | ||
4 | // poor man's async | ||
5 | function asyncForEach(items, handler, callback) { | ||
6 | var cur = 0; | ||
7 | |||
8 | if (items.length === 0) return callback(); | ||
9 | |||
10 | (function iterator() { | ||
11 | handler(items[cur], function (error) { | ||
12 | if (error) return callback(error); | ||
13 | if (cur >= items.length-1) return callback(); | ||
14 | ++cur; | ||
15 | |||
16 | iterator(); | ||
17 | }); | ||
18 | })(); | ||
19 | } | ||
20 | |||
4 | function getProfile(accessToken, callback) { | 21 | function getProfile(accessToken, callback) { |
5 | callback = callback || function (error) { if (error) console.error(error); }; | 22 | callback = callback || function (error) { if (error) console.error(error); }; |
6 | 23 | ||
@@ -114,14 +131,12 @@ function up() { | |||
114 | function uploadFiles(files) { | 131 | function uploadFiles(files) { |
115 | if (!files || !files.length) return; | 132 | if (!files || !files.length) return; |
116 | 133 | ||
117 | app.uploadStatus = { | 134 | app.uploadStatus.busy = true; |
118 | busy: true, | 135 | app.uploadStatus.count = files.length; |
119 | count: files.length, | 136 | app.uploadStatus.done = 0; |
120 | done: 0, | 137 | app.uploadStatus.percentDone = 0; |
121 | percentDone: 0 | ||
122 | }; | ||
123 | 138 | ||
124 | function uploadFile(file) { | 139 | asyncForEach(files, function (file, callback) { |
125 | var path = encode(sanitize(app.path + '/' + file.name)); | 140 | var path = encode(sanitize(app.path + '/' + file.name)); |
126 | 141 | ||
127 | var formData = new FormData(); | 142 | var formData = new FormData(); |
@@ -129,28 +144,24 @@ function uploadFiles(files) { | |||
129 | 144 | ||
130 | superagent.post('/api/files' + path).query({ access_token: localStorage.accessToken }).send(formData).end(function (error, result) { | 145 | superagent.post('/api/files' + path).query({ access_token: localStorage.accessToken }).send(formData).end(function (error, result) { |
131 | if (result && result.statusCode === 401) return logout(); | 146 | if (result && result.statusCode === 401) return logout(); |
132 | if (result && result.statusCode !== 201) console.error('Error uploading file: ', result.statusCode); | 147 | if (result && result.statusCode !== 201) return callback('Error uploading file: ', result.statusCode); |
133 | if (error) console.error(error); | 148 | if (error) return callback(error); |
134 | 149 | ||
135 | app.uploadStatus.done += 1; | 150 | app.uploadStatus.done += 1; |
136 | app.uploadStatus.percentDone = Math.round(app.uploadStatus.done / app.uploadStatus.count * 100); | 151 | app.uploadStatus.percentDone = Math.round(app.uploadStatus.done / app.uploadStatus.count * 100); |
137 | 152 | ||
138 | if (app.uploadStatus.done >= app.uploadStatus.count) { | 153 | callback(); |
139 | app.uploadStatus = { | ||
140 | busy: false, | ||
141 | count: 0, | ||
142 | done: 0, | ||
143 | percentDone: 100 | ||
144 | }; | ||
145 | |||
146 | refresh(); | ||
147 | } | ||
148 | }); | 154 | }); |
149 | } | 155 | }, function (error) { |
156 | if (error) console.error(error); | ||
150 | 157 | ||
151 | for(var i = 0; i < app.uploadStatus.count; ++i) { | 158 | app.uploadStatus.busy = false; |
152 | uploadFile(files[i]); | 159 | app.uploadStatus.count = 0; |
153 | } | 160 | app.uploadStatus.done = 0; |
161 | app.uploadStatus.percentDone = 100; | ||
162 | |||
163 | refresh(); | ||
164 | }); | ||
154 | } | 165 | } |
155 | 166 | ||
156 | function dragOver(event) { | 167 | function dragOver(event) { |