diff --git a/assets/js/editor-assets.js b/assets/js/editor-assets.js index 6de407c3..f7a45262 100644 --- a/assets/js/editor-assets.js +++ b/assets/js/editor-assets.js @@ -71,6 +71,7 @@ import { progress } from "./uploader.mjs"; default: // note, the #runapp hash is used by js-dos } + // New file download form event listener. document.body.addEventListener("htmx:afterRequest", function (event) { afterFormRequest( @@ -110,11 +111,38 @@ import { progress } from "./uploader.mjs"; "artifact-editor-link-delete", "artifact-editor-link-feedback" ); + afterLinkRequest( + event, + "artifact-editor-comp-previewcopy", + "artifact-editor-comp-feedback" + ); + afterLinkRequest( + event, + "artifact-editor-comp-previewtext", + "artifact-editor-comp-feedback" + ); + afterLinkRequest( + event, + "artifact-editor-comp-textcopy", + "artifact-editor-comp-feedback" + ); }); - function afterDeleteRequest(event, inputId, feedbackId) { + /** + * After link request event listener. + * @param {Event} event - The htmx event. + * @param {string} inputId - The inputId is the id of the input element that triggered the request, + * or the name of the input element that triggered the request. + * @param {string} feedbackId - The feedback name. + * @returns {void} + **/ + function afterLinkRequest(event, inputId, feedbackId) { if (event.detail.elt === null) return; - if (event.detail.elt.id !== `${inputId}`) return; + if ( + event.detail.elt.id !== `${inputId}` && + event.detail.elt.name !== inputId + ) + return; const feedback = document.getElementById(feedbackId); if (feedback === null) { throw new Error( @@ -122,15 +150,10 @@ import { progress } from "./uploader.mjs"; ); } const errClass = "text-danger"; - const okClass = "text-success"; const xhr = event.detail.xhr; if (event.detail.successful) { - feedback.innerText = `The delete request was successful, about to refresh the page.`; + feedback.innerText = `${xhr.responseText}`; feedback.classList.remove(errClass); - feedback.classList.add(okClass); - setTimeout(() => { - location.reload(); - }, 500); return; } if (event.detail.failed && event.detail.xhr) { @@ -146,7 +169,7 @@ import { progress } from "./uploader.mjs"; " please try again or refresh the page."; } - function afterLinkRequest(event, inputId, feedbackId) { + function afterDeleteRequest(event, inputId, feedbackId) { if (event.detail.elt === null) return; if (event.detail.elt.id !== `${inputId}`) return; const feedback = document.getElementById(feedbackId); @@ -156,10 +179,15 @@ import { progress } from "./uploader.mjs"; ); } const errClass = "text-danger"; + const okClass = "text-success"; const xhr = event.detail.xhr; if (event.detail.successful) { - feedback.innerText = `${xhr.responseText}`; + feedback.innerText = `The delete request was successful, about to refresh the page.`; feedback.classList.remove(errClass); + feedback.classList.add(okClass); + setTimeout(() => { + location.reload(); + }, 500); return; } if (event.detail.failed && event.detail.xhr) { diff --git a/go.mod b/go.mod index bef7f5ac..61a61bce 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/Defacto2/server go 1.22.7 require ( - github.com/Defacto2/archive v1.0.1 + github.com/Defacto2/archive v1.0.2 github.com/Defacto2/helper v1.1.1 github.com/Defacto2/magicnumber v1.0.1 github.com/Defacto2/releaser v1.0.4 @@ -33,6 +33,11 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) +replace ( + github.com/Defacto2/archive => /home/ben/github/archive + github.com/Defacto2/helper => /home/ben/github/helper +) + require ( cloud.google.com/go/auth v0.9.4 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect diff --git a/go.sum b/go.sum index af490842..2cd94855 100644 --- a/go.sum +++ b/go.sum @@ -69,8 +69,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM= github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Defacto2/archive v1.0.1 h1:f6qli42DWJWwNLbcB6SS0MSmVmaUzCJGXzTRsk8PskE= -github.com/Defacto2/archive v1.0.1/go.mod h1:0/aa1BwDOBp4d87R/N33Lcr3+WzELv041wunK8R5A5c= github.com/Defacto2/helper v1.1.1 h1:wu8ynKF4ZXruTZNrDumzPVyXxFwhCvtWlsdimPNSXXc= github.com/Defacto2/helper v1.1.1/go.mod h1:vtHe6R1Pl3YsxsqXe/UZldvNx1n1Y6dM1JUL9Uczr6g= github.com/Defacto2/magicnumber v1.0.1 h1:UmiBUrYwTk3NPR1lGaaQ3Js+3YllBRf9XxSKInE3Da4= diff --git a/handler/app/internal/filerecord/filerecord.go b/handler/app/internal/filerecord/filerecord.go index 6389316a..74897f1d 100644 --- a/handler/app/internal/filerecord/filerecord.go +++ b/handler/app/internal/filerecord/filerecord.go @@ -58,65 +58,64 @@ type ListEntry struct { UniqueID string Executable magicnumber.Windows Images, Programs, Texts bool + name string + platform string + section string + bytes int64 } // HTML returns the HTML for an file item in the "Download content" section of the File editor. -func (m ListEntry) HTML(bytes int64, platform, section string) string { - name := url.QueryEscape(m.RelativeName) - titlename := m.RelativeName +func (m *ListEntry) HTML(bytes int64, platform, section string) string { + m.name = url.QueryEscape(m.RelativeName) + m.bytes = bytes + m.platform = platform + m.section = section displayname := m.RelativeName if strings.EqualFold(platform, tags.DOS.String()) { if msdos.Rename(displayname) != displayname { displayname = `` + displayname + `` } } - htm := fmt.Sprintf(`
%s
`, titlename, displayname) - return m.Column1(bytes, htm, name, platform, section) -} - -// osTool returns true if the file extension matches the known operating system tools. -// This includes batch scripts, executables, commands and ini configurations files. -func osTool(ext string) bool { - switch ext { - case bat, exe, com, ini: - return true - default: - return false - } + htm := fmt.Sprintf(`
%s
`, + displayname) + return m.Column1(htm) } -func (m ListEntry) Column1(bytes int64, htm, name, platform, section string) string { +func (m ListEntry) Column1(htm string) string { const blank = `
` - ext := strings.ToLower(filepath.Ext(name)) + ext := strings.ToLower(filepath.Ext(m.name)) switch { case osTool(ext): htm += blank case m.Images: - htm += previewcopy(m.UniqueID, name) + htm += previewcopy(m.UniqueID, m.name) case m.Texts: - htm += readmepreview(m.UniqueID, name) + htm += readmepreview(m.UniqueID, m.name) default: htm += blank } - return m.readme(bytes, htm, platform, section) + return m.Column2(htm) } -func (m ListEntry) readme(bytes int64, htm, platform, section string) string { +func (m ListEntry) Column2(htm string) string { soloText := func() bool { - if !strings.EqualFold(platform, tags.Text.String()) && !strings.EqualFold(platform, textamiga) { + if !strings.EqualFold(m.platform, tags.Text.String()) && + !strings.EqualFold(m.platform, textamiga) { return false } - return strings.EqualFold(section, tags.Nfo.String()) + return strings.EqualFold(m.section, tags.Nfo.String()) } const blank = `
` name := url.QueryEscape(m.RelativeName) ext := strings.ToLower(filepath.Ext(name)) switch { case - m.Programs && ext == exe, + m.Programs, + ext == exe, ext == com: - htm += `
` + + `
` case osTool(ext): htm += blank @@ -125,18 +124,19 @@ func (m ListEntry) readme(bytes int64, htm, platform, section string) string { default: htm += blank } - htm += fmt.Sprintf(`
%s`, bytes, m.Filesize) - return m.binaries(bytes, ext, htm) + htm += fmt.Sprintf(`
%s`, + m.bytes, m.Filesize) + return m.Column1and2(ext, htm) } -func (m ListEntry) binaries(bytes int64, ext, htm string) string { +func (m ListEntry) Column1and2(ext, htm string) string { switch { case m.Texts && (ext == bat || ext == cmd): htm += fmt.Sprintf(` %s
`, "command script") case m.Texts && (ext == ini): htm += fmt.Sprintf(` %s
`, "configuration textfile") case m.Programs || ext == com: - htm = progr(m.Executable, ext, htm, bytes) + htm = progr(m.Executable, ext, htm, m.bytes) case m.MusicConfig != "": htm += fmt.Sprintf(` %s
`, m.MusicConfig) case m.Images: @@ -149,8 +149,9 @@ func (m ListEntry) binaries(bytes int64, ext, htm string) string { } func previewcopy(uniqueID, name string) string { - return `
` + - fmt.Sprintf(`` + + fmt.Sprintf(``, uniqueID, name) + `
` + - fmt.Sprintf(`` + + fmt.Sprintf(``, uniqueID, name) + `
` + - fmt.Sprintf(`` + + fmt.Sprintf(``, uniqueID, name) + `Thumb created, the browser will refresh.`) + `Thumb created, the browser will refresh.`) } func RecordThumbAlignment(c echo.Context, align command.Align, dirs command.Dirs) error { @@ -58,7 +58,7 @@ func RecordThumbAlignment(c echo.Context, align command.Align, dirs command.Dirs } c = pageRefresh(c) return c.String(http.StatusOK, - `Thumb realigned, the browser will refresh.`) + `Thumb realigned, the browser will refresh.`) } func RecordImageCropper(c echo.Context, crop command.Crop, dirs command.Dirs) error { @@ -69,7 +69,7 @@ func RecordImageCropper(c echo.Context, crop command.Crop, dirs command.Dirs) er } c = pageRefresh(c) return c.String(http.StatusOK, - `Images cropped, the browser will refresh.`) + `Images cropped, the browser will refresh.`) } func RecordImageCopier(c echo.Context, debug *zap.SugaredLogger, dirs command.Dirs) error { @@ -99,7 +99,7 @@ func RecordImageCopier(c echo.Context, debug *zap.SugaredLogger, dirs command.Di } c = pageRefresh(c) return c.String(http.StatusOK, - `Images copied, the browser will refresh.`) + `Images copied, the browser will refresh.`) } func RecordReadmeImager(c echo.Context, logger *zap.SugaredLogger, dirs command.Dirs) error { @@ -126,7 +126,7 @@ func RecordReadmeImager(c echo.Context, logger *zap.SugaredLogger, dirs command. } c = pageRefresh(c) return c.String(http.StatusOK, - `Text filed imaged, the browser will refresh.`) + `Text filed imaged, the browser will refresh.`) } func RecordReadmeCopier(c echo.Context, extraDir string) error { @@ -154,7 +154,7 @@ func RecordReadmeCopier(c echo.Context, extraDir string) error { } c = pageRefresh(c) return c.String(http.StatusOK, - `Images copied, the browser will refresh.`) + `Images copied, the browser will refresh.`) } func RecordImagePixelator(c echo.Context, dirs ...string) error { @@ -164,7 +164,7 @@ func RecordImagePixelator(c echo.Context, dirs ...string) error { } c = pageRefresh(c) return c.String(http.StatusOK, - `Images pixelated, the browser will refresh.`) + `Images pixelated, the browser will refresh.`) } func RecordImagesDeleter(c echo.Context, dirs ...string) error { diff --git a/public/js/editor-assets.min.js b/public/js/editor-assets.min.js index 651be233..748ad5e4 100644 --- a/public/js/editor-assets.min.js +++ b/public/js/editor-assets.min.js @@ -1,2 +1,2 @@ /* editor-assets.min.js © Defacto2 2024 */ -(()=>{var k=100,L=1024*1024,H=100*L;function d(s,a){if(s==null)throw new Error("The formId value of progress is null.");if(a==null)throw new Error("The elementId value of progress is null.");htmx.on(`#${s}`,"htmx:xhr:progress",function(l){l.target.id==`${s}`&&htmx.find(`#${a}`).setAttribute("value",l.detail.loaded/l.detail.total*k)})}(()=>{"use strict";d("artifact-editor-dl-form","artifact-editor-dl-progress"),d("artifact-editor-preview-form","artifact-editor-preview-progress");let s=document.getElementById("artifact-editor-preview-reset");if(s==null){console.error("the reset preview button is missing");return}let a=document.getElementById("artifact-editor-replace-preview");if(a==null){console.error("the form preview input is missing");return}let l=document.getElementById("artifact-editor-dl-reset");if(l==null){console.error("the reset button is missing");return}let c=document.getElementById("artifact-editor-dl-up");if(c==null){console.error("the artifact file input is missing");return}let f=document.getElementById("artifact-editor-modal");if(f==null){console.error("the data editor modal is missing");return}let h=document.getElementById("asset-editor-modal");if(h==null){console.error("the asset editor modal is missing");return}let m=document.getElementById("emulate-editor-modal");if(m==null){console.error("the emulate editor modal is missing");return}let x=new bootstrap.Modal(f),v=new bootstrap.Modal(h),g=new bootstrap.Modal(m);switch(new URL(window.location.href).hash){case"#data-editor":x.show(),history.replaceState(null,"",window.location.pathname);break;case"#file-editor":v.show(),history.replaceState(null,"",window.location.pathname);break;case"#emulate-editor":g.show(),history.replaceState(null,"",window.location.pathname);break;default:}document.body.addEventListener("htmx:afterRequest",function(e){w(e,"artifact-editor-dl-form","artifact-editor-dl-up","artifact-editor-dl-feedback"),w(e,"artifact-editor-preview-form","artifact-editor-replace-preview","artifact-editor-preview-feedback"),u(e,"artifact-editor-image-delete","artifact-editor-image-feedback"),u(e,"artifact-editor-imagepreview-delete","artifact-editor-image-feedback"),u(e,"artifact-editor-imagethumb-delete","artifact-editor-image-feedback"),u(e,"artifact-editor-image-pixelate","artifact-editor-preview-feedback"),T(e,"artifact-editor-link-delete","artifact-editor-link-feedback")});function u(e,o,r){if(e.detail.elt===null||e.detail.elt.id!==`${o}`)return;let t=document.getElementById(r);if(t===null)throw new Error(`The htmx successful feedback element ${r} is null`);let n="text-danger",i="text-success",p=e.detail.xhr;if(e.detail.successful){t.innerText="The delete request was successful, about to refresh the page.",t.classList.remove(n),t.classList.add(i),setTimeout(()=>{location.reload()},500);return}if(e.detail.failed&&e.detail.xhr){t.classList.add(n),t.innerText=`Something on the server is not working, ${p.status} status: ${p.responseText}.`;return}t.classList.add(n),t.innerText="Something with the browser is not working, please try again or refresh the page."}function T(e,o,r){if(e.detail.elt===null||e.detail.elt.id!==`${o}`)return;let t=document.getElementById(r);if(t===null)throw new Error(`The htmx successful feedback element ${r} is null`);let n="text-danger",i=e.detail.xhr;if(e.detail.successful){t.innerText=`${i.responseText}`,t.classList.remove(n);return}if(e.detail.failed&&e.detail.xhr){t.classList.add(n),t.innerText=`Something on the server is not working, ${i.status} status: ${i.responseText}.`;return}t.classList.add(n),t.innerText="Something with the browser is not working, please try again or refresh the page."}function w(e,o,r,t){if(e.detail.elt===null||e.detail.elt.id!==`${o}`)return;let n=document.getElementById(r);if(n===null)throw new Error(`The htmx successful input element ${r} is null`);let i=document.getElementById(t);if(i===null)throw new Error(`The htmx successful feedback element ${t} is null`);if(e.detail.successful)return E(e,n,i);if(e.detail.failed&&e.detail.xhr)return b(e,n,i);y(n,i)}function E(e,o,r){let t=e.detail.xhr;r.innerText=`${t.responseText}`,r.classList.remove("invalid-feedback"),r.classList.add("valid-feedback"),o.classList.remove("is-invalid"),o.classList.add("is-valid"),setTimeout(()=>{location.reload()},500)}function b(e,o,r){let t=e.detail.xhr;r.innerText=`Something on the server is not working, ${t.status} status: ${t.responseText}.`,r.classList.remove("valid-feedback"),r.classList.add("invalid-feedback"),o.classList.remove("is-valid"),o.classList.add("is-invalid")}function y(e,o){e.classList.remove("is-valid"),e.classList.add("is-invalid"),o.innerText="Something with the browser is not working, please try again or refresh the page.",o.classList.remove("d-none")}l.addEventListener("click",function(){c.value="",c.classList.remove("is-invalid","is-valid")}),s.addEventListener("click",function(){a.value="",a.classList.remove("is-invalid","is-valid")})})();})(); +(()=>{var k=100,L=1024*1024,H=100*L;function f(s,a){if(s==null)throw new Error("The formId value of progress is null.");if(a==null)throw new Error("The elementId value of progress is null.");htmx.on(`#${s}`,"htmx:xhr:progress",function(l){l.target.id==`${s}`&&htmx.find(`#${a}`).setAttribute("value",l.detail.loaded/l.detail.total*k)})}(()=>{"use strict";f("artifact-editor-dl-form","artifact-editor-dl-progress"),f("artifact-editor-preview-form","artifact-editor-preview-progress");let s=document.getElementById("artifact-editor-preview-reset");if(s==null){console.error("the reset preview button is missing");return}let a=document.getElementById("artifact-editor-replace-preview");if(a==null){console.error("the form preview input is missing");return}let l=document.getElementById("artifact-editor-dl-reset");if(l==null){console.error("the reset button is missing");return}let d=document.getElementById("artifact-editor-dl-up");if(d==null){console.error("the artifact file input is missing");return}let h=document.getElementById("artifact-editor-modal");if(h==null){console.error("the data editor modal is missing");return}let m=document.getElementById("asset-editor-modal");if(m==null){console.error("the asset editor modal is missing");return}let w=document.getElementById("emulate-editor-modal");if(w==null){console.error("the emulate editor modal is missing");return}let v=new bootstrap.Modal(h),g=new bootstrap.Modal(m),T=new bootstrap.Modal(w);switch(new URL(window.location.href).hash){case"#data-editor":v.show(),history.replaceState(null,"",window.location.pathname);break;case"#file-editor":g.show(),history.replaceState(null,"",window.location.pathname);break;case"#emulate-editor":T.show(),history.replaceState(null,"",window.location.pathname);break;default:}document.body.addEventListener("htmx:afterRequest",function(e){p(e,"artifact-editor-dl-form","artifact-editor-dl-up","artifact-editor-dl-feedback"),p(e,"artifact-editor-preview-form","artifact-editor-replace-preview","artifact-editor-preview-feedback"),c(e,"artifact-editor-image-delete","artifact-editor-image-feedback"),c(e,"artifact-editor-imagepreview-delete","artifact-editor-image-feedback"),c(e,"artifact-editor-imagethumb-delete","artifact-editor-image-feedback"),c(e,"artifact-editor-image-pixelate","artifact-editor-preview-feedback"),u(e,"artifact-editor-link-delete","artifact-editor-link-feedback"),u(e,"artifact-editor-comp-previewcopy","artifact-editor-comp-feedback"),u(e,"artifact-editor-comp-previewtext","artifact-editor-comp-feedback"),u(e,"artifact-editor-comp-textcopy","artifact-editor-comp-feedback")});function u(e,o,r){if(e.detail.elt===null||e.detail.elt.id!==`${o}`&&e.detail.elt.name!==o)return;let t=document.getElementById(r);if(t===null)throw new Error(`The htmx successful feedback element ${r} is null`);let i="text-danger",n=e.detail.xhr;if(e.detail.successful){t.innerText=`${n.responseText}`,t.classList.remove(i);return}if(e.detail.failed&&e.detail.xhr){t.classList.add(i),t.innerText=`Something on the server is not working, ${n.status} status: ${n.responseText}.`;return}t.classList.add(i),t.innerText="Something with the browser is not working, please try again or refresh the page."}function c(e,o,r){if(e.detail.elt===null||e.detail.elt.id!==`${o}`)return;let t=document.getElementById(r);if(t===null)throw new Error(`The htmx successful feedback element ${r} is null`);let i="text-danger",n="text-success",x=e.detail.xhr;if(e.detail.successful){t.innerText="The delete request was successful, about to refresh the page.",t.classList.remove(i),t.classList.add(n),setTimeout(()=>{location.reload()},500);return}if(e.detail.failed&&e.detail.xhr){t.classList.add(i),t.innerText=`Something on the server is not working, ${x.status} status: ${x.responseText}.`;return}t.classList.add(i),t.innerText="Something with the browser is not working, please try again or refresh the page."}function p(e,o,r,t){if(e.detail.elt===null||e.detail.elt.id!==`${o}`)return;let i=document.getElementById(r);if(i===null)throw new Error(`The htmx successful input element ${r} is null`);let n=document.getElementById(t);if(n===null)throw new Error(`The htmx successful feedback element ${t} is null`);if(e.detail.successful)return E(e,i,n);if(e.detail.failed&&e.detail.xhr)return b(e,i,n);y(i,n)}function E(e,o,r){let t=e.detail.xhr;r.innerText=`${t.responseText}`,r.classList.remove("invalid-feedback"),r.classList.add("valid-feedback"),o.classList.remove("is-invalid"),o.classList.add("is-valid"),setTimeout(()=>{location.reload()},500)}function b(e,o,r){let t=e.detail.xhr;r.innerText=`Something on the server is not working, ${t.status} status: ${t.responseText}.`,r.classList.remove("valid-feedback"),r.classList.add("invalid-feedback"),o.classList.remove("is-valid"),o.classList.add("is-invalid")}function y(e,o){e.classList.remove("is-valid"),e.classList.add("is-invalid"),o.innerText="Something with the browser is not working, please try again or refresh the page.",o.classList.remove("d-none")}l.addEventListener("click",function(){d.value="",d.classList.remove("is-invalid","is-valid")}),s.addEventListener("click",function(){a.value="",a.classList.remove("is-invalid","is-valid")})})();})(); diff --git a/view/app/artifactfile.tmpl b/view/app/artifactfile.tmpl index b897472c..bef28ef4 100644 --- a/view/app/artifactfile.tmpl +++ b/view/app/artifactfile.tmpl @@ -281,54 +281,35 @@
-
+

README +

{{- if eq (len .modAssetExtra) 0}}
No extras in use
{{else}} -
- -
- {{- end}} - {{- if ne "" (index . "modReadmeSuggest")}} -
- +
+ +
+ {{- end}} + {{- if ne "" (index . "modReadmeSuggest")}} +
+ +
> {{$modReadmeSuggest}}
+
-
> {{$modReadmeSuggest}}
{{- end}}

-
-
-
-

- Repacked ZIP - {{- if eq $notFound $statSizeB}}

download file not found
- {{- else if eq "" (index . "modZipContent")}}
The download is not an archive
- {{- else if eq "Zip archive" $magicNum}}
Repacking is not required
- {{- else}} -
- {{recordReadme (index . "modNoReadme") }} - -
feature not used, download is not an obsolete archive
-
Saved, {{$refreshPage}}
-
error placeholder
-
- {{- end}} -

-
-
-