Skip to content

Commit

Permalink
🎨 [#1309] Added file-input toggle, file info and file error styles
Browse files Browse the repository at this point in the history
  • Loading branch information
jiromaykin committed Apr 19, 2023
1 parent 3e8b963 commit fe4ef13
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 102 deletions.
2 changes: 1 addition & 1 deletion src/open_inwoner/accounts/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ def __init__(self, users, *args, **kwargs):

class CaseUploadForm(forms.Form):
title = forms.CharField(
label=_("Titel"), max_length=255, validators=[validate_charfield_entry]
label=_("Titel bestand"), max_length=255, validators=[validate_charfield_entry]
)
type = forms.ModelChoiceField(
ZaakTypeInformatieObjectTypeConfig.objects.none(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{% load i18n form_tags button_tags %}

<div class="form__control {{ extra_classes|default:"upload" }}">
<div id="inputfile-group" class="inputfile-group">
<label class="label">
{{ field|addclass:"inputfile" }}
<label class="label__label">
{{ text }}
{% if field.field.required %}<span class="label__label--required"> * </span>{% endif %}
</label>
{% if field.errors %}
{% errors errors=field.errors %}
{% endif %}
</label>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
hx-select="{{ async_selector }}"
hx-target="{{ async_selector }}"
{% endif %}

{# HTML attribute to bypass browser defaults and show validation #}
novalidate
>
{% if form.non_field_errors %}
{% errors errors=form.non_field_errors %}
Expand Down
16 changes: 16 additions & 0 deletions src/open_inwoner/components/templatetags/form_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,22 @@ def input(field, **kwargs):
return {**kwargs, "field": field}


@register.inclusion_tag("components/Form/FileInput.html")
def file_input(file, text, **kwargs):
"""
Displaying a file upload interface.
Usage:
{% file_input form.field text="Bestanden uploaden" %}
Variables:
+ field: Field | The field that needs to be rendered.
- extra_classes: string| classes which should be added to the top-level container
"""
kwargs["text"] = text
return {**kwargs, "field": file}


@register.inclusion_tag("components/Form/DateField.html")
def date_field(field, **kwargs):
return {**kwargs, "field": field}
Expand Down
58 changes: 2 additions & 56 deletions src/open_inwoner/js/components/upload-document/index.js
Original file line number Diff line number Diff line change
@@ -1,56 +1,2 @@
// class UploadDocument {
// constructor(node) {
// this.node = node
// this.node.addEventListener('click', this.toggleOpen.bind(this))
// }
//
// toggleOpen(event) {
// event.preventDefault()
// this.node.parentElement.parentElement.classList.toggle('upload--open')
// }
// }
//
// const uploadButtons = document.querySelectorAll('.upload__button .button')
// ;[...uploadButtons].forEach((uploadButton) => new UploadDocument(uploadButton))

const fileEle = document.getElementById('id_file')
const sizeEle = document.getElementById('upload-size')
const nameEle = document.getElementById('upload-name')
const closeUpload = document.getElementById('closeUpload')

fileEle.addEventListener('change', function (e) {
const files = e.target.files
if (files.length === 0) {
// Hide the size element if user doesn't choose any file
sizeEle.innerHTML = ''
sizeEle.style.display = 'none'
nameEle.innerHTML = ''
nameEle.style.display = 'none'
} else {
// Convert the file size to a readable format
const formatFileSize = function (bytes) {
const sufixes = ['B', 'kB', 'MB', 'GB', 'TB']
const i = Math.floor(Math.log(bytes) / Math.log(1024))
return `${(bytes / Math.pow(1024, i)).toFixed(2)} ${sufixes[i]}`
}
// File size in bytes
sizeEle.innerHTML = formatFileSize(files[0].size)
nameEle.innerHTML = `${files[0].name}`

// Display it
sizeEle.style.display = 'block'
nameEle.style.display = 'block'
}
})

closeUpload.onclick = function (e, fileEle, sizeEle, nameEle) {
const files = e.target.files
document.getElementById('id_file').value = null
sizeEle.innerHTML = "null"
nameEle.innerHTML = "null"

// Display it
sizeEle.style.display = 'block'
nameEle.style.display = 'block'
console.log('close button clicked')
}
import './show-file-info'
import './toggle-file-input'
45 changes: 45 additions & 0 deletions src/open_inwoner/js/components/upload-document/show-file-info.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const fileUploadInput = document.getElementById('id_file')
const sizeInfo = document.getElementById('uploadSize')
const nameInfo = document.getElementById('uploadName')
// const closeButton = document.getElementById('closeUpload')

if (fileUploadInput) {
// Convert the file size to a readable format
const formatFileSize = function (bytes) {
const suffixes = ['B', 'kB', 'MB', 'GB', 'TB']
const i = Math.floor(Math.log(bytes) / Math.log(1024))
return `${(bytes / Math.pow(1024, i)).toFixed(2)} ${suffixes[i]}`
}

fileUploadInput.addEventListener('change', function (e) {
const files = e.target.files

if ((files.length === 0) | (files === null) | (files === undefined)) {
// Hide the size element if user doesn't choose any file
sizeInfo.textContent = '(Titel bestand)'
nameInfo.textContent = '(Bestandsgrootte)'
} else {
// Display the file size
sizeInfo.textContent = formatFileSize(files[0].size)
// Display the file name
nameInfo.textContent = `${files[0].name}`
// Display in DOM
sizeInfo.style.display = 'inline-block'
nameInfo.style.display = 'inline-block'
}
})

const element = document.getElementById('closeUpload')
if (typeof element != 'undefined' && element != null) {
console.log('reset exists')
}

// if (closeButton) {
// console.log('reset exists')
// closeButton.addEventListener('click', (event) => {
// sizeInfo.textContent = ''
// nameInfo.textContent = ''
// console.log('File-input reset')
// })
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class UploadDocument {
constructor(node) {
this.node = node
this.node.addEventListener('click', this.toggleOpen.bind(this))
}

toggleOpen(event) {
event.preventDefault()
this.node.parentElement.classList.toggle('upload--open')
}
}

const uploadButtons = document.querySelectorAll('.upload__button')
// const uploadInterface = document.querySelectorAll('.form__open-upload')
const documentUpload = document.getElementById('formOpenUpload')
const uploadError = document.querySelectorAll('.notifications')

// if errors are present, trigger opened state
if (uploadError.length > 1) {
console.log(uploadError)
console.log('Please look at the errors in the form')
documentUpload.scrollIntoView({
block: 'center',
behavior: 'smooth',
})
documentUpload.classList.add('upload--open')
}

;[...uploadButtons].forEach((uploadButton) => new UploadDocument(uploadButton))
122 changes: 122 additions & 0 deletions src/open_inwoner/scss/components/Form/DocumentUpload.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,130 @@
#document-upload {
gap: var(--spacing-tiny);

.button[type='submit']:disabled {
background-color: var(--color-gray) !important;
border-color: var(--color-gray) !important;
color: var(--color-gray-light);
pointer-events: none;
cursor: default;
}

.form__control.upload .form__submit {
*[class*='icon'],
.button {
position: initial;
margin-top: 2em;
}
}

input[type='text'] {
width: 360px;
}

.inputfile-group {
display: block;

.label,
.close {
display: block;
}
}
}

.form__open-upload {
.upload-interface {
display: block;
width: 0;
height: 0;
opacity: 0;
padding: 0;
margin: 0;
}
.upload-button--disabled {
background-color: var(--color-gray);
}
.upload__button,
.upload-button--disabled {
width: 360px;
display: block;
margin-top: var(--spacing-medium);
}

&.upload--open {
.upload-interface {
display: block;
width: 100%;
height: initial;
opacity: 1;
}
.upload__button,
.upload-button--disabled {
display: none;
}
}

.close .button--transparent {
color: red;
}

// styled file input label
input[type='file'] {
background-color: var(--color-primary);
color: transparent;
border: 0;
border-radius: 4px;
display: flex;
flex-direction: column;
width: 360px;
clip: rect(0 0 0 0);
margin-top: var(--spacing-medium);
overflow: hidden;
cursor: pointer;
}
input[type='file']::file-selector-button {
color: white;
background-color: var(--color-primary);
text-transform: uppercase;
border: 1px;
border-radius: 4px;
font-size: var(--font-size-body);
line-height: var(--font-line-height-body);
height: var(--row-height);
font-weight: normal;
text-align: center;
vertical-align: middle;
cursor: pointer;
white-space: nowrap;
padding: 0 12px;
width: 200px;
}

.fieldset-container {
padding-top: var(--spacing-small);
display: flex;
flex-direction: row;
justify-content: space-around;
border: 1px solid lightgray;
border-radius: 4px;
max-width: 360px;
height: 80px;
margin-bottom: 20px;

.fieldset__content {
padding-top: var(--spacing-small);
color: var(--color-mute);
width: 200px;

.upload-info {
display: inline-block;
font-family: var(--font-family-body);
font-size: var(--font-size-body);
color: var(--color-mute);
width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
8 changes: 8 additions & 0 deletions src/open_inwoner/scss/components/Form/Form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@
}
}
}
&__control
.label
.notifications__errors
.notification--warning
*[class*='icon'] {
position: static;
transform: translateY(-5px);
}

&__control > .label .p:last-child {
font-size: var(--font-size-body-small);
Expand Down
Loading

0 comments on commit fe4ef13

Please sign in to comment.