Compare commits
5 Commits
feat/issue
...
18cad798fc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18cad798fc | ||
|
|
0ddf43947b | ||
|
|
45f7642f8d | ||
|
|
5a13e61357 | ||
|
|
a91ee1f26d |
@@ -13,6 +13,8 @@ public class DocumentUpdateDTO {
|
|||||||
private LocalDate documentDate;
|
private LocalDate documentDate;
|
||||||
private String location;
|
private String location;
|
||||||
private String documentLocation;
|
private String documentLocation;
|
||||||
|
private String archiveBox;
|
||||||
|
private String archiveFolder;
|
||||||
private String transcription;
|
private String transcription;
|
||||||
private String summary;
|
private String summary;
|
||||||
private UUID senderId;
|
private UUID senderId;
|
||||||
|
|||||||
@@ -271,6 +271,8 @@ public class DocumentService {
|
|||||||
doc.setTranscription(dto.getTranscription());
|
doc.setTranscription(dto.getTranscription());
|
||||||
doc.setSummary(dto.getSummary());
|
doc.setSummary(dto.getSummary());
|
||||||
doc.setDocumentLocation(dto.getDocumentLocation());
|
doc.setDocumentLocation(dto.getDocumentLocation());
|
||||||
|
doc.setArchiveBox(dto.getArchiveBox());
|
||||||
|
doc.setArchiveFolder(dto.getArchiveFolder());
|
||||||
|
|
||||||
List<String> tags = new ArrayList<>();
|
List<String> tags = new ArrayList<>();
|
||||||
if (dto.getTags() != null && !dto.getTags().isBlank()) {
|
if (dto.getTags() != null && !dto.getTags().isBlank()) {
|
||||||
|
|||||||
@@ -121,6 +121,23 @@ class DocumentServiceTest {
|
|||||||
.isInstanceOf(DomainException.class);
|
.isInstanceOf(DomainException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateDocument_setsArchiveBoxAndFolder() throws Exception {
|
||||||
|
UUID id = UUID.randomUUID();
|
||||||
|
Document doc = Document.builder().id(id).receivers(new HashSet<>()).tags(new HashSet<>()).build();
|
||||||
|
when(documentRepository.findById(id)).thenReturn(Optional.of(doc));
|
||||||
|
when(documentRepository.save(any())).thenReturn(doc);
|
||||||
|
|
||||||
|
DocumentUpdateDTO dto = new DocumentUpdateDTO();
|
||||||
|
dto.setArchiveBox("K-03");
|
||||||
|
dto.setArchiveFolder("Mappe B");
|
||||||
|
|
||||||
|
documentService.updateDocument(id, dto, null, null);
|
||||||
|
|
||||||
|
assertThat(doc.getArchiveBox()).isEqualTo("K-03");
|
||||||
|
assertThat(doc.getArchiveFolder()).isEqualTo("Mappe B");
|
||||||
|
}
|
||||||
|
|
||||||
// ─── deleteTagCascading ───────────────────────────────────────────────────
|
// ─── deleteTagCascading ───────────────────────────────────────────────────
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ let selectedReceivers = $state<Person[]>(untrack(() => initialReceivers));
|
|||||||
let dateIso = $state('');
|
let dateIso = $state('');
|
||||||
let tags = $state<Tag[]>([]);
|
let tags = $state<Tag[]>([]);
|
||||||
// Bulk-edit only — replace-on-non-blank semantics.
|
// Bulk-edit only — replace-on-non-blank semantics.
|
||||||
let documentLocation = $state('');
|
|
||||||
let archiveBox = $state('');
|
let archiveBox = $state('');
|
||||||
let archiveFolder = $state('');
|
let archiveFolder = $state('');
|
||||||
|
|
||||||
@@ -231,7 +230,6 @@ async function saveBulkEdit() {
|
|||||||
tagNames: tags.map((t) => t.name),
|
tagNames: tags.map((t) => t.name),
|
||||||
senderId: senderId || null,
|
senderId: senderId || null,
|
||||||
receiverIds: selectedReceivers.map((r) => r.id),
|
receiverIds: selectedReceivers.map((r) => r.id),
|
||||||
documentLocation: documentLocation || null,
|
|
||||||
archiveBox: archiveBox || null,
|
archiveBox: archiveBox || null,
|
||||||
archiveFolder: archiveFolder || null
|
archiveFolder: archiveFolder || null
|
||||||
};
|
};
|
||||||
@@ -442,7 +440,6 @@ async function retrySave() {
|
|||||||
/>
|
/>
|
||||||
<DescriptionSection
|
<DescriptionSection
|
||||||
bind:tags={tags}
|
bind:tags={tags}
|
||||||
bind:documentLocation={documentLocation}
|
|
||||||
bind:archiveBox={archiveBox}
|
bind:archiveBox={archiveBox}
|
||||||
bind:archiveFolder={archiveFolder}
|
bind:archiveFolder={archiveFolder}
|
||||||
hideTitle
|
hideTitle
|
||||||
@@ -494,7 +491,6 @@ async function retrySave() {
|
|||||||
/>
|
/>
|
||||||
<DescriptionSection
|
<DescriptionSection
|
||||||
bind:tags={tags}
|
bind:tags={tags}
|
||||||
bind:documentLocation={documentLocation}
|
|
||||||
bind:archiveBox={archiveBox}
|
bind:archiveBox={archiveBox}
|
||||||
bind:archiveFolder={archiveFolder}
|
bind:archiveFolder={archiveFolder}
|
||||||
hideTitle
|
hideTitle
|
||||||
|
|||||||
@@ -397,8 +397,8 @@ describe('BulkDocumentEditLayout — mode="edit"', () => {
|
|||||||
initialEditEntries: [editEntry(1)]
|
initialEditEntries: [editEntry(1)]
|
||||||
});
|
});
|
||||||
const replaceBadges = container.querySelectorAll('[data-testid="field-label-badge-replace"]');
|
const replaceBadges = container.querySelectorAll('[data-testid="field-label-badge-replace"]');
|
||||||
// sender + documentLocation + archiveBox + archiveFolder = 4
|
// sender + archiveBox + archiveFolder = 3
|
||||||
expect(replaceBadges.length).toBeGreaterThanOrEqual(4);
|
expect(replaceBadges.length).toBeGreaterThanOrEqual(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('topbar reads "Massenbearbeitung" + "{count} werden bearbeitet" in edit mode', async () => {
|
it('topbar reads "Massenbearbeitung" + "{count} werden bearbeitet" in edit mode', async () => {
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ let {
|
|||||||
archiveBox = $bindable(''),
|
archiveBox = $bindable(''),
|
||||||
archiveFolder = $bindable(''),
|
archiveFolder = $bindable(''),
|
||||||
initialTitle = '',
|
initialTitle = '',
|
||||||
initialDocumentLocation = '',
|
initialArchiveBox = '',
|
||||||
|
initialArchiveFolder = '',
|
||||||
initialSummary = '',
|
initialSummary = '',
|
||||||
titleRequired = false,
|
titleRequired = false,
|
||||||
suggestedTitle = '',
|
suggestedTitle = '',
|
||||||
@@ -24,7 +25,8 @@ let {
|
|||||||
archiveBox?: string;
|
archiveBox?: string;
|
||||||
archiveFolder?: string;
|
archiveFolder?: string;
|
||||||
initialTitle?: string;
|
initialTitle?: string;
|
||||||
initialDocumentLocation?: string;
|
initialArchiveBox?: string;
|
||||||
|
initialArchiveFolder?: string;
|
||||||
initialSummary?: string;
|
initialSummary?: string;
|
||||||
titleRequired?: boolean;
|
titleRequired?: boolean;
|
||||||
suggestedTitle?: string;
|
suggestedTitle?: string;
|
||||||
@@ -41,7 +43,8 @@ let {
|
|||||||
let titleDirty = $state(false);
|
let titleDirty = $state(false);
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (!currentTitle && initialTitle) currentTitle = initialTitle;
|
if (!currentTitle && initialTitle) currentTitle = initialTitle;
|
||||||
if (!documentLocation && initialDocumentLocation) documentLocation = initialDocumentLocation;
|
if (!archiveBox && initialArchiveBox) archiveBox = initialArchiveBox;
|
||||||
|
if (!archiveFolder && initialArchiveFolder) archiveFolder = initialArchiveFolder;
|
||||||
});
|
});
|
||||||
const titleValue = $derived(titleDirty ? currentTitle : suggestedTitle || currentTitle);
|
const titleValue = $derived(titleDirty ? currentTitle : suggestedTitle || currentTitle);
|
||||||
</script>
|
</script>
|
||||||
@@ -110,55 +113,36 @@ const titleValue = $derived(titleDirty ? currentTitle : suggestedTitle || curren
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- Aufbewahrungsort (optional) -->
|
<!-- Karton -->
|
||||||
<div data-testid="description-document-location">
|
<div data-testid="description-archive-box">
|
||||||
<label for="documentLocation" class="mb-1 block text-sm font-medium text-ink-2"
|
<label for="archiveBox" class="mb-1 block text-sm font-medium text-ink-2">
|
||||||
>{m.form_label_archive_location()}
|
{m.form_label_archive_box()}
|
||||||
{#if editMode}<FieldLabelBadge variant="replace" />{/if}
|
{#if editMode}<FieldLabelBadge variant="replace" />{/if}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="documentLocation"
|
id="archiveBox"
|
||||||
type="text"
|
type="text"
|
||||||
name="documentLocation"
|
name="archiveBox"
|
||||||
bind:value={documentLocation}
|
bind:value={archiveBox}
|
||||||
placeholder={m.form_placeholder_archive_location()}
|
|
||||||
class="block w-full rounded border border-line p-2 text-sm shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
class="block w-full rounded border border-line p-2 text-sm shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
||||||
/>
|
/>
|
||||||
<p class="mt-1 text-xs text-ink-3">{m.form_helper_archive_location()}</p>
|
<p class="mt-1 text-xs text-ink-3">{m.form_helper_archive_box()}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if editMode}
|
<!-- Mappe -->
|
||||||
<!-- Karton (only in editMode — bulk-editable replace) -->
|
<div data-testid="description-archive-folder">
|
||||||
<div data-testid="description-archive-box">
|
<label for="archiveFolder" class="mb-1 block text-sm font-medium text-ink-2">
|
||||||
<label for="archiveBox" class="mb-1 block text-sm font-medium text-ink-2">
|
{m.form_label_archive_folder()}
|
||||||
{m.form_label_archive_box()}
|
{#if editMode}<FieldLabelBadge variant="replace" />{/if}
|
||||||
<FieldLabelBadge variant="replace" />
|
</label>
|
||||||
</label>
|
<input
|
||||||
<input
|
id="archiveFolder"
|
||||||
id="archiveBox"
|
type="text"
|
||||||
type="text"
|
name="archiveFolder"
|
||||||
name="archiveBox"
|
bind:value={archiveFolder}
|
||||||
bind:value={archiveBox}
|
class="block w-full rounded border border-line p-2 text-sm shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
||||||
class="block w-full rounded border border-line p-2 text-sm shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
/>
|
||||||
/>
|
<p class="mt-1 text-xs text-ink-3">{m.form_helper_archive_folder()}</p>
|
||||||
<p class="mt-1 text-xs text-ink-3">{m.form_helper_archive_box()}</p>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Mappe (only in editMode — bulk-editable replace) -->
|
|
||||||
<div data-testid="description-archive-folder">
|
|
||||||
<label for="archiveFolder" class="mb-1 block text-sm font-medium text-ink-2">
|
|
||||||
{m.form_label_archive_folder()}
|
|
||||||
<FieldLabelBadge variant="replace" />
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="archiveFolder"
|
|
||||||
type="text"
|
|
||||||
name="archiveFolder"
|
|
||||||
bind:value={archiveFolder}
|
|
||||||
class="block w-full rounded border border-line p-2 text-sm shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
|
||||||
/>
|
|
||||||
<p class="mt-1 text-xs text-ink-3">{m.form_helper_archive_folder()}</p>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -21,19 +21,10 @@ describe('DescriptionSection — onMount seeding (Felix B1/B2 fix regression fen
|
|||||||
expect(titleInput.value).toBe('Parent Title');
|
expect(titleInput.value).toBe('Parent Title');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('pre-fills the documentLocation input from initialDocumentLocation', async () => {
|
it('always renders archiveBox + archiveFolder fields regardless of editMode', async () => {
|
||||||
render(DescriptionSection, { initialDocumentLocation: 'Schrank 3, Mappe B' });
|
render(DescriptionSection, { editMode: false });
|
||||||
const locationInput = document.querySelector('input#documentLocation') as HTMLInputElement;
|
expect(document.querySelector('[data-testid="description-archive-box"]')).not.toBeNull();
|
||||||
expect(locationInput.value).toBe('Schrank 3, Mappe B');
|
expect(document.querySelector('[data-testid="description-archive-folder"]')).not.toBeNull();
|
||||||
});
|
|
||||||
|
|
||||||
it('does not stomp a parent-bound documentLocation that is already non-empty', async () => {
|
|
||||||
render(DescriptionSection, {
|
|
||||||
documentLocation: 'Bound Value',
|
|
||||||
initialDocumentLocation: 'Should Not Win'
|
|
||||||
});
|
|
||||||
const locationInput = document.querySelector('input#documentLocation') as HTMLInputElement;
|
|
||||||
expect(locationInput.value).toBe('Bound Value');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders the editMode-only archiveBox + archiveFolder fields when editMode=true', async () => {
|
it('renders the editMode-only archiveBox + archiveFolder fields when editMode=true', async () => {
|
||||||
@@ -42,9 +33,25 @@ describe('DescriptionSection — onMount seeding (Felix B1/B2 fix regression fen
|
|||||||
expect(document.querySelector('[data-testid="description-archive-folder"]')).not.toBeNull();
|
expect(document.querySelector('[data-testid="description-archive-folder"]')).not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('hides the editMode-only archive fields when editMode=false', async () => {
|
it('pre-fills archiveBox from initialArchiveBox when archiveBox is empty', async () => {
|
||||||
render(DescriptionSection, { editMode: false });
|
render(DescriptionSection, { initialArchiveBox: 'K-03', hideTitle: true });
|
||||||
expect(document.querySelector('[data-testid="description-archive-box"]')).toBeNull();
|
const input = document.querySelector('input#archiveBox') as HTMLInputElement;
|
||||||
expect(document.querySelector('[data-testid="description-archive-folder"]')).toBeNull();
|
expect(input.value).toBe('K-03');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pre-fills archiveFolder from initialArchiveFolder when archiveFolder is empty', async () => {
|
||||||
|
render(DescriptionSection, { initialArchiveFolder: 'Mappe B', hideTitle: true });
|
||||||
|
const input = document.querySelector('input#archiveFolder') as HTMLInputElement;
|
||||||
|
expect(input.value).toBe('Mappe B');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not stomp a parent-bound archiveBox that is already non-empty', async () => {
|
||||||
|
render(DescriptionSection, {
|
||||||
|
archiveBox: 'Parent Value',
|
||||||
|
initialArchiveBox: 'Should Not Win',
|
||||||
|
hideTitle: true
|
||||||
|
});
|
||||||
|
const input = document.querySelector('input#archiveBox') as HTMLInputElement;
|
||||||
|
expect(input.value).toBe('Parent Value');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -207,7 +207,8 @@ async function handleReplaceFile(e: Event) {
|
|||||||
bind:tags={tags}
|
bind:tags={tags}
|
||||||
bind:currentTitle={currentTitle}
|
bind:currentTitle={currentTitle}
|
||||||
initialTitle={doc.title ?? ''}
|
initialTitle={doc.title ?? ''}
|
||||||
initialDocumentLocation={doc.documentLocation ?? ''}
|
initialArchiveBox={doc.archiveBox ?? ''}
|
||||||
|
initialArchiveFolder={doc.archiveFolder ?? ''}
|
||||||
initialSummary={doc.summary ?? ''}
|
initialSummary={doc.summary ?? ''}
|
||||||
titleRequired={true}
|
titleRequired={true}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -13,14 +13,12 @@ let {
|
|||||||
items,
|
items,
|
||||||
canWrite,
|
canWrite,
|
||||||
error,
|
error,
|
||||||
total = 0,
|
|
||||||
q = '',
|
q = '',
|
||||||
sort = 'DATE'
|
sort = 'DATE'
|
||||||
}: {
|
}: {
|
||||||
items: DocumentSearchItem[];
|
items: DocumentSearchItem[];
|
||||||
canWrite: boolean;
|
canWrite: boolean;
|
||||||
error?: string | null;
|
error?: string | null;
|
||||||
total?: number;
|
|
||||||
q?: string;
|
q?: string;
|
||||||
sort?: SortMode;
|
sort?: SortMode;
|
||||||
} = $props();
|
} = $props();
|
||||||
@@ -71,29 +69,6 @@ function groupByReceiver(docItems: DocumentSearchItem[]) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- DOCUMENT LIST HEADER -->
|
|
||||||
<div class="mb-2 flex justify-end">
|
|
||||||
{#if canWrite}
|
|
||||||
<a
|
|
||||||
href="/documents/new"
|
|
||||||
class="inline-flex items-center gap-1 text-sm font-medium text-ink-2 transition-colors hover:text-ink"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Add/Add-General-MD.svg"
|
|
||||||
alt=""
|
|
||||||
aria-hidden="true"
|
|
||||||
class="h-4 w-4"
|
|
||||||
/>
|
|
||||||
{m.docs_btn_new()}
|
|
||||||
</a>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- RESULT COUNT -->
|
|
||||||
{#if total > 0}
|
|
||||||
<p class="mb-3 font-sans text-base text-ink-2">{m.docs_result_count({ count: total })}</p>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- ERROR -->
|
<!-- ERROR -->
|
||||||
{#if error}
|
{#if error}
|
||||||
<div class="border border-line bg-surface shadow-sm">
|
<div class="border border-line bg-surface shadow-sm">
|
||||||
|
|||||||
@@ -234,28 +234,54 @@ $effect(() => {
|
|||||||
onblur={() => (qFocused = false)}
|
onblur={() => (qFocused = false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{#if data.canWrite && data.totalElements > 0}
|
<div class="mb-3 flex items-center justify-between gap-4">
|
||||||
<div class="mb-2 flex flex-col items-end gap-1">
|
<p class="font-sans text-base text-ink-2">
|
||||||
<button
|
{#if data.totalElements > 0}{m.docs_result_count({ count: data.totalElements })}{/if}
|
||||||
type="button"
|
</p>
|
||||||
onclick={editAllMatching}
|
{#if data.canWrite}
|
||||||
disabled={editingAll}
|
<div class="flex flex-col items-end gap-1">
|
||||||
class="inline-flex items-center gap-1 text-sm font-medium text-ink-2 transition-colors hover:text-ink disabled:opacity-50"
|
<div class="flex items-center gap-4">
|
||||||
data-testid="bulk-edit-all-x"
|
{#if data.totalElements > 0}
|
||||||
>
|
<button
|
||||||
{m.bulk_edit_all_x({ count: data.totalElements })}
|
type="button"
|
||||||
</button>
|
onclick={editAllMatching}
|
||||||
{#if editAllError}
|
disabled={editingAll}
|
||||||
<p role="alert" class="text-xs text-danger" data-testid="bulk-edit-all-x-error">
|
class="inline-flex cursor-pointer items-center gap-1 text-sm font-medium text-ink-2 transition-colors hover:text-ink disabled:opacity-50"
|
||||||
{editAllError}
|
data-testid="bulk-edit-all-x"
|
||||||
</p>
|
>
|
||||||
{/if}
|
<img
|
||||||
</div>
|
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Edit-Content-MD.svg"
|
||||||
{/if}
|
alt=""
|
||||||
|
aria-hidden="true"
|
||||||
|
class="h-4 w-4"
|
||||||
|
/>
|
||||||
|
{m.bulk_edit_all_x({ count: data.totalElements })}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
<a
|
||||||
|
href="/documents/new"
|
||||||
|
class="inline-flex items-center gap-1 text-sm font-medium text-ink-2 transition-colors hover:text-ink"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Add/Add-General-MD.svg"
|
||||||
|
alt=""
|
||||||
|
aria-hidden="true"
|
||||||
|
class="h-4 w-4"
|
||||||
|
/>
|
||||||
|
{m.docs_btn_new()}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{#if editAllError}
|
||||||
|
<p role="alert" class="text-xs text-danger" data-testid="bulk-edit-all-x-error">
|
||||||
|
{editAllError}
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
<DocumentList
|
<DocumentList
|
||||||
items={data.items}
|
items={data.items}
|
||||||
total={data.totalElements}
|
|
||||||
q={data.q}
|
q={data.q}
|
||||||
canWrite={data.canWrite}
|
canWrite={data.canWrite}
|
||||||
error={data.error}
|
error={data.error}
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ export const actions = {
|
|||||||
if (doc.title) formData.set('title', doc.title);
|
if (doc.title) formData.set('title', doc.title);
|
||||||
if (doc.documentDate) formData.set('documentDate', doc.documentDate);
|
if (doc.documentDate) formData.set('documentDate', doc.documentDate);
|
||||||
if (doc.location) formData.set('location', doc.location);
|
if (doc.location) formData.set('location', doc.location);
|
||||||
if (doc.documentLocation) formData.set('documentLocation', doc.documentLocation);
|
if (doc.archiveBox) formData.set('archiveBox', doc.archiveBox);
|
||||||
|
if (doc.archiveFolder) formData.set('archiveFolder', doc.archiveFolder);
|
||||||
if (doc.transcription) formData.set('transcription', doc.transcription);
|
if (doc.transcription) formData.set('transcription', doc.transcription);
|
||||||
if (doc.summary) formData.set('summary', doc.summary);
|
if (doc.summary) formData.set('summary', doc.summary);
|
||||||
if (doc.sender?.id) formData.set('senderId', doc.sender.id);
|
if (doc.sender?.id) formData.set('senderId', doc.sender.id);
|
||||||
|
|||||||
Reference in New Issue
Block a user