-
Notifications
You must be signed in to change notification settings - Fork 1
Per 9261 search by tag public archive #490
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #490 +/- ##
==========================================
+ Coverage 42.98% 43.05% +0.06%
==========================================
Files 360 362 +2
Lines 10985 11035 +50
Branches 1793 1799 +6
==========================================
+ Hits 4722 4751 +29
- Misses 6103 6121 +18
- Partials 160 163 +3 ☔ View full report in Codecov by Sentry. |
meisekimiu
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments, but not all of them need to be explicitly addressed (some of them are more pieces of advice in general and do not need to be specifically applied if they aren't applicable).
| let queryString = `/search/folderAndRecord?query=${query}&archiveId=${archiveId}&publicOnly=true&numberOfResults=${limit}`; | ||
|
|
||
| if (tags.length) { | ||
| queryString += `&tags[0][tagId]=${tags[0].tagId}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This functionality should probably be covered with tests. Also, are we only supposed to be able to search for one tag?
| archiveId, | ||
| publicOnly: true, | ||
| }; | ||
| let queryString = `/search/folderAndRecord?query=${query}&archiveId=${archiveId}&publicOnly=true&numberOfResults=${limit}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a piece of advice that can lead to better practices when writing JavaScript. Most of the time, when you use the let keyword, there's probably some way to rewrite all of it using the const keyword instead. There are some exceptions like loop structures, but in general it's preferable to use const whenever you can and things like string manipulation can be expressed with all const's:
// This is not necessarily a full suggestion of how to rewrite this code, see another comment for a more specific suggestion!
const endpoint = "/search/folderAndRecord";
const tagsQuery = tags.map((tag, index) => `tags[${index}][tagId]=${tag.tagId}`).join('&');
const queryString = `query=${query}&archiveId=${archiveId}&publicOnly=true&numberOfResults=${limit}&${tagsQuery}`;
return getFirst(
this.httpV2.get<SearchResponse>(`${endpoint}?${queryString}`, {}, null, {
authToken: false,
}),
);The benefit of this is just that it makes things a bit more stable; we can't accidentally reassign or delete the endpoint name and each constituent part of the query is also just broken up in a way that communicates how it's generated a bit more clearly.
|
|
||
| return getFirst( | ||
| this.httpV2.get<SearchResponse>('/search/folderAndRecord', data, null, { | ||
| this.httpV2.get<SearchResponse>(queryString, {}, null, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unlike the "V1" HttpService, the HttpV2Service allows you to pass in data as an object and it will generate the query parameters and append them to the URL itself (see: HttpV2Service::getEndpointWithData). I'm not sure if this directly works with the array syntax the PHP backend is expecting, but we should be able to modify the HttpV2Service itself to handle this kind of query parameter if it doesn't. The point of this is so that we don't have to manually generate query parameters in every single API function every time and we can instead just pass in a data object like we do with POST requests.
| ); | ||
| } | ||
|
|
||
| public getPublicArchiveTags(archiveId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a typing for archiveId here. Ideally it would be nice to have test coverage for this function as well, even if it's very simple.
| @Input() searchResults = []; | ||
| @Input() tags = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These values should have type annotations, since I think right now they are any[].
| public types = { | ||
| 'type.folder.private': 'Folder', | ||
| 'type.folder.public': 'Folder', | ||
| 'type.record.image': 'Image', | ||
| 'type.record.video': 'Video', | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might not need to move this but lately I've been trying to catch myself when I end up writing something like this and asking myself: "Is something like this defined elsewhere in the application?" Ideally when we add a new type of file to support in the future, we shouldn't have to change hundreds of places in the code to support that new file type.
So my question is: Is there already some code somewhere that converts item types into human readable strings like this? I'm not sure but it might be useful to see if there's an opportunity here to make a reusable shared function that many components can use at once (and, for the sake of this component, may be used through an Angular Pipe or something like that). I know the design only points out folders, images, and videos as recognized file types but we probably want to support other types, right? And it'd be annoying to have multiple locations in the codebase that do this same conversion in a slightly different way each time.
|
@meisekimiu did the suggested changes. Thanks a lot for your suggestions! |
| const endpoint = '/search/folderAndRecord'; | ||
|
|
||
| const tagsQuery = tags | ||
| .map((tag, index) => `tags[${index}][tagId]=${tag.tagId}`) | ||
| .join('&'); | ||
|
|
||
| const queryString = | ||
| `query=${query}&archiveId=${archiveId}&publicOnly=true` + | ||
| (limit ? `&numberOfResults=${limit}` : '') + | ||
| (tagsQuery ? `&${tagsQuery}` : ''); | ||
|
|
||
| return getFirst( | ||
| this.httpV2.get<SearchResponse>('/search/folderAndRecord', data, null, { | ||
| this.httpV2.get<SearchResponse>(`${endpoint}?${queryString}`, {}, null, { | ||
| authToken: false, | ||
| }), | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit on me for using this code as an example of how we can use const in most places in JavaScript, but I didn't actually want my example to be directly used here. As mentioned in this comment, we don't actually have to manually build up the query string as the HttpV2Service can take in a data object like a POST request, and generate and append a query string automatically.
My const suggestion was more a standard JavaScript tip, though it still had applicability in this function. Instead of building up a query string with consts, we should be building up a const data object we pass into the httpV2.get method. And since the parameters for this method are somewhat complex, we probably have to compose this data object out of multiple consts, or at least inlined expressions.
// I have not tested this code!
// This is just a sketch of what the code might look like.
// It definitely needs adjustments for typescript!
const tagQueries = tags.reduce((obj, tag, index) => {
obj[`tags[${index}][tagId]`] = tag.tagId;
return obj;
}, {});
const data = {
query,
archiveId,
publicOnly: 'true'
...tagQueries
};
if (limit) {
data.numberOfResults = limit;
}
return getFirst(
this.httpV2.get<SearchResponse>('/search/folderAndRecord', data, null, {
authToken: false,
})
);|
@meisekimiu Thanks! Pushed the changes! |
yeslikesolo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Search my tags working great, thanks Andrei!
b305367 to
1dadb08
Compare
This pull request adds the public tag search functionality to the app.
Steps to test: