Merge pull request 'Correction affichage edition' (#27) from fix/5-probleme-rendu-html-du-markdown into develop
Reviewed-on: Bonsai/Bonsai-webapp#27
This commit is contained in:
@@ -138,6 +138,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Description */
|
/* Description */
|
||||||
|
.description-action-btn {
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 400;
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: normal;
|
||||||
|
color: #6b7280;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-action-btn:hover {
|
||||||
|
color: #111827;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.description-textarea {
|
.description-textarea {
|
||||||
min-height: 40rem;
|
min-height: 40rem;
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
@@ -145,7 +162,6 @@
|
|||||||
|
|
||||||
.description-preview {
|
.description-preview {
|
||||||
min-height: 7rem;
|
min-height: 7rem;
|
||||||
white-space: pre-wrap;
|
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
color: #374151;
|
color: #374151;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
|
|||||||
@@ -176,7 +176,12 @@
|
|||||||
|
|
||||||
<!-- Description -->
|
<!-- Description -->
|
||||||
<div class="card shadow-sm mb-3">
|
<div class="card shadow-sm mb-3">
|
||||||
<div class="card-header section-header">Description</div>
|
<div class="card-header section-header d-flex align-items-center justify-content-between">
|
||||||
|
<span>Description</span>
|
||||||
|
@if (!editingDescription) {
|
||||||
|
<button type="button" class="description-action-btn" (click)="startEditDescription()">Modifier</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@if (editingDescription) {
|
@if (editingDescription) {
|
||||||
<textarea
|
<textarea
|
||||||
@@ -184,13 +189,17 @@
|
|||||||
class="form-control border-0 shadow-none p-0 description-textarea"
|
class="form-control border-0 shadow-none p-0 description-textarea"
|
||||||
placeholder="Ajouter une description..."
|
placeholder="Ajouter une description..."
|
||||||
[(ngModel)]="issue.description"
|
[(ngModel)]="issue.description"
|
||||||
(blur)="editingDescription = false; saveIssue()"
|
(keydown.escape)="cancelEditDescription()"
|
||||||
(paste)="onDescriptionPaste($event)"
|
(paste)="onDescriptionPaste($event)"
|
||||||
></textarea>
|
></textarea>
|
||||||
|
<div class="d-flex gap-2 mt-2">
|
||||||
|
<button type="button" class="btn btn-sm btn-primary" (click)="saveDescription()">Enregistrer</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary" (click)="cancelEditDescription()">Annuler</button>
|
||||||
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
<div
|
<div
|
||||||
class="description-preview"
|
class="description-preview"
|
||||||
(click)="editingDescription = true"
|
(click)="startEditDescription()"
|
||||||
title="Cliquer pour éditer"
|
title="Cliquer pour éditer"
|
||||||
>
|
>
|
||||||
@if (issue.description) {
|
@if (issue.description) {
|
||||||
|
|||||||
@@ -519,6 +519,32 @@ describe('IssueDetail — existing issue', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('description edit flow', () => {
|
||||||
|
it('startEditDescription sets editingDescription to true and stores original text', () => {
|
||||||
|
(component as any).issue.description = 'original';
|
||||||
|
(component as any).startEditDescription();
|
||||||
|
expect((component as any).editingDescription).toBe(true);
|
||||||
|
expect((component as any)._descriptionBeforeEdit).toBe('original');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('saveDescription exits edit mode and persists the description', async () => {
|
||||||
|
(component as any).issue.description = 'updated';
|
||||||
|
(component as any).editingDescription = true;
|
||||||
|
await (component as any).saveDescription();
|
||||||
|
expect((component as any).editingDescription).toBe(false);
|
||||||
|
expect(store.getById(1)?.description).toBe('updated');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancelEditDescription restores the original description and exits edit mode', () => {
|
||||||
|
(component as any).issue.description = 'original';
|
||||||
|
(component as any).startEditDescription();
|
||||||
|
(component as any).issue.description = 'changed mid-edit';
|
||||||
|
(component as any).cancelEditDescription();
|
||||||
|
expect((component as any).issue.description).toBe('original');
|
||||||
|
expect((component as any).editingDescription).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('onDescriptionPaste', () => {
|
describe('onDescriptionPaste', () => {
|
||||||
afterEach(() => vi.unstubAllGlobals());
|
afterEach(() => vi.unstubAllGlobals());
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ export class IssueDetail {
|
|||||||
protected showAddDependency = false;
|
protected showAddDependency = false;
|
||||||
protected selectedCandidateId: number | null = null;
|
protected selectedCandidateId: number | null = null;
|
||||||
protected editingDescription = false;
|
protected editingDescription = false;
|
||||||
|
private _descriptionBeforeEdit = '';
|
||||||
protected showAddToEpic = false;
|
protected showAddToEpic = false;
|
||||||
protected selectedEpicCandidateId: number | null = null;
|
protected selectedEpicCandidateId: number | null = null;
|
||||||
protected showCreateInEpic = false;
|
protected showCreateInEpic = false;
|
||||||
@@ -237,6 +238,21 @@ export class IssueDetail {
|
|||||||
return !!this.issue.epic;
|
return !!this.issue.epic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected startEditDescription(): void {
|
||||||
|
this._descriptionBeforeEdit = this.issue.description;
|
||||||
|
this.editingDescription = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async saveDescription(): Promise<void> {
|
||||||
|
this.editingDescription = false;
|
||||||
|
await this.saveIssue();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected cancelEditDescription(): void {
|
||||||
|
this.issue.description = this._descriptionBeforeEdit;
|
||||||
|
this.editingDescription = false;
|
||||||
|
}
|
||||||
|
|
||||||
protected onDescriptionPaste(event: ClipboardEvent): void {
|
protected onDescriptionPaste(event: ClipboardEvent): void {
|
||||||
const ta = event.target as HTMLTextAreaElement;
|
const ta = event.target as HTMLTextAreaElement;
|
||||||
const start = ta.selectionStart;
|
const start = ta.selectionStart;
|
||||||
|
|||||||
Reference in New Issue
Block a user