Skip to content

Commit

Permalink
dr-story service testing + DigitalReader Component nav-bar test page
Browse files Browse the repository at this point in the history
Committing the majority of the testing work I've been doing over the last week or so.
  • Loading branch information
DavidMockler committed Jul 12, 2024
1 parent c7bec9d commit 732bf27
Show file tree
Hide file tree
Showing 12 changed files with 742 additions and 0 deletions.
29 changes: 29 additions & 0 deletions api/src/endpoint/digitalReader/dr-ify_html.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {API400Error} from '../../utils/APIError';
//import { segment } from '../../utils/segment';
//const { spawn } = require('node:child_process');
import { spawn } from 'node:child_process'

// tokenise story text into sentences
export default async function convertHtmlToDigitalReaderDoc (req, res) {
if (!req.body.text) throw new API400Error('Must include text parameter in the request body.');
//const tokens = segment(req.body.text);
// We want to split any tokens containing newline symbols into separate tokens.
// @ts-ignore -- for some reason it thinks acc has never[] type... but it should be string[]
//const tokensWithoutNewlines = tokens.reduce((acc, curr) => acc.concat(curr.split("\n")), []);
//res.json(tokensWithoutNewlines);

// test.py not yet added to GitHub
/*const py = spawn('python', ['./bin/python/test.py']);
let result = ''
py.stdout.on('data', (data) => {
result += data
});
py.on('close', () => {
//add try catch
res.json(JSON.parse(result))
});
py.on('error', (err) => {
res.json(err)
});*/
}
23 changes: 23 additions & 0 deletions api/src/endpoint/digitalReader/unzip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {API400Error} from '../../utils/APIError';
//import { segment } from '../../utils/segment';
//const { spawn } = require('node:child_process');
import { spawn } from 'node:child_process'

// tokenise story text into sentences
export default async function unzipHtml (req, res) {
if (!req.body.file) throw new API400Error('Must include file parameter in the request body.');

const unzip = spawn('bash', ['./bin/unzip/unzipHtml.bash']);

let result = ''
unzip.stdout.on('data', (data) => {
result += data
});
unzip.on('close', () => {
//add try catch
res.json(JSON.parse(result))
});
unzip.on('error', (err) => {
res.json(err)
});
}
8 changes: 8 additions & 0 deletions api/src/routes/digitalReader.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const makeEndpoints = require('../utils/makeEndpoints');

export = makeEndpoints({
post: {
'/convert': require('../endpoint/digitalReader/dr-ify_html').default, //convert a html document to a digital-reader story
//'/unzip': require('../endpoint/digitalReader/unzip') //currently there is a bug with this code
},
});
2 changes: 2 additions & 0 deletions api/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const gramadoirRoute = require('./routes/gramadoir.route');
const synthesisRoute = require('./routes/synthesis.route');
const nlpRoute = require('./routes/nlp.route');
import feedbackCommentRoute from './routes/feedbackComment.route';
const digitalReaderRoute = require("./routes/digitalReader.route");

mongoose.Promise = global.Promise;
mongoose.set('strictQuery', false)
Expand Down Expand Up @@ -122,6 +123,7 @@ app.use('/gramadoir', expressQueue({activeLimit: 40, queuedLimit: -1}), gramadoi
app.use('/recordings', recordingRoute);
app.use('/nlp', nlpRoute);
app.use('/feedbackComment', feedbackCommentRoute);
app.use('/digitalReader', digitalReaderRoute);

app.use('/proxy', expressQueue({activeLimit: 2, queuedLimit: -1}), async (req,res,next)=>{
function allowUrl(url) {
Expand Down
15 changes: 15 additions & 0 deletions ngapp/src/app/core/services/dr-story.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { TestBed } from '@angular/core/testing';
import { DigitalReaderStoryService } from './dr-story.service';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';

describe('DigitalReaderStoryService', () => {
beforeEach(() => TestBed.configureTestingModule({
imports: [RouterTestingModule, HttpClientTestingModule]
}));

it('should be created', () => {
const service: DigitalReaderStoryService = TestBed.inject(DigitalReaderStoryService);
expect(service).toBeTruthy();
});
});
255 changes: 255 additions & 0 deletions ngapp/src/app/core/services/dr-story.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
import { Injectable } from '@angular/core';
//import { DigitalReaderStory } from 'app/core/models/dr-story';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { AuthenticationService } from 'app/core/services/authentication.service';
import { Observable } from 'rxjs';
import { EngagementService } from 'app/core/services/engagement.service';
import { EventType } from 'app/core/models/event';
import { TranslationService } from 'app/core/services/translation.service';
import config from 'abairconfig';
import { firstValueFrom, tap } from 'rxjs';


@Injectable({
providedIn: 'root'
})
export class DigitalReaderStoryService {

constructor(
private http: HttpClient,
private router: Router,
private auth: AuthenticationService,
private engagement: EngagementService,
private ts: TranslationService,
) { }

baseUrl: string = config.baseurl //+ 'nlp/';
segmentableTags: string = 'p, h1, h2, h3, h4, h5, h6, li, title, th, td'

async tokenizeSentence(input: string) {
const sentences = await firstValueFrom(
this.http.post<Array<string>>(this.baseUrl + 'nlp/sentenceTokenize', {text: input})
)
return sentences
}

/*async testChildProcess() {
const out = await firstValueFrom(
this.http.post<{id: string}>(this.baseUrl + 'digitalReader/convert', {text: 'test!\nrud eile\nrud eile'})
)
return out
}*/

//may need to parse from a string rather than a document
extractText(inputHtml: Document) {
const textTags = inputHtml.querySelectorAll(this.segmentableTags)

const textChunks = []
for (let i = 0; i < textTags.length; i++) {
textChunks.push(textTags[i].textContent)
}

return textChunks
}

async segmentText(document: Document) {

const chunkedText = this.extractText(document)

const segmentedSentences = []
for (let chunk of chunkedText) {
const segmentedChunkSentences = await this.tokenizeSentence(chunk)
//console.log('test')
//console.log(segmentedChunkSentences)

for (let i = 0; i < segmentedChunkSentences.length; i++) {
const segmentedChunkSentence = segmentedChunkSentences[i];
segmentedSentences.push(segmentedChunkSentence)
}
}

return segmentedSentences
}

async testChildProcess() {
const out = await firstValueFrom(
this.http.post<string>(this.baseUrl + 'digitalReader/unzip', {body: 'test!\nrud eile\nrud eile'})
)
return out
}

/*
createDRStory(title: string, date: Date, dialects: Array<string>, htmlText: string, author: string) {
const drstoryObj = {
title: title,
dialects: dialects,
//text: text,
htmlText: htmlText,
author: author,
//createdWithPrompts: createdWithPrompts,
//activeRecording: null
};
console.log(drstoryObj);
this.engagement.addEvent(EventType['CREATE-DR-STORY'], {storyObject: drstoryObj});
return this.http.post<{id: string}>(this.baseUrl + 'create', drstoryObj);
}
getDRStoriesFor(author : string): Observable<DigitalReaderStory[]> {
return this.http.get<DigitalReaderStory[]>(this.baseUrl + author);
}
getDRStoriesByOwner(owner: string) : Observable<DigitalReaderStory[]> {
return this.http.get<DigitalReaderStory[]>(this.baseUrl + 'owner/' + owner);
}
getDRStory(id: string) : Observable<any> {
return this.http.get(this.baseUrl + 'withId/' + id);
}
getDRStoriesByDate(studentId:string, startDate:string, endDate:string) : Observable<any> {
return this.http.post(this.baseUrl + "getStoriesByDate/" + studentId, {startDate:startDate, endDate:endDate});
}
getDRStoriesForLoggedInUser(): Observable<DigitalReaderStory[]> {
const userDetails = this.auth.getUserDetails();
if(!userDetails) {
return new Observable(subscriber=>{
subscriber.next([]);
subscriber.complete();
});
}
return this.getDRStoriesByOwner(userDetails._id);
}
saveStory(title: string, date: Date, dialect: string, text: string, author: string, createdWithPrompts: boolean) {
const storyObj = {
title: title,
dialect: dialect,
text: text,
htmlText: text,
author: author,
createdWithPrompts: createdWithPrompts,
activeRecording: null
};
console.log(storyObj);
this.engagement.addEvent(EventType['CREATE-STORY'], {storyObject: storyObj});
return this.http.post<{id: string}>(this.baseUrl + 'create', storyObj);
}
getStoriesFor(author : string): Observable<Story[]> {
return this.http.get<Story[]>(this.baseUrl + author);
}
getStoriesByOwner(owner: string) : Observable<Story[]> {
return this.http.get<Story[]>(this.baseUrl + 'owner/' + owner);
}
getStory(id: string) : Observable<any> {
return this.http.get(this.baseUrl + 'withId/' + id);
}
getStoriesByDate(studentId:string, startDate:string, endDate:string) : Observable<any> {
return this.http.post(this.baseUrl + "getStoriesByDate/" + studentId, {startDate:startDate, endDate:endDate});
}
getStoriesForLoggedInUser(): Observable<Story[]> {
const userDetails = this.auth.getUserDetails();
if(!userDetails) {
return new Observable(subscriber=>{
subscriber.next([]);
subscriber.complete();
});
}
return this.getStoriesByOwner(userDetails._id);
}
updateStoryTitleAndDialect(story: Story, title:string, dialect:any): Observable<any> {
let updatedStory = story;
if (title) updatedStory.title = title;
if (dialect == this.ts.l.connacht) updatedStory.dialect = 'connemara';
if (dialect == this.ts.l.munster) updatedStory.dialect = 'kerry';
if (dialect == this.ts.l.ulster) updatedStory.dialect = 'donegal';
console.log(updatedStory);
return this.http.post(this.baseUrl + 'update/' + story._id, updatedStory);
}
updateTitle(storyId: string, title:string): Observable<any> {
return this.http.post(this.baseUrl + 'updateTitle/' + storyId, {title});
}
getStoriesForClassroom(owner: string, date = 'empty'): Observable<any> {
return this.http.get(this.baseUrl + "getStoriesForClassroom/" + owner + "/" + date);
}
getNumberOfStories(owner: string, date = 'empty'): Observable<any> {
return this.http.get(this.baseUrl + "getNumberOfStories/" + owner + "/" + date);
}
updateStory(updateData: any, id: string): Observable<any> {
return this.http.post(
this.baseUrl + 'update/' + id,
updateData);
}
deleteStory(id: string) {
return this.http.get(this.baseUrl + 'delete/' + id);
}
deleteAllStories(id: string) {
return this.http.get(this.baseUrl + 'deleteAllStories/' + id);
}
updateFeedbackStatus(id: string, feedbackMarkup: string, hasComments: boolean) : Observable<any> {
return this.http.post(this.baseUrl + "updateFeedbackStatus/" + id, {feedbackMarkup: feedbackMarkup, hasComments: hasComments});
}
updateFeedbackMarkup(id: string, feedbackMarkup: string) : Observable<any> {
return this.http.post(this.baseUrl + "updateFeedbackMarkup/" + id, {feedbackMarkup: feedbackMarkup});
}
getFeedback(id: string) : Observable<any> {
return this.http.get(this.baseUrl + "feedback/" + id);
}
viewFeedback(id: string) : Observable<any> {
return this.http.post(this.baseUrl + "viewFeedback/" + id, {});
}
getFeedbackAudio(id: string) : Observable<any> {
return this.http.get(this.baseUrl + "feedbackAudio/" + id, {responseType: "blob"});
}
addFeedbackAudio(id: string, audioBlob: Blob) : Observable<any>{
let formData = new FormData();
formData.append('audio', audioBlob);
return this.http.post(this.baseUrl + "addFeedbackAudio/" + id, formData);
}
synthesise(id: string): Observable<any> {
return this.http.get(this.baseUrl + 'synthesise/' + id);
}
synthesiseObject(storyObject: Story): Observable<any> {
return this.http.post(this.baseUrl + 'synthesiseObject/', {story: storyObject});
}
updateActiveRecording(storyId: string, recordingId: string): Observable<any> {
return this.http.post(this.baseUrl + 'updateActiveRecording/' + storyId + '/', {activeRecording: recordingId});
}
averageWordCount(studentId:string, startDate:string, endDate:string) : Observable<any> {
return this.http.post(this.baseUrl + "averageWordCount/" + studentId, {startDate:startDate, endDate:endDate});
}
countGrammarErrors(studentId:string) : Observable<any> {
return this.http.get(this.baseUrl + "countGrammarErrors/" + studentId);
}
getStoryStats() : Observable<any> {
return this.http.get(this.baseUrl + "getStoryStats/allDB");
}*/
}
Loading

0 comments on commit 732bf27

Please sign in to comment.