mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-14 17:41:33 +03:00
links: update for new groups layout
This commit is contained in:
parent
cf38904b81
commit
24c9067921
@ -5,7 +5,6 @@
|
||||
|%
|
||||
++ noun upd
|
||||
++ json (update:enjs upd)
|
||||
++ noun upd
|
||||
--
|
||||
::
|
||||
++ grab
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -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();
|
||||
|
@ -38,7 +38,7 @@ export interface StoreState {
|
||||
permissions: Permissions;
|
||||
s3: S3State;
|
||||
graphs: Graphs;
|
||||
graphKeys: Set<String>;
|
||||
graphKeys: Set<string>;
|
||||
|
||||
|
||||
// App specific states
|
||||
|
@ -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[] = [
|
||||
|
@ -17,3 +17,4 @@ export * from './permission-update';
|
||||
export * from './publish-response';
|
||||
export * from './publish-update';
|
||||
export * from './s3-update';
|
||||
export * from './workspace';
|
||||
|
@ -51,4 +51,5 @@ interface Metadata {
|
||||
'date-created': string;
|
||||
description: string;
|
||||
title: string;
|
||||
module: string;
|
||||
}
|
||||
|
@ -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>;
|
||||
|
@ -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} />
|
||||
<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"
|
||||
|
@ -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) {
|
||||
|
144
pkg/interface/src/views/apps/links/LinkResource.tsx
Normal file
144
pkg/interface/src/views/apps/links/LinkResource.tsx
Normal 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>
|
||||
);
|
||||
}
|
@ -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"
|
||||
<Col height="100%" justifyContent="space-between" ml={2}>
|
||||
<Anchor
|
||||
lineHeight="tall"
|
||||
textDecoration="none"
|
||||
href={contents[1].url}
|
||||
width="100%"
|
||||
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>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
if (!props.graph && props.graphResource) {
|
||||
useEffect(() => {
|
||||
props.api.graph.getGraph(
|
||||
`~${props.match.params.ship}`,
|
||||
props.match.params.name
|
||||
);
|
||||
});
|
||||
}, [props.match.params.ship, props.match.params.name]);
|
||||
|
||||
return (
|
||||
<div>Loading...</div>
|
||||
);
|
||||
if (!props.graph && props.graphResource) {
|
||||
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'
|
||||
<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 }}>
|
||||
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,12 +58,9 @@ 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) => {
|
||||
{Array.from(props.graph.values()).map((node) => {
|
||||
return (
|
||||
<LinkItem
|
||||
resource={resource}
|
||||
@ -74,11 +70,9 @@ export const LinkList = (props) => {
|
||||
hideNicknames={props.hideNicknames}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user