Skip to content

Commit

Permalink
Add comment locking and fix comment update
Browse files Browse the repository at this point in the history
  • Loading branch information
minottic committed Oct 9, 2023
1 parent 56c9489 commit dbcba7f
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 50 deletions.
2 changes: 1 addition & 1 deletion scilog/src/app/core/remote-data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export class LogbookItemDataService extends RemoteDataService {
}
// console.log(httpFilter);
// console.log(tagContainer);
httpFilter["include"] = [{ "relation": "subsnippets" }];
httpFilter["include"] = [{ "relation": "subsnippets", "scope": {include: [{"relation": "subsnippets", scope: {where: {snippetType: 'edit'}}}]} }];
return httpFilter;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ describe('AddContentComponent', () => {

it('should mark for deletion and send message', () => {
spyOn(component, 'sendMessage');
component.notification.snippetType = 'edit';
component.dialogTitle = 'Modify data snippet';
component['sendEditDelitionMessage']();
expect(component.sendMessage).toHaveBeenCalledTimes(1);
expect(component.notification.toDelete).toEqual(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ export class AddContentComponent implements OnInit {
}

sendEditDelitionMessage() {
if (this.notification.snippetType === 'edit') {
if (this.dialogTitle === 'Modify data snippet') {
this.notification.snippetType = 'edit';
this.notification.toDelete = true;
this.sendMessage();
}
Expand Down
6 changes: 3 additions & 3 deletions scilog/src/app/logbook/core/snippet/snippet.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@
</mat-card>

<div *ngFor="let snippet of snippet?.subsnippets; let i = index">
<ng-container *ngIf="(snippet?.linkType!='quote') && (snippet?.snippetType=='paragraph')">
<snippet [snippet]="snippet" [updatedAt]="snippet?.updatedAt" [index]=i [config]="config"
[hideMetadata]='hideMetadata'></snippet>
<ng-container *ngIf="snippet.linkType!='quote' && snippet.snippetType === 'paragraph'">
<snippet [snippet]="snippet" [updatedAt]="snippet.updatedAt" [index]=i [config]="config"
[hideMetadata]='hideMetadata' [subsnippets]="snippet.subsnippets"></snippet>
</ng-container>
</div>
6 changes: 6 additions & 0 deletions scilog/src/app/logbook/core/snippet/snippet.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,10 @@ describe('SnippetComponent', () => {
expect(component.getLastEditedSnippet(subs)).toEqual(subs[0]);
})

it('should call setLocked after subsnippets change', () => {
spyOn(component, "setLocked");
component.subsnippets = [{parentId: "123"}];
expect(component.setLocked).toHaveBeenCalledTimes(1);
})

});
30 changes: 24 additions & 6 deletions scilog/src/app/logbook/core/snippet/snippet.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Component, OnInit, Input, SecurityContext, ElementRef, ViewChild, Output, EventEmitter } from '@angular/core';
import { Component, OnInit, Input, SecurityContext, ElementRef, ViewChild, Output, EventEmitter, ChangeDetectorRef, SimpleChange, SimpleChanges } from '@angular/core';
import { ChangeStreamNotification } from '../changestreamnotification.model';
import { DomSanitizer } from '@angular/platform-browser';
import { MatDialogConfig, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { AddContentComponent } from '../add-content/add-content.component';
import { Paragraphs, LinkType } from '@model/paragraphs';
import { Subscription } from 'rxjs';
import { BehaviorSubject, Subscription } from 'rxjs';
import { SnippetContentComponent } from './snippet-content/snippet-content.component';
import { UserPreferencesService } from '@shared/user-preferences.service';
import { SnippetDashboardNameComponent } from './snippet-dashboard-name/snippet-dashboard-name.component';
Expand All @@ -13,6 +13,7 @@ import { LogbookItemDataService } from '@shared/remote-data.service';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { WidgetItemConfig } from '@model/config';
import { Edits } from 'src/app/core/model/edits';
import { Basesnippets } from 'src/app/core/model/basesnippets';


@Component({
Expand Down Expand Up @@ -55,7 +56,6 @@ export class SnippetComponent implements OnInit {
@Input()
showEditButtonsMenu: boolean = true;


@Input()
linkType: LinkType = LinkType.PARAGRAPH;

Expand Down Expand Up @@ -93,6 +93,8 @@ export class SnippetComponent implements OnInit {
@ViewChild('snippetContainer', { read: ElementRef }) snippetContainerRef: ElementRef;
@ViewChild('snippetContent') snippetContentRef: SnippetContentComponent;

_subsnippets: BehaviorSubject<Basesnippets[]>;

constructor(
private sanitizer: DomSanitizer,
public dialog: MatDialog,
Expand Down Expand Up @@ -143,7 +145,22 @@ export class SnippetComponent implements OnInit {
}
// enable edit for snippet
this.enableEdit = true;
this.setLocked();
this._subsnippets = new BehaviorSubject(this.snippet.subsnippets);
}

@Input('subsnippets')
set subsnippets(subsnippets: Basesnippets[]) {
this._subsnippets?.next(subsnippets ?? []);
}

get subsnippets() {
return this._subsnippets.value;
}

ngAfterContentInit() {
this._subsnippets.subscribe(() => {
this.setLocked()
});
}


Expand Down Expand Up @@ -255,7 +272,7 @@ export class SnippetComponent implements OnInit {
this.timerId = setTimeout(async () => {
console.log("unlocking");
await this.releaseLock();
this._editDialog.close();
this._editDialog?.close();
}, timeOut);
}

Expand Down Expand Up @@ -363,7 +380,7 @@ export class SnippetComponent implements OnInit {
}

setLocked() {
const lastEdited = this.getLastEditedSnippet(this.snippet.subsnippets);
const lastEdited = this.getLastEditedSnippet(this.subsnippets);
if (!lastEdited) return
const timeFromLock = new Date().getTime() - Date.parse(lastEdited.createdAt);
if (!lastEdited.toDelete && timeFromLock < this._timeoutMilliseconds) {
Expand All @@ -377,4 +394,5 @@ export class SnippetComponent implements OnInit {
this.subscriptions.forEach(
(subscription) => subscription.unsubscribe());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,7 @@ describe('LogbookItemComponent', () => {
snippetType: notificationMock.snippetType,
parentId: notificationMock.id,
toDelete: notificationMock.toDelete,
linkType: notificationMock.linkType,
});
})

Expand All @@ -553,28 +554,29 @@ describe('LogbookItemComponent', () => {
expect(component.findPos(notificationMock, "id", "parentId")[0]).toEqual(0);
})

it('should not fire delete edits', async () => {
it('should append subsnippets', async () => {
const snippetMock = jasmine.createSpyObj(
"SnippetComponent",
["lockEditUntilTimeout"],
{},
{snippet: {id: "123", updatedBy: "aFiringUser"}}
);
spyOn(component["childSnippets"], "toArray").and.returnValue([snippetMock]);
const notificationMock: ChangeStreamNotification = {content: { parentId: "123" }};
const notificationMock: ChangeStreamNotification = {content: { parentId: "123", snippetType: "edit" }};
await component.fireEditCondition(notificationMock);
expect(snippetMock.lockEditUntilTimeout).toHaveBeenCalledOnceWith("aFiringUser");
expect(snippetMock.subsnippets).toEqual([notificationMock.content]);
})

it('should fire edit condition', async () => {
it('should append grand subsnippets', async () => {
const snippetMock = jasmine.createSpyObj(
"SnippetComponent",
["releaseLock"],
{snippet: {id: "123", updatedBy: "aFiringUser"}}
{},
{snippet: {subsnippets: [{}]}}
);
spyOn(component, "findPos").and.returnValue([0, 0]);
spyOn(component["childSnippets"], "toArray").and.returnValue([snippetMock]);
const notificationMock: ChangeStreamNotification = {content: { parentId: "123", toDelete: true }};
const notificationMock: ChangeStreamNotification = {content: { parentId: "123", snippetType: "edit" }};
await component.fireEditCondition(notificationMock);
expect(snippetMock.releaseLock).toHaveBeenCalledTimes(1);
expect(snippetMock.snippet.subsnippets[0].subsnippets).toEqual([notificationMock.content]);
})

it('should parse new edit notification', () => {
Expand All @@ -587,20 +589,12 @@ describe('LogbookItemComponent', () => {
expect(component.fireEditCondition).toHaveBeenCalledTimes(1);
})

it('should unlock on update notification', async () => {
const notificationMock: ChangeStreamNotification = {
operationType: "update",
id: "123",
content: { updatedBy: "aFiringUser", id_session: "456" }
};
const snippetMock = jasmine.createSpyObj(
"SnippetComponent",
["releaseLock", "updateContent"],
{snippet: { id: "123" }}
);
spyOn(component["childSnippets"], "toArray").and.returnValue([snippetMock]);
await component.parseNotification(notificationMock);
expect(snippetMock.releaseLock).toHaveBeenCalledTimes(1);
it('should update snippet values', () => {
const content = { dashboardName: "new" };
const snippet = { dashboardName: "old", parentId: "123" };
component["updateSnippetValues"](content, snippet);
expect(snippet.dashboardName).toEqual(content.dashboardName);
expect(snippet.parentId).toEqual(snippet.parentId);
})

});
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { TagService } from '@shared/tag.service';
import { CKeditorConfig } from '@shared/ckeditor/ckeditor-config';
import { LogbookScrollService } from '@shared/logbook-scroll.service';
import { ScrollToElementService } from '@shared/scroll-to-element.service';
import { LinkType } from 'src/app/core/model/paragraphs';


@Component({
Expand Down Expand Up @@ -319,19 +320,19 @@ export class LogbookItemComponent implements OnInit {
} else {
// true update
// we only need to update already rendered elements. The data is anyway already up to date in the backend
if (subPos?.length === 2) {
const snippetPos = this.childSnippets.toArray()[subPos[0]].snippet;
const subSnippet = snippetPos.subsnippets[subPos[1]];
this.updateSnippetValues(notification.content, subSnippet);
snippetPos.subsnippets = [subSnippet];
}
if (updatePos < this.childSnippets.toArray().length) {
let updateEntry = this.childSnippets.toArray()[updatePos];
console.log(updatePos);
for (const key in notification.content) {
updateEntry.snippet[key] = notification.content[key];
}
// this.array[updatePos] = updateEntry;
this.updateSnippetValues(notification.content, updateEntry.snippet);
console.log("updated array at pos ", updatePos);
console.log(updateEntry);
updateEntry.updateContent();
if (updateEntry?.snippet.id_session) {
await updateEntry.releaseLock();
}
}
this.logbookScrollService.updateViewportEstimate();
}
Expand All @@ -340,7 +341,7 @@ export class LogbookItemComponent implements OnInit {
break;
case "insert":
if (notification.content.snippetType === "edit") {
await this.fireEditCondition(notification)
return await this.fireEditCondition(notification)
}
if ((notification.content.snippetType == "paragraph") || (notification.content.snippetType == "image")) {
// first check if the incoming message satisfies the current filters
Expand Down Expand Up @@ -441,6 +442,18 @@ export class LogbookItemComponent implements OnInit {
}
}

private updateSnippetValues(content: Basesnippets, snippet: Basesnippets) {
for (const key in content) {
snippet[key] = content[key];
}
}

// private updateSnippetValues(notification: ChangeStreamNotification, subSnippet: any) {
// for (const key in notification.content) {
// subSnippet[key] = notification.content[key];
// }
// }

submitContent(msg: ChangeStreamNotification) {
// in the future, this should be extended to support inserting snippets below/above other snippets
// for now, I just take the last array entry
Expand All @@ -454,8 +467,8 @@ export class LogbookItemComponent implements OnInit {
// }
if (msg.snippetType === "edit") {
// POST -- EDIT SNIPPET
let payload: ChangeStreamNotification = this._prepareEditPostPayload(referenceEntry, msg);
this.logbookItemDataService.uploadParagraph(payload)
let payload: ChangeStreamNotification = this._prepareEditPostPayload(referenceEntry, msg);
this.logbookItemDataService.uploadParagraph(payload);
} else if ((typeof msg.id != "undefined") && (msg.id != '')) {
// PATCH -- UPDATE SNIPPET
let payload = this._preparePatchPayload(referenceEntry, msg);
Expand All @@ -476,6 +489,7 @@ export class LogbookItemComponent implements OnInit {
snippetType: msg.snippetType,
parentId: msg.id,
toDelete: msg.toDelete,
linkType: msg.linkType,
};
}

Expand Down Expand Up @@ -526,11 +540,13 @@ export class LogbookItemComponent implements OnInit {
}

async fireEditCondition(notification: ChangeStreamNotification) {
const pos = this.findPos(notification.content, "id", "parentId")[0];
const posChild = this.childSnippets.toArray()[pos];
if (!notification.content.toDelete)
return posChild.lockEditUntilTimeout(posChild.snippet.updatedBy);
await posChild.releaseLock();
const pos = this.findPos(notification.content, "id", "parentId", notification.content.linkType === LinkType.COMMENT);
let posChild: (SnippetComponent | Basesnippets) = this.childSnippets.toArray()[pos[0]];
if (pos.length === 2) {
posChild = (posChild as SnippetComponent).snippet.subsnippets[pos[1]] as Basesnippets;
posChild.snippetType = 'paragraph';
}
posChild.subsnippets = [...(posChild.subsnippets?? []).filter(s => s.snippetType !== 'edit') , notification.content];
}

applyFilters(snippets: Basesnippets[]) {
Expand Down

0 comments on commit dbcba7f

Please sign in to comment.