- Split monolithic app.js/style.css into Alpine.js components (icons, store, fileSection, confirm)
- Add central Alpine.store('files') as single source of truth for file lists and actions
- Replace duplicated Inbox/Outbox markup with reusable fileSection component (props: dir, canShare)
- Add shared window.Icons module to remove duplicated inline SVGs
- Replace browser-native confirm() for file deletion with a styled, accessible modal dialog
- Split CSS into design tokens, base, and component layers; modernize visuals
- Update web.go embed and server static routes for the new component/style dirs
45 lines
1.2 KiB
JavaScript
45 lines
1.2 KiB
JavaScript
/**
|
|
* fileSection component.
|
|
*
|
|
* A single reusable component parametrized by `dir` and `canShare`. Both the
|
|
* Inbox and Outbox on the page are the same component instance with different
|
|
* props, replacing the previously copy-pasted <section> blocks.
|
|
*
|
|
* Usage:
|
|
* <section x-data="fileSection('inbox', { canShare: true })"> ... </section>
|
|
*/
|
|
(function () {
|
|
function register() {
|
|
Alpine.data('fileSection', (dir, opts = {}) => ({
|
|
dir,
|
|
canShare: opts.canShare ?? false,
|
|
dragover: false,
|
|
|
|
get files() {
|
|
return Alpine.store('files').files[dir];
|
|
},
|
|
get count() {
|
|
return this.files.length;
|
|
},
|
|
get title() {
|
|
return dir === 'inbox' ? 'Inbox' : 'Outbox';
|
|
},
|
|
get icon() {
|
|
return dir === 'inbox' ? window.Icons.inbox : window.Icons.outbox;
|
|
},
|
|
|
|
async onSelect(e) {
|
|
await Alpine.store('files').upload(this.dir, e.target.files);
|
|
e.target.value = '';
|
|
},
|
|
|
|
async onDrop(e) {
|
|
await Alpine.store('files').upload(this.dir, e.dataTransfer.files);
|
|
},
|
|
}));
|
|
}
|
|
|
|
if (window.Alpine) register();
|
|
else document.addEventListener('alpine:init', register);
|
|
})();
|