2023-07-26 18:46:09 +00:00
|
|
|
<!--
|
|
|
|
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
-->
|
|
|
|
{{ define "error-attrs" }}{{ if .Error }}aria-invalid="true" aria-errormessage="{{ .Name }}-error"{{ end }}{{ end }}
|
|
|
|
|
|
|
|
{{ define "error-message" -}}
|
|
|
|
{{ if .Error -}}
|
2024-02-24 19:03:11 +00:00
|
|
|
<strong id="{{ .Name }}-error" class="error">{{ .Error }}</strong><br>
|
2023-07-26 18:46:09 +00:00
|
|
|
{{- end }}
|
|
|
|
{{- end }}
|
|
|
|
|
|
|
|
{{ define "list-options" -}}
|
|
|
|
{{- range .Options }}
|
|
|
|
<option value="{{ .Value }}" {{ if $.IsSelected .Value }} selected="selected"{{ end }}>{{ .Label }}</option>
|
|
|
|
{{- end }}
|
|
|
|
{{- end }}
|
Manage all media uploads in a single place
It made no sense to have a file upload in each form that needs a media,
because to reuse an existing media users would need to upload the exact
same file again; this is very unusual and unfriendly.
A better option is to have a “centralized” media section, where people
can upload files there, and then have a picker to select from there.
Ideally, there would be an upload option in the picker, but i did not
add it yet.
I’ve split the content from the media because i want users to have the
option to update a media, for instance when they need to upload a
reduced or cropped version of the same photo, without an edit they would
need to upload the file as a new media and then update all places where
the old version was used. And i did not want to trouble people that
uploads the same photo twice: without the separate relation, doing so
would throw a constraint error.
I do not believe there is any security problem to have all companies
link their media to the same file, as they were already readable by
everyone and could upload the data from a different company to their
own; in other words, it is not worse than it was now.
2023-09-20 23:56:44 +00:00
|
|
|
|
2023-10-27 14:04:43 +00:00
|
|
|
{{ define "radio-options" -}}
|
|
|
|
{{- range .Options }}
|
|
|
|
<label><input type="radio" name="{{ $.Name }}" value="{{ .Value }}"
|
|
|
|
{{ if $.IsSelected .Value }}checked{{ end }}> {{ .Label }}</label>
|
|
|
|
{{- end }}
|
|
|
|
{{- end }}
|
|
|
|
|
2024-04-19 09:29:43 +00:00
|
|
|
{{ define "month-input" -}}
|
|
|
|
<label>
|
|
|
|
<span class="sr-only">{{( pgettext "Month" "input" )}}</span>
|
|
|
|
<select name="{{ .Name }}.month">
|
|
|
|
<option value="1"{{ if eq .Month 1}} selected{{ end }}>{{( pgettext "January" "month" )}}</option>
|
|
|
|
<option value="2"{{ if eq .Month 2}} selected{{ end }}>{{( pgettext "February" "month" )}}</option>
|
|
|
|
<option value="3"{{ if eq .Month 3}} selected{{ end }}>{{( pgettext "March" "month" )}}</option>
|
|
|
|
<option value="4"{{ if eq .Month 4}} selected{{ end }}>{{( pgettext "April" "month" )}}</option>
|
|
|
|
<option value="5"{{ if eq .Month 5}} selected{{ end }}>{{( pgettext "May" "month" )}}</option>
|
|
|
|
<option value="6"{{ if eq .Month 6}} selected{{ end }}>{{( pgettext "June" "month" )}}</option>
|
|
|
|
<option value="7"{{ if eq .Month 7}} selected{{ end }}>{{( pgettext "July" "month" )}}</option>
|
|
|
|
<option value="8"{{ if eq .Month 8}} selected{{ end }}>{{( pgettext "August" "month" )}}</option>
|
|
|
|
<option value="9"{{ if eq .Month 9}} selected{{ end }}>{{( pgettext "September" "month" )}}</option>
|
|
|
|
<option value="10"{{ if eq .Month 10}} selected{{ end }}>{{( pgettext "October" "month" )}}</option>
|
|
|
|
<option value="11"{{ if eq .Month 11}} selected{{ end }}>{{( pgettext "November" "month" )}}</option>
|
|
|
|
<option value="12"{{ if eq .Month 12}} selected{{ end }}>{{( pgettext "December" "month" )}}</option>
|
|
|
|
</select>
|
|
|
|
</label>
|
|
|
|
<label>
|
|
|
|
<span class="sr-only">{{( pgettext "Year" "input" )}}</span>
|
|
|
|
<input name="{{ .Name }}.year" type="number" value="{{ .Year }}">
|
|
|
|
</label>
|
|
|
|
{{- end }}
|
|
|
|
|
Manage all media uploads in a single place
It made no sense to have a file upload in each form that needs a media,
because to reuse an existing media users would need to upload the exact
same file again; this is very unusual and unfriendly.
A better option is to have a “centralized” media section, where people
can upload files there, and then have a picker to select from there.
Ideally, there would be an upload option in the picker, but i did not
add it yet.
I’ve split the content from the media because i want users to have the
option to update a media, for instance when they need to upload a
reduced or cropped version of the same photo, without an edit they would
need to upload the file as a new media and then update all places where
the old version was used. And i did not want to trouble people that
uploads the same photo twice: without the separate relation, doing so
would throw a constraint error.
I do not believe there is any security problem to have all companies
link their media to the same file, as they were already readable by
everyone and could upload the data from a different company to their
own; in other words, it is not worse than it was now.
2023-09-20 23:56:44 +00:00
|
|
|
{{ define "media-picker" -}}
|
|
|
|
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/form.Media*/ -}}
|
Add the upload form to the media picker
It makes easier to upload new images from the place where we need it,
instead of having to go to the media section each time.
It was a little messy, this one.
First of all, I realized that POSTint to /admin/media/picker to get the
new media field was wrong: i was not asking the server to “accept an
entity”, but only requesting a new HTML value, just like a GET to
/admin/media/upload requests the form to upload a new media, thus here
i should do the same, except i needed the query parameters to change the
field, which is fine—it is actually a different resource, thus a
different URL.
Then, i thought that i could not POST the upload to /admin/media,
because i returned a different HTML —the media field—, so i reused the
recently unused POST to /admin/media/picker to upload that file and
return the HTML for the field. It was wrong, because i was not
requesting the server to put the file as a subordinate of
/admin/media/picker, only /admin/media, but i did not come up with any
other solution.
Since i had two different upload functions now, i created uploadForm’s
Handle method to refactorize the duplicated logic to a single place.
Unfortunately, i did not work as i expected because uploadForm’s and
mediaPicker’s MustRender methods are different, and mediaPicker has to
embed uploadForm to render the form in the picker. That made me change
Handle’s output to a boolean and error in order for the HTTP handler
function know when to render the form with the error messages with the
proper MustRender handler.
However, I saw the opportunity of reusing that Handler method for
editMedia, that was doing mostly the same job, but had to call a
different Validate than uploadForm’s, because editMedia does not require
the uploaded file. That’s when i realized that i could use an interface
and that this interface could be reused not only within media but
throughout the application, and added HandleMultipart in form.
Had to create a different interface for multipart forms because they
need different parameters in Parse that non-multipart form, when i add
that interface, hence had to also change Parse to ParseForm to account
for the difference in signature; not a big deal.
After all that, i realized that i **could** POST to /admin/media in both
cases, because i always return “an HTML entity”, it just happens that
for the media section it is empty with a redirect, and for the picker is
the field. That made the whole Handle method a bit redundant, but i
left it nevertheless, as i find it slightly easier to read the
uploadMedia function now.
2023-09-21 23:40:22 +00:00
|
|
|
<fieldset data-hx-target="this" data-hx-swap="outerHTML">
|
Manage all media uploads in a single place
It made no sense to have a file upload in each form that needs a media,
because to reuse an existing media users would need to upload the exact
same file again; this is very unusual and unfriendly.
A better option is to have a “centralized” media section, where people
can upload files there, and then have a picker to select from there.
Ideally, there would be an upload option in the picker, but i did not
add it yet.
I’ve split the content from the media because i want users to have the
option to update a media, for instance when they need to upload a
reduced or cropped version of the same photo, without an edit they would
need to upload the file as a new media and then update all places where
the old version was used. And i did not want to trouble people that
uploads the same photo twice: without the separate relation, doing so
would throw a constraint error.
I do not believe there is any security problem to have all companies
link their media to the same file, as they were already readable by
everyone and could upload the data from a different company to their
own; in other words, it is not worse than it was now.
2023-09-20 23:56:44 +00:00
|
|
|
<legend>{{( pgettext .Label "input" )}}</legend>
|
|
|
|
<input type="hidden" name="{{ .Name }}" value="{{ .Val }}">
|
Change media picker from <div> to <dialog> and make it modal
Have to call Dialog.showModal when HTMx loaded the dialog in the DOM,
so had to add a onLoad event listened that checks whether the loaded
element is actually a DIALOG.
Had to restrict the margin: 0 for all elements (*) to exclude dialog,
because the browser sets it to auto, and i did not want to set it again
just because i was too overzealous with my “reset”.
The rest of the CSS is just to have a sticky header and footer, and see
the cancel button, that works as a “close”, all the time.
Finally, i realized that if i add the dialog at the end of the fieldset
and let HTMx inherit its hx-target and hx-swap, i no longer need to set
them in the dialog, as HTMx will always replace the fieldset, and i can
have the dialog side by side the current content of the fieldset, that
it was very confusing seeing it disappear when trying to select a new
media.
The cancel button could now just remove the dialog instead of making the
POST, but in local it makes no difference; we’lls see what happens on
production.
2023-09-22 00:11:03 +00:00
|
|
|
<button type="button"
|
|
|
|
data-hx-get="/admin/media/picker?name={{ .Name | queryEscape }}&value={{ .Val | queryEscape }}&label={{ .Label | queryEscape }}&prompt={{ .Prompt | queryEscape }}"
|
|
|
|
data-hx-swap="beforeend"
|
|
|
|
>
|
Manage all media uploads in a single place
It made no sense to have a file upload in each form that needs a media,
because to reuse an existing media users would need to upload the exact
same file again; this is very unusual and unfriendly.
A better option is to have a “centralized” media section, where people
can upload files there, and then have a picker to select from there.
Ideally, there would be an upload option in the picker, but i did not
add it yet.
I’ve split the content from the media because i want users to have the
option to update a media, for instance when they need to upload a
reduced or cropped version of the same photo, without an edit they would
need to upload the file as a new media and then update all places where
the old version was used. And i did not want to trouble people that
uploads the same photo twice: without the separate relation, doing so
would throw a constraint error.
I do not believe there is any security problem to have all companies
link their media to the same file, as they were already readable by
everyone and could upload the data from a different company to their
own; in other words, it is not worse than it was now.
2023-09-20 23:56:44 +00:00
|
|
|
{{ if .Val -}}
|
|
|
|
<img src="/admin/media/{{ .Val }}/content" alt="">
|
|
|
|
{{ else -}}
|
|
|
|
{{( pgettext .Prompt "action" )}}
|
|
|
|
{{- end }}
|
|
|
|
</button>
|
|
|
|
{{ template "error-message" . }}
|
|
|
|
</fieldset>
|
|
|
|
{{- end }}
|
2024-01-10 20:52:49 +00:00
|
|
|
|
2024-01-12 18:51:12 +00:00
|
|
|
{{ define "init-lang" }}x-data="{ lang: '{{ .DefaultLang }}' }"{{ end }}
|
|
|
|
|
2024-01-10 20:52:49 +00:00
|
|
|
{{ define "lang-selector" -}}
|
|
|
|
<div class="lang-selector" role="toolbar">
|
|
|
|
{{ range $lang, $input := . -}}
|
|
|
|
<button :aria-pressed="lang === '{{ $lang }}'"
|
|
|
|
@click.prevent="lang = '{{ $lang }}'">{{ $lang }}</button>
|
|
|
|
{{- end }}
|
|
|
|
</div>
|
|
|
|
{{- end }}
|