From 63515c573a8b955756cd5b1953887e2c8e141862 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Wed, 25 Aug 2021 17:45:20 +1000 Subject: [PATCH] grid: lag, blocking from kiln --- pkg/grid/src/nav/Nav.tsx | 2 + pkg/grid/src/nav/Notifications.tsx | 126 ++++-------------- pkg/grid/src/nav/Search.tsx | 4 +- .../nav/notifications/SystemNotification.tsx | 52 ++++++-- pkg/grid/src/nav/search/Apps.tsx | 7 +- pkg/grid/src/nav/search/Home.tsx | 12 +- .../search/{AppInfo.tsx => TreatyInfo.tsx} | 33 ++--- pkg/grid/src/pages/Grid.tsx | 22 +-- pkg/grid/src/tiles/TileInfo.tsx | 21 +++ 9 files changed, 123 insertions(+), 156 deletions(-) rename pkg/grid/src/nav/search/{AppInfo.tsx => TreatyInfo.tsx} (71%) create mode 100644 pkg/grid/src/tiles/TileInfo.tsx diff --git a/pkg/grid/src/nav/Nav.tsx b/pkg/grid/src/nav/Nav.tsx index 22fadc5438..3e04e162d9 100644 --- a/pkg/grid/src/nav/Nav.tsx +++ b/pkg/grid/src/nav/Nav.tsx @@ -40,6 +40,8 @@ export const useLeapStore = create((set) => ({ }) })); +window.leap = useLeapStore.getState; + export type MenuState = | 'closed' | 'search' diff --git a/pkg/grid/src/nav/Notifications.tsx b/pkg/grid/src/nav/Notifications.tsx index 2c79315a5a..fce72b485f 100644 --- a/pkg/grid/src/nav/Notifications.tsx +++ b/pkg/grid/src/nav/Notifications.tsx @@ -1,105 +1,23 @@ -import React, { FC, useEffect, useState } from 'react'; -import cn from 'classnames'; +import React, { useEffect } from 'react'; import { Link } from 'react-router-dom'; import { useLeapStore } from './Nav'; import { useBlockers, useLag } from '../state/kiln'; -import { useCharge } from '../state/docket'; -import { DocketImage } from '../components/DocketImage'; -import api from '../state/api'; -import { kilnSuspend } from '../../../npm/api/hood'; import { Button } from '../components/Button'; import { useHarkStore } from '../state/hark'; import { Notification } from '../state/hark-types'; import { BasicNotification } from './notifications/BasicNotification'; -import { SystemNotification } from './notifications/SystemNotification'; - -interface INotification { - title: string; - body: string; - actions: { - title: string; - role: 'primary' | 'destructive' | 'none'; - link: string; - }[]; -} - -interface NotificationProps { - notification?: INotification; - read?: boolean; - className?: string; - children?: React.ReactNode; -} - -const Notification: FC = ({ className, children }) => ( -
{children}
-); - -const LagNotification = () => ( - -

- The runtime of this ship is out of date, and preventing a kernel upgrade. Please upgrade to - the latest runtime version. If you are hosted, please contact your hosting provider -

-
-); - -const DeskIcon = ({ desk }) => { - const { title, image, color } = useCharge(desk); - - return ( -
- -

{title}

-
- ); -}; - -interface BlockNotificationProps { - desks: string[]; -} -const BlockNotification: React.FC = ({ desks }) => { - const count = desks.length; - const [dismissed, setDismissed] = useState(false); - const onArchive = async () => { - await Promise.all(desks.map((d) => api.poke(kilnSuspend(d)))); - }; - - if (dismissed) { - return null; - } - return ( - -

The following {desks.length} apps blocked a System Update:

-
- {desks.map((desk) => ( - - ))} -
-

- In order to proceed with the System Update, you’ll need to temporarily archive these apps, - which will render them unusable, but with data intact. -
-
- Archived apps will automatically un-archive and resume operation when their developer - provides an app update. -

-
- - -
-
- ); -}; +import { + BaseBlockedNotification, + RuntimeLagNotification +} from './notifications/SystemNotification'; function renderNotification(notification: Notification, key: string) { if (notification.type === 'system-updates-blocked') { - return ; + return ; + } + if (notification.type === 'runtime-lag') { + return ; } - return ; } @@ -109,22 +27,31 @@ const Empty = () => ( ); +function getSystemNotifications(lag: boolean, blockers: string[]) { + const nots = [] as Notification[]; + if (lag) { + nots.push({ type: 'runtime-lag' }); + } + if (blockers.length > 0) { + nots.push({ type: 'system-updates-blocked', desks: blockers }); + } + return nots; +} + export const Notifications = () => { const select = useLeapStore((s) => s.select); const notifications = useHarkStore((s) => s.notifications); - const hasNotifications = notifications.length > 0; + const blockers = useBlockers(); + const lag = useLag(); + const systemNotifications = getSystemNotifications(lag, blockers); + const hasNotifications = notifications.length > 0 || systemNotifications.length > 0; useEffect(() => { select('Notifications'); }, []); - const blockers = useBlockers(); - const lag = useLag(); - return (
- {lag && } - {blockers.length > 0 ? : null}
diff --git a/pkg/grid/src/nav/Search.tsx b/pkg/grid/src/nav/Search.tsx index b3e746cfc6..455333b281 100644 --- a/pkg/grid/src/nav/Search.tsx +++ b/pkg/grid/src/nav/Search.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Route, RouteComponentProps, Switch } from 'react-router-dom'; -import { AppInfo } from './search/AppInfo'; +import { TreatyInfo } from './search/TreatyInfo'; import { Apps } from './search/Apps'; import { Home } from './search/Home'; import { Providers } from './search/Providers'; @@ -12,7 +12,7 @@ type SearchProps = RouteComponentProps<{ export const Search = ({ match }: SearchProps) => { return ( - + diff --git a/pkg/grid/src/nav/notifications/SystemNotification.tsx b/pkg/grid/src/nav/notifications/SystemNotification.tsx index e65ca03cd8..2f627781a6 100644 --- a/pkg/grid/src/nav/notifications/SystemNotification.tsx +++ b/pkg/grid/src/nav/notifications/SystemNotification.tsx @@ -1,30 +1,58 @@ import { pick } from 'lodash-es'; import React, { useCallback } from 'react'; +import { kilnSuspend } from '@urbit/api/hood'; import { AppList } from '../../components/AppList'; import { Button } from '../../components/Button'; import { Dialog, DialogClose, DialogContent, DialogTrigger } from '../../components/Dialog'; import { Elbow } from '../../components/icons/Elbow'; +import api from '../../state/api'; import { useCharges } from '../../state/docket'; -import { SystemNotification as SystemNotificationType } from '../../state/hark-types'; +import { + BaseBlockedNotification as BaseBlockedNotificationType, +} from '../../state/hark-types'; + import { NotificationButton } from './NotificationButton'; -interface SystemNotificationProps { - notification: SystemNotificationType; +interface BaseBlockedNotificationProps { + notification: BaseBlockedNotificationType; } -export const SystemNotification = ({ notification }: SystemNotificationProps) => { - const keys = notification.charges; +export const RuntimeLagNotification = () => ( +
+
+
+ + Landscape +
+
+ +

The runtime blocked a System Update

+
+
+
+

+ In order to proceed with the System Update, you’ll need to upgrade the runtime. If you are + using a hosted ship, you should contact your hosting provider. +

+
+
+); + +export const BaseBlockedNotification = ({ notification }: BaseBlockedNotificationProps) => { + const { desks } = notification; const charges = useCharges(); - const blockedCharges = Object.values(pick(charges, keys)); + const blockedCharges = Object.values(pick(charges, desks)); const count = blockedCharges.length; - const handlePauseOTAs = useCallback(() => { - console.log('pause updates'); - }, []); + const handlePauseOTAs = useCallback(() => {}, []); - const handleArchiveApps = useCallback(() => { - console.log('archive apps'); - }, []); + const handleArchiveApps = useCallback(async () => { + await Promise.all(desks.map(d => api.poke(kilnSuspend(d)))); + // TODO: retrigger OTA? + }, [desks]); return (
{ })); const provider = match?.params.ship; const treaties = useAllyTreaties(provider); + console.log(treaties); const results = useMemo(() => { if (!treaties) { return undefined; @@ -46,12 +47,14 @@ export const Apps = ({ match }: AppsProps) => { const count = results?.length; useEffect(() => { + const { fetchAllyTreaties } = useDocketState.getState(); + fetchAllyTreaties(provider); select( <> Apps by ); - }, []); + }, [provider]); useEffect(() => { if (results) { @@ -82,7 +85,7 @@ export const Apps = ({ match }: AppsProps) => { apps={results} labelledBy="developed-by" matchAgainst={selectedMatch} - to={(app) => `${match?.path.replace(':ship', provider)}/${slugify(app.base)}`} + to={(app) => `${match?.path.replace(':ship', provider)}/${app.ship}/${slugify(app.desk)}`} /> )}

That's it!

diff --git a/pkg/grid/src/nav/search/Home.tsx b/pkg/grid/src/nav/search/Home.tsx index 1d62418874..7e69cb848c 100644 --- a/pkg/grid/src/nav/search/Home.tsx +++ b/pkg/grid/src/nav/search/Home.tsx @@ -58,9 +58,19 @@ export const useRecentsStore = create( ) ); +window.recents = useRecentsStore.getState; + +export function addRecentDev(dev: Provider) { + return useRecentsStore.getState().addRecentDev(dev); +} + +export function addRecentApp(docket: Docket) { + return useRecentsStore.getState().addRecentApp(docket); +} + export const Home = () => { const selectedMatch = useLeapStore((state) => state.selectedMatch); - const { recentApps, recentDevs, addRecentApp, addRecentDev } = useRecentsStore(); + const { recentApps, recentDevs } = useRecentsStore(); const charges = useCharges(); const groups = charges?.groups; const zod = { shipName: '~zod' }; diff --git a/pkg/grid/src/nav/search/AppInfo.tsx b/pkg/grid/src/nav/search/TreatyInfo.tsx similarity index 71% rename from pkg/grid/src/nav/search/AppInfo.tsx rename to pkg/grid/src/nav/search/TreatyInfo.tsx index 89f5239e74..d4de7e79e0 100644 --- a/pkg/grid/src/nav/search/AppInfo.tsx +++ b/pkg/grid/src/nav/search/TreatyInfo.tsx @@ -1,27 +1,17 @@ -import { chadIsRunning } from '@urbit/api/docket'; -import clipboardCopy from 'clipboard-copy'; import React, { useEffect } from 'react'; import { useParams } from 'react-router-dom'; -import { Button, PillButton } from '../../components/Button'; -import { Dialog, DialogClose, DialogContent, DialogTrigger } from '../../components/Dialog'; -import { DocketHeader } from '../../components/DocketHeader'; +import { AppInfo } from '../../components/AppInfo'; import { ShipName } from '../../components/ShipName'; -import { Spinner } from '../../components/Spinner'; -import { TreatyMeta } from '../../components/TreatyMeta'; -import useDocketState, { useCharges, useTreaty } from '../../state/docket'; -import { getAppHref } from '../../state/util'; +import { useCharge, useTreaty } from '../../state/docket'; +import { useVat } from '../../state/kiln'; import { useLeapStore } from '../Nav'; -import { useRecentsStore } from './Home'; -export const AppInfo = () => { - const addRecentApp = useRecentsStore((state) => state.addRecentApp); +export const TreatyInfo = () => { const select = useLeapStore((state) => state.select); const { ship, host, desk } = useParams<{ ship: string; host: string; desk: string }>(); const treaty = useTreaty(host, desk); - const charges = useCharges(); - const charge = (charges || {})[desk]; - const installed = charge && chadIsRunning(charge.chad); - const installing = charge && 'install' in charge.chad; + const vat = useVat(desk); + const charge = useCharge(desk); useEffect(() => { select( @@ -31,13 +21,6 @@ export const AppInfo = () => { ); }, [treaty?.title]); - const installApp = async () => { - await useDocketState.getState().installDocket(ship, desk); - }; - const copyApp = () => { - clipboardCopy(`web+urbitgraph://app/${ship}/${desk}`); - }; - if (!treaty) { // TODO: maybe replace spinner with skeletons return ( @@ -46,8 +29,11 @@ export const AppInfo = () => { ); } + return ; + /* return ( +
@@ -100,4 +86,5 @@ export const AppInfo = () => {
); + */ }; diff --git a/pkg/grid/src/pages/Grid.tsx b/pkg/grid/src/pages/Grid.tsx index 955bfff367..13bf098b3f 100644 --- a/pkg/grid/src/pages/Grid.tsx +++ b/pkg/grid/src/pages/Grid.tsx @@ -1,14 +1,13 @@ import { map, omit } from 'lodash-es'; import React, { FunctionComponent, useEffect } from 'react'; import { Route, RouteComponentProps } from 'react-router-dom'; -import { KilnDiff } from '@urbit/api/hood'; import { MenuState, Nav } from '../nav/Nav'; import useDocketState, { useCharges } from '../state/docket'; import { useKilnState } from '../state/kiln'; import { RemoveApp } from '../tiles/RemoveApp'; import { SuspendApp } from '../tiles/SuspendApp'; import { Tile } from '../tiles/Tile'; -import api from '../state/api'; +import { TileInfo } from '../tiles/TileInfo'; type GridProps = RouteComponentProps<{ menu?: MenuState; @@ -25,22 +24,6 @@ export const Grid: FunctionComponent = ({ match }) => { fetchAllies(); fetchVats(); fetchLag(); - api - .subscribe({ - app: 'hood', - path: '/kiln/vats', - event: (data: KilnDiff) => { - console.log(data); - }, - err: () => {}, - quit: () => {} - }) - .catch((e) => { - console.log(e); - }) - .then((r) => { - console.log(r); - }); }, []); return ( @@ -59,6 +42,9 @@ export const Grid: FunctionComponent = ({ match }) => { ))}
)} + + + diff --git a/pkg/grid/src/tiles/TileInfo.tsx b/pkg/grid/src/tiles/TileInfo.tsx new file mode 100644 index 0000000000..1d2f915510 --- /dev/null +++ b/pkg/grid/src/tiles/TileInfo.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { useHistory, useParams } from 'react-router-dom'; +import { Dialog, DialogContent } from '../components/Dialog'; +import { AppInfo } from '../components/AppInfo'; +import { useCharge } from '../state/docket'; +import { useVat } from '../state/kiln'; + +export const TileInfo = () => { + const { desk } = useParams<{ desk: string }>(); + const { push } = useHistory(); + const charge = useCharge(desk); + const vat = useVat(desk); + + return ( + !open && push('/')}> + + + + + ); +};