fixed relation and file custom change event trigger
This commit is contained in:
File diff suppressed because one or more lines are too long
2
ui/dist/index.html
vendored
2
ui/dist/index.html
vendored
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<!-- prism -->
|
<!-- prism -->
|
||||||
<script src="./libs/prism/prism.js" data-manual></script>
|
<script src="./libs/prism/prism.js" data-manual></script>
|
||||||
<script type="module" crossorigin src="./assets/index-DhtJzO0I.js"></script>
|
<script type="module" crossorigin src="./assets/index-OxsdchXY.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="./assets/pocketbase.es-B_4DUNUU.js">
|
<link rel="modulepreload" crossorigin href="./assets/pocketbase.es-B_4DUNUU.js">
|
||||||
<link rel="stylesheet" crossorigin href="./assets/index-BLIFQr7L.css">
|
<link rel="stylesheet" crossorigin href="./assets/index-BLIFQr7L.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -4,8 +4,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "dprint fmt && vite build"
|
||||||
"format": "dprint fmt"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export function input(props) {
|
|||||||
|
|
||||||
// trigger custom change event for clearing field errors
|
// trigger custom change event for clearing field errors
|
||||||
function triggerChangeEvent() {
|
function triggerChangeEvent() {
|
||||||
fieldEl?.dispatchEvent(
|
fieldContentEl?.dispatchEvent(
|
||||||
new CustomEvent("change", {
|
new CustomEvent("change", {
|
||||||
detail: { data: props },
|
detail: { data: props },
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
@@ -92,7 +92,6 @@ export function input(props) {
|
|||||||
const fileInput = t.input({
|
const fileInput = t.input({
|
||||||
type: "file",
|
type: "file",
|
||||||
hidden: true,
|
hidden: true,
|
||||||
name: () => props.field.name,
|
|
||||||
multiple: () => props.field.maxSelect > 1,
|
multiple: () => props.field.maxSelect > 1,
|
||||||
accept: () => props.field.mimeTypes?.join(",") || undefined,
|
accept: () => props.field.mimeTypes?.join(",") || undefined,
|
||||||
onchange: (e) => {
|
onchange: (e) => {
|
||||||
@@ -101,37 +100,11 @@ export function input(props) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const fieldEl = t.div(
|
const fieldContentEl = t.output(
|
||||||
{
|
{
|
||||||
className: "record-field-input field-type-file",
|
className: "field-content",
|
||||||
ondragover: (e) => {
|
name: () => props.field.name,
|
||||||
e.preventDefault(); // prevent default to allow drop
|
|
||||||
},
|
},
|
||||||
ondrop: (e) => {
|
|
||||||
const files = e.dataTransfer?.files || [];
|
|
||||||
if (!files.length) {
|
|
||||||
return; // not a file drop
|
|
||||||
}
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (local.maxReached) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
addFiles(files);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
t.div(
|
|
||||||
{ className: () => `field ${props.field.required ? "required" : ""}` },
|
|
||||||
t.label(
|
|
||||||
{ htmlFor: uniqueId },
|
|
||||||
t.i({ className: app.fieldTypes.file.icon, ariaHidden: true }),
|
|
||||||
t.span({ className: "txt" }, () => props.field.name),
|
|
||||||
),
|
|
||||||
fileInput,
|
|
||||||
t.div(
|
|
||||||
{ className: "field-content" },
|
|
||||||
// @todo enable ordering new files before/inbetween existing
|
// @todo enable ordering new files before/inbetween existing
|
||||||
app.components.sortable({
|
app.components.sortable({
|
||||||
className: "list",
|
className: "list",
|
||||||
@@ -235,7 +208,7 @@ export function input(props) {
|
|||||||
disabled: () => local.maxReached,
|
disabled: () => local.maxReached,
|
||||||
onclick: (e) => {
|
onclick: (e) => {
|
||||||
if (!local.maxReached) {
|
if (!local.maxReached) {
|
||||||
fileInput.click();
|
fileInput?.click();
|
||||||
}
|
}
|
||||||
document.activeElement?.blur();
|
document.activeElement?.blur();
|
||||||
},
|
},
|
||||||
@@ -243,7 +216,38 @@ export function input(props) {
|
|||||||
t.i({ className: "ri-upload-cloud-line", ariaHidden: true }),
|
t.i({ className: "ri-upload-cloud-line", ariaHidden: true }),
|
||||||
t.span({ className: "txt" }, "Upload or drop new file"),
|
t.span({ className: "txt" }, "Upload or drop new file"),
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return t.div(
|
||||||
|
{
|
||||||
|
className: "record-field-input field-type-file",
|
||||||
|
ondragover: (e) => {
|
||||||
|
e.preventDefault(); // prevent default to allow drop
|
||||||
|
},
|
||||||
|
ondrop: (e) => {
|
||||||
|
const files = e.dataTransfer?.files || [];
|
||||||
|
if (!files.length) {
|
||||||
|
return; // not a file drop
|
||||||
|
}
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (local.maxReached) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addFiles(files);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
t.div(
|
||||||
|
{ className: () => `field ${props.field.required ? "required" : ""}` },
|
||||||
|
t.label(
|
||||||
|
{ htmlFor: uniqueId },
|
||||||
|
t.i({ className: app.fieldTypes.file.icon, ariaHidden: true }),
|
||||||
|
t.span({ className: "txt" }, () => props.field.name),
|
||||||
),
|
),
|
||||||
|
fileInput,
|
||||||
|
fieldContentEl,
|
||||||
),
|
),
|
||||||
() => {
|
() => {
|
||||||
if (props.field.help) {
|
if (props.field.help) {
|
||||||
@@ -251,6 +255,4 @@ export function input(props) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return fieldEl;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export function input(props) {
|
|||||||
|
|
||||||
// trigger custom change event for clearing field errors
|
// trigger custom change event for clearing field errors
|
||||||
function triggerChangeEvent() {
|
function triggerChangeEvent() {
|
||||||
fieldEl?.dispatchEvent(
|
fieldContentEl?.dispatchEvent(
|
||||||
new CustomEvent("change", {
|
new CustomEvent("change", {
|
||||||
detail: { data: props },
|
detail: { data: props },
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
@@ -87,6 +87,7 @@ export function input(props) {
|
|||||||
|
|
||||||
function updateRecordValue(ids = []) {
|
function updateRecordValue(ids = []) {
|
||||||
props.record[props.field.name] = props.field.maxSelect > 1 ? ids : ids?.[0] || "";
|
props.record[props.field.name] = props.field.maxSelect > 1 ? ids : ids?.[0] || "";
|
||||||
|
triggerChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
const watchers = [
|
const watchers = [
|
||||||
@@ -96,21 +97,7 @@ export function input(props) {
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
const fieldEl = t.div(
|
const fieldContentEl = t.output(
|
||||||
{
|
|
||||||
className: "record-field-input field-type-relation",
|
|
||||||
onunmount: () => {
|
|
||||||
watchers.forEach((w) => w?.unwatch());
|
|
||||||
},
|
|
||||||
},
|
|
||||||
t.div(
|
|
||||||
{ className: () => `field ${props.field.required ? "required" : ""}` },
|
|
||||||
t.label(
|
|
||||||
{ htmlFor: uniqueId },
|
|
||||||
t.i({ className: app.fieldTypes.relation.icon, ariaHidden: true }),
|
|
||||||
t.span({ className: "txt" }, () => props.field.name),
|
|
||||||
),
|
|
||||||
t.output(
|
|
||||||
{
|
{
|
||||||
className: "field-content",
|
className: "field-content",
|
||||||
name: () => props.field.name,
|
name: () => props.field.name,
|
||||||
@@ -136,7 +123,6 @@ export function input(props) {
|
|||||||
onchange: (sortedList) => {
|
onchange: (sortedList) => {
|
||||||
local.selected = sortedList;
|
local.selected = sortedList;
|
||||||
updateRecordValue(sortedList.map((r) => r.id));
|
updateRecordValue(sortedList.map((r) => r.id));
|
||||||
triggerChangeEvent();
|
|
||||||
},
|
},
|
||||||
dataItem: (record, relIndex) => {
|
dataItem: (record, relIndex) => {
|
||||||
return t.div(
|
return t.div(
|
||||||
@@ -184,7 +170,23 @@ export function input(props) {
|
|||||||
t.i({ className: "ri-magic-line", ariaHidden: true }),
|
t.i({ className: "ri-magic-line", ariaHidden: true }),
|
||||||
t.span({ className: "txt" }, "Open records picker"),
|
t.span({ className: "txt" }, "Open records picker"),
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return t.div(
|
||||||
|
{
|
||||||
|
className: "record-field-input field-type-relation",
|
||||||
|
onunmount: () => {
|
||||||
|
watchers.forEach((w) => w?.unwatch());
|
||||||
|
},
|
||||||
|
},
|
||||||
|
t.div(
|
||||||
|
{ className: () => `field ${props.field.required ? "required" : ""}` },
|
||||||
|
t.label(
|
||||||
|
{ htmlFor: uniqueId },
|
||||||
|
t.i({ className: app.fieldTypes.relation.icon, ariaHidden: true }),
|
||||||
|
t.span({ className: "txt" }, () => props.field.name),
|
||||||
),
|
),
|
||||||
|
fieldContentEl,
|
||||||
),
|
),
|
||||||
() => {
|
() => {
|
||||||
if (props.field.help) {
|
if (props.field.help) {
|
||||||
@@ -192,6 +194,4 @@ export function input(props) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return fieldEl;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user