Skip to content

Commit

Permalink
Main file upload (#5556)
Browse files Browse the repository at this point in the history
* feat: File upload client validation

issue: TOBAGO-2353
  • Loading branch information
lofwyr14 authored Oct 8, 2024
1 parent cce91f3 commit 73f7794
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
import org.apache.myfaces.tobago.util.ComponentUtils;
import org.apache.myfaces.tobago.util.ResourceUtils;
import org.apache.myfaces.tobago.validator.FileItemValidator;
import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
import org.slf4j.Logger;
Expand All @@ -47,8 +48,10 @@
import jakarta.servlet.http.Part;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

@ListenerFor(systemEventClass = PostAddToViewEvent.class)
public class FileRenderer<T extends AbstractUIFile>
Expand Down Expand Up @@ -205,15 +208,15 @@ private String createAcceptFromValidators(final AbstractUIFile file) {
}
}

private Long createMaxSizeFromValidators(final AbstractUIFile file) {
private long createMaxSizeFromValidators(final AbstractUIFile file) {
long maxSize = Long.MAX_VALUE;
for (final Validator validator : file.getValidators()) {
if (validator instanceof FileItemValidator) {
final FileItemValidator fileItemValidator = (FileItemValidator) validator;
maxSize = Long.min(maxSize, fileItemValidator.getMaxSize());
}
}
return maxSize != Long.MAX_VALUE ? maxSize : null;
return maxSize != Long.MAX_VALUE ? maxSize : 0;
}

@Override
Expand All @@ -232,8 +235,14 @@ protected void writeAdditionalAttributes(
final String forId = ComponentUtils.evaluateClientId(facesContext, input, dropZone);
writer.writeAttribute(CustomAttributes.DROP_ZONE, forId, true);
}
final Long maxSize = createMaxSizeFromValidators(input);
writer.writeAttribute(CustomAttributes.MAX_SIZE, maxSize);
final long maxSize = createMaxSizeFromValidators(input);
if (maxSize > 0) {
writer.writeAttribute(CustomAttributes.MAX_SIZE, maxSize);
final Locale locale = facesContext.getViewRoot().getLocale();
final MessageFormat maxSizeMessage
= new MessageFormat(ResourceUtils.getString(facesContext, "file.maxSizeMessage"), locale);
writer.writeAttribute(CustomAttributes.MAX_SIZE_MESSAGE, maxSizeMessage.format(new Object[]{maxSize}), true);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public enum CustomAttributes implements MarkupLanguageAttributes {
LOCALE("locale"),
LOCAL_MENU("local-menu"),
MAX_SIZE("max-size"),
MAX_SIZE_MESSAGE("max-size-message"),
MAX_ITEMS("max-items"),
MIN_CHARS("min-chars"),
OMIT("omit"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ date.today=Today
date.cancel=Cancel
date.clear=Clear
date.week=Week
file.maxSizeMessage=The selected file exceeds the maximum allowed size of {0} bytes.
severity.fatal=Fatal
severity.error=Error
severity.warn=Warning
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ date.today=Heute
date.cancel=Abbrechen
date.clear=L\u00F6schen
date.week=Woche
file.maxSizeMessage=Die ausgewählte Datei überschreitet die maximal erlaubte Größe von {0} Bytes.
severity.fatal=Fatal
severity.error=Fehler
severity.warn=Warnung
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ date.today=Hoy
date.cancel=Cancelar
date.clear=Borrar
date.week=Semana
file.maxSizeMessage=El archivo seleccionado excede el tamaño máximo permitido de {0} bytes.
severity.fatal=Fatal
severity.error=Error
severity.warn=Advertencia
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.myfaces.tobago.component.UIFile;
import org.apache.myfaces.tobago.component.UIPanel;
import org.apache.myfaces.tobago.util.ComponentUtils;
import org.apache.myfaces.tobago.validator.FileItemValidator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

Expand All @@ -41,6 +42,20 @@ public void fileLabel() throws IOException {
Assertions.assertEquals(loadHtml("renderer/file/file-label.html"), formattedResult());
}

@Test
public void fileValidator() throws IOException {
final UIFile c = (UIFile) ComponentUtils.createComponent(
facesContext, Tags.file.componentType(), RendererTypes.File, "id");
c.setLabel("label");
final FileItemValidator validator = new FileItemValidator();
validator.setMaxSize(1000L);
validator.setContentType(new String[]{".png", "applicaiton/pdf"});
c.addValidator(validator);
c.encodeAll(facesContext);

Assertions.assertEquals(loadHtml("renderer/file/file-validator.html"), formattedResult());
}

@Test
public void fileDropZoneThis() throws IOException {
final UIPanel panel = (UIPanel) ComponentUtils.createComponent(
Expand Down
24 changes: 24 additions & 0 deletions tobago-core/src/test/resources/renderer/file/file-validator.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!--
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-->

<tobago-file id='id' class='tobago-label-container tobago-auto-spacing' max-size='1000' max-size-message='The selected file exceeds the maximum allowed size of 1,000 bytes.'>
<label for='id::field' class='col-form-label'>label</label>
<div class='input-group'>
<input type='file' accept='.png,applicaiton/pdf' tabindex='-1' id='id::field' class='form-control' name='id'>
<label class='input-group-text' for='id::field'><span><i class='bi-folder2-open'></i></span></label>
</div>
</tobago-file>
8 changes: 4 additions & 4 deletions tobago-theme/tobago-theme-standard/src/main/js/tobago.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export class File extends HTMLElement {
return Number.isNaN(number) ? 0 : number;
}

get maxSizeMessage(): string {
return this.getAttribute("max-size-message");
}

static isTypeFile(event: DragEvent): boolean {
if (event.dataTransfer) {
for (const item of event.dataTransfer.items) {
Expand Down Expand Up @@ -120,7 +124,7 @@ export class File extends HTMLElement {
let error = false;
for (const file of files) {
if (file.size > this.maxSize) {
window.alert(`The file ${file.name} is too big! Maximum size is ${this.maxSize} bytes.`);
window.alert(this.maxSizeMessage);
input.value = "";
error = true;
}
Expand Down

0 comments on commit 73f7794

Please sign in to comment.