Skip to content

Commit d00b5bf

Browse files
committed
Update getWithChildren to use stela
This continues our migration away from the PHP api / into stela. Similar to the work around get record we want to decouple the actual API calls from our component implementations. Once we're fully onto Stela we can update our components to use the stela data format.
1 parent c51157e commit d00b5bf

File tree

3 files changed

+209
-37
lines changed

3 files changed

+209
-37
lines changed

src/app/shared/services/api/folder.repo.ts

Lines changed: 188 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
import { FolderVO, FolderVOData, ItemVO } from '@root/app/models';
22
import { BaseResponse, BaseRepo } from '@shared/services/api/base';
3-
import { Observable } from 'rxjs';
3+
import { firstValueFrom, Observable } from 'rxjs';
44
import { DataStatus } from '@models/data-status.enum';
5+
import {
6+
convertStelaLocationToLocnVOData,
7+
convertStelaRecordToRecordVO,
8+
convertStelaSharetoShareVO,
9+
convertStelaTagToTagVO,
10+
StelaLocation,
11+
StelaShare,
12+
StelaTag,
13+
type StelaRecord,
14+
} from './record.repo';
515

616
const MIN_WHITELIST: (keyof FolderVO)[] = [
717
'folderId',
@@ -17,6 +27,119 @@ const DEFAULT_WHITELIST: (keyof FolderVO)[] = [
1727
'view',
1828
];
1929

30+
// This is hard coded for now as we transition away from the PHP backend.
31+
// In future we hope to remove the need for time zone objects entirely.
32+
export const CENTRAL_TIMEZONE_VO = {
33+
timeZoneId: 88,
34+
displayName: 'Central Time',
35+
timeZonePlace: 'America/Chicago',
36+
stdName: 'Central Standard Time',
37+
stdAbbrev: 'CST',
38+
stdOffset: '-06:00',
39+
dstName: 'Central Daylight Time',
40+
dstAbbrev: 'CDT',
41+
dstOffset: '-05:00',
42+
};
43+
44+
interface StelaFolder {
45+
folderId: string;
46+
size: number;
47+
location: StelaLocation;
48+
parentFolder: {
49+
id: string;
50+
};
51+
shares: Array<StelaShare>;
52+
tags: Array<StelaTag>;
53+
archive: {
54+
id: string;
55+
name: string;
56+
};
57+
createdAt: string;
58+
updatedAt: string;
59+
description: string;
60+
displayTimestamp: string;
61+
displayEndTimestamp: string;
62+
displayName: string;
63+
downloadName: string;
64+
imageRatio: number;
65+
paths: {
66+
names: string[];
67+
};
68+
publicAt: string;
69+
sort: string;
70+
thumbnailUrls: {
71+
'200': string;
72+
'256': string;
73+
'500': string;
74+
'1000': string;
75+
'2000': string;
76+
};
77+
type: string;
78+
status: string;
79+
view: string;
80+
children?: StelaFolderChild[];
81+
}
82+
83+
interface PagedStelaResponse<T> {
84+
items: Array<T>;
85+
}
86+
87+
type StelaFolderChild = StelaFolder | StelaRecord;
88+
89+
const isStelaRecord = (child: StelaFolderChild): child is StelaRecord =>
90+
child && 'recordId' in child;
91+
92+
const convertStelaFolderToFolderVO = (stelaFolder: StelaFolder): FolderVO => {
93+
stelaFolder.children ??= [];
94+
const childFolderVOs = stelaFolder.children
95+
.filter((child): child is StelaFolder => !isStelaRecord(child))
96+
.map(convertStelaFolderToFolderVO);
97+
const childRecordVOs = stelaFolder.children
98+
.filter(isStelaRecord)
99+
.map(convertStelaRecordToRecordVO);
100+
return new FolderVO({
101+
...stelaFolder,
102+
folderId: stelaFolder.folderId,
103+
archiveId: stelaFolder.archive.id,
104+
displayName: stelaFolder.displayName,
105+
displayDT: stelaFolder.displayTimestamp,
106+
displayEndDT: stelaFolder.displayEndTimestamp,
107+
derivedDT: stelaFolder.displayTimestamp,
108+
derivedEndDT: stelaFolder.displayEndTimestamp,
109+
note: '',
110+
description: stelaFolder.description,
111+
sort: stelaFolder.sort,
112+
locnId: stelaFolder.location.id,
113+
timeZoneId: 88, // Hard coded for now
114+
view: stelaFolder.view,
115+
imageRatio: stelaFolder.imageRatio,
116+
type: stelaFolder.type,
117+
thumbStatus: stelaFolder.status,
118+
thumbURL200: stelaFolder.thumbnailUrls['200'],
119+
thumbURL500: stelaFolder.thumbnailUrls['500'],
120+
thumbURL1000: stelaFolder.thumbnailUrls['1000'],
121+
thumbURL2000: stelaFolder.thumbnailUrls['2000'],
122+
thumbDT: stelaFolder.displayTimestamp,
123+
thumbnail256: stelaFolder.thumbnailUrls['256'],
124+
thumbnail256CloudPath: stelaFolder.thumbnailUrls['256'],
125+
status: stelaFolder.status,
126+
publicDT: stelaFolder.publicAt,
127+
parentFolderId: stelaFolder.parentFolder.id,
128+
pathAsText: stelaFolder.paths.names,
129+
ParentFolderVOs: [new FolderVO({ folderId: stelaFolder.parentFolder.id })],
130+
ChildFolderVOs: childFolderVOs,
131+
RecordVOs: childRecordVOs,
132+
LocnVO: convertStelaLocationToLocnVOData(stelaFolder.location),
133+
TimezoneVO: CENTRAL_TIMEZONE_VO,
134+
TagVOs: (stelaFolder.tags ?? []).map((stelaTag) =>
135+
convertStelaTagToTagVO(stelaTag, stelaFolder.archive.id),
136+
),
137+
ChildItemVOs: [...childRecordVOs, ...childFolderVOs],
138+
ShareVOs: (stelaFolder.shares ?? []).map(convertStelaSharetoShareVO),
139+
isFolder: true,
140+
});
141+
};
142+
20143
export class FolderRepo extends BaseRepo {
21144
public async getRoot(): Promise<FolderResponse> {
22145
return await this.http.sendRequestPromise<FolderResponse>(
@@ -46,20 +169,73 @@ export class FolderRepo extends BaseRepo {
46169
);
47170
}
48171

172+
private async getStelaFolder(folderVO: FolderVO): Promise<StelaFolder> {
173+
const queryData = {
174+
folderIds: [folderVO.folderId],
175+
};
176+
const folderResponse = (
177+
await firstValueFrom(
178+
this.httpV2.get<PagedStelaResponse<StelaFolder>>(
179+
`v2/folder`,
180+
queryData,
181+
),
182+
)
183+
)[0];
184+
return folderResponse.items[0];
185+
}
186+
187+
private async getStelaFolderChildren(
188+
folderVO: FolderVO,
189+
): Promise<StelaFolderChild[]> {
190+
const queryData = {
191+
pageSize: 99999999, // We want all results in one request
192+
};
193+
const childrenResponse = (
194+
await firstValueFrom(
195+
this.httpV2.get<PagedStelaResponse<StelaFolderChild>>(
196+
`v2/folder/${folderVO.folderId}/children`,
197+
queryData,
198+
),
199+
)
200+
)[0];
201+
return childrenResponse.items;
202+
}
203+
49204
public async getWithChildren(folderVOs: FolderVO[]): Promise<FolderResponse> {
50-
const data = folderVOs.map((folderVO) => ({
51-
FolderVO: {
52-
archiveNbr: folderVO.archiveNbr,
53-
folder_linkId: folderVO.folder_linkId,
54-
folderId: folderVO.folderId,
55-
},
56-
}));
205+
// Stela has two separate endpoints -- one for loading the folder, one for loading the children.
206+
const requests = folderVOs.map(async (folderVO) => {
207+
const stelaFolder = await this.getStelaFolder(folderVO);
208+
const stelaFolderChildren = await this.getStelaFolderChildren(folderVO);
209+
return {
210+
...stelaFolder,
211+
children: stelaFolderChildren,
212+
};
213+
});
57214

58-
return await this.http.sendRequestPromise<FolderResponse>(
59-
'/folder/getWithChildren',
60-
data,
61-
{ responseClass: FolderResponse },
215+
const stelaFolders = (await Promise.all(requests)).flat();
216+
217+
// We need the `Results` to look the way v1 results look, for now.
218+
const simulatedV1FolderResponseResults = stelaFolders.map(
219+
(stelaFolder) => ({
220+
data: [
221+
{
222+
FolderVO: convertStelaFolderToFolderVO(stelaFolder),
223+
},
224+
],
225+
message: ['Folder retrieved'],
226+
status: true,
227+
resultDT: new Date().toISOString(),
228+
createdDT: null,
229+
updatedDT: null,
230+
}),
62231
);
232+
233+
const folderResponse = new FolderResponse({
234+
isSuccessful: true,
235+
isSystemUp: true,
236+
Results: simulatedV1FolderResponseResults,
237+
});
238+
return folderResponse;
63239
}
64240

65241
public navigate(folderVO: FolderVO): Observable<FolderResponse> {

src/app/shared/services/api/record.repo.ts

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { FileFormat, PermanentFile } from '@models/file-vo';
1919
import { ShareStatus } from '@models/share-vo';
2020
import { AccessRoleType } from '@models/access-role';
2121
import { getFirst } from '../http-v2/http-v2.service';
22+
import { CENTRAL_TIMEZONE_VO } from './folder.repo';
2223

2324
class MultipartUploadUrlsList {
2425
public urls: string[] = [];
@@ -52,7 +53,7 @@ class MultipartUploadUrlsList {
5253
// to simply use what stela provides, but there is work to be done regarding
5354
// overall type safety in this code base before we want to take that project
5455
// on.
55-
interface StelaTag {
56+
export interface StelaTag {
5657
id: string;
5758
name: string;
5859
type: string;
@@ -67,8 +68,8 @@ interface StelaFile {
6768
updatedAt: string;
6869
downloadUrl: string;
6970
}
70-
interface StelaLocation {
71-
id: number;
71+
export interface StelaLocation {
72+
id: string;
7273
streetNumber: string;
7374
streetName: string;
7475
locality: string;
@@ -85,17 +86,17 @@ interface StelaArchive {
8586
archiveNumber: string;
8687
name: string;
8788
}
88-
interface StelaShare {
89+
export interface StelaShare {
8990
id: string;
9091
status: ShareStatus;
9192
accessRole: AccessRoleType;
9293
archive: {
93-
id: number;
94-
name: string;
94+
id: string;
9595
thumbUrl200: string;
96+
name: string;
9697
};
9798
}
98-
type StelaRecord = Omit<RecordVO, 'files'> & {
99+
export type StelaRecord = Omit<RecordVO, 'files'> & {
99100
tags: Array<StelaTag>;
100101
archiveNumber: string;
101102
displayDate: string;
@@ -122,7 +123,10 @@ const resolveTagName = (tag: StelaTag): string => {
122123
return tag.name;
123124
};
124125

125-
const convertStelaTagToTagVO = (stelaTag: StelaTag, archiveId: string): TagVO =>
126+
export const convertStelaTagToTagVO = (
127+
stelaTag: StelaTag,
128+
archiveId: string,
129+
): TagVO =>
126130
new TagVO({
127131
tagId: Number.parseInt(stelaTag.id),
128132
name: resolveTagName(stelaTag),
@@ -138,7 +142,7 @@ const convertStelaFileToPermanentFile = (
138142
downloadURL: stelaFile.downloadUrl,
139143
});
140144

141-
const convertStelaSharetoShareVO = (stelaShare: StelaShare): ShareVO =>
145+
export const convertStelaSharetoShareVO = (stelaShare: StelaShare): ShareVO =>
142146
new ShareVO({
143147
shareId: stelaShare.id,
144148
status: stelaShare.status,
@@ -150,17 +154,19 @@ const convertStelaSharetoShareVO = (stelaShare: StelaShare): ShareVO =>
150154
},
151155
});
152156

153-
const convertStelaLocationToLocnVOData = (
157+
export const convertStelaLocationToLocnVOData = (
154158
stelaLocation: StelaLocation,
155159
): LocnVOData =>
156160
stelaLocation.id
157161
? {
158162
...stelaLocation,
159-
locnId: stelaLocation.id,
163+
locnId: Number.parseInt(stelaLocation.id, 10),
160164
}
161165
: null;
162166

163-
const convertStelaRecordToRecordVO = (stelaRecord: StelaRecord): RecordVO =>
167+
export const convertStelaRecordToRecordVO = (
168+
stelaRecord: StelaRecord,
169+
): RecordVO =>
164170
new RecordVO({
165171
...stelaRecord,
166172
TagVOs: stelaRecord.tags.map((stelaTag) =>
@@ -178,18 +184,8 @@ const convertStelaRecordToRecordVO = (stelaRecord: StelaRecord): RecordVO =>
178184
parentFolder_linkId: stelaRecord.parentFolderLinkId,
179185
TextDataVOs: [],
180186
ArchiveVOs: [],
181-
timeZoneId: 88, // Hard coded for now
182-
TimezoneVO: {
183-
timeZoneId: 88,
184-
displayName: 'Central Time',
185-
timeZonePlace: 'America/Chicago',
186-
stdName: 'Central Standard Time',
187-
stdAbbrev: 'CST',
188-
stdOffset: '-06:00',
189-
dstName: 'Central Daylight Time',
190-
dstAbbrev: 'CDT',
191-
dstOffset: '-05:00',
192-
},
187+
timeZoneId: CENTRAL_TIMEZONE_VO.timeZoneId,
188+
TimezoneVO: CENTRAL_TIMEZONE_VO,
193189
ShareVOs: (stelaRecord.shares ?? []).map(convertStelaSharetoShareVO),
194190
});
195191

src/app/shared/services/data/data.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ export class DataService {
338338

339339
return await Promise.resolve(true);
340340
})
341-
.catch((e) => {
341+
.catch(() => {
342342
itemRejects.forEach((reject, index) => {
343343
items[index].fetched = null;
344344
reject();

0 commit comments

Comments
 (0)