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

Fix #1459: Added Post and Posts to NextJS #1504

Merged
merged 6 commits into from
Jan 22, 2021

Conversation

rogercyyu
Copy link
Contributor

Issue This PR Addresses

This issue address #1459.

Type of Change

  • Bugfix: Change which fixes an issue
  • New Feature: Change which adds functionality
  • Documentation Update: Change which improves documentation
  • UI: Change which improves UI

Description

This port Post/ and Posts/ to Next,js and converts it to TypeScript (most i think?).

  • Tested it by commenting out things that aren't implemented yet. So works mostly.
  • Requires a lot more components that haven't been implemented yet.
  • Moved telescope-post-content.css to \styles.
  • Probably some bugs yet to be discovered.

Thoughts?

Thank you for your time and review.

Checklist

  • Quality: This PR builds and passes our npm test and works locally
  • Tests: This PR includes thorough tests or an explanation of why it does not
  • Screenshots: This PR includes screenshots or GIFs of the changes made or an explanation of why it does not (if applicable)
  • Documentation: This PR includes updated/added documentation to user exposed functionality or configuration variables are added/changed or an explanation of why it does not(if applicable)

import { Box, Grid, Typography, ListSubheader, createStyles } from '@material-ui/core';

// For style, need to add:
// import '../styles/telescope-post-content.css';
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Typo: This statement needs to be added to index.tsx to work properly.

Copy link
Contributor

Choose a reason for hiding this comment

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

cc @tonyvugithub, can you take over the global styling we need? We should get an issue filed to move the telescope-post-content.css file into our global css for next.js.

Copy link
Contributor

Choose a reason for hiding this comment

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

@humphd : I believe @PedroFonsecaDEV is currently working on the global.css file in #1548

Copy link
Contributor

Choose a reason for hiding this comment

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

Also can we convert the css file of Post to JSS to keep it consistent with the rest of the components? And then we don't have to worry about moving the css to global.css

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we can, or we can't do it easily.

The way we load and display posts now is to send raw HTML and inject it as innerHTML. This means we can't rely on module scoped CSS for a component, since it isn't really a component.

It might be possible down the road to use something like Server Components, but they are still very new. https://addyosmani.com/blog/react-server-components/ has a good discussion. This is a research problem we could tackle on the way to 2.0.

For now, we should probably port it as is.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, left a comment in #1548.

Copy link
Contributor

Choose a reason for hiding this comment

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

You can remove this comment now, @PedroFonsecaDEV is doing it in another PR in the global stylesheet.

@rogercyyu rogercyyu added area: front-end area: nextjs Nextjs related issues labels Dec 8, 2020
@rogercyyu rogercyyu self-assigned this Dec 8, 2020
@tonyvugithub
Copy link
Contributor

@rogercyyu : Hi there, we are in the process of reviewing these migrated to Next PRs. Just wonder if you are still interested to work on this as we would like you to make some changes to your PR. Please let us know in case you decided to drop this then we can assign the issue to others. Thank you.

@rogercyyu
Copy link
Contributor Author

@tonyvugithub I am happy to make some changes to this PR. Thanks

@tonyvugithub
Copy link
Contributor

Got it. Thanks. We keep you posted about the progress.

@@ -0,0 +1,210 @@
import React, { useRef, useState } from 'react';
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need to import React in next.js, but the other two are fine.

import { Box, Grid, Typography, ListSubheader, createStyles } from '@material-ui/core';

// For style, need to add:
// import '../styles/telescope-post-content.css';
Copy link
Contributor

Choose a reason for hiding this comment

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

cc @tonyvugithub, can you take over the global styling we need? We should get an issue filed to move the telescope-post-content.css file into our global css for next.js.

// For style, need to add:
// import '../styles/telescope-post-content.css';

interface Props {
Copy link
Contributor

Choose a reason for hiding this comment

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

The next.js docs/examples on using TypeScript suggest using type vs. interface for Props.

// We need a ref to our post content, which we inject into a <section> below.
const sectionEl = useRef(null);
// Grab the post data from our backend so we can render it
const getData = async (url: string) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should file an issue to switch this to use useSWR instead.

postUrl: string;
}

interface DataItem {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is really a Post vs. DataItem. We probably should create something like this: https://github.com/vercel/next.js/tree/canary/examples/with-typescript/interfaces and move interface Feed {...} and interface Post {...} in there, then import them into this file so we can use them.

html: string;
}

const useStyles = makeStyles((theme) =>
Copy link
Contributor

Choose a reason for hiding this comment

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


interface DataItem {
type DataItem = {
Copy link
Contributor

Choose a reason for hiding this comment

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

No. The difference here between Props, which is done correctly, and this (which isn't) is that Props is internal to this code. Whereas, we'll share the definition of Feed and Post throughout the frontend.

We need to create a folder at the same level as components and include an index.ts file, like this: https://github.com/vercel/next.js/tree/canary/examples/with-typescript/interfaces

Inside it, you can export two types:

export type Feed  = {
  link: string
  author: string
}

export type Post {
  feed: Feed
  id: string
  post: string
  title: string
  updated: string
  url: string
  html: string
}

Then you can import and use them here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you for the detail feedback

import { useRef, useState } from 'react';

import useSWR from 'swr';
import 'highlight.js/styles/github.css';
Copy link
Contributor

Choose a reason for hiding this comment

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

next.js won't let us do this, we'll have to load this globally, see https://nextjs.org/docs/basic-features/built-in-css-support.

return res.json();
};

const { data: post, error } = useSWR<PostType>(postUrl, getData);
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like you have both a fetch and a useSWR way in the same file. Can we just do useSWR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean, change to:

  // Grab the post data from our backend so we can render it
  const fetcher = (url: string) => fetch(url).then((r) => r.json());

  const { data: post, error } = useSWR<Post>(postUrl, fetcher);

?

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, you don't need to fetch() and useSWR(), they accomplish the same thing, and the latter is better (it will cache it for offline use).


function LoadAutoScroll({ onScroll }: Scroll) {
const classes = useStyles();
const $buttonRef = useRef(null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure, if I fixed this correctly.

import { usePrevious } from 'react-use';
import SentimentDissatisfiedRoundedIcon from '@material-ui/icons/SentimentDissatisfiedRounded';
import Timeline from './Timeline';
// TODO: Change these to new ones whenever import to NextJS
Copy link
Contributor

Choose a reason for hiding this comment

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

I've got these finished and merged now, if you want to rebase.

import useSiteMetaData from '../../hooks/use-site-metadata';

type Props = {
pages: Array<any> | undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

This will be an Array of Post objects, so we should be able to type it with your interface.

author: string;
};

export type PostType = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Drop the *Type suffix.

@@ -1,5 +1,7 @@
import { AppProps } from 'next/app';
import '../styles/globals.css';
import '../styles/empty.css';
import '../styles/Post.css';
Copy link
Contributor

Choose a reason for hiding this comment

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

These won't work here, needs to be globally imported.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Whoops, those are mistakes leftover from testing.

import { Box, Grid, Typography, ListSubheader, createStyles } from '@material-ui/core';

// For style, need to add:
// import '../styles/telescope-post-content.css';
Copy link
Contributor

Choose a reason for hiding this comment

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

You can remove this comment now, @PedroFonsecaDEV is doing it in another PR in the global stylesheet.

return `Last Updated ${formatted}`;
};

const Post = ({ postUrl }: Props) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

We can't have 2 things named Post. You are importing a Post type, and now defining another Post as the component. You could call this PostComponent if you want.

const Post = ({ postUrl }: Props) => {
const classes = useStyles();
// We need a ref to our post content, which we inject into a <section> below.
const sectionEl = useRef(null);
Copy link
Contributor

Choose a reason for hiding this comment

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

We should type this: useRef<HTMLSectionElement>(); I think.

// Grab the post data from our backend so we can render it
const fetcher = (url: string) => fetch(url).then((r) => r.json());

const { data: post, error } = useSWR<PostType>(postUrl, fetcher);
Copy link
Contributor

Choose a reason for hiding this comment

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

Post vs. PostType

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, I don't think we need this fetcher since it's the default. You can drop the second arg and delete line 110, 111.

return (
<Box className={classes.root} boxShadow={2}>
<ListSubheader className={classes.header}>
<AdminButtons />
Copy link
Contributor

Choose a reason for hiding this comment

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

You need to import AdminButtons to use it here. It's happening in #1515, which we need to land to get it here.


<Grid container justify="center">
<Grid item className={classes.spinner}>
<Spinner animation="border" variant="light">
Copy link
Contributor

Choose a reason for hiding this comment

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

You need Spinner, see #1479

@@ -0,0 +1,58 @@
import { FC } from 'react';
Copy link
Contributor

Choose a reason for hiding this comment

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

You can drop this.

import useSiteMetaData from '../../hooks/use-site-metadata';

type Props = {
pages: Array<typeof Post> | undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

Array<Post>

src/frontend/next/src/pages/_app.tsx Outdated Show resolved Hide resolved
@@ -0,0 +1,127 @@
.telescope-post-content {
Copy link
Contributor

Choose a reason for hiding this comment

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

This file can be removed, @PedroFonsecaDEV is doing it globally.

@PedroFonsecaDEV
Copy link
Contributor

PedroFonsecaDEV commented Jan 21, 2021

This PR looks good.
Still depending on #1515.
Maybe a good option would be to create a simple AdminButtons on the right folder to merge this one? Like a skeleton.
Something like this:

const AdminButtons = () => <h3> AdminButtons<h3>

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.

Thanks for jumping on these fixes, we really need this PR to land soon, so the new frontend can be tested with our backend data.

src/frontend/next/src/components/Post/PostComponent.tsx Outdated Show resolved Hide resolved
observer.observe($buttonRef.current!);

return () => {
observer.unobserve($buttonRef.current!);
Copy link
Contributor

Choose a reason for hiding this comment

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

Need to fix the eslint warning you have on $buttonRef.current. cc @birtony, who just fixed this kind of thing for #1227.

@@ -0,0 +1,107 @@
import { useState, useEffect } from 'react';
Copy link
Contributor

Choose a reason for hiding this comment

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

This file can be renamed to src/frontend/next/src/components/Posts/index.tsx

import useSiteMetaData from '../../hooks/use-site-metadata';
import useFaviconBadge from '../../hooks/use-favicon-badge';

interface PostData {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not use a proper Post type from our interfaces?

* Fixed eslint issues (hopefully) & PR changes
@rogercyyu
Copy link
Contributor Author

Thanks for jumping on these fixes, we really need this PR to land soon, so the new frontend can be tested with our backend data.

Your welcome. Happy to help!

@humphd
Copy link
Contributor

humphd commented Jan 21, 2021

@rogercyuu is this ready for re-review then?

@rogercyyu
Copy link
Contributor Author

@humphd yup


// Iterate over all the pages (an array of arrays) and then convert all post
// elements to <Post>
const postsTimeline = pages.map((page: Post[]): any =>
Copy link
Contributor

Choose a reason for hiding this comment

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

@humphd : What does this mean in TS? I thought page already have type Post[]. The return? If so it would return a list of , no idea how to express that in syntax

import Timeline from './Timeline';
import useSiteMetaData from '../../hooks/use-site-metadata';
import useFaviconBadge from '../../hooks/use-favicon-badge';
import { Post } from '../../interfaces/index';
Copy link
Contributor

Choose a reason for hiding this comment

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

I think index work here as Posts have dependent component. Instead of doing /Posts/Posts.tsx, no?

@@ -0,0 +1,190 @@
import { useRef, useState } from 'react';
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like you can just move this Posts.tsx component inside the Posts folder.


// Iterate over all the pages (an array of arrays) and then convert all post
// elements to <Post>
const postsTimeline = pages.map((page: Post[]): any =>
Copy link
Contributor

Choose a reason for hiding this comment

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

@rogercyyu : I would say keep any for now.

Copy link
Contributor

@PedroFonsecaDEV PedroFonsecaDEV left a comment

Choose a reason for hiding this comment

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

Well Done!

@manekenpix manekenpix dismissed PedroFonsecaDEV’s stale review January 22, 2021 03:58

There are somet things that need to be fixed

@PedroFonsecaDEV
Copy link
Contributor

@rogercyyu, how did you tested the PR?
We are experiencing some issues regarding the infinity scroll.

@rogercyyu
Copy link
Contributor Author

rogercyyu commented Jan 22, 2021

@PedroFonsecaDEV hmmm works fine on my end. Not sure what's happening. I used the npm run develop:next. Is the build or serve one not working?

@PedroFonsecaDEV
Copy link
Contributor

@PedroFonsecaDEV hmmm works fine on my end. Not sure what's happening. I used the npm run develop:next. Is the build or serve one not working?

The infinity scroll starts an infinite loop after 4+ posts loads.

@humphd humphd added this to the 1.5 Release milestone Jan 22, 2021
@humphd
Copy link
Contributor

humphd commented Jan 22, 2021

I want to land this today, what's missing that needs to happen? If there's a scrolling bug, let's file that for follow-up vs holding this up. Please update ASAP.

@humphd
Copy link
Contributor

humphd commented Jan 22, 2021

Looks like a rebase is needed for sure...

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 think this is good for 1.5, and we can fix anything that comes of it in follow-ups.

const [currentPostId, setCurrentPostId] = useState<string | null>();

const { data, size, setSize, error } = useSWRInfinite<Post[]>(
(index: number) => `${telescopeUrl}/posts?page=${index + 1}`,
Copy link
Contributor

Choose a reason for hiding this comment

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

When I load https://deploy-preview-1504--telescope-next.netlify.app/ it looks like telescopeUrl is undefined on Netlify, it is loading this URL:

https://deploy-preview-1504--telescope-next.netlify.app/undefined/posts?page=1

Filed #1589 to deal with this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: front-end area: nextjs Nextjs related issues
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants