[#4033] added option to duplicate fields

This commit is contained in:
Gani Georgiev
2024-01-21 20:22:56 +02:00
parent ba56623245
commit f0410a7625
45 changed files with 152 additions and 112 deletions
@@ -45,6 +45,23 @@
}
}
function duplicateField(fieldIndex) {
const field = collection.schema[fieldIndex];
if (!field) {
return; // nothing to duplicate
}
field.onMountSelect = false;
const clone = structuredClone(field);
clone.id = "";
clone.name = getUniqueFieldName(clone.name + "_copy");
clone.onMountSelect = true;
collection.schema.splice(fieldIndex + 1, 0, clone);
collection.schema = collection.schema;
}
function newField(fieldType = "text") {
const field = CommonHelper.initSchemaField({
name: getUniqueFieldName(),
@@ -57,14 +74,21 @@
collection.schema = collection.schema;
}
function getUniqueFieldName(base = "field") {
let counter = "";
function getUniqueFieldName(name = "field") {
let result = name;
let counter = 2;
while (hasFieldWithName(base + counter)) {
++counter;
let suffix = name.match(/[123456789]+$/)?.[0] || ""; // extract numeric suffix
// name without the suffix
let base = suffix ? name.substring(0, name.length - suffix.length) : name;
while (hasFieldWithName(result)) {
result = base + ((suffix << 0) + counter);
counter++;
}
return base + counter;
return result;
}
function hasFieldWithName(name) {
@@ -138,6 +162,7 @@
key={getSchemaFieldIndex(field)}
bind:field
on:remove={() => removeField(i)}
on:duplicate={() => duplicateField(i)}
on:rename={(e) => replaceIndexesColumn(e.detail.oldName, e.detail.newName)}
/>
</Draggable>
@@ -54,6 +54,7 @@
function remove() {
if (!field.id) {
collapse();
dispatch("remove");
} else {
field.toDelete = true;
@@ -67,6 +68,13 @@
setErrors({});
}
function duplicate() {
if (!field.toDelete) {
collapse();
dispatch("duplicate");
}
}
function normalizeFieldName(name) {
return CommonHelper.slugify(name);
}
@@ -211,7 +219,7 @@
class="ri-information-line link-hint"
use:tooltip={{
text: `Requires the field value NOT to be ${CommonHelper.zeroDefaultStr(
field
field,
)}.`,
}}
/>
@@ -235,22 +243,29 @@
{#if !field.toDelete}
<div class="m-l-auto txt-right">
<div class="flex-fill" />
<div class="inline-flex flex-gap-sm flex-nowrap">
<button
type="button"
aria-label="More"
class="btn btn-circle btn-sm btn-transparent"
>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div tabindex="0" aria-label="More" class="btn btn-circle btn-sm btn-transparent">
<i class="ri-more-line" />
<Toggler
class="dropdown dropdown-sm dropdown-upside dropdown-right dropdown-nowrap no-min-width"
>
<button type="button" class="dropdown-item txt-right" on:click={remove}>
<button
type="button"
class="dropdown-item txt-right"
on:click|preventDefault={duplicate}
>
<span class="txt">Duplicate</span>
</button>
<button
type="button"
class="dropdown-item txt-right"
on:click|preventDefault={remove}
>
<span class="txt">Remove</span>
</button>
</Toggler>
</button>
</div>
</div>
</div>
{/if}
@@ -5,4 +5,4 @@
export let key = "";
</script>
<SchemaField bind:field {key} on:rename on:remove {...$$restProps} />
<SchemaField bind:field {key} on:rename on:remove on:duplicate {...$$restProps} />
@@ -26,7 +26,7 @@
}
</script>
<SchemaField bind:field {key} on:rename on:remove {...$$restProps}>
<SchemaField bind:field {key} on:rename on:remove on:duplicate {...$$restProps}>
<svelte:fragment slot="options">
<div class="grid grid-sm">
<div class="col-sm-6">
@@ -18,7 +18,7 @@
}
</script>
<SchemaField bind:field {key} on:rename on:remove {...$$restProps}>
<SchemaField bind:field {key} on:rename on:remove on:duplicate {...$$restProps}>
<svelte:fragment slot="optionsFooter">
<Field class="form-field form-field-toggle" name="schema.{key}.options.convertUrls" let:uniqueId>
<input type="checkbox" id={uniqueId} bind:checked={field.options.convertUrls} />
@@ -9,7 +9,7 @@
export let key = "";
</script>
<SchemaField bind:field {key} on:rename on:remove {...$$restProps}>
<SchemaField bind:field {key} on:rename on:remove on:duplicate {...$$restProps}>
<svelte:fragment slot="options">
<div class="grid grid-sm">
<div class="col-sm-6">
@@ -70,7 +70,7 @@
}
</script>
<SchemaField bind:field {key} on:rename on:remove {...$$restProps}>
<SchemaField bind:field {key} on:rename on:remove on:duplicate {...$$restProps}>
<svelte:fragment let:interactive>
<div class="separator" />
@@ -20,7 +20,7 @@
}
</script>
<SchemaField bind:field {key} on:rename on:remove {...$$restProps}>
<SchemaField bind:field {key} on:rename on:remove on:duplicate {...$$restProps}>
<svelte:fragment slot="options">
<Field class="form-field required m-b-sm" name="schema.{key}.options.maxSize" let:uniqueId>
<label for={uniqueId}>Max size <small>(bytes)</small></label>
@@ -7,7 +7,7 @@
export let key = "";
</script>
<SchemaField bind:field {key} on:rename on:remove {...$$restProps}>
<SchemaField bind:field {key} on:rename on:remove on:duplicate {...$$restProps}>
<svelte:fragment slot="options">
<div class="grid grid-sm">
<div class="col-sm-6">
@@ -55,7 +55,7 @@
}
</script>
<SchemaField bind:field {key} on:rename on:remove {...$$restProps}>
<SchemaField bind:field {key} on:rename on:remove on:duplicate {...$$restProps}>
<svelte:fragment let:interactive>
<div class="separator" />
@@ -40,7 +40,7 @@
}
</script>
<SchemaField bind:field {key} on:rename on:remove {...$$restProps}>
<SchemaField bind:field {key} on:rename on:remove on:duplicate {...$$restProps}>
<svelte:fragment let:interactive>
<div class="separator" />
@@ -6,7 +6,7 @@
export let key = "";
</script>
<SchemaField bind:field {key} on:rename on:remove {...$$restProps}>
<SchemaField bind:field {key} on:rename on:remove on:duplicate {...$$restProps}>
<svelte:fragment slot="options">
<div class="grid grid-sm">
<div class="col-sm-3">
@@ -6,4 +6,4 @@
</script>
<!-- shares the same options with the email field -->
<SchemaFieldEmail bind:field {key} on:rename on:remove {...$$restProps} />
<SchemaFieldEmail bind:field {key} on:rename on:remove on:duplicate {...$$restProps} />