Skip to content

Commit

Permalink
feat(frontend): Diff modal
Browse files Browse the repository at this point in the history
  • Loading branch information
Clashsoft committed Dec 13, 2023
1 parent 082921d commit 4986d76
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<ngbx-modal [back]="['..']" size="lg" #modal>
<ng-container modal-title>
Differences
</ng-container>
<ng-container modal-body>
<h5>Metadata</h5>
<pre [innerHTML]="diffMetadata | safeHtml"></pre>
<h5>Tasks</h5>
<pre [innerHTML]="diffTasks | safeHtml"></pre>
</ng-container>
<ng-container modal-footer>
<button type="button" class="btn btn-secondary" (click)="modal.close()">
Close
</button>
</ng-container>
</ngbx-modal>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {Component, OnInit} from '@angular/core';
import {AssignmentService} from "../../../services/assignment.service";
import * as jsdiff from "diff";
import {ActivatedRoute} from "@angular/router";
import {AssignmentContext} from "../../../services/assignment.context";
import {switchMap} from "rxjs/operators";
import {TaskMarkdownService} from "../task-markdown.service";

@Component({
selector: 'app-diff-modal',
templateUrl: './diff-modal.component.html',
styleUrl: './diff-modal.component.scss'
})
export class DiffModalComponent implements OnInit {
diffMetadata = '';
diffTasks = '';

constructor(
private route: ActivatedRoute,
private context: AssignmentContext,
private assignmentService: AssignmentService,
private taskMarkdownService: TaskMarkdownService,
) {
}

ngOnInit() {
this.route.params.pipe(
switchMap(({aid}) => this.assignmentService.get(aid)),
).subscribe(oldAssignment => {
const {tasks: oldTasks, ...old} = oldAssignment;
const {tasks: newTasks, ...current} = this.context.assignment;
this.diffMetadata = renderDiff(jsdiff.diffJson(old, current));
const oldTasksMd = this.taskMarkdownService.renderTasks(oldTasks);
const newTasksMd = this.taskMarkdownService.renderTasks(newTasks);
this.diffTasks = renderDiff(jsdiff.diffWords(oldTasksMd, newTasksMd));
});
}
}

function escapeHtml(text: string) {
return text.replace(/[&<>"'`=\/]/g, function (s) {
return `&#${s.charCodeAt(0)};`;
});
}

function renderDiff(diff: jsdiff.Change[]) {
return diff.map(part => {
const color = part.added ? 'text-success' : part.removed ? 'text-danger' : '';
return `<span class="${color}">${escapeHtml(part.value)}</span>`;
}).join('');
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {PreviewComponent} from './preview/preview.component';
import {TasksComponent} from './tasks/tasks.component';
import {PlagiarismDetectionComponent} from "./plagiarism-detection/plagiarism-detection.component";
import {CodeSearchComponent} from "./code-search/code-search.component";
import {DiffModalComponent} from "./diff-modal/diff-modal.component";

export const editAssignmentChildRoutes: Routes = [
{path: 'info', component: InfoComponent, data: {title: 'Info'}},
Expand All @@ -32,6 +33,7 @@ const routes: Routes = [
data: {title: 'Edit Assignment'},
children: [
...editAssignmentChildRoutes,
{path: 'diff', component: DiffModalComponent, data: {title: 'Differences'}},
{path: '', redirectTo: 'info', pathMatch: 'full'},
],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ import {InfoComponent} from './info/info.component';
import {PreviewComponent} from './preview/preview.component';
import {TasksComponent} from './tasks/tasks.component';
import {TaskMarkdownService} from "./task-markdown.service";
import { CodeSearchComponent } from './code-search/code-search.component';
import { PlagiarismDetectionComponent } from './plagiarism-detection/plagiarism-detection.component';
import {CodeSearchComponent} from './code-search/code-search.component';
import {PlagiarismDetectionComponent} from './plagiarism-detection/plagiarism-detection.component';
import {DiffModalComponent} from "./diff-modal/diff-modal.component";


@NgModule({
Expand All @@ -31,6 +32,7 @@ import { PlagiarismDetectionComponent } from './plagiarism-detection/plagiarism-
TasksComponent,
CodeSearchComponent,
PlagiarismDetectionComponent,
DiffModalComponent,
],
imports: [
CommonModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ <h1>
<a class="btn btn-secondary ms-2" routerLink="/assignments">
Cancel
</a>
@if (context.assignment['_id']) {
<a class="btn btn-info ms-2" routerLink="diff">
View Diff
</a>
}
@if (draft) {
<button class="btn btn-warning ms-2" (click)="deleteDraft()">
Delete Draft
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@
</div>
</div>

@if (diffMetadata && diffTasks) {
<h2>Differences</h2>
<h3>Metadata</h3>
<pre [innerHTML]="diffMetadata | safeHtml"></pre>
<h3>Tasks</h3>
<pre [innerHTML]="diffTasks | safeHtml"></pre>
}
@if (!loggedIn) {
<div class="alert alert-warning" role="alert">
<h4 class="alert-heading">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,7 @@ import {Component, OnInit} from '@angular/core';
import {KeycloakService} from 'keycloak-angular';
import {CreateAssignmentDto} from '../../../model/assignment';
import {AssignmentContext} from '../../../services/assignment.context';
import * as jsdiff from 'diff';
import {AssignmentService} from "../../../services/assignment.service";
import {TaskMarkdownService} from "../task-markdown.service";

function escapeHtml(text: string) {
return text.replace(/[&<>"'`=\/]/g, function (s) {
return `&#${s.charCodeAt(0)};`;
});
}

function renderDiff(diff: jsdiff.Change[]) {
return diff.map(part => {
const color = part.added ? 'text-success' : part.removed ? 'text-danger' : '';
return `<span class="${color}">${escapeHtml(part.value)}</span>`;
}).join('');
}

@Component({
selector: 'app-edit-assignment-preview',
Expand All @@ -26,33 +11,18 @@ function renderDiff(diff: jsdiff.Change[]) {
})
export class PreviewComponent implements OnInit {
assignment: CreateAssignmentDto;
diffMetadata?: string;
diffTasks?: string;

loggedIn = false;

constructor(
private keycloakService: KeycloakService,
context: AssignmentContext,
private assignmentService: AssignmentService,
private taskMarkdownService: TaskMarkdownService,
) {
this.assignment = context.getAssignment();
}

ngOnInit(): void {
this.loggedIn = this.keycloakService.isLoggedIn();

if ('_id' in this.assignment) {
this.assignmentService.get(this.assignment._id as string).subscribe(oldAssignment => {
const {tasks: oldTasks, ...old} = oldAssignment;
const {tasks: newTasks, ...current} = this.assignment;
this.diffMetadata = renderDiff(jsdiff.diffJson(old, current));
const oldTasksMd = this.taskMarkdownService.renderTasks(oldTasks);
const newTasksMd = this.taskMarkdownService.renderTasks(newTasks);
this.diffTasks = renderDiff(jsdiff.diffWords(oldTasksMd, newTasksMd));
});
}
}

login(): void {
Expand Down

0 comments on commit 4986d76

Please sign in to comment.