Skip to content

Commit fe7b696

Browse files
matthewcaremikecp
andauthored
Add support for media saving messages in dropzone (#11304)
* WIP Waiting for a response on the issue about how to proceed * Support messages in dropzone Update dropzone to allow the showing of messages that may be added in a media saving notification / handler * Remove test code Remove code used for testing * Sort usings Remove unused using * Fix ordering Ordering of files when they were being processed was backwards / out of order * Add button to "okay" all messages PR Feedback to add a button to dismiss all of the messages all at once. Fixing a referencing issue with `currentFile` Co-authored-by: Michael Latouche <[email protected]>
1 parent 570841b commit fe7b696

File tree

3 files changed

+139
-176
lines changed

3 files changed

+139
-176
lines changed

src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfiledropzone.directive.js

Lines changed: 68 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ angular.module("umbraco.directives")
3131
propertyAlias: '@',
3232
accept: '@',
3333
maxFileSize: '@',
34-
34+
3535
compact: '@',
3636
hideDropzone: '@',
3737
acceptedMediatypes: '=',
@@ -42,9 +42,10 @@ angular.module("umbraco.directives")
4242
},
4343
link: function(scope, element, attrs) {
4444
scope.queue = [];
45-
scope.done = [];
46-
scope.rejected = [];
45+
scope.totalQueued = 0;
4746
scope.currentFile = undefined;
47+
scope.processed = [];
48+
scope.totalMessages = 0;
4849

4950
function _filterFile(file) {
5051
var ignoreFileNames = ['Thumbs.db'];
@@ -65,51 +66,50 @@ angular.module("umbraco.directives")
6566
function _filesQueued(files, event) {
6667
//Push into the queue
6768
Utilities.forEach(files, file => {
68-
if (_filterFile(file) === true) {
69-
70-
if (file.$error) {
71-
scope.rejected.push(file);
72-
} else {
73-
scope.queue.push(file);
74-
}
69+
if (_filterFile(file) === true) {
70+
file.messages = [];
71+
scope.queue.push(file);
7572
}
7673
});
7774

78-
//when queue is done, kick the uploader
79-
if (!scope.working) {
80-
// Upload not allowed
81-
if (!scope.acceptedMediatypes || !scope.acceptedMediatypes.length) {
82-
files.map(file => {
83-
file.uploadStatus = "error";
84-
file.serverErrorMessage = "File type is not allowed here";
85-
scope.rejected.push(file);
86-
});
87-
scope.queue = [];
88-
}
89-
// If we have Accepted Media Types, we will ask to choose Media Type, if Choose Media Type returns false, it only had one choice and therefor no reason to
90-
if (scope.acceptedMediatypes && _requestChooseMediaTypeDialog() === false) {
91-
scope.contentTypeAlias = "umbracoAutoSelect";
75+
// Upload not allowed
76+
if (!scope.acceptedMediatypes || !scope.acceptedMediatypes.length) {
77+
files.map(file => {
78+
file.messages.push({message: "File type is not allowed here", type: "Error"});
79+
});
80+
}
9281

93-
_processQueueItem();
94-
}
82+
// If we have Accepted Media Types, we will ask to choose Media Type, if Choose Media Type returns false, it only had one choice and therefor no reason to
83+
if (scope.acceptedMediatypes && _requestChooseMediaTypeDialog() === false) {
84+
scope.contentTypeAlias = "umbracoAutoSelect";
9585
}
86+
87+
// Add the processed length, as we might be uploading in stages
88+
scope.totalQueued = scope.queue.length + scope.processed.length;
89+
90+
_processQueueItems();
9691
}
9792

98-
function _processQueueItem() {
99-
if (scope.queue.length > 0) {
93+
function _processQueueItems() {
94+
// if we have processed all files, either by successful
95+
// upload, or attending to all messages, we deem the
96+
// action complete, else continue processing files
97+
scope.totalMessages = scope.processed.filter(e => e.messages.length > 0).length;
98+
if (scope.totalQueued === scope.processed.length) {
99+
if (scope.totalMessages === 0) {
100+
if (scope.filesUploaded) {
101+
//queue is empty, trigger the done action
102+
scope.filesUploaded(scope.done);
103+
}
104+
//auto-clear the done queue after 3 secs
105+
var currentLength = scope.processed.length;
106+
$timeout(function() {
107+
scope.processed.splice(0, currentLength);
108+
}, 3000);
109+
}
110+
} else {
100111
scope.currentFile = scope.queue.shift();
101112
_upload(scope.currentFile);
102-
} else if (scope.done.length > 0) {
103-
if (scope.filesUploaded) {
104-
//queue is empty, trigger the done action
105-
scope.filesUploaded(scope.done);
106-
}
107-
108-
//auto-clear the done queue after 3 secs
109-
var currentLength = scope.done.length;
110-
$timeout(function() {
111-
scope.done.splice(0, currentLength);
112-
}, 3000);
113113
}
114114
}
115115

@@ -134,55 +134,36 @@ angular.module("umbraco.directives")
134134
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10);
135135
// set percentage property on file
136136
file.uploadProgress = progressPercentage;
137-
// set uploading status on file
138-
file.uploadStatus = "uploading";
139137
}
140138
})
141-
.success(function(data, status, headers, config) {
142-
if (data.notifications && data.notifications.length > 0) {
143-
// set error status on file
144-
file.uploadStatus = "error";
145-
// Throw message back to user with the cause of the error
146-
file.serverErrorMessage = data.notifications[0].message;
147-
// Put the file in the rejected pool
148-
scope.rejected.push(file);
149-
} else {
150-
// set done status on file
151-
file.uploadStatus = "done";
152-
file.uploadProgress = 100;
153-
// set date/time for when done - used for sorting
154-
file.doneDate = new Date();
155-
// Put the file in the done pool
156-
scope.done.push(file);
157-
}
139+
.success(function (data, status, headers, config) {
140+
// Set server messages
141+
file.messages = data.notifications;
142+
scope.processed.push(file);
143+
//after processing, test if everything is done
158144
scope.currentFile = undefined;
159-
//after processing, test if everthing is done
160-
_processQueueItem();
145+
_processQueueItems();
161146
})
162147
.error(function(evt, status, headers, config) {
163-
// set status done
164-
file.uploadStatus = "error";
165148
//if the service returns a detailed error
166149
if (evt.InnerException) {
167-
file.serverErrorMessage = evt.InnerException.ExceptionMessage;
150+
file.messages.push({ message: evt.InnerException.ExceptionMessage, type: "Error" });
168151
//Check if its the common "too large file" exception
169152
if (evt.InnerException.StackTrace &&
170153
evt.InnerException.StackTrace.indexOf("ValidateRequestEntityLength") > 0) {
171-
file.serverErrorMessage = "File too large to upload";
154+
file.messages.push({ message: "File too large to upload", type: "Error" });
172155
}
173156
} else if (evt.Message) {
174-
file.serverErrorMessage = evt.Message;
175-
} else if (evt && typeof evt === 'string') {
176-
file.serverErrorMessage = evt;
157+
file.messages.push({message: evt.Message, type: "Error"});
158+
} else if (evt && typeof evt === "string") {
159+
file.messages.push({message: evt, type: "Error"});
177160
}
178161
// If file not found, server will return a 404 and display this message
179162
if (status === 404) {
180-
file.serverErrorMessage = "File not found";
163+
file.messages.push({message: "File not found", type: "Error"});
181164
}
182-
//after processing, test if everthing is done
183-
scope.rejected.push(file);
184165
scope.currentFile = undefined;
185-
_processQueueItem();
166+
_processQueueItems();
186167
});
187168
}
188169

@@ -224,16 +205,14 @@ angular.module("umbraco.directives")
224205
availableItems: filteredMediaTypes,
225206
submit: function (model) {
226207
scope.contentTypeAlias = model.selectedItem.alias;
227-
_processQueueItem();
208+
_processQueueItems();
228209

229210
overlayService.close();
230211
},
231212
close: function () {
232213

233214
scope.queue.map(function (file) {
234-
file.uploadStatus = "error";
235-
file.serverErrorMessage = "No files uploaded, no mediatype selected";
236-
scope.rejected.push(file);
215+
file.messages.push({message:"No files uploaded, no mediatype selected", type: "Error"});
237216
});
238217
scope.queue = [];
239218

@@ -245,14 +224,26 @@ angular.module("umbraco.directives")
245224
overlayService.open(dialog);
246225
});
247226

248-
return true;// yes, we did open the choose-media dialog, therefor we return true.
227+
return true; // yes, we did open the choose-media dialog, therefore we return true.
228+
}
229+
230+
scope.dismissMessages = function (file) {
231+
file.messages = [];
232+
_processQueueItems();
233+
}
234+
235+
scope.dismissAllMessages = function () {
236+
Utilities.forEach(scope.processed, file => {
237+
file.messages = [];
238+
});
239+
_processQueueItems();
249240
}
250241

251242
scope.handleFiles = function(files, event, invalidFiles) {
252243
const allFiles = [...files, ...invalidFiles];
253244

254245
// add unique key for each files to use in ng-repeats
255-
allFiles.forEach(file => {
246+
Utilities.forEach(allFiles, file => {
256247
file.key = String.CreateGuid();
257248
});
258249

src/Umbraco.Web.UI.Client/src/less/components/umb-file-dropzone.less

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11

22
.umb-file-dropzone {
3-
43
// drop zone
54
// tall and small version - animate height
65
.dropzone {
@@ -21,17 +20,16 @@
2120

2221
&.is-small {
2322
height: 100px;
23+
2424
.illustration {
2525
width: 200px;
2626
}
2727
}
28-
28+
2929
&.drag-over {
3030
border: 1px dashed @gray-1;
3131
}
3232
}
33-
34-
3533
// center the content of the drop zone
3634
.content {
3735
position: absolute;
@@ -41,8 +39,6 @@
4139
display: flex;
4240
flex-direction: column;
4341
}
44-
45-
4642
// file select link
4743
.file-select {
4844
background: transparent;
@@ -54,11 +50,10 @@
5450
margin-top: 10px;
5551

5652
&:hover {
57-
color: @ui-action-discreet-type-hover;
58-
text-decoration: none;
53+
color: @ui-action-discreet-type-hover;
54+
text-decoration: none;
5955
}
6056
}
61-
6257
// uploading / uploaded file list
6358
.file-list {
6459
list-style: none;
@@ -67,26 +62,32 @@
6762
padding: 10px 20px;
6863

6964
.file {
70-
//border-bottom: 1px dashed @orange;
71-
display: block;
72-
width: 100%;
7365
padding: 5px 0;
7466
position: relative;
7567
border-top: 1px solid @gray-8;
68+
7669
&:first-child {
7770
border-top: none;
7871
}
7972

8073
&.ng-enter {
8174
animation: fadeIn 0.5s;
8275
}
76+
8377
&.ng-leave {
8478
animation: fadeOut 2s;
8579
}
80+
8681
.file-description {
8782
color: @gray-3;
8883
font-size: 12px;
84+
display: flex;
85+
align-items: center;
86+
justify-content: space-between;
8987
width: 100%;
88+
}
89+
90+
.file-messages, .file-messages span {
9091
display: block;
9192
}
9293

@@ -95,25 +96,11 @@
9596
width: 100%;
9697
}
9798

98-
.file-icon {
99-
position: absolute;
100-
right: 0;
101-
bottom: 0;
102-
103-
.icon {
104-
font-size: 20px;
105-
&.ng-enter {
106-
animation: fadeIn 0.5s;
107-
}
108-
&.ng-leave {
109-
animation: fadeIn 0.5s;
110-
}
111-
}
99+
.ok-all {
100+
margin-left: auto;
112101
}
113102
}
114103
}
115-
116-
117104
// progress bars
118105
// could be moved to its own less file
119106
.file-progress {
@@ -131,5 +118,4 @@
131118
width: 0;
132119
}
133120
}
134-
135121
}

0 commit comments

Comments
 (0)