Skip to content

Commit

Permalink
SF-3083 Resolve icon should change when editing resolved note (#2964)
Browse files Browse the repository at this point in the history
  • Loading branch information
pmachapman authored Jan 23, 2025
1 parent 98b0adc commit 333c5d3
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -367,15 +367,63 @@ describe('BiblicalTermsComponent', () => {
env.setupProjectData('en');
env.wait();

// SUT
env.biblicalTermsNotesButton.click();
env.wait();
env.mockNoteDialogRef.close({ status: NoteStatus.Resolved });
env.wait();

verify(mockedMatDialog.open(NoteDialogComponent, anything())).once();
const noteThread: NoteThread = env.getNoteThreadDoc(projectId, 'threadId01').data!;
expect(noteThread.status).toEqual(NoteStatus.Resolved);
expect(noteThread.status).toBe(NoteStatus.Resolved);
expect(noteThread.notes[1].content).toBeUndefined();
expect(noteThread.notes[1].status).toBe(NoteStatus.Resolved);
}));

it('can resolve and edit a note for a biblical term', fakeAsync(async () => {
const projectId = 'project01';
const newContent = 'Updated Note Content';
const env = new TestEnvironment(projectId, 1, 1);
env.setupProjectData('en');
env.wait();

// Make the note editable
const noteThreadDoc: NoteThreadDoc = env.getNoteThreadDoc(projectId, 'threadId01');
await noteThreadDoc.submitJson0Op(op => op.set(nt => nt.notes[0].editable, true));

// SUT
env.biblicalTermsNotesButton.click();
env.wait();
env.mockNoteDialogRef.close({ status: NoteStatus.Resolved, noteContent: newContent, noteDataId: 'note01' });
env.wait();

verify(mockedMatDialog.open(NoteDialogComponent, anything())).once();
const noteThread: NoteThread = env.getNoteThreadDoc(projectId, 'threadId01').data!;
expect(noteThread.status).toBe(NoteStatus.Resolved);
expect(noteThread.notes[0].content).toBe(newContent);
expect(noteThread.notes[0].status).toBe(NoteStatus.Resolved);
}));

it('cannot resolve a non-editable note for a biblical term', fakeAsync(() => {
const projectId = 'project01';
const env = new TestEnvironment(projectId, 1, 1);
env.setupProjectData('en');
env.wait();

// Stub the error message display
const dialogMessage = spyOn((env.component as any).dialogService, 'message').and.stub();

// SUT
env.biblicalTermsNotesButton.click();
env.wait();
env.mockNoteDialogRef.close({ status: NoteStatus.Resolved, noteDataId: 'note01' });
env.wait();

verify(mockedMatDialog.open(NoteDialogComponent, anything())).once();
const noteThread: NoteThread = env.getNoteThreadDoc(projectId, 'threadId01').data!;
expect(noteThread.status).toEqual(NoteStatus.Todo);
expect(noteThread.notes.length).toBe(1);
expect(dialogMessage).toHaveBeenCalledTimes(1);
}));

it('should show the not found message if no messages were found', fakeAsync(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ export class BiblicalTermsComponent extends DataLoadingComponent implements OnDe
const currentDate: string = new Date().toJSON();
const threadId = `BT_${biblicalTermDoc.data.termId}`;
const noteContent: string | undefined = params.content == null ? undefined : XmlUtils.encodeForXml(params.content);
const noteStatus: NoteStatus = params.status ?? NoteStatus.Todo;
// Configure the note
const note: Note = {
dateCreated: currentDate,
Expand All @@ -561,7 +562,7 @@ export class BiblicalTermsComponent extends DataLoadingComponent implements OnDe
content: noteContent,
conflictType: NoteConflictType.DefaultValue,
type: NoteType.Normal,
status: params.status ?? NoteStatus.Todo,
status: noteStatus,
deleted: false,
editable: true,
versionNumber: 1
Expand Down Expand Up @@ -597,10 +598,18 @@ export class BiblicalTermsComponent extends DataLoadingComponent implements OnDe
);
const noteIndex: number = threadDoc.data!.notes.findIndex(n => n.dataId === params.dataId);
if (noteIndex >= 0) {
await threadDoc!.submitJson0Op(op => {
op.set(t => t.notes[noteIndex].content, noteContent);
op.set(t => t.notes[noteIndex].dateModified, currentDate);
});
// updated the existing note
if (threadDoc.data?.notes[noteIndex].editable === true) {
await threadDoc!.submitJson0Op(op => {
op.set(t => t.notes[noteIndex].content, noteContent);
op.set(t => t.notes[noteIndex].dateModified, currentDate);
op.set(t => t.notes[noteIndex].status, noteStatus);
// also set the status of the thread to be the status of the note
op.set(t => t.status, noteStatus);
});
} else {
this.dialogService.message('biblical_terms.cannot_edit_note_paratext');
}
} else {
note.threadId = threadDoc.data!.threadId;
await threadDoc.submitJson0Op(op => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3025,6 +3025,54 @@ describe('EditorComponent', () => {
env.dispose();
}));

it('allows editing and resolving a note', fakeAsync(async () => {
const projectId: string = 'project01';
const threadDataId: string = 'dataid01';
const content: string = 'This thread is resolved.';
const env = new TestEnvironment();
let noteThread: NoteThreadDoc = env.getNoteThreadDoc(projectId, threadDataId);
expect(noteThread.data!.notes.length).toEqual(3);
// Mark the note as editable
await noteThread.submitJson0Op(op => op.set(nt => nt.notes[0].editable, true));
env.setProjectUserConfig();
env.wait();
let noteThreadIconElem: HTMLElement | null = env.getNoteThreadIconElement('verse_1_1', threadDataId);
noteThreadIconElem!.click();
verify(mockedMatDialog.open(NoteDialogComponent, anything())).once();
env.mockNoteDialogRef.close({ noteContent: content, status: NoteStatus.Resolved, noteDataId: 'thread01_note0' });
env.wait();
noteThread = env.getNoteThreadDoc(projectId, threadDataId);
expect(noteThread.data!.notes.length).toEqual(3);
expect(noteThread.data!.notes[0].content).toEqual(content);
expect(noteThread.data!.notes[0].status).toEqual(NoteStatus.Resolved);

// the icon should be hidden from the editor
noteThreadIconElem = env.getNoteThreadIconElement('verse_1_1', threadDataId);
expect(noteThreadIconElem).toBeNull();
env.dispose();
}));

it('does not allow editing and resolving a non-editable note', fakeAsync(() => {
const projectId: string = 'project01';
const threadDataId: string = 'dataid01';
const content: string = 'This thread is resolved.';
const env = new TestEnvironment();
const dialogMessage = spyOn((env.component as any).dialogService, 'message').and.stub();
let noteThread: NoteThreadDoc = env.getNoteThreadDoc(projectId, threadDataId);
expect(noteThread.data!.notes.length).toEqual(3);
env.setProjectUserConfig();
env.wait();
let noteThreadIconElem: HTMLElement | null = env.getNoteThreadIconElement('verse_1_1', threadDataId);
noteThreadIconElem!.click();
verify(mockedMatDialog.open(NoteDialogComponent, anything())).once();
env.mockNoteDialogRef.close({ noteContent: content, status: NoteStatus.Resolved, noteDataId: 'thread01_note0' });
env.wait();
noteThread = env.getNoteThreadDoc(projectId, threadDataId);
expect(noteThread.data!.notes.length).toEqual(3);
expect(dialogMessage).toHaveBeenCalledTimes(1);
env.dispose();
}));

it('can open dialog of the second note on the verse', fakeAsync(() => {
const env = new TestEnvironment();
env.setProjectUserConfig();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,7 @@ export class EditorComponent extends DataLoadingComponent implements OnDestroy,
const tagId: number | undefined =
params.threadDataId == null ? this.projectDoc?.data?.translateConfig.defaultNoteTagId : undefined;
const noteContent: string | undefined = params.content == null ? undefined : XmlUtils.encodeForXml(params.content);
const noteStatus: NoteStatus = params.status ?? NoteStatus.Todo;
// Configure the note
const note: Note = {
dateCreated: currentDate,
Expand All @@ -1377,7 +1378,7 @@ export class EditorComponent extends DataLoadingComponent implements OnDestroy,
content: noteContent,
conflictType: NoteConflictType.DefaultValue,
type: NoteType.Normal,
status: params.status ?? NoteStatus.Todo,
status: noteStatus,
deleted: false,
editable: true,
versionNumber: 1
Expand Down Expand Up @@ -1411,9 +1412,12 @@ export class EditorComponent extends DataLoadingComponent implements OnDestroy,
await threadDoc!.submitJson0Op(op => {
op.set(t => t.notes[noteIndex].content, noteContent);
op.set(t => t.notes[noteIndex].dateModified, currentDate);
op.set(t => t.notes[noteIndex].status, noteStatus);
// also set the status of the thread to be the status of the note
op.set(t => t.status, noteStatus);
});
} else {
this.dialogService.message(this.i18n.translate('editor.cannot_edit_note_paratext'));
this.dialogService.message('editor.cannot_edit_note_paratext');
}
} else {
note.threadId = threadDoc.data!.threadId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,27 @@ describe('NoteDialogComponent', () => {
expect(env.dialogResult).toEqual({ noteContent: content, noteDataId: 'note05' });
}));

it('allows user to resolve the last note in the thread', fakeAsync(() => {
env = new TestEnvironment({ noteThread: TestEnvironment.getNoteThread(undefined, undefined, true) });
// note03 is marked as deleted
expect(env.notes.length).toEqual(4);
const noteThread: NoteThreadDoc = env.getNoteThreadDoc('dataid01');
expect(noteThread.data!.notes[4].content).toEqual('note05');
const noteNumbers = [1, 2, 3];
noteNumbers.forEach(n => expect(env.noteHasEditActions(n)).toBe(false));
expect(env.noteHasEditActions(4)).toBe(true);
env.clickEditNote();
expect(env.noteInputElement).toBeTruthy();
expect(env.notes.length).toEqual(3);
noteNumbers.forEach(n => expect(env.noteHasEditActions(n)).toBe(false));
expect(env.component.currentNoteContent).toEqual('note05');
const content = 'note 05 edited content';
env.enterNoteContent(content);
env.selectResolveOption();
env.submit();
expect(env.dialogResult).toEqual({ noteContent: content, noteDataId: 'note05', status: NoteStatus.Resolved });
}));

it('does not allow user to edit the last note in the thread if it is not editable', fakeAsync(() => {
env = new TestEnvironment({ noteThread: TestEnvironment.getNoteThread() });
// note03 is marked as deleted
Expand Down Expand Up @@ -494,7 +515,7 @@ describe('NoteDialogComponent', () => {
env.enterNoteContent(content);
env.selectResolveOption();
env.submit();
expect(env.dialogResult).toEqual({ status: NoteStatus.Resolved, noteContent: content });
expect(env.dialogResult).toEqual({ status: NoteStatus.Resolved, noteContent: content, noteDataId: undefined });
}));

it('allows changing save option', fakeAsync(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ export class NoteDialogComponent implements OnInit {
const content: NoteDialogResult = { status: NoteStatus.Resolved };
if (this.currentNoteContent.trim().length > 0) {
content.noteContent = this.currentNoteContent;
content.noteDataId = this.noteIdBeingEdited;
}
this.dialogRef.close(content);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"all": "All",
"biblical_terms_renderings": "Biblical Terms Renderings",
"blank": "(Blank)",
"cannot_edit_note_paratext": "You cannot edit this note as it has been edited in Paratext.",
"category": "Category",
"current_book": "Current Book",
"current_chapter": "Current Chapter",
Expand Down

0 comments on commit 333c5d3

Please sign in to comment.