Skip to content
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

Implement UI for certificate #232

Merged
merged 1 commit into from
Feb 20, 2023
Merged

Conversation

Ririio
Copy link
Contributor

@Ririio Ririio commented Feb 16, 2023

This pr is based on issue #213

Here's a live demo of the UI:

2023-02-15.19-37-31.mp4
  • I decided to use an Accordion instead of a textArea, I find it a lot more cleaner
  • I used useState to display different components once the user has pressed the Request a Certificate button
  • Instead of having a large download button for each key, I decided to switch it to a button that has hover effect, tooltip and gap, to ensure that user don't accidentally press the button
  • I'm unable to access the seed certificate, so I'm using a temporary object to produce the necessary output

@Ririio Ririio added category: front end Front end part of our web service area: web Web development related things [front end/back end] labels Feb 16, 2023
@Ririio Ririio added this to the Milestone 0.3 milestone Feb 16, 2023
@Ririio Ririio self-assigned this Feb 16, 2023
ghost
ghost previously requested changes Feb 16, 2023
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the loading progress is not the correct UX here.

A certificate request will probably take at the very minimum 1-2 minutes, users will not wait that long for that animation (it looks cool for sure, but still)

Also, it feels like it tries to keep the user glued to the screen, but the process is unfortunately not that fast for this to be feasible.

This is why we talked about showing some kind of pending state in the same structure we are showing the certificate details in the second screen in your video

@ghost
Copy link

ghost commented Feb 16, 2023

On the other hand, the cert details screen looks very nice :)

@Ririio
Copy link
Contributor Author

Ririio commented Feb 16, 2023

I think the loading progress is not the correct UX here.

A certificate request will probably take at the very minimum 1-2 minutes, users will not wait that long for that animation (it looks cool for sure, but still)

Also, it feels like it tries to keep the user glued to the screen, but the process is unfortunately not that fast for this to be feasible.

This is why we talked about showing some kind of pending state in the same structure we are showing the certificate details in the second screen in your video

Yeah... I'm struggling a bit with understanding what a good UX is for the loading page. From what I can understand, you want to head directly to the 2nd page, but provide some sort of a "loading" buffer before displaying the details? Like a spinning wheel of some kind?

@ghost
Copy link

ghost commented Feb 16, 2023

Yes, with some kind of description, that we are creating the certificate, but this is an asyncrhronous process, requiring multiple 3rd party providers (route53 and let's encrypt), so for this reason it will take a few minutes

@ghost
Copy link

ghost commented Feb 16, 2023

also a note that the user can leave the page and come back later, the process will continue in the background

@Ririio
Copy link
Contributor Author

Ririio commented Feb 16, 2023

The loading page is meant to stay regardless on whether the user refresh the page or not. The state will only change after the certificate becomes valid (at least that's how I thought it would work...). Right now it's handled by a timeout

@humphd
Copy link
Contributor

humphd commented Feb 16, 2023

I really love this @Ririio, great job. A few comments:

  • For the "pending" screen, I think it should be static (i.e., no animation), which will help with it taking a while and not seeming broken. We could include an image from https://undraw.co/illustrations coloured red for example. Not this one, but something like this with text saying, "We've ordered your certificate and will notify you when it's ready":

Screenshot 2023-02-16 at 1 19 22 PM

  • We said that the main part of the UI should be centred vs. left-aligned.

@Ririio
Copy link
Contributor Author

Ririio commented Feb 16, 2023

For the "pending" screen, I think it should be static (i.e., no animation), which will help with it taking a while and not seeming broken. We could include an image from https://undraw.co/illustrations coloured red for example. Not this one, but something like this with text saying, "We've ordered your certificate and will notify you when it's ready":

We're allowed to use this website for illustration? I

We said that the main part of the UI should be centred vs. left-aligned

I recall there was a discussion for the ui to be left-aligned-- I had to change the layout on the figma template

@humphd
Copy link
Contributor

humphd commented Feb 16, 2023

We're allowed to use this website for illustration?

Yes, it is open licensed

I recall there was a discussion for the ui to be left-aligned-- I had to change the layout on the figma template

What I heard in that meeting was "left-aligned in a container that is centred," but if I'm wrong, do what you have.

cc @Myrfion, @Eakam1007

@Eakam1007
Copy link
Contributor

Eakam1007 commented Feb 16, 2023

What I heard in that meeting was "left-aligned in a container that is centered," but if I'm wrong, do what you have.

Yeah, I believe it was discussed that the form should not touch the left edge but should be a bit more towards the center (so basically a margin on the left)

I think this suggestion should make it work

@Ririio
Copy link
Contributor Author

Ririio commented Feb 16, 2023

Yeah, I believe it was discussed that the form should not touch the left edge but should be a bit more towards the center (so basically a margin on the left)

Just to be clear, I just have to move the container more to the center, and have its content left align?

@Eakam1007
Copy link
Contributor

Just to be clear, I just have to move the container more to the center, and have its content left align?

I would say it is up to you how you decide to do it. But yeah, I think that should work

@humphd
Copy link
Contributor

humphd commented Feb 16, 2023

What I'm more looking for is that this be responsive. When we're on a really wide screen, it's nicer to put it in the middle. On a narrower screen, it's going to be more on the left, etc.

We can also do that stuff in a follow up. But putting the "main" part of this in a container that is in the center, and the contents are left-aligned within it, seems good to me.

If it doesn't work, don't do it. Just a thought.

@Ririio
Copy link
Contributor Author

Ririio commented Feb 17, 2023

@humphd @dadolhay I changed the loading screen, and aligned the containers in the middle as per your suggestion. If you don't mind taking a look here's a demo...

2023-02-16.19-00-15.mp4

@humphd humphd requested a review from Myrfion February 17, 2023 00:18
Copy link
Contributor

@humphd humphd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like where this is going.

Reading the code, I wonder if we should be splitting this up into a few larger components vs. having such deep nesting on state. That could happen in a follow-up, so we don't block this for 0.3, but I think this file is getting pretty big, and we could separate the three states into smaller pieces of code that would be easier to maintain.

I'm tagging some other reviewers who can help with thinking about the front-end stuff.

@Ririio
Copy link
Contributor Author

Ririio commented Feb 17, 2023

Reading the code, I wonder if we should be splitting this up into a few larger components vs. having such deep nesting on state. That could happen in a follow-up, so we don't block this for 0.3, but I think this file is getting pretty big, and we could separate the three states into smaller pieces of code that would be easier to maintain.

If we're splitting them up, can I create a directory called components underneath the certificate to split the code? I'm not familiar with the standard practice of remix in terms of creating components, so I refrained from doing it. Am I allowed to do something like this?

image

@Eakam1007
Copy link
Contributor

I believe there already is a components directory under app. I think you could use that?

@Ririio
Copy link
Contributor Author

Ririio commented Feb 17, 2023

I believe there already is a components directory under app. I think you could use that?

sure

@Ririio
Copy link
Contributor Author

Ririio commented Feb 17, 2023

@Eakam1007 is this what you meant?

@Ririio Ririio requested a review from a user February 17, 2023 04:02
Copy link
Contributor

@humphd humphd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

certificate-display.tsx does the exact same UI twice. You could break that up into re-usable pieces too, which will halve this code, and pass the things that are different (e.g., the title, the value in the accordion view) as props.

Because you have a bunch of "certificate" components (e.g., loading is pretty vague, I'd put them all under app/components/certificate/*` so they are logically grouped together. Then you can break out smaller bits without it getting overwhelming.

In your certificate/index.tsx, don't be afraid to use an if:

if(loading) {
  return <Loading />
}

if(certificate) {
  return <CertificateDetails certificate={certificate} />
}

return <RequestCertificate />

let key = props.cert.certificate;
let val = 'Public Key';

if (props.priv) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing this, pass down the title to show (e.g., 'Private Key') and also the value to use (i.e., the specific PEM string to show). This component shouldn't have to know anything about what it's showing, do that above it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused as to what you mean, do you mind explaining it one more time?

<Heading as="h4" size="sm">
{props.priv ? 'Private Key' : 'Public Key'}
</Heading>
<Tooltip label="Copy Public Key">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This public vs. private logic should get figured out via props vs hard-coding like this and below.

Copy link
Contributor Author

@Ririio Ririio Feb 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to create a switch and 3 new variables that will be used for the key, currentState and Description. This should remove any need for hard coding, because the output is dependent on the current state of the isPrivate props

onClick={() => onCopy()}
/>
</Tooltip>
<Tooltip label="Download Public Key">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

Copy link
Contributor Author

@Ririio Ririio Feb 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I create a variable that changes depending on the state of isPrivate?

app/components/certificate/certificate-display.tsx Outdated Show resolved Hide resolved
app/components/certificate/description.tsx Outdated Show resolved Hide resolved
<HStack gap="6" marginTop="2">
<VStack>
<Text fontWeight="bold">Created On</Text>
<Text>{props.cert.validFrom.toDateString()}</Text>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use chakra.time for a <time> element, and use the datatime attribute to set a machine readable value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry I can't seem to find the document relating to chakra.time do you happen to have the link for it?

@@ -0,0 +1,18 @@
import { Center, Flex, Box, Image, Heading } from '@chakra-ui/react';

import image from 'img/undraw_Processing_re_tbdu.png';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unclear how Remix handles assets. Are these supposed to go in public/ or in the tree like this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll also need to include the license for this image, or we are breaking the license.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also not sure... Alex might know a bit more about it, because she has also have files on the img directory

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was looking for someone to go read the docs, which are here https://remix.run/docs/en/v1/guides/migrating-react-router-app#asset-imports.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another question: does undraw not supply these as SVGs? They will scale much better if so.

import type { Certificate } from '@prisma/client';

interface Props {
cert: Certificate;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass the specific thing down you want to show: domainName

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not quite sure what you mean by this?

app/routes/__index/certificate/index.tsx Outdated Show resolved Hide resolved
</Heading>
</div>
);
const [request, setRequest] = useState(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does request represent? Would this not be certificate (i.e., you'd show the certificate display only if you have a certificate)?

Copy link
Contributor Author

@Ririio Ririio Feb 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the 'request' is a state when the certificate has already been requested (true) or not (false). This helps when rendering pages depending on whether we have a new certificate. If you have a different idea I can change the current iteration

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is whether or not the certificate has been requested, use that: certificateRequested

Copy link
Contributor

@Myrfion Myrfion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, PR looks good! I added some minor change requests that would improve code quality in my opinion

app/components/certificate/certificate-display.tsx Outdated Show resolved Hide resolved
app/components/certificate/certificate-display.tsx Outdated Show resolved Hide resolved
app/components/certificate/certificate-display.tsx Outdated Show resolved Hide resolved
app/routes/__index/certificate/index.tsx Outdated Show resolved Hide resolved
app/routes/__index/certificate/index.tsx Outdated Show resolved Hide resolved
app/components/certificate/request.tsx Outdated Show resolved Hide resolved
app/components/certificate/description.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@Eakam1007 Eakam1007 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add e2e tests for this or create a issue for them?

app/components/certificate/certificate-display.tsx Outdated Show resolved Hide resolved
app/components/certificate/certificate-display.tsx Outdated Show resolved Hide resolved
app/components/certificate/description.tsx Outdated Show resolved Hide resolved
app/components/certificate/description.tsx Outdated Show resolved Hide resolved
app/components/certificate/description.tsx Outdated Show resolved Hide resolved
app/components/certificate/description.tsx Outdated Show resolved Hide resolved
@@ -0,0 +1,18 @@
import { Center, Flex, Box, Image, Heading } from '@chakra-ui/react';

import image from 'img/undraw_Processing_re_tbdu.png';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was looking for someone to go read the docs, which are here https://remix.run/docs/en/v1/guides/migrating-react-router-app#asset-imports.

app/components/certificate/request.tsx Outdated Show resolved Hide resolved
</Heading>
</div>
);
const [request, setRequest] = useState(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is whether or not the certificate has been requested, use that: certificateRequested

@@ -0,0 +1,18 @@
import { Center, Flex, Box, Image, Heading } from '@chakra-ui/react';

import image from 'img/undraw_Processing_re_tbdu.png';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another question: does undraw not supply these as SVGs? They will scale much better if so.

@Ririio Ririio requested a review from humphd February 19, 2023 14:48
}

export default function CertificateDisplay(props: CertificateDisplayProps) {
const { title, description, value } = props;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

export default function CertificateDisplay({ title, description, value }: CertificateDisplayProps) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh that makes it much better than calling it again inside

function onCopy() {
navigator.clipboard.writeText(value);
toast({
title: `${title} was copied to clipboard`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"the clipboard"

app/components/certificate/loading.tsx Show resolved Hide resolved
/>
</>
)}
{!certificateRequested && (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern feels off to me. We have a state that will result in one of two component sub-trees being rendered in this view. I think you should make two components and do:

{ certificateRequested ? <View1 /> : <View2 /> }

Maybe name them:

  1. CertificateRequested
  2. CertificateAvailable

There might be something better, not sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually thought about doing this on my previous commits, but I can't seem to figure out how I'll handle the button for request certificate

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh it's actually fairly simple to do...

@Ririio Ririio requested a review from humphd February 19, 2023 21:10
Copy link
Contributor

@humphd humphd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking better and better. A few more things

app/components/certificate/certificate-available.tsx Outdated Show resolved Hide resolved
app/components/certificate/certificate-request.tsx Outdated Show resolved Hide resolved
app/components/certificate/certificate-request.tsx Outdated Show resolved Hide resolved
app/components/certificate/description.tsx Outdated Show resolved Hide resolved
@Ririio Ririio requested a review from humphd February 19, 2023 21:42
Copy link
Contributor

@humphd humphd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small change, and this is r+ from me

app/components/certificate/certificate-request.tsx Outdated Show resolved Hide resolved
replacing privkey with privateKey

center components | adding unDraw illustration

creating 'loading' and 'certificate-display' components

creating new components for certificate

Implementing advice from reviews

Changing function name to be more descriptive

passing props instead of using logic in child component

Trimming the index to only contain two components as to a tree

all logic should occur in the parent component

following react event handler prefix
@Ririio Ririio dismissed stale reviews from Myrfion and ghost February 19, 2023 22:00

Outdated

Copy link
Contributor

@Eakam1007 Eakam1007 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The page is not really responsive:

image

Though this can be addressed in another issue, if you would like to create one. And same goes for e2e tests for this

Otherwise, looks good

@Ririio Ririio merged commit ab1dad8 into DevelopingSpace:main Feb 20, 2023
@Ririio Ririio deleted the issue-213 branch February 25, 2023 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: web Web development related things [front end/back end] category: front end Front end part of our web service
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants