links: update for new groups layout

This commit is contained in:
Liam Fitzgerald 2020-09-25 10:44:10 +10:00
parent cf38904b81
commit 24c9067921
13 changed files with 275 additions and 83 deletions

View File

@ -5,7 +5,6 @@
|%
++ noun upd
++ json (update:enjs upd)
++ noun upd
--
::
++ grab

View File

@ -5,7 +5,7 @@ import { Path, Patp } from '~/types/noun';
export default class MetadataApi extends BaseApi<StoreState> {
metadataAdd(appName: string, appPath: Path, groupPath: Path, title: string, description: string, dateCreated: string, color: string) {
metadataAdd(appName: string, appPath: Path, groupPath: Path, title: string, description: string, dateCreated: string, color: string, module: string = '') {
const creator = `~${this.ship}`;
return this.metadataAction({
add: {
@ -19,7 +19,8 @@ export default class MetadataApi extends BaseApi<StoreState> {
description,
color,
'date-created': dateCreated,
creator
creator,
module
}
}
});

View File

@ -18,6 +18,19 @@ import LaunchReducer from '../reducers/launch-update';
import LinkListenReducer from '../reducers/listen-update';
import ConnectionReducer from '../reducers/connection';
export const homeAssociation = {
"app-path": "/home",
"app-name": "contact",
"group-path": "/home",
metadata: {
color: "0x0",
title: "Home",
description: "",
"date-created": "",
module: "",
},
};
export default class GlobalStore extends BaseStore<StoreState> {
inviteReducer = new InviteReducer();

View File

@ -38,7 +38,7 @@ export interface StoreState {
permissions: Permissions;
s3: S3State;
graphs: Graphs;
graphKeys: Set<String>;
graphKeys: Set<string>;
// App specific states

View File

@ -15,12 +15,12 @@ const chatSubscriptions: AppSubscription[] = [
];
const publishSubscriptions: AppSubscription[] = [
['/primary', 'publish'],
// ['/primary', 'publish'],
];
const linkSubscriptions: AppSubscription[] = [
['/json/seen', 'link-view'],
['/listening', 'link-listen-hook']
// ['/json/seen', 'link-view'],
// ['/listening', 'link-listen-hook']
]
const groupSubscriptions: AppSubscription[] = [

View File

@ -17,3 +17,4 @@ export * from './permission-update';
export * from './publish-response';
export * from './publish-update';
export * from './s3-update';
export * from './workspace';

View File

@ -51,4 +51,5 @@ interface Metadata {
'date-created': string;
description: string;
title: string;
module: string;
}

View File

@ -18,7 +18,7 @@ export type Serial = string;
export type Jug<K,V> = Map<K,Set<V>>;
// name of app
export type AppName = 'chat' | 'link' | 'contacts' | 'publish';
export type AppName = 'chat' | 'link' | 'contacts' | 'publish' | 'graph';
export function getTagFromFrond<O>(frond: O): keyof O {
const tags = Object.keys(frond) as Array<keyof O>;

View File

@ -1,12 +1,14 @@
import React from 'react';
import Helmet from 'react-helmet';
import { Link } from 'react-router-dom';
import { Box } from '@tlon/indigo-react';
import { Box, Row, Icon, Text } from '@tlon/indigo-react';
import './css/custom.css';
import Tiles from './components/tiles';
import Welcome from './components/welcome';
import Groups from './components/Groups';
export default class LaunchApp extends React.Component {
@ -25,8 +27,30 @@ export default class LaunchApp extends React.Component {
<title>OS1 - Home</title>
</Helmet>
<div className="h-100 flex flex-column h-100">
<div className='v-mid ph2 dtc-m dtc-l dtc-xl flex justify-between flex-wrap' style={{ maxWidth: '40rem' }}>
<Welcome firstTime={props.launch.firstTime} api={props.api} />
<Welcome firstTime={props.launch.firstTime} api={props.api} />
<Row flexWrap="wrap" mb={4} pitch={4}>
<Box
border={1}
borderRadius={1}
borderColor="lightGray"
m={2}
bg="white"
width="126px"
height="126px"
>
<Link to='/~groups/home'>
<Box p={2} bg="washedGreen" width="100%" height="100%">
<Row alignItems="center">
<Icon
stroke="green"
fill="rgba(0,0,0,0)"
icon="CircleDot"
/>
<Text ml="1" color="green">Home</Text>
</Row>
</Box>
</Link>
</Box>
<Tiles
tiles={props.launch.tiles}
tileOrdering={props.launch.tileOrdering}
@ -34,7 +58,8 @@ export default class LaunchApp extends React.Component {
location={props.userLocation}
weather={props.weather}
/>
</div>
</Row>
<Groups associations={props.associations} />
<Box
position="absolute"
fontFamily="mono"

View File

@ -10,7 +10,9 @@ export default class Tiles extends React.PureComponent {
const { props } = this;
const tiles = props.tileOrdering.filter((key) => {
return props.tiles[key].isShown;
const tile = props.tiles[key];
return tile.isShown;
}).map((key) => {
const tile = props.tiles[key];
if ('basic' in tile.type) {

View File

@ -0,0 +1,144 @@
import React, { useEffect } from "react";
import { Box, Row, Col, Center } from "@tlon/indigo-react";
import { Switch, Route, Link } from "react-router-dom";
import GlobalApi from "~/logic/api/global";
import { StoreState } from "~/logic/store/type";
import { Association, GraphNode } from "~/types";
import { RouteComponentProps } from "react-router-dom";
import { LinkList } from "./components/link-list";
import { LinkDetail } from "./components/link-detail";
import { LinkItem } from "./components/lib/link-item";
import { LinkSubmit } from "./components/lib/link-submit";
import { LinkPreview } from "./components/lib/link-preview";
import { CommentSubmit } from "./components/lib/comment-submit";
import { Comments } from "./components/lib/comments";
import "./css/custom.css";
type LinkResourceProps = StoreState & {
association: Association;
api: GlobalApi;
baseUrl: string;
} & RouteComponentProps;
export function LinkResource(props: LinkResourceProps) {
const {
association,
api,
baseUrl,
graphs,
contacts,
groups,
associations,
graphKeys,
s3,
hideAvatars,
hideNicknames,
remoteContentPolicy,
} = props;
const appPath = association["app-path"];
const relativePath = (p: string) => `${baseUrl}/resource/link${appPath}${p}`;
const [, , ship, name] = appPath.split("/");
const resourcePath = `${ship.slice(1)}/${name}`;
const resource = associations.graph[resourcePath]
? associations.graph[resourcePath]
: { metadata: {} };
const contactDetails = contacts[resource["group-path"]] || {};
const popout = props.match.url.includes("/popout/");
const graph = graphs[resourcePath] || null;
useEffect(() => {
api.graph.getGraph(ship, name);
}, [association]);
const resourceUrl = `${baseUrl}/resource/link${appPath}`;
if (!graph) {
return <Center>Loading...</Center>;
}
return (
<Col alignItems="center" height="100%" width="100%" overflowY="auto">
<Switch>
<Route
exact
path={relativePath("")}
render={(props) => {
return (
<Col width="100%" p={3} alignItems="center" maxWidth="640px">
<Row>
<LinkSubmit name={name} ship={ship.slice(1)} api={api} />
</Row>
{Array.from(graph.values()).map((node: GraphNode) => {
const contact = contactDetails[node.post.author];
return (
<LinkItem
resource={resourcePath}
node={node}
nickname={contact?.nickname}
hideAvatars={hideAvatars}
hideNicknames={hideNicknames}
baseUrl={resourceUrl}
/>
);
})}
</Col>
);
}}
/>
<Route
path={relativePath("/:index")}
render={(props) => {
const indexArr = props.match.params.index.split("-");
if (indexArr.length <= 1) {
return <div>Malformed URL</div>;
}
const index = parseInt(indexArr[1], 10);
const node = !!graph ? graph.get(index) : null;
if (!node) {
return <Box>Not found</Box>;
}
const contact = contactDetails[node.post.author];
return (
<Col width="100%" p={3} maxWidth="640px">
<Link to={resourceUrl}>{"<- Back"}</Link>
<LinkPreview
resourcePath={resourcePath}
post={node.post}
nickname={contact?.nickname}
hideNicknames={hideNicknames}
commentNumber={node.children.size}
/>
<Row>
<CommentSubmit
name={name}
ship={ship}
api={api}
parentIndex={node.post.index}
/>
</Row>
<Comments
comments={node.children}
resourcePath={resourcePath}
contacts={contactDetails}
popout={false}
api={api}
hideAvatars={hideAvatars}
hideNicknames={hideNicknames}
/>
</Col>
);
}}
/>
</Switch>
</Col>
);
}

View File

@ -1,4 +1,5 @@
import React, { Component } from 'react';
import { Row, Col, Anchor, Box, Text } from '@tlon/indigo-react';
import { Sigil } from '~/logic/lib/sigil';
import { Link } from 'react-router-dom';
@ -24,32 +25,43 @@ export const LinkItem = (props) => {
const mono = showNickname ? 'inter white-d' : 'mono white-d';
const img = showAvatar
? <img src={props.avatar} height={38} width={38} className="dib" />
: <Sigil ship={`~${author}`} size={38} color={'#' + props.color} />;
? <img src={props.avatar} height={36} width={36} className="dib" />
: <Sigil ship={`~${author}`} size={36} color={'#' + props.color} />;
const baseUrl = props.baseUrl || `/~link/${resource}`;
let hostname = '';
try {
const url = new URL(contents[1].url);
hostname = url.hostname;
} catch (e) {}
return (
<div className="w-100 pv3 flex bg-white bg-gray0-d lh-solid">
<Row alignItems="center" py={3} bg="white">
{img}
<div className="flex flex-column ml2 flex-auto">
<a href={contents[1].url}
className="w-100 flex"
target="_blank"
rel="noopener noreferrer">
<p className="f8 truncate">{props.title}</p>
<span className="gray2 dib v-btm ml2 f8 flex-shrink-0">
{contents[0].text}
</span>
</a>
<div className="w-100">
<span className={'f9 pr2 pl2 dib ' + mono} title={author}>
{ showNickname ? nickname : cite(author) }
</span>
<Link to={`/~link/${resource}/${index}`}>
<span className="f9 inter gray2 dib">{size} comments</span>
<Col height="100%" justifyContent="space-between" ml={2}>
<Anchor
lineHeight="tall"
textDecoration="none"
href={contents[1].url}
width="100%"
target="_blank"
rel="noopener noreferrer">
<Text> {contents[0].text}</Text>
<Text ml="2" color="gray">{hostname} </Text>
</Anchor>
<Box width="100%">
<Text
fontFamily={showNickname ? 'sans' : 'mono'} pr={2}>
{showNickname ? nickname : cite(author) }
</Text>
<Link to={`${baseUrl}/${index}`}>
<Text color="gray">{size} comments</Text>
</Link>
</div>
</div>
</div>
</Box>
</Col>
</Row>
);
}

View File

@ -1,54 +1,53 @@
import React, { Component, useEffect } from 'react';
import React, { Component, useEffect } from "react";
import { TabBar } from '~/views/components/chat-link-tabbar';
import { SidebarSwitcher } from '~/views/components/SidebarSwitch';
import { Link } from 'react-router-dom';
import { LinkItem } from './lib/link-item';
import { LinkSubmit } from './lib/link-submit';
import { TabBar } from "~/views/components/chat-link-tabbar";
import { SidebarSwitcher } from "~/views/components/SidebarSwitch";
import { Link } from "react-router-dom";
import { LinkItem } from "./lib/link-item";
import { LinkSubmit } from "./lib/link-submit";
import { getContactDetails } from '~/logic/lib/util';
import { getContactDetails } from "~/logic/lib/util";
export const LinkList = (props) => {
const resource = `${props.ship}/${props.name}`;
const title = props.metadata.title || resource;
useEffect(() => {
props.api.graph.getGraph(
`~${props.match.params.ship}`,
props.match.params.name
);
}, [props.match.params.ship, props.match.params.name]);
if (!props.graph && props.graphResource) {
useEffect(() => {
props.api.graph.getGraph(
`~${props.match.params.ship}`,
props.match.params.name
);
});
return (
<div>Loading...</div>
);
return <div>Loading...</div>;
}
if (!props.graph) {
return (
<div>Not found</div>
);
return <div>Not found</div>;
}
return (
<div className="h-100 w-100 overflow-hidden flex flex-column">
<div
className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8"
style={{ height: '1rem' }}>
<Link to="/~link">{'⟵ All Channels'}</Link>
style={{ height: "1rem" }}
>
<Link to="/~link">{"⟵ All Channels"}</Link>
</div>
<div className={
'pl4 pt2 flex relative overflow-x-scroll' +
'overflow-x-auto-l overflow-x-auto-xl flex-shrink-0' +
'bb b--gray4 b--gray1-d bg-gray0-d'
}
style={{ height: 48 }}>
<div
className={
"pl4 pt2 flex relative overflow-x-scroll" +
"overflow-x-auto-l overflow-x-auto-xl flex-shrink-0" +
"bb b--gray4 b--gray1-d bg-gray0-d"
}
style={{ height: 48 }}
>
<SidebarSwitcher
sidebarShown={props.sidebarShown}
popout={props.popout}
api={props.api} />
<h2 className='white-d dib f9 fw4 lh-solid v-top pt2'>{title}</h2>
api={props.api}
/>
<h2 className="white-d dib f9 fw4 lh-solid v-top pt2">{title}</h2>
<TabBar
location={props.location}
popout={props.popout}
@ -59,26 +58,21 @@ export const LinkList = (props) => {
<div className="w-100 mt6 flex justify-center overflow-y-scroll ph4 pb4">
<div className="w-100 mw7">
<div className="flex">
<LinkSubmit
name={props.name}
ship={props.ship}
api={props.api} />
<LinkSubmit name={props.name} ship={props.ship} api={props.api} />
</div>
{ Array.from(props.graph.values()).map((node) => {
return (
<LinkItem
resource={resource}
node={node}
nickname={props.metadata.nickname}
hideAvatars={props.hideAvatars}
hideNicknames={props.hideNicknames}
/>
);
})
}
{Array.from(props.graph.values()).map((node) => {
return (
<LinkItem
resource={resource}
node={node}
nickname={props.metadata.nickname}
hideAvatars={props.hideAvatars}
hideNicknames={props.hideNicknames}
/>
);
})}
</div>
</div>
</div>
);
}
};