From 2e028992a37e1a6ed1f00110f8a1c3bfd54b3b69 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sun, 26 Sep 2021 17:31:49 +0100 Subject: [PATCH] Use placeholders to prevent layout flow disruptions --- chartered-frontend/package-lock.json | 15 +++++++++++++++ chartered-frontend/package.json | 1 + chartered-frontend/src/index.sass | 1 + chartered-frontend/src/util.tsx | 17 +++++++++++++++++ chartered-frontend/src/pages/crate/CrateView.tsx | 8 +++++--- chartered-frontend/src/pages/crate/Members.tsx | 12 +++++++----- chartered-frontend/src/pages/crate/OrganisationView.tsx | 61 +++++++++++++++++++++++++++++++++++++++++++++++++------------ chartered-frontend/src/pages/organisations/ListOrganisations.tsx | 7 ++----- 8 files changed, 85 insertions(+), 37 deletions(-) diff --git a/chartered-frontend/package-lock.json b/chartered-frontend/package-lock.json index 4a3e4f3..2b644f3 100644 --- a/chartered-frontend/package-lock.json +++ a/chartered-frontend/package-lock.json @@ -18,6 +18,7 @@ "react-dom": "^17.0.2", "react-human-time": "^1.2.0", "react-markdown": "^7.0.1", + "react-placeholder": "^4.1.0", "react-router-dom": "^5.3.0", "react-syntax-highlighter": "^15.4.4", "remark-gfm": "^2.0.0", @@ -9081,6 +9082,14 @@ "react-dom": ">=16.3.0" } }, + "node_modules/react-placeholder": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/react-placeholder/-/react-placeholder-4.1.0.tgz", + "integrity": "sha512-z1HGD86NWJTYTQumHsmGH9jkozv4QHa9dju/vHVUd4f1svu23pf5v7QoBLBfs3kA1S9GLJaCeRMHLbO2SCdz5A==", + "peerDependencies": { + "react": "^16.8.0 || ^17" + } + }, "node_modules/react-popper": { "version": "1.3.11", "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz", @@ -18803,6 +18812,12 @@ "uncontrollable": "^7.2.1", "warning": "^4.0.3" } + }, + "react-placeholder": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/react-placeholder/-/react-placeholder-4.1.0.tgz", + "integrity": "sha512-z1HGD86NWJTYTQumHsmGH9jkozv4QHa9dju/vHVUd4f1svu23pf5v7QoBLBfs3kA1S9GLJaCeRMHLbO2SCdz5A==", + "requires": {} }, "react-popper": { "version": "1.3.11", diff --git a/chartered-frontend/package.json b/chartered-frontend/package.json index 8f4910c..171a23b 100644 --- a/chartered-frontend/package.json +++ a/chartered-frontend/package.json @@ -32,6 +32,7 @@ "react-dom": "^17.0.2", "react-human-time": "^1.2.0", "react-markdown": "^7.0.1", + "react-placeholder": "^4.1.0", "react-router-dom": "^5.3.0", "react-syntax-highlighter": "^15.4.4", "remark-gfm": "^2.0.0", diff --git a/chartered-frontend/src/index.sass b/chartered-frontend/src/index.sass index db918e5..99df259 100644 --- a/chartered-frontend/src/index.sass +++ a/chartered-frontend/src/index.sass @@ -1,7 +1,8 @@ $primary: #0d6efd $font-family-monospace: "Source Code Pro", SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace $enable-cssgrid: true +@import "../node_modules/react-placeholder/lib/reactPlaceholder.css" @import "~bootstrap/scss/bootstrap.scss" @import "../node_modules/source-code-pro/source-code-pro.css" diff --git a/chartered-frontend/src/util.tsx b/chartered-frontend/src/util.tsx index 8b3da03..23b861c 100644 --- a/chartered-frontend/src/util.tsx +++ a/chartered-frontend/src/util.tsx @@ -1,4 +1,5 @@ import React = require("react"); +import ReactPlaceholder from "react-placeholder"; import { AuthContext } from "./useAuth"; export const BASE_URL = "http://localhost:8888"; @@ -37,4 +38,20 @@ }, reloadOn); return { response, error }; +} + +export function RoundedPicture({ src, height, width, className }: { src: string, height: string, width: string, className?: string }) { + const [imageLoaded, setImageLoaded] = React.useState(false); + + return ( +
+ <> + setImageLoaded(true)} + className="rounded-circle" + /> +
+ ); } diff --git a/chartered-frontend/src/pages/crate/CrateView.tsx b/chartered-frontend/src/pages/crate/CrateView.tsx index c0d5f96..c0eae91 100644 --- a/chartered-frontend/src/pages/crate/CrateView.tsx +++ a/chartered-frontend/src/pages/crate/CrateView.tsx @@ -19,7 +19,7 @@ Square, } from "react-bootstrap-icons"; import { useParams, NavLink, Redirect, Link } from "react-router-dom"; -import { authenticatedEndpoint, useAuthenticatedRequest } from "../../util"; +import { authenticatedEndpoint, RoundedPicture, RoundedPicture, useAuthenticatedRequest } from "../../util"; import Prism from "react-syntax-highlighter/dist/cjs/prism"; import ReactMarkdown from "react-markdown"; @@ -374,9 +374,11 @@
By - {version.uploader}
diff --git a/chartered-frontend/src/pages/crate/Members.tsx b/chartered-frontend/src/pages/crate/Members.tsx index 40df340..0ab68c1 100644 --- a/chartered-frontend/src/pages/crate/Members.tsx +++ a/chartered-frontend/src/pages/crate/Members.tsx @@ -7,12 +7,13 @@ Save, PlusLg, } from "react-bootstrap-icons"; -import { authenticatedEndpoint, useAuthenticatedRequest } from "../../util"; +import { authenticatedEndpoint, RoundedPicture, RoundedPicture, useAuthenticatedRequest } from "../../util"; import { useAuth } from "../../useAuth"; import { Button, Modal } from "react-bootstrap"; import { AsyncTypeahead } from "react-bootstrap-typeahead"; import { debounce } from "lodash"; import _ = require("lodash"); +import ReactPlaceholder from "react-placeholder"; interface Member { uuid: string; @@ -203,7 +204,7 @@ - + @@ -310,10 +311,11 @@ ref={searchRef} renderMenuItemChildren={(option, props) => ( <> - {option.username} {option.username} diff --git a/chartered-frontend/src/pages/crate/OrganisationView.tsx b/chartered-frontend/src/pages/crate/OrganisationView.tsx index 1e69361..2020605 100644 --- a/chartered-frontend/src/pages/crate/OrganisationView.tsx +++ a/chartered-frontend/src/pages/crate/OrganisationView.tsx @@ -1,10 +1,10 @@ import React = require("react"); import { useState, useEffect } from "react"; import { Link, useParams } from "react-router-dom"; import Nav from "../../sections/Nav"; import { useAuth } from "../../useAuth"; -import { useAuthenticatedRequest, authenticatedEndpoint } from "../../util"; +import { useAuthenticatedRequest, authenticatedEndpoint, RoundedPicture } from "../../util"; import { BoxSeam, Plus, Trash } from "react-bootstrap-icons"; import { @@ -19,6 +19,7 @@ import ErrorPage from "../ErrorPage"; import Loading from "../Loading"; import Members from "./Members"; +import ReactPlaceholder from "react-placeholder"; interface OrganisationDetails { possible_permissions?: string[]; @@ -60,10 +61,11 @@ if (error) { return ; - } else if (!organisationDetails) { - return ; } + const ready = !!organisationDetails; + const [imageLoaded, setImageLoaded] = useState(false); + return (
diff --git a/chartered-frontend/src/pages/organisations/ListOrganisations.tsx b/chartered-frontend/src/pages/organisations/ListOrganisations.tsx index d878cc7..6ee604f 100644 --- a/chartered-frontend/src/pages/organisations/ListOrganisations.tsx +++ a/chartered-frontend/src/pages/organisations/ListOrganisations.tsx @@ -1,9 +1,9 @@ import React = require("react"); import { Link } from "react-router-dom"; import Nav from "../../sections/Nav"; import { useAuth } from "../../useAuth"; -import { useAuthenticatedRequest } from "../../util"; +import { RoundedPicture, useAuthenticatedRequest } from "../../util"; import ErrorPage from "../ErrorPage"; import Loading from "../Loading"; @@ -48,10 +48,7 @@ {list.organisations.map((v, i) => ( - + -- rgit 0.1.3