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

notebook cleanups #21

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open

notebook cleanups #21

wants to merge 10 commits into from

Conversation

qti3e
Copy link
Collaborator

@qti3e qti3e commented May 12, 2018

TODO:

  • Move db types to types.ts
  • Remove ../src from import statements
  • Components
    • Snippet NotebookPreview
    • NotebookList
    • Profile
    • Recent
  • Break common.tsx down to small files and move notebook components to ./components
  • Remove notebook_root.ts
  • Use preact-router and change routes

@qti3e qti3e requested review from ry and piscisaureus May 12, 2018 21:30
Copy link
Contributor

@ry ry left a comment

Choose a reason for hiding this comment

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

Looks good! Let me know when I should review again.

src/types.ts Outdated

/**
* This file contains common types we use across the project.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: 1 line instead of 3

// Common types used across the project.

src/snippet.tsx Outdated
*/

/**
* Snippet is a cell showsing preview of a notebook.
Copy link
Contributor

Choose a reason for hiding this comment

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

typo "showsing"

Also - this could use a better name - like "NotebookPreview" or something.

src/list.tsx Outdated
onClick?: (nbId: string) => void;
}

export class List extends Component<ListProps, {}> {
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe call it NotebookList?

src/profile.tsx Outdated
const doc = this.props.notebooks[0].doc;
// TODO Profile is reusing the most-recent css class, because it's a very
// similar layout. The CSS class should be renamed something appropriate
// for both of them, maybe nb-listing.
Copy link
Contributor

Choose a reason for hiding this comment

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

Good TODO. Let's try to move towards consistency between the CSS classes and the component names.

@qti3e qti3e force-pushed the q/cleanup branch 3 times, most recently from 55feba0 to b3ff2fe Compare May 13, 2018 17:14
@qti3e
Copy link
Collaborator Author

qti3e commented May 14, 2018

Waiting for preactjs/preact-router#281 to be resolved...

limitations under the License.
*/

// tslint:disable:variable-name
Copy link
Member

Choose a reason for hiding this comment

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

I would suggest to use tslint:disable-next-line:variable-name and move it where it's needed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed


export const PropelIndex = props => {
let md = readFileSync(__dirname + "/../README.md", "utf8");
console.log(__dirname);
Copy link
Member

Choose a reason for hiding this comment

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

leftover debug statement?

Copy link
Collaborator Author

@qti3e qti3e May 15, 2018

Choose a reason for hiding this comment

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

removed, thank you Bert

@piscisaureus
Copy link
Member

@qti3e

  • I landed some of your commits (including moving components to src/components).
  • I rebased the other patches you made and updated this pull request. The original branch is still there as q/cleanup_backup, should you need it (but the diff is minimal).

@qti3e qti3e force-pushed the q/cleanup branch 4 times, most recently from 64ecd69 to 2ea7e8b Compare May 18, 2018 07:58
@qti3e qti3e changed the title [WIP] notebook clean ups notebook cleanups May 18, 2018
@qti3e
Copy link
Collaborator Author

qti3e commented May 18, 2018

@ry @piscisaureus PTAL

@ry
Copy link
Contributor

ry commented May 18, 2018

@qti3e This branch needs to be rebased

src/app.tsx Outdated
error: string;
}

function bind(C, bindProps: BindProps) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this a common react pattern? Can you add docs or a link to a description?

Copy link
Collaborator Author

@qti3e qti3e May 18, 2018

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

ok - Please add that link to the source code

this.loadData();
const { data, error } = this.state;
if (error) return <ErrorPage message={error} />;
if (!data) return <Loading />;

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as resolved.

src/app.tsx Outdated
<div class="notebook">
<GlobalHeader subtitle="Notebook" subtitleLink="/">
<UserMenu userInfo={userInfo} />
</GlobalHeader>
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice that we have a single reference to the global header now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

: )

@piscisaureus
Copy link
Member

// Careful, S3 is finicky about what URLs it serves. So
// /notebook?nbId=blah will get redirect to /notebook/
// because it is a directory with an index.html in it.
const u = window.location.origin + "/notebook/?nbId=" + nbId;
Copy link
Member

Choose a reason for hiding this comment

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

This needs to be rebased.

src/app.tsx Outdated
created: new Date(),
owner: {
displayName: "Anonymous",
photoURL: "/static/img/anon_profile.png?",
Copy link
Member

Choose a reason for hiding this comment

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

This needs to be rebased

@@ -19,6 +19,7 @@
"preserveConstEnums": true,
"pretty": true,
"sourceMap": true,
"allowSyntheticDefaultImports": true,
Copy link
Member

Choose a reason for hiding this comment

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

Why is this needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

import pathToRegexp from "path-to-regexp";

the default export of path-to-regexp is a function and we need to use that, on the other hand,when allowSyntheticDefaultImports is disabled, ts will throw an error:

"path-to-regexp" has no default export.

Copy link
Member

Choose a reason for hiding this comment

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

Did you try import * as pathToRegExp from "path-to-regexp" ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@piscisaureus yeah, but it would throw a run-time error (see my comment below)

@piscisaureus
Copy link
Member

@qti3e I rebased this branch again.
But made no changes to the router.

@qti3e
Copy link
Collaborator Author

qti3e commented May 19, 2018

@piscisaureus @ry I made some changes to the router and implemented a new component (<Link />) so we can deploy on GitHub pages, I think this patch is ready to land now : )

src/app.tsx Outdated
import { Recent } from "./components/recent";

interface BindProps {
[key: string]: (props: any) => Promise<any>;
Copy link
Member

Choose a reason for hiding this comment

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

The issue I have with this is that it breaks the type-checker.

Copy link
Member

Choose a reason for hiding this comment

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

I can somewhat bring back type safety by applying the following patch:

diff --git a/src/app.tsx b/src/app.tsx
index 85d3297..318aa28 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -27,15 +27,26 @@ import { Notebook } from "./components/notebook";
 import { Profile } from "./components/profile";
 import { Recent } from "./components/recent";
 
-interface BindProps {
-  [key: string]: (props: any) => Promise<any>;
+type Partial<T> = {
+  [K in keyof T]?: T[K];
+};
+
+type BindProps<P> = {
+  readonly [K in keyof P]?: (props: P) => Promise<P[K]>;
+};
+
+interface BindStateNormal<P> {
+  data: { [K in keyof P]: P[K] };
+  error: null;
 }
 
-interface BindState {
-  data: { [key: string]: string };
+interface BindStateError {
+  data: null;
   error: string;
 }
 
+type BindState<P> = BindStateNormal<P> | BindStateError;
+
 /**
  * This react HOC can be used to bind result of some async
  * methods to props of the given component (C).
@@ -48,8 +59,8 @@ interface BindState {
  *     }
  *   });
  */
-function bind(C, bindProps: BindProps) {
-  return class extends Component<any, BindState> {
+function bind<P>(C, bindProps: BindProps<P>) {
+  return class extends Component<Partial<P>, BindState<P>> {
     state = { data: null, error: null };
     prevMatches = null;
     componentRef;
@@ -61,7 +72,7 @@ function bind(C, bindProps: BindProps) {
     async loadData() {
       if (equal(this.props.matches, this.prevMatches)) return;
       this.prevMatches = this.props.matches;
-      const data = {};
+      const data: any = {};
       for (const key in bindProps) {
         if (!bindProps[key]) continue;
         try {

However typescript complains about the fact that the onReady and matches properties aren't defined anywhere, and it looks like it's right about that...
Same for the path attribute used when instantiating the page components (<RecentPage path="/" userInfo={userInfo} /> etc.)

I am not afraid of some black magic voodoo code, but it has to be correct before I am going to accept it.

On an aside, did you consider simply using getters/setters? Maybe that's a bit easier to reason about.

@piscisaureus piscisaureus force-pushed the q/cleanup branch 4 times, most recently from 7332616 to c519b5c Compare May 20, 2018 06:31
@piscisaureus
Copy link
Member

@qti3e See c519b5c for my attempt to make bind() type safe. I hope we can do something that's a little easier to understand.

@qti3e
Copy link
Collaborator Author

qti3e commented May 20, 2018

@piscisaureus I dropped 1e67a10 due to:

TypeError: pathToRegexp is not a function
    at match (db.ts:312)
    at Router.onLocationChange (db.ts:312)
    at Router.componentWillMount (db.ts:312)
    at setComponentProps (test.b1fdbaba.js:1545)
    at buildComponentFromVNode (test.b1fdbaba.js:1742)
    at idiff (test.b1fdbaba.js:1283)
    at diff (test.b1fdbaba.js:1234)
    at Object.render (test.b1fdbaba.js:1875)
    at router (router_test.tsx:24)
    at runTests (tester.ts:104)

@qti3e
Copy link
Collaborator Author

qti3e commented May 21, 2018

@piscisaureus PTAL

@qti3e qti3e force-pushed the q/cleanup branch 3 times, most recently from b1c80a2 to 2d5018d Compare May 21, 2018 13:21
Copy link
Contributor

@ry ry left a comment

Choose a reason for hiding this comment

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

LGTM - cursory review - I defer to @piscisaureus for the final approval

this.loadData();
const { data, error } = this.state;
if (error) return <ErrorPage message={error} />;
if (!data) return <Loading />;

This comment was marked as resolved.

src/app.tsx Outdated
}

// An anonymous notebook doc for when users aren't logged in
const anonDoc = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be exported so it could be used in tests?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

await flush();
assertEqual(path(), "/page/345");
assertEqual(activePage(), "p3");
assertEqual(matchedProps.get("p3").v, "345");
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice test!

message: string;
}

export function ErrorPage(props: ErrorPageProps) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: This could be done in one line...

function ErrorPage(props: { header?: string, message: string }): JSX.Element {

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

max-line-length: Exceeds maximum line length of 80

@qti3e
Copy link
Collaborator Author

qti3e commented May 23, 2018

@piscisaureus any comments? : )

}

render() {
this.loadData();
Copy link
Member

Choose a reason for hiding this comment

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

I'm sorry but this just isn't right.
Since loadData() is async, it causes the following loop:

tick 1: render() -> starts loadData()
tick 2: loadData() calls setState() -> render() gets called -> starts another loadData().

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@piscisaureus loadData only calls setState when props has been changed

+      if (equal(this.props.matches, this.prevMatches)) return;
+      this.prevMatches = this.props.matches;

}
});

export const HomePage = bind(Home as any, {});
Copy link
Member

Choose a reason for hiding this comment

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

as any is inappropriate here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

that's because Home is a functional component... I'll try again to remove this any

@qti3e qti3e mentioned this pull request Jun 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants