@internetarchive/radio-player 0.0.4-alpha.1 → 0.1.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -661
- package/README.md +142 -142
- package/index.d.ts +15 -15
- package/index.js +28 -28
- package/lib/src/assets/img/left.d.ts +2 -2
- package/lib/src/assets/img/left.js +15 -15
- package/lib/src/assets/img/right.d.ts +2 -2
- package/lib/src/assets/img/right.js +15 -15
- package/lib/src/models/music-zone.d.ts +12 -12
- package/lib/src/models/music-zone.js +15 -15
- package/lib/src/models/radio-player-config.d.ts +26 -26
- package/lib/src/models/radio-player-config.js +27 -27
- package/lib/src/radio-player.d.ts +589 -589
- package/lib/src/radio-player.js +1337 -1338
- package/lib/src/radio-player.js.map +1 -1
- package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-backend.d.ts +82 -82
- package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-backend.js +107 -107
- package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-delegate.d.ts +9 -0
- package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-delegate.js +1 -0
- package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-delegate.js.map +1 -0
- package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-response.d.ts +48 -48
- package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-response.js +58 -58
- package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-service-interface.d.ts +16 -16
- package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-service-interface.js +1 -1
- package/lib/src/search-handler/search-backends/local-search-backend/local-search-backend.d.ts +27 -27
- package/lib/src/search-handler/search-backends/local-search-backend/local-search-backend.js +42 -42
- package/lib/src/search-handler/search-backends/search-backend-interface.d.ts +9 -9
- package/lib/src/search-handler/search-backends/search-backend-interface.js +1 -1
- package/lib/src/search-handler/search-handler-interface.d.ts +17 -17
- package/lib/src/search-handler/search-handler-interface.js +1 -1
- package/lib/src/search-handler/search-handler.d.ts +83 -83
- package/lib/src/search-handler/search-handler.js +177 -177
- package/lib/src/search-handler/search-helper.d.ts +12 -12
- package/lib/src/search-handler/search-helper.js +22 -22
- package/lib/src/search-handler/search-index.d.ts +53 -0
- package/lib/src/search-handler/search-index.js +118 -0
- package/lib/src/search-handler/search-index.js.map +1 -0
- package/lib/src/search-handler/search-models.d.ts +45 -45
- package/lib/src/search-handler/search-models.js +49 -49
- package/lib/src/search-handler/transcript-index-interface.d.ts +38 -38
- package/lib/src/search-handler/transcript-index-interface.js +1 -1
- package/lib/src/search-handler/transcript-index.d.ts +53 -53
- package/lib/src/search-handler/transcript-index.js +80 -80
- package/lib/src/search-results-switcher.d.ts +58 -58
- package/lib/src/search-results-switcher.js +133 -133
- package/package.json +93 -93
- package/src/assets/img/left.ts +17 -17
- package/src/assets/img/right.ts +17 -17
- package/src/models/music-zone.ts +17 -17
- package/src/models/radio-player-config.ts +47 -47
- package/src/radio-player.ts +1398 -1402
- package/src/search-handler/search-backends/full-text-search-backend/full-text-search-backend.ts +140 -140
- package/src/search-handler/search-backends/full-text-search-backend/full-text-search-response.ts +110 -110
- package/src/search-handler/search-backends/full-text-search-backend/full-text-search-service-interface.ts +17 -17
- package/src/search-handler/search-backends/local-search-backend/local-search-backend.ts +50 -50
- package/src/search-handler/search-backends/search-backend-interface.ts +10 -10
- package/src/search-handler/search-handler-interface.ts +18 -18
- package/src/search-handler/search-handler.ts +217 -217
- package/src/search-handler/search-helper.ts +25 -25
- package/src/search-handler/search-models.ts +69 -69
- package/src/search-handler/transcript-index-interface.ts +42 -42
- package/src/search-handler/transcript-index.ts +93 -93
- package/src/search-results-switcher.ts +131 -131
- package/lib/demo/full-text-search-service.d.ts +0 -14
- package/lib/demo/full-text-search-service.js +0 -34
- package/lib/demo/full-text-search-service.js.map +0 -1
- package/lib/demo/radio-player-controller.d.ts +0 -41
- package/lib/demo/radio-player-controller.js +0 -200
- package/lib/demo/radio-player-controller.js.map +0 -1
package/src/search-handler/search-backends/full-text-search-backend/full-text-search-backend.ts
CHANGED
|
@@ -1,140 +1,140 @@
|
|
|
1
|
-
import { Range } from '../../search-models';
|
|
2
|
-
import { SearchBackendInterface } from '../search-backend-interface';
|
|
3
|
-
import { FullTextSearchResponseDoc } from './full-text-search-response';
|
|
4
|
-
import { FullTextSearchServiceInterface } from './full-text-search-service-interface';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* This class is responsible for taking the response from the full text search backend
|
|
8
|
-
* and converting the results into start and end indices for each of the matches.
|
|
9
|
-
*
|
|
10
|
-
* The start and end indices are then used by the SearchHandler to re-build the
|
|
11
|
-
* transcript, separated by search results in their original time codes.
|
|
12
|
-
*/
|
|
13
|
-
export class FullTextSearchBackend implements SearchBackendInterface {
|
|
14
|
-
/**
|
|
15
|
-
* A FullTextSearchService that provides the fetching layer for results. This
|
|
16
|
-
* object can make AJAX requests or any other backend call needed to return
|
|
17
|
-
* a response.
|
|
18
|
-
*
|
|
19
|
-
* @private
|
|
20
|
-
* @type {FullTextSearchServiceInterface}
|
|
21
|
-
* @memberof FullTextSearchBackend
|
|
22
|
-
*/
|
|
23
|
-
private service: FullTextSearchServiceInterface;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* The start tag to match a search result, like `{{{` or `<em>`
|
|
27
|
-
*
|
|
28
|
-
* @private
|
|
29
|
-
* @type {string}
|
|
30
|
-
* @memberof FullTextSearchBackend
|
|
31
|
-
*/
|
|
32
|
-
private startTag: string;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* The end tag to match a search result, like `}}}` or `</em>`
|
|
36
|
-
*
|
|
37
|
-
* @private
|
|
38
|
-
* @type {string}
|
|
39
|
-
* @memberof FullTextSearchBackend
|
|
40
|
-
*/
|
|
41
|
-
private endTag: string;
|
|
42
|
-
|
|
43
|
-
constructor(service: FullTextSearchServiceInterface, startTag = '{{{', endTag = '}}}') {
|
|
44
|
-
this.service = service;
|
|
45
|
-
this.startTag = startTag;
|
|
46
|
-
this.endTag = endTag;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Finds all of the ranges of all the search results across the entire transcript.
|
|
51
|
-
*
|
|
52
|
-
* @private
|
|
53
|
-
* @param {string} query
|
|
54
|
-
* @returns {Promise<Range[]>}
|
|
55
|
-
* @memberof SearchBackendInterface
|
|
56
|
-
*/
|
|
57
|
-
async getSearchRanges(query: string): Promise<Range[]> {
|
|
58
|
-
let ranges: Range[] = [];
|
|
59
|
-
|
|
60
|
-
const results = await this.service.searchRequested(query);
|
|
61
|
-
|
|
62
|
-
results.value.docs.forEach((result: FullTextSearchResponseDoc) => {
|
|
63
|
-
const transcript = result.text;
|
|
64
|
-
result.highlight.cc.forEach((highlight: string) => {
|
|
65
|
-
const newRanges: Range[] = this.rangesOfResultInTranscript(highlight, transcript);
|
|
66
|
-
ranges = ranges.concat(newRanges);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
return new Promise((resolve) => {
|
|
71
|
-
resolve(ranges);
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Find the Range (start and end indices) of the results
|
|
77
|
-
* from the `highlight` in the `transcript`.
|
|
78
|
-
*
|
|
79
|
-
* Example:
|
|
80
|
-
* If `highlight` = `bar {{{baz}}} snip\n snap`
|
|
81
|
-
* and
|
|
82
|
-
* `transcript` = `beep boop\n foo bar baz snip\n snap`
|
|
83
|
-
*
|
|
84
|
-
* This will return [Range(20, 22)] because `baz` starts at index 20 and ends at 22
|
|
85
|
-
* in the transcript.
|
|
86
|
-
*
|
|
87
|
-
* @param {string} highlight
|
|
88
|
-
* @param {string} transcript
|
|
89
|
-
* @returns {Range[]}
|
|
90
|
-
*/
|
|
91
|
-
private rangesOfResultInTranscript(highlight: string, transcript: string): Range[] {
|
|
92
|
-
const regex = new RegExp(`${this.startTag}(.*?)${this.endTag}`, 'gm');
|
|
93
|
-
|
|
94
|
-
const startIndexOfHighlight = this.getStartIndexOfHighlight(highlight, transcript);
|
|
95
|
-
const totalTagLength = this.startTag.length + this.endTag.length;
|
|
96
|
-
|
|
97
|
-
const ranges: Range[] = [];
|
|
98
|
-
|
|
99
|
-
let matchIndex = 0;
|
|
100
|
-
let match;
|
|
101
|
-
// eslint-disable-next-line no-cond-assign
|
|
102
|
-
while ((match = regex.exec(highlight)) !== null) {
|
|
103
|
-
const startIndex = match.index;
|
|
104
|
-
const matchLength = match[1].length;
|
|
105
|
-
|
|
106
|
-
const adjustedMatchStart = startIndex - matchIndex * totalTagLength;
|
|
107
|
-
const overallMatchStart = startIndexOfHighlight + adjustedMatchStart;
|
|
108
|
-
const matchEnd = overallMatchStart + matchLength;
|
|
109
|
-
const range = new Range(overallMatchStart, matchEnd);
|
|
110
|
-
ranges.push(range);
|
|
111
|
-
matchIndex += 1;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return ranges;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* This method finds the highlight's overall location within the transcript.
|
|
119
|
-
*
|
|
120
|
-
* To do this, it strips out the start and end tags to treat it as a raw string.
|
|
121
|
-
*
|
|
122
|
-
* Example:
|
|
123
|
-
* If `highlight` = `bar {{{baz}}} snip\n snap`
|
|
124
|
-
* and
|
|
125
|
-
* `transcript` = `beep boop\n foo bar baz snip\n snap`
|
|
126
|
-
*
|
|
127
|
-
* This will return 16 because `bar baz snip...` starts at index 16.
|
|
128
|
-
*
|
|
129
|
-
* @param {string} highlight The highlighted string to find
|
|
130
|
-
* @param {string} transcript The transcript in which to find the highlight
|
|
131
|
-
* @returns {number}
|
|
132
|
-
*/
|
|
133
|
-
private getStartIndexOfHighlight(highlight: string, transcript: string): number {
|
|
134
|
-
const startTagRegex = new RegExp(this.startTag, 'gm');
|
|
135
|
-
const endTagRegex = new RegExp(this.endTag, 'gm');
|
|
136
|
-
const untokenizedHighlight = highlight.replace(startTagRegex, '').replace(endTagRegex, '');
|
|
137
|
-
const startIndexOfHighlight = transcript.indexOf(untokenizedHighlight);
|
|
138
|
-
return startIndexOfHighlight;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
1
|
+
import { Range } from '../../search-models';
|
|
2
|
+
import { SearchBackendInterface } from '../search-backend-interface';
|
|
3
|
+
import { FullTextSearchResponseDoc } from './full-text-search-response';
|
|
4
|
+
import { FullTextSearchServiceInterface } from './full-text-search-service-interface';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This class is responsible for taking the response from the full text search backend
|
|
8
|
+
* and converting the results into start and end indices for each of the matches.
|
|
9
|
+
*
|
|
10
|
+
* The start and end indices are then used by the SearchHandler to re-build the
|
|
11
|
+
* transcript, separated by search results in their original time codes.
|
|
12
|
+
*/
|
|
13
|
+
export class FullTextSearchBackend implements SearchBackendInterface {
|
|
14
|
+
/**
|
|
15
|
+
* A FullTextSearchService that provides the fetching layer for results. This
|
|
16
|
+
* object can make AJAX requests or any other backend call needed to return
|
|
17
|
+
* a response.
|
|
18
|
+
*
|
|
19
|
+
* @private
|
|
20
|
+
* @type {FullTextSearchServiceInterface}
|
|
21
|
+
* @memberof FullTextSearchBackend
|
|
22
|
+
*/
|
|
23
|
+
private service: FullTextSearchServiceInterface;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The start tag to match a search result, like `{{{` or `<em>`
|
|
27
|
+
*
|
|
28
|
+
* @private
|
|
29
|
+
* @type {string}
|
|
30
|
+
* @memberof FullTextSearchBackend
|
|
31
|
+
*/
|
|
32
|
+
private startTag: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The end tag to match a search result, like `}}}` or `</em>`
|
|
36
|
+
*
|
|
37
|
+
* @private
|
|
38
|
+
* @type {string}
|
|
39
|
+
* @memberof FullTextSearchBackend
|
|
40
|
+
*/
|
|
41
|
+
private endTag: string;
|
|
42
|
+
|
|
43
|
+
constructor(service: FullTextSearchServiceInterface, startTag = '{{{', endTag = '}}}') {
|
|
44
|
+
this.service = service;
|
|
45
|
+
this.startTag = startTag;
|
|
46
|
+
this.endTag = endTag;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Finds all of the ranges of all the search results across the entire transcript.
|
|
51
|
+
*
|
|
52
|
+
* @private
|
|
53
|
+
* @param {string} query
|
|
54
|
+
* @returns {Promise<Range[]>}
|
|
55
|
+
* @memberof SearchBackendInterface
|
|
56
|
+
*/
|
|
57
|
+
async getSearchRanges(query: string): Promise<Range[]> {
|
|
58
|
+
let ranges: Range[] = [];
|
|
59
|
+
|
|
60
|
+
const results = await this.service.searchRequested(query);
|
|
61
|
+
|
|
62
|
+
results.value.docs.forEach((result: FullTextSearchResponseDoc) => {
|
|
63
|
+
const transcript = result.text;
|
|
64
|
+
result.highlight.cc.forEach((highlight: string) => {
|
|
65
|
+
const newRanges: Range[] = this.rangesOfResultInTranscript(highlight, transcript);
|
|
66
|
+
ranges = ranges.concat(newRanges);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
resolve(ranges);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Find the Range (start and end indices) of the results
|
|
77
|
+
* from the `highlight` in the `transcript`.
|
|
78
|
+
*
|
|
79
|
+
* Example:
|
|
80
|
+
* If `highlight` = `bar {{{baz}}} snip\n snap`
|
|
81
|
+
* and
|
|
82
|
+
* `transcript` = `beep boop\n foo bar baz snip\n snap`
|
|
83
|
+
*
|
|
84
|
+
* This will return [Range(20, 22)] because `baz` starts at index 20 and ends at 22
|
|
85
|
+
* in the transcript.
|
|
86
|
+
*
|
|
87
|
+
* @param {string} highlight
|
|
88
|
+
* @param {string} transcript
|
|
89
|
+
* @returns {Range[]}
|
|
90
|
+
*/
|
|
91
|
+
private rangesOfResultInTranscript(highlight: string, transcript: string): Range[] {
|
|
92
|
+
const regex = new RegExp(`${this.startTag}(.*?)${this.endTag}`, 'gm');
|
|
93
|
+
|
|
94
|
+
const startIndexOfHighlight = this.getStartIndexOfHighlight(highlight, transcript);
|
|
95
|
+
const totalTagLength = this.startTag.length + this.endTag.length;
|
|
96
|
+
|
|
97
|
+
const ranges: Range[] = [];
|
|
98
|
+
|
|
99
|
+
let matchIndex = 0;
|
|
100
|
+
let match;
|
|
101
|
+
// eslint-disable-next-line no-cond-assign
|
|
102
|
+
while ((match = regex.exec(highlight)) !== null) {
|
|
103
|
+
const startIndex = match.index;
|
|
104
|
+
const matchLength = match[1].length;
|
|
105
|
+
|
|
106
|
+
const adjustedMatchStart = startIndex - matchIndex * totalTagLength;
|
|
107
|
+
const overallMatchStart = startIndexOfHighlight + adjustedMatchStart;
|
|
108
|
+
const matchEnd = overallMatchStart + matchLength;
|
|
109
|
+
const range = new Range(overallMatchStart, matchEnd);
|
|
110
|
+
ranges.push(range);
|
|
111
|
+
matchIndex += 1;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return ranges;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* This method finds the highlight's overall location within the transcript.
|
|
119
|
+
*
|
|
120
|
+
* To do this, it strips out the start and end tags to treat it as a raw string.
|
|
121
|
+
*
|
|
122
|
+
* Example:
|
|
123
|
+
* If `highlight` = `bar {{{baz}}} snip\n snap`
|
|
124
|
+
* and
|
|
125
|
+
* `transcript` = `beep boop\n foo bar baz snip\n snap`
|
|
126
|
+
*
|
|
127
|
+
* This will return 16 because `bar baz snip...` starts at index 16.
|
|
128
|
+
*
|
|
129
|
+
* @param {string} highlight The highlighted string to find
|
|
130
|
+
* @param {string} transcript The transcript in which to find the highlight
|
|
131
|
+
* @returns {number}
|
|
132
|
+
*/
|
|
133
|
+
private getStartIndexOfHighlight(highlight: string, transcript: string): number {
|
|
134
|
+
const startTagRegex = new RegExp(this.startTag, 'gm');
|
|
135
|
+
const endTagRegex = new RegExp(this.endTag, 'gm');
|
|
136
|
+
const untokenizedHighlight = highlight.replace(startTagRegex, '').replace(endTagRegex, '');
|
|
137
|
+
const startIndexOfHighlight = transcript.indexOf(untokenizedHighlight);
|
|
138
|
+
return startIndexOfHighlight;
|
|
139
|
+
}
|
|
140
|
+
}
|
package/src/search-handler/search-backends/full-text-search-backend/full-text-search-response.ts
CHANGED
|
@@ -1,110 +1,110 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* This file contains the response models for the full text search backend.
|
|
5
|
-
*
|
|
6
|
-
* On receiving the response, we deserialize the raw JSON into `FullTextSearchResponse`,
|
|
7
|
-
* which cascades down into all of the child models.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export class FullTextSearchResponseValueHighlighting {
|
|
11
|
-
text: string[];
|
|
12
|
-
|
|
13
|
-
constructor(payload: any) {
|
|
14
|
-
this.text = payload.text;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class FullTextSearchResponseValueFacetCounts {
|
|
19
|
-
facetFields: object;
|
|
20
|
-
|
|
21
|
-
facetDates: object;
|
|
22
|
-
|
|
23
|
-
constructor(payload: any) {
|
|
24
|
-
this.facetDates = payload.facet_dates;
|
|
25
|
-
this.facetFields = payload.facet_fields;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class FullTextSearchResponseDocHighlight {
|
|
30
|
-
cc: string[];
|
|
31
|
-
|
|
32
|
-
constructor(payload: any) {
|
|
33
|
-
this.cc = payload.cc;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export class FullTextSearchResponseDoc {
|
|
38
|
-
identifier: string;
|
|
39
|
-
|
|
40
|
-
title: string;
|
|
41
|
-
|
|
42
|
-
text: string;
|
|
43
|
-
|
|
44
|
-
times: string;
|
|
45
|
-
|
|
46
|
-
downloads: number;
|
|
47
|
-
|
|
48
|
-
collection: string;
|
|
49
|
-
|
|
50
|
-
highlight: FullTextSearchResponseDocHighlight;
|
|
51
|
-
|
|
52
|
-
description: string;
|
|
53
|
-
|
|
54
|
-
mediatype: string;
|
|
55
|
-
|
|
56
|
-
__href__: string;
|
|
57
|
-
|
|
58
|
-
'SE-BYPASS': number;
|
|
59
|
-
|
|
60
|
-
constructor(payload: any) {
|
|
61
|
-
this.identifier = payload.identifier;
|
|
62
|
-
this.title = payload.title;
|
|
63
|
-
this.text = payload.text;
|
|
64
|
-
this.times = payload.times;
|
|
65
|
-
this.downloads = payload.downloads;
|
|
66
|
-
this.collection = payload.collection;
|
|
67
|
-
this.highlight = new FullTextSearchResponseDocHighlight(payload.highlight);
|
|
68
|
-
this.description = payload.description;
|
|
69
|
-
this.mediatype = payload.mediatype;
|
|
70
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
71
|
-
this.__href__ = payload.__href__;
|
|
72
|
-
this['SE-BYPASS'] = payload['SE-BYPASS'];
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export class FullTextSearchResponseValue {
|
|
77
|
-
numFound: number;
|
|
78
|
-
|
|
79
|
-
start: number;
|
|
80
|
-
|
|
81
|
-
docs: FullTextSearchResponseDoc[];
|
|
82
|
-
|
|
83
|
-
highlighting: { [key: string]: FullTextSearchResponseValueHighlighting } = {};
|
|
84
|
-
|
|
85
|
-
facetCounts: FullTextSearchResponseValueFacetCounts;
|
|
86
|
-
|
|
87
|
-
constructor(payload: any) {
|
|
88
|
-
this.numFound = payload.numFound;
|
|
89
|
-
this.start = payload.start;
|
|
90
|
-
this.docs = payload.docs.map((doc: any) => new FullTextSearchResponseDoc(doc));
|
|
91
|
-
|
|
92
|
-
Object.keys(payload.highlighting).forEach((key) => {
|
|
93
|
-
const highlighting = payload.highlighting[key];
|
|
94
|
-
this.highlighting[key] = new FullTextSearchResponseValueHighlighting(highlighting);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
this.facetCounts = new FullTextSearchResponseValueFacetCounts(payload.facet_counts);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export class FullTextSearchResponse {
|
|
102
|
-
success: boolean;
|
|
103
|
-
|
|
104
|
-
value: FullTextSearchResponseValue;
|
|
105
|
-
|
|
106
|
-
constructor(payload: any) {
|
|
107
|
-
this.success = payload.success;
|
|
108
|
-
this.value = new FullTextSearchResponseValue(payload.value);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This file contains the response models for the full text search backend.
|
|
5
|
+
*
|
|
6
|
+
* On receiving the response, we deserialize the raw JSON into `FullTextSearchResponse`,
|
|
7
|
+
* which cascades down into all of the child models.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export class FullTextSearchResponseValueHighlighting {
|
|
11
|
+
text: string[];
|
|
12
|
+
|
|
13
|
+
constructor(payload: any) {
|
|
14
|
+
this.text = payload.text;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class FullTextSearchResponseValueFacetCounts {
|
|
19
|
+
facetFields: object;
|
|
20
|
+
|
|
21
|
+
facetDates: object;
|
|
22
|
+
|
|
23
|
+
constructor(payload: any) {
|
|
24
|
+
this.facetDates = payload.facet_dates;
|
|
25
|
+
this.facetFields = payload.facet_fields;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class FullTextSearchResponseDocHighlight {
|
|
30
|
+
cc: string[];
|
|
31
|
+
|
|
32
|
+
constructor(payload: any) {
|
|
33
|
+
this.cc = payload.cc;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export class FullTextSearchResponseDoc {
|
|
38
|
+
identifier: string;
|
|
39
|
+
|
|
40
|
+
title: string;
|
|
41
|
+
|
|
42
|
+
text: string;
|
|
43
|
+
|
|
44
|
+
times: string;
|
|
45
|
+
|
|
46
|
+
downloads: number;
|
|
47
|
+
|
|
48
|
+
collection: string;
|
|
49
|
+
|
|
50
|
+
highlight: FullTextSearchResponseDocHighlight;
|
|
51
|
+
|
|
52
|
+
description: string;
|
|
53
|
+
|
|
54
|
+
mediatype: string;
|
|
55
|
+
|
|
56
|
+
__href__: string;
|
|
57
|
+
|
|
58
|
+
'SE-BYPASS': number;
|
|
59
|
+
|
|
60
|
+
constructor(payload: any) {
|
|
61
|
+
this.identifier = payload.identifier;
|
|
62
|
+
this.title = payload.title;
|
|
63
|
+
this.text = payload.text;
|
|
64
|
+
this.times = payload.times;
|
|
65
|
+
this.downloads = payload.downloads;
|
|
66
|
+
this.collection = payload.collection;
|
|
67
|
+
this.highlight = new FullTextSearchResponseDocHighlight(payload.highlight);
|
|
68
|
+
this.description = payload.description;
|
|
69
|
+
this.mediatype = payload.mediatype;
|
|
70
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
71
|
+
this.__href__ = payload.__href__;
|
|
72
|
+
this['SE-BYPASS'] = payload['SE-BYPASS'];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export class FullTextSearchResponseValue {
|
|
77
|
+
numFound: number;
|
|
78
|
+
|
|
79
|
+
start: number;
|
|
80
|
+
|
|
81
|
+
docs: FullTextSearchResponseDoc[];
|
|
82
|
+
|
|
83
|
+
highlighting: { [key: string]: FullTextSearchResponseValueHighlighting } = {};
|
|
84
|
+
|
|
85
|
+
facetCounts: FullTextSearchResponseValueFacetCounts;
|
|
86
|
+
|
|
87
|
+
constructor(payload: any) {
|
|
88
|
+
this.numFound = payload.numFound;
|
|
89
|
+
this.start = payload.start;
|
|
90
|
+
this.docs = payload.docs.map((doc: any) => new FullTextSearchResponseDoc(doc));
|
|
91
|
+
|
|
92
|
+
Object.keys(payload.highlighting).forEach((key) => {
|
|
93
|
+
const highlighting = payload.highlighting[key];
|
|
94
|
+
this.highlighting[key] = new FullTextSearchResponseValueHighlighting(highlighting);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
this.facetCounts = new FullTextSearchResponseValueFacetCounts(payload.facet_counts);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export class FullTextSearchResponse {
|
|
102
|
+
success: boolean;
|
|
103
|
+
|
|
104
|
+
value: FullTextSearchResponseValue;
|
|
105
|
+
|
|
106
|
+
constructor(payload: any) {
|
|
107
|
+
this.success = payload.success;
|
|
108
|
+
this.value = new FullTextSearchResponseValue(payload.value);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { FullTextSearchResponse } from './full-text-search-response';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The `FullTextSearchServiceInterface` allows the `FullTextSearchBackend` to hand off
|
|
5
|
-
* the network request to the consumer. This allows alternatives to AJAX calls
|
|
6
|
-
* for other consumers like the DWeb project.
|
|
7
|
-
*/
|
|
8
|
-
export interface FullTextSearchServiceInterface {
|
|
9
|
-
/**
|
|
10
|
-
* Execute the search and return a Promise with a FullTextSearchResponse.
|
|
11
|
-
*
|
|
12
|
-
* @param {string} query
|
|
13
|
-
* @returns {Promise<FullTextSearchResponse>}
|
|
14
|
-
* @memberof FullTextSearchServiceInterface
|
|
15
|
-
*/
|
|
16
|
-
searchRequested(query: string): Promise<FullTextSearchResponse>;
|
|
17
|
-
}
|
|
1
|
+
import { FullTextSearchResponse } from './full-text-search-response';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `FullTextSearchServiceInterface` allows the `FullTextSearchBackend` to hand off
|
|
5
|
+
* the network request to the consumer. This allows alternatives to AJAX calls
|
|
6
|
+
* for other consumers like the DWeb project.
|
|
7
|
+
*/
|
|
8
|
+
export interface FullTextSearchServiceInterface {
|
|
9
|
+
/**
|
|
10
|
+
* Execute the search and return a Promise with a FullTextSearchResponse.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} query
|
|
13
|
+
* @returns {Promise<FullTextSearchResponse>}
|
|
14
|
+
* @memberof FullTextSearchServiceInterface
|
|
15
|
+
*/
|
|
16
|
+
searchRequested(query: string): Promise<FullTextSearchResponse>;
|
|
17
|
+
}
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { Range } from '../../search-models';
|
|
2
|
-
import { TranscriptIndexInterface } from '../../transcript-index-interface';
|
|
3
|
-
import { SearchBackendInterface } from '../search-backend-interface';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* The LocalSearchBackend is a simple browser-side search backend that
|
|
7
|
-
* can be substituted for the FullTextSearchBackend. It implements
|
|
8
|
-
* the `SearchBackendInterface` so you can inject it into the `SearchHandler`.
|
|
9
|
-
*/
|
|
10
|
-
export class LocalSearchBackend implements SearchBackendInterface {
|
|
11
|
-
/**
|
|
12
|
-
* The TranscriptIndex allows quick lookup
|
|
13
|
-
*
|
|
14
|
-
* @private
|
|
15
|
-
* @memberof LocalSearchBackend
|
|
16
|
-
*/
|
|
17
|
-
private transcriptIndex: TranscriptIndexInterface;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Finds all of the ranges of all the search results across the entire transcript.
|
|
21
|
-
*
|
|
22
|
-
* @private
|
|
23
|
-
* @param {string} query
|
|
24
|
-
* @returns {Promise<Range[]>}
|
|
25
|
-
* @memberof SearchBackendInterface
|
|
26
|
-
*/
|
|
27
|
-
async getSearchRanges(query: string): Promise<Range[]> {
|
|
28
|
-
const ranges: Range[] = [];
|
|
29
|
-
const queryLowerCased: string = query.toLowerCase();
|
|
30
|
-
|
|
31
|
-
let index = -1;
|
|
32
|
-
/* eslint-disable no-cond-assign */
|
|
33
|
-
while (
|
|
34
|
-
(index = this.transcriptIndex.mergedTranscriptLowercased.indexOf(
|
|
35
|
-
queryLowerCased,
|
|
36
|
-
index + 1,
|
|
37
|
-
)) !== -1
|
|
38
|
-
) {
|
|
39
|
-
const newRange: Range = new Range(index, index + queryLowerCased.length);
|
|
40
|
-
ranges.push(newRange);
|
|
41
|
-
}
|
|
42
|
-
/* eslint-enable no-cond-assign */
|
|
43
|
-
|
|
44
|
-
return new Promise(resolve => resolve(ranges));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
constructor(transcriptIndex: TranscriptIndexInterface) {
|
|
48
|
-
this.transcriptIndex = transcriptIndex;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
1
|
+
import { Range } from '../../search-models';
|
|
2
|
+
import { TranscriptIndexInterface } from '../../transcript-index-interface';
|
|
3
|
+
import { SearchBackendInterface } from '../search-backend-interface';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The LocalSearchBackend is a simple browser-side search backend that
|
|
7
|
+
* can be substituted for the FullTextSearchBackend. It implements
|
|
8
|
+
* the `SearchBackendInterface` so you can inject it into the `SearchHandler`.
|
|
9
|
+
*/
|
|
10
|
+
export class LocalSearchBackend implements SearchBackendInterface {
|
|
11
|
+
/**
|
|
12
|
+
* The TranscriptIndex allows quick lookup
|
|
13
|
+
*
|
|
14
|
+
* @private
|
|
15
|
+
* @memberof LocalSearchBackend
|
|
16
|
+
*/
|
|
17
|
+
private transcriptIndex: TranscriptIndexInterface;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Finds all of the ranges of all the search results across the entire transcript.
|
|
21
|
+
*
|
|
22
|
+
* @private
|
|
23
|
+
* @param {string} query
|
|
24
|
+
* @returns {Promise<Range[]>}
|
|
25
|
+
* @memberof SearchBackendInterface
|
|
26
|
+
*/
|
|
27
|
+
async getSearchRanges(query: string): Promise<Range[]> {
|
|
28
|
+
const ranges: Range[] = [];
|
|
29
|
+
const queryLowerCased: string = query.toLowerCase();
|
|
30
|
+
|
|
31
|
+
let index = -1;
|
|
32
|
+
/* eslint-disable no-cond-assign */
|
|
33
|
+
while (
|
|
34
|
+
(index = this.transcriptIndex.mergedTranscriptLowercased.indexOf(
|
|
35
|
+
queryLowerCased,
|
|
36
|
+
index + 1,
|
|
37
|
+
)) !== -1
|
|
38
|
+
) {
|
|
39
|
+
const newRange: Range = new Range(index, index + queryLowerCased.length);
|
|
40
|
+
ranges.push(newRange);
|
|
41
|
+
}
|
|
42
|
+
/* eslint-enable no-cond-assign */
|
|
43
|
+
|
|
44
|
+
return new Promise(resolve => resolve(ranges));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
constructor(transcriptIndex: TranscriptIndexInterface) {
|
|
48
|
+
this.transcriptIndex = transcriptIndex;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Range } from '../search-models';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* An interface to define the responsibilities of the SearchBackend.
|
|
5
|
-
*
|
|
6
|
-
* Search Backends are injected into the SearchHandler for different cases (offline, online, etc)
|
|
7
|
-
*/
|
|
8
|
-
export interface SearchBackendInterface {
|
|
9
|
-
getSearchRanges(query: string): Promise<Range[]>;
|
|
10
|
-
}
|
|
1
|
+
import { Range } from '../search-models';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* An interface to define the responsibilities of the SearchBackend.
|
|
5
|
+
*
|
|
6
|
+
* Search Backends are injected into the SearchHandler for different cases (offline, online, etc)
|
|
7
|
+
*/
|
|
8
|
+
export interface SearchBackendInterface {
|
|
9
|
+
getSearchRanges(query: string): Promise<Range[]>;
|
|
10
|
+
}
|