-
Notifications
You must be signed in to change notification settings - Fork 0
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
Added paper details to Paper View #144
base: develop
Are you sure you want to change the base?
Conversation
LCOV of commit
|
c954292
to
80315d4
Compare
fbf4abf
to
bc421b7
Compare
006741b
to
4f9045f
Compare
ce16465
to
c2cd179
Compare
dd81310
to
5ffeec4
Compare
Due to not finding any other solution I decided to write an action that automatically calculates the max height according to the screen height and the position of the text area. This is updated whenever the screen size changes.
5ffeec4
to
c7c8eab
Compare
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.
The page looks great, nice work. 👍
I stumbled upon issues with the integration tests though, I attached some details in the form of a log.
The pipeline doesn't seem to encounter the same problem.
Due to the upcoming gRPC work, I did not review changes regarding controllers or backend APIs.
@@ -7,15 +7,17 @@ | |||
import Tooltip from "./Tooltip.svelte"; | |||
|
|||
interface Props { | |||
paperId: number; | |||
loadingPaperId: Promise<number>; |
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.
What's your reasoning for pulling that promise inside this component?
Couldn't this component be used as is when wrapped in svelte's {#await ...}
?
This question arises multiple times throughout the code, one comment thread is enough though imo.
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.
I used this because the component does not heavily rely on the asynchronous loading, i.e., we can just display the component and as soon as the paper is loaded the functionality works as well.
Therefore, wrapping the component in an await block seemed too much to me.
Where else did you notice this?
use:autosize | ||
use:inputAction={inputActionProps} |
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.
Do you think this workaround is necessary? The abstract's textarea
could instead fill the remaining space. It would reduce complexity with the caveat of always filling the remaining space even when provided with a short text (see image below). Visually there wouldn't be too much of a difference with that one exception.
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.
What did you use to produce that?
I tried plenty of approaches and none worked when the text overflows. The action was some sort of last resort.
{#if "id" in paper} | ||
<div class="w-fit text-default-sb-nc text-neutral-500">#{paper.id}</div> | ||
{/if} |
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.
Is there a reason the id
could be missing?
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.
Yes, this is used when the data is only a PaperSpec
with no ID. This is the case on the paper create page.
|
||
type Props = WithElementRef<HTMLAttributes<HTMLDivElement>> & { | ||
key: string; | ||
value: unknown; |
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.
As far as I can tell value
is used for class names and content at the same time. This should probably be explained somewhere.
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.
Great catch! I added it to the component documentation.
let basicInfos: BasicInfos = $state({ | ||
Title: "w-[6rem] sm:w-[7.5rem] md:w-[11rem] lg:w-[19.8rem]", | ||
Authors: "w-[4rem] sm:w-[5rem] md:w-[7.3rem] lg:w-[13rem]", | ||
Year: "w-[2rem] sm:w-[2.5rem] md:w-[3rem] lg:w-[3.5rem]", | ||
Publisher: "w-[5rem] sm:w-[6rem] md:w-[8.6rem] lg:w-[15rem]", | ||
}); | ||
loadingPaper | ||
.then((paper) => { | ||
basicInfos = { | ||
Title: paper.title, | ||
Authors: getNames(paper.authors), | ||
Year: paper.year?.toString() ?? "N/A", | ||
Publisher: "N/A", | ||
}; | ||
}) | ||
.catch(() => { | ||
basicInfos = { Title: "", Authors: "", Year: "", Publisher: "" }; | ||
}); |
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.
I recognize a common pattern: Instead of relying on svelte's {#await ...}
a state rune is used with a default value. In case you want to avoid {#await ...}
(previous comment), I'd recommend simplifying that behavior similar to what is shown here:
// resource.svelte.ts
export let resource = <T>(
fn: () => Promise<T>,
initialValue?: T
) => {
const _rune = $state<{ value: T | undefined }>({
value: initialValue
});
$effect(() => {
fn().then((data) => {
_rune.value = data;
});
});
return _rune;
};
This could also be extended with a default error value. Maybe something like this:
export let resource = <T>(
fn: () => Promise<T>,
initialValue?: T,
onSuccess: (...) => T,
onError?: (...) => T
) => { ... }
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.
Nice suggestion, I like it. It's way more clean and descriptive now.
<Skeleton class="flex h-[1.625rem] rounded-full w-[100%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[95%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[70%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[82%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[50%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[75%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[90%]" /> |
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.
<Skeleton class="flex h-[1.625rem] rounded-full w-[100%]" /> | |
<Skeleton class="flex h-[1.625rem] rounded-full w-[95%]" /> | |
<Skeleton class="flex h-[1.625rem] rounded-full w-[70%]" /> | |
<Skeleton class="flex h-[1.625rem] rounded-full w-[82%]" /> | |
<Skeleton class="flex h-[1.625rem] rounded-full w-[50%]" /> | |
<Skeleton class="flex h-[1.625rem] rounded-full w-[75%]" /> | |
<Skeleton class="flex h-[1.625rem] rounded-full w-[90%]" /> | |
{#each [100,95,70,82,50,75,90] as width} | |
<Skeleton class="flex h-[1.625rem] rounded-full w-[{width}%]" /> | |
{/each} |
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.
Good catch. I added it.
let paperId = $state<number | undefined>(undefined); | ||
loadingPaperId.then((id) => (paperId = id)).catch(() => (paperId = undefined)); |
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.
Why not a nullable id?
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 elaborate.
expect(screen.queryByTestId("skeleton")).not.toBeNull(); | ||
}); | ||
|
||
test("When paper loading failed without error, then errot text is shown", async () => { |
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.
test("When paper loading failed without error, then errot text is shown", async () => { | |
test("When paper loading failed without error, then error text is shown", async () => { |
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.
Good catch. Changed it.
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.
Thank you for the review.
I couldn't reproduce the errors you got in that log. On which commit did you experience that?
@@ -7,15 +7,17 @@ | |||
import Tooltip from "./Tooltip.svelte"; | |||
|
|||
interface Props { | |||
paperId: number; | |||
loadingPaperId: Promise<number>; |
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.
I used this because the component does not heavily rely on the asynchronous loading, i.e., we can just display the component and as soon as the paper is loaded the functionality works as well.
Therefore, wrapping the component in an await block seemed too much to me.
Where else did you notice this?
use:autosize | ||
use:inputAction={inputActionProps} |
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.
What did you use to produce that?
I tried plenty of approaches and none worked when the text overflows. The action was some sort of last resort.
{#if "id" in paper} | ||
<div class="w-fit text-default-sb-nc text-neutral-500">#{paper.id}</div> | ||
{/if} |
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.
Yes, this is used when the data is only a PaperSpec
with no ID. This is the case on the paper create page.
|
||
type Props = WithElementRef<HTMLAttributes<HTMLDivElement>> & { | ||
key: string; | ||
value: unknown; |
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.
Great catch! I added it to the component documentation.
<Skeleton class="flex h-[1.625rem] rounded-full w-[100%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[95%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[70%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[82%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[50%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[75%]" /> | ||
<Skeleton class="flex h-[1.625rem] rounded-full w-[90%]" /> |
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.
Good catch. I added it.
let paperId = $state<number | undefined>(undefined); | ||
loadingPaperId.then((id) => (paperId = id)).catch(() => (paperId = undefined)); |
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 elaborate.
expect(screen.queryByTestId("skeleton")).not.toBeNull(); | ||
}); | ||
|
||
test("When paper loading failed without error, then errot text is shown", async () => { |
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.
Good catch. Changed it.
let basicInfos: BasicInfos = $state({ | ||
Title: "w-[6rem] sm:w-[7.5rem] md:w-[11rem] lg:w-[19.8rem]", | ||
Authors: "w-[4rem] sm:w-[5rem] md:w-[7.3rem] lg:w-[13rem]", | ||
Year: "w-[2rem] sm:w-[2.5rem] md:w-[3rem] lg:w-[3.5rem]", | ||
Publisher: "w-[5rem] sm:w-[6rem] md:w-[8.6rem] lg:w-[15rem]", | ||
}); | ||
loadingPaper | ||
.then((paper) => { | ||
basicInfos = { | ||
Title: paper.title, | ||
Authors: getNames(paper.authors), | ||
Year: paper.year?.toString() ?? "N/A", | ||
Publisher: "N/A", | ||
}; | ||
}) | ||
.catch(() => { | ||
basicInfos = { Title: "", Authors: "", Year: "", Publisher: "" }; | ||
}); |
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.
Nice suggestion, I like it. It's way more clean and descriptive now.
Those are mainly for the developer and don't provide any advantage for the user
a4ba269
to
c0b18be
Compare
Closes #41
What I have made
PaperDetailsCard.svelte
now displays all the information, planned in the designToggleableInput
component, which is an auto-sizing textareaChecklist
Either tick or cross out the items that do not apply (using ~~example text~~) and give a reason why the item does not apply.
[ ] unit testsno logic that be tested by a unit test added[ ] end-to-end testsnot available yet