mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-12 15:01:38 +03:00
Merge pull request #4345 from urbit/mp/profile/stubs
profile: more stubs
This commit is contained in:
commit
6927327c7f
@ -1,6 +1,6 @@
|
|||||||
/- spider,
|
/- spider,
|
||||||
graph=graph-store,
|
graph=graph-store,
|
||||||
*metadata-store,
|
met=metadata-store,
|
||||||
*group,
|
*group,
|
||||||
group-store,
|
group-store,
|
||||||
inv=invite-store
|
inv=invite-store
|
||||||
@ -57,18 +57,18 @@
|
|||||||
::
|
::
|
||||||
:: Setup metadata
|
:: Setup metadata
|
||||||
::
|
::
|
||||||
=/ =metadata
|
=/ =metadatum:met
|
||||||
%* . *metadata
|
%* . *metadatum:met
|
||||||
title title.action
|
title title.action
|
||||||
description description.action
|
description description.action
|
||||||
date-created now.bowl
|
date-created now.bowl
|
||||||
creator our.bowl
|
creator our.bowl
|
||||||
module module.action
|
module module.action
|
||||||
==
|
==
|
||||||
=/ =metadata-action
|
=/ met-action=action:met
|
||||||
[%add group graph+rid.action metadata]
|
[%add group graph+rid.action metadatum]
|
||||||
;< ~ bind:m
|
;< ~ bind:m
|
||||||
(poke-our %metadata-store %metadata-action !>(metadata-action))
|
(poke-our %metadata-store %metadata-action !>(met-action))
|
||||||
;< ~ bind:m
|
;< ~ bind:m
|
||||||
(poke-our %metadata-push-hook %push-hook-action !>([%add group]))
|
(poke-our %metadata-push-hook %push-hook-action !>([%add group]))
|
||||||
::
|
::
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/- spider, graph-view, graph=graph-store, *metadata-store, *group
|
/- spider, graph-view, graph=graph-store, met=metadata-store, *group
|
||||||
/+ strandio, resource
|
/+ strandio, resource
|
||||||
=>
|
=>
|
||||||
|%
|
|%
|
||||||
@ -9,16 +9,14 @@
|
|||||||
++ scry-metadata
|
++ scry-metadata
|
||||||
|= rid=resource
|
|= rid=resource
|
||||||
=/ m (strand ,(unit resource))
|
=/ m (strand ,(unit resource))
|
||||||
;< paxs=(unit (set path)) bind:m
|
;< group=(unit resource) bind:m
|
||||||
%+ scry:strandio ,(unit (set path))
|
%+ scry:strandio ,(unit resource)
|
||||||
;: weld
|
;: weld
|
||||||
/gx/metadata-store/resource/graph
|
/gx/metadata-store/resource/graph
|
||||||
(en-path:resource rid)
|
(en-path:resource rid)
|
||||||
/noun
|
/noun
|
||||||
==
|
==
|
||||||
?~ paxs (pure:m ~)
|
(pure:m group)
|
||||||
?~ u.paxs (pure:m ~)
|
|
||||||
(pure:m `(de-path:resource n.u.paxs))
|
|
||||||
::
|
::
|
||||||
++ scry-group
|
++ scry-group
|
||||||
|= rid=resource
|
|= rid=resource
|
||||||
@ -42,11 +40,7 @@
|
|||||||
;< ~ bind:m
|
;< ~ bind:m
|
||||||
(poke-our %graph-push-hook %push-hook-action !>([%remove rid]))
|
(poke-our %graph-push-hook %push-hook-action !>([%remove rid]))
|
||||||
;< ~ bind:m
|
;< ~ bind:m
|
||||||
%+ poke-our %metadata-hook
|
(poke-our %metadata-push-hook %push-hook-action !>([%remove rid]))
|
||||||
:- %metadata-action
|
|
||||||
!> :+ %remove
|
|
||||||
(en-path:resource group-rid)
|
|
||||||
[%graph (en-path:resource rid)]
|
|
||||||
(pure:m ~)
|
(pure:m ~)
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
@ -74,6 +68,5 @@
|
|||||||
(poke-our %group-push-hook %push-hook-action !>([%remove rid.action]))
|
(poke-our %group-push-hook %push-hook-action !>([%remove rid.action]))
|
||||||
;< ~ bind:m (delete-graph u.ugroup-rid rid.action)
|
;< ~ bind:m (delete-graph u.ugroup-rid rid.action)
|
||||||
;< ~ bind:m
|
;< ~ bind:m
|
||||||
%+ poke-our %metadata-hook
|
(poke-our %metadata-push-hook %push-hook-action !>([%remove rid.action]))
|
||||||
metadata-hook-action+!>([%remove (en-path:resource u.ugroup-rid)])
|
|
||||||
(pure:m !>(~))
|
(pure:m !>(~))
|
||||||
|
@ -22,6 +22,8 @@ export default class ContactsApi extends BaseApi<StoreState> {
|
|||||||
{color: 'fff'} // with no 0x prefix
|
{color: 'fff'} // with no 0x prefix
|
||||||
{avatar: null}
|
{avatar: null}
|
||||||
{avatar: ''}
|
{avatar: ''}
|
||||||
|
{add-group: {ship, name}}
|
||||||
|
{remove-group: {ship, name}}
|
||||||
*/
|
*/
|
||||||
console.log(ship, editField);
|
console.log(ship, editField);
|
||||||
return this.storeAction({
|
return this.storeAction({
|
||||||
|
@ -116,7 +116,7 @@ export default function index(contacts, associations, apps, currentGroup, groups
|
|||||||
title,
|
title,
|
||||||
`/~landscape${group}/join/${app}${each.resource}`,
|
`/~landscape${group}/join/${app}${each.resource}`,
|
||||||
app.charAt(0).toUpperCase() + app.slice(1),
|
app.charAt(0).toUpperCase() + app.slice(1),
|
||||||
(associations?.contacts?.[each.group]?.metadata?.title || null)
|
(associations?.groups?.[each.group]?.metadata?.title || null)
|
||||||
);
|
);
|
||||||
subscriptions.push(obj);
|
subscriptions.push(obj);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ export function getTitleFromWorkspace(
|
|||||||
case "home":
|
case "home":
|
||||||
return "DMs + Drafts";
|
return "DMs + Drafts";
|
||||||
case "group":
|
case "group":
|
||||||
const association = associations.contacts[workspace.group];
|
const association = associations.groups[workspace.group];
|
||||||
return association?.metadata?.title || "";
|
return association?.metadata?.title || "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ export type Serial = string;
|
|||||||
export type Jug<K,V> = Map<K,Set<V>>;
|
export type Jug<K,V> = Map<K,Set<V>>;
|
||||||
|
|
||||||
// name of app
|
// name of app
|
||||||
export type AppName = 'chat' | 'link' | 'contacts' | 'publish' | 'graph';
|
export type AppName = 'contacts' | 'groups' | 'graph';
|
||||||
|
|
||||||
export function getTagFromFrond<O>(frond: O): keyof O {
|
export function getTagFromFrond<O>(frond: O): keyof O {
|
||||||
const tags = Object.keys(frond) as Array<keyof O>;
|
const tags = Object.keys(frond) as Array<keyof O>;
|
||||||
|
@ -36,7 +36,7 @@ const getGraphNotifications = (associations: Associations, unreads: Unreads) =>
|
|||||||
export default function Groups(props: GroupsProps & Parameters<typeof Box>[0]) {
|
export default function Groups(props: GroupsProps & Parameters<typeof Box>[0]) {
|
||||||
const { associations, unreads, inbox, ...boxProps } = props;
|
const { associations, unreads, inbox, ...boxProps } = props;
|
||||||
|
|
||||||
const groups = Object.values(associations?.contacts || {})
|
const groups = Object.values(associations?.groups || {})
|
||||||
.filter((e) => e?.group in props.groups)
|
.filter((e) => e?.group in props.groups)
|
||||||
.sort(sortGroupsAlph);
|
.sort(sortGroupsAlph);
|
||||||
const graphUnreads = getGraphUnreads(associations || {}, unreads);
|
const graphUnreads = getGraphUnreads(associations || {}, unreads);
|
||||||
|
@ -63,7 +63,7 @@ export function Header(props: {
|
|||||||
|
|
||||||
const time = moment(props.time).format("HH:mm");
|
const time = moment(props.time).format("HH:mm");
|
||||||
const groupTitle =
|
const groupTitle =
|
||||||
props.associations.contacts?.[props.group]?.metadata?.title;
|
props.associations.groups?.[props.group]?.metadata?.title;
|
||||||
|
|
||||||
const app = props.chat ? 'chat' : 'graph';
|
const app = props.chat ? 'chat' : 'graph';
|
||||||
const channelTitle =
|
const channelTitle =
|
||||||
|
@ -31,7 +31,7 @@ export function Invites(props: InvitesProps) {
|
|||||||
const resourcePath = resourceAsPath(invite.resource);
|
const resourcePath = resourceAsPath(invite.resource);
|
||||||
if (app === "contacts") {
|
if (app === "contacts") {
|
||||||
await api.contacts.join(resource);
|
await api.contacts.join(resource);
|
||||||
await waiter((p) => resourcePath in p.associations?.contacts);
|
await waiter((p) => resourcePath in p.associations?.groups);
|
||||||
await api.invite.accept(app, uid);
|
await api.invite.accept(app, uid);
|
||||||
history.push(`/~landscape${resourcePath}`);
|
history.push(`/~landscape${resourcePath}`);
|
||||||
} else if (app === "graph") {
|
} else if (app === "graph") {
|
||||||
|
@ -44,7 +44,7 @@ export default function NotificationsScreen(props: any) {
|
|||||||
filter.groups.length === 0
|
filter.groups.length === 0
|
||||||
? "All"
|
? "All"
|
||||||
: filter.groups
|
: filter.groups
|
||||||
.map((g) => props.associations?.contacts?.[g]?.metadata?.title)
|
.map((g) => props.associations?.groups?.[g]?.metadata?.title)
|
||||||
.join(", ");
|
.join(", ");
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
|
@ -21,6 +21,8 @@ import { AsyncButton } from "~/views/components/AsyncButton";
|
|||||||
import { ColorInput } from "~/views/components/ColorInput";
|
import { ColorInput } from "~/views/components/ColorInput";
|
||||||
import { ImageInput } from "~/views/components/ImageInput";
|
import { ImageInput } from "~/views/components/ImageInput";
|
||||||
import { MarkdownField } from "~/views/apps/publish/components/MarkdownField";
|
import { MarkdownField } from "~/views/apps/publish/components/MarkdownField";
|
||||||
|
import { resourceFromPath } from "~/logic/lib/group";
|
||||||
|
import GroupSearch from "~/views/components/GroupSearch";
|
||||||
|
|
||||||
|
|
||||||
const formSchema = Yup.object({
|
const formSchema = Yup.object({
|
||||||
@ -62,8 +64,15 @@ export function EditProfile(props: any) {
|
|||||||
return acc.then(() =>
|
return acc.then(() =>
|
||||||
api.contacts.setPublic(newValue)
|
api.contacts.setPublic(newValue)
|
||||||
);
|
);
|
||||||
|
} else if (key === 'groups') {
|
||||||
|
newValue.map((e) => {
|
||||||
|
if (!contact['groups']?.[e]) {
|
||||||
|
return acc.then(() => {
|
||||||
|
api.contacts.edit(ship, { 'add-group': resourceFromPath(e) });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
} else if (
|
} else if (
|
||||||
key !== "groups" &&
|
|
||||||
key !== "last-updated" &&
|
key !== "last-updated" &&
|
||||||
key !== "isPublic"
|
key !== "isPublic"
|
||||||
) {
|
) {
|
||||||
@ -105,7 +114,8 @@ export function EditProfile(props: any) {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Checkbox mb={3} id="isPublic" label="Public Profile" />
|
<Checkbox mb={3} id="isPublic" label="Public Profile" />
|
||||||
<AsyncButton primary loadingText="Updating..." border>
|
<GroupSearch label="Pinned Groups" id="groups" groups={props.groups} associations={props.associations} />
|
||||||
|
<AsyncButton primary loadingText="Updating..." border mt={3}>
|
||||||
Submit
|
Submit
|
||||||
</AsyncButton>
|
</AsyncButton>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -66,6 +66,8 @@ export function Profile(props: any) {
|
|||||||
contact={contact}
|
contact={contact}
|
||||||
s3={props.s3}
|
s3={props.s3}
|
||||||
api={props.api}
|
api={props.api}
|
||||||
|
groups={props.groups}
|
||||||
|
associations={props.associations}
|
||||||
isPublic={isPublic}/>
|
isPublic={isPublic}/>
|
||||||
) : (
|
) : (
|
||||||
<ViewProfile ship={ship} contact={contact} isPublic={isPublic} />
|
<ViewProfile ship={ship} contact={contact} isPublic={isPublic} />
|
||||||
|
@ -45,6 +45,8 @@ export default function ProfileScreen(props: any) {
|
|||||||
<Box>
|
<Box>
|
||||||
<Profile
|
<Profile
|
||||||
ship={ship}
|
ship={ship}
|
||||||
|
associations={props.associations}
|
||||||
|
groups={props.groups}
|
||||||
contact={contact}
|
contact={contact}
|
||||||
api={props.api}
|
api={props.api}
|
||||||
s3={props.s3}
|
s3={props.s3}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useMemo, useCallback } from "react";
|
import React, { useMemo, useCallback, useState, useEffect } from 'react';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Text,
|
Text,
|
||||||
@ -6,17 +6,17 @@ import {
|
|||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
Icon,
|
Icon,
|
||||||
ErrorLabel,
|
ErrorLabel
|
||||||
} from "@tlon/indigo-react";
|
} from '@tlon/indigo-react';
|
||||||
import _ from "lodash";
|
import _ from 'lodash';
|
||||||
import { useField } from "formik";
|
import { useField } from 'formik';
|
||||||
import styled from "styled-components";
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import { roleForShip } from "~/logic/lib/group";
|
import { roleForShip } from '~/logic/lib/group';
|
||||||
|
|
||||||
import { DropdownSearch } from "./DropdownSearch";
|
import { DropdownSearch } from './DropdownSearch';
|
||||||
import { Groups } from "~/types";
|
import { Groups } from '~/types';
|
||||||
import { Associations, Association } from "~/types/metadata-update";
|
import { Associations, Association } from '~/types/metadata-update';
|
||||||
|
|
||||||
interface InviteSearchProps {
|
interface InviteSearchProps {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
@ -26,11 +26,12 @@ interface InviteSearchProps {
|
|||||||
label: string;
|
label: string;
|
||||||
caption?: string;
|
caption?: string;
|
||||||
id: string;
|
id: string;
|
||||||
|
maxLength?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CandidateBox = styled(Box)<{ selected: boolean }>`
|
const CandidateBox = styled(Box)<{ selected: boolean }>`
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: ${(p) => p.theme.colors.washedGray};
|
background-color: ${p => p.theme.colors.washedGray};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -64,38 +65,45 @@ function renderCandidate(
|
|||||||
|
|
||||||
export function GroupSearch(props: InviteSearchProps) {
|
export function GroupSearch(props: InviteSearchProps) {
|
||||||
const { id, caption, label } = props;
|
const { id, caption, label } = props;
|
||||||
|
const [selected, setSelected] = useState([] as string[]);
|
||||||
const groups: Association[] = useMemo(() => {
|
const groups: Association[] = useMemo(() => {
|
||||||
return props.adminOnly
|
return props.adminOnly
|
||||||
? Object.values(
|
? Object.values(
|
||||||
Object.keys(props.associations?.contacts)
|
Object.keys(props.associations?.groups)
|
||||||
.filter(
|
.filter(
|
||||||
(e) => roleForShip(props.groups[e], window.ship) === "admin"
|
e => roleForShip(props.groups[e], window.ship) === 'admin'
|
||||||
)
|
)
|
||||||
.reduce((obj, key) => {
|
.reduce((obj, key) => {
|
||||||
obj[key] = props.associations?.contacts[key];
|
obj[key] = props.associations?.groups[key];
|
||||||
return obj;
|
return obj;
|
||||||
}, {}) || {}
|
}, {}) || {}
|
||||||
)
|
)
|
||||||
: Object.values(props.associations?.contacts || {});
|
: Object.values(props.associations?.groups || {});
|
||||||
}, [props.associations?.contacts]);
|
}, [props.associations?.groups]);
|
||||||
|
|
||||||
const [{ value }, meta, { setValue, setTouched }] = useField(props.id);
|
const [{ value }, meta, { setValue, setTouched }] = useField(props.id);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setValue(selected);
|
||||||
|
}, [selected])
|
||||||
|
|
||||||
const { title: groupTitle } =
|
const { title: groupTitle } =
|
||||||
props.associations.contacts?.[value]?.metadata || {};
|
props.associations.groups?.[value]?.metadata || {};
|
||||||
|
|
||||||
const onSelect = useCallback(
|
const onSelect = useCallback(
|
||||||
(a: Association) => {
|
(s: string) => {
|
||||||
setValue(a.group);
|
|
||||||
setTouched(true);
|
setTouched(true);
|
||||||
|
setSelected(v => _.uniq([...v, s]));
|
||||||
},
|
},
|
||||||
[setValue]
|
[setTouched, setSelected]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onUnselect = useCallback(() => {
|
const onRemove = useCallback(
|
||||||
setValue(undefined);
|
(s: string) => {
|
||||||
setTouched(true);
|
setSelected(groups => groups.filter(group => group !== s))
|
||||||
}, [setValue]);
|
},
|
||||||
|
[setSelected]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col>
|
<Col>
|
||||||
@ -105,25 +113,11 @@ export function GroupSearch(props: InviteSearchProps) {
|
|||||||
{caption}
|
{caption}
|
||||||
</Label>
|
</Label>
|
||||||
)}
|
)}
|
||||||
{value && (
|
|
||||||
<Row
|
|
||||||
borderRadius="1"
|
|
||||||
mt="2"
|
|
||||||
width="fit-content"
|
|
||||||
border="1"
|
|
||||||
borderColor="gray"
|
|
||||||
height="32px"
|
|
||||||
px="2"
|
|
||||||
alignItems="center"
|
|
||||||
>
|
|
||||||
<Text mr="2">{groupTitle || value}</Text>
|
|
||||||
<Icon onClick={onUnselect} icon="X" />
|
|
||||||
</Row>
|
|
||||||
)}
|
|
||||||
{!value && (
|
|
||||||
<DropdownSearch<Association>
|
<DropdownSearch<Association>
|
||||||
mt="2"
|
mt="2"
|
||||||
candidates={groups}
|
candidates={groups}
|
||||||
|
placeholder="Search for groups..."
|
||||||
|
disabled={props.maxLength ? selected.length >= props.maxLength : false}
|
||||||
renderCandidate={renderCandidate}
|
renderCandidate={renderCandidate}
|
||||||
search={(s: string, a: Association) =>
|
search={(s: string, a: Association) =>
|
||||||
a.metadata.title.toLowerCase().startsWith(s.toLowerCase())
|
a.metadata.title.toLowerCase().startsWith(s.toLowerCase())
|
||||||
@ -131,8 +125,27 @@ export function GroupSearch(props: InviteSearchProps) {
|
|||||||
getKey={(a: Association) => a.group}
|
getKey={(a: Association) => a.group}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
/>
|
/>
|
||||||
|
{value?.length > 0 && (
|
||||||
|
value.map((e) => {
|
||||||
|
return (
|
||||||
|
<Row
|
||||||
|
key={e}
|
||||||
|
borderRadius="1"
|
||||||
|
mt="2"
|
||||||
|
width="fit-content"
|
||||||
|
border="1"
|
||||||
|
borderColor="gray"
|
||||||
|
height="32px"
|
||||||
|
px="2"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text mr="2">{groupTitle || e}</Text>
|
||||||
|
<Icon onClick={onRemove} icon="X" />
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
})
|
||||||
)}
|
)}
|
||||||
<ErrorLabel hasError={!!(meta.touched && meta.error)}>
|
<ErrorLabel hasError={Boolean(meta.touched && meta.error)}>
|
||||||
{meta.error}
|
{meta.error}
|
||||||
</ErrorLabel>
|
</ErrorLabel>
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -173,7 +173,7 @@ export function ShipSearch(props: InviteSearchProps) {
|
|||||||
const result = ob.isValidPatp(ship);
|
const result = ob.isValidPatp(ship);
|
||||||
return result ? deSig(s) ?? undefined : undefined;
|
return result ? deSig(s) ?? undefined : undefined;
|
||||||
}}
|
}}
|
||||||
placeholder="Search for ships"
|
placeholder="Search for ships..."
|
||||||
candidates={peers}
|
candidates={peers}
|
||||||
renderCandidate={renderCandidate}
|
renderCandidate={renderCandidate}
|
||||||
disabled={props.maxLength ? selected.length >= props.maxLength : false}
|
disabled={props.maxLength ? selected.length >= props.maxLength : false}
|
||||||
|
@ -42,9 +42,9 @@ function RecentGroups(props: { recent: string[]; associations: Associations }) {
|
|||||||
Recent Groups
|
Recent Groups
|
||||||
</Box>
|
</Box>
|
||||||
{props.recent.filter((e) => {
|
{props.recent.filter((e) => {
|
||||||
return (e in associations?.contacts);
|
return (e in associations?.groups);
|
||||||
}).slice(1, 5).map((g) => {
|
}).slice(1, 5).map((g) => {
|
||||||
const assoc = associations.contacts[g];
|
const assoc = associations.groups[g];
|
||||||
const color = uxToHex(assoc?.metadata?.color || '0x0');
|
const color = uxToHex(assoc?.metadata?.color || '0x0');
|
||||||
return (
|
return (
|
||||||
<Link key={g} style={{ minWidth: 0 }} to={`/~landscape${g}`}>
|
<Link key={g} style={{ minWidth: 0 }} to={`/~landscape${g}`}>
|
||||||
@ -78,7 +78,7 @@ export function GroupSwitcher(props: {
|
|||||||
}) {
|
}) {
|
||||||
const { associations, workspace, isAdmin } = props;
|
const { associations, workspace, isAdmin } = props;
|
||||||
const title = getTitleFromWorkspace(associations, workspace);
|
const title = getTitleFromWorkspace(associations, workspace);
|
||||||
const metadata = workspace.type === 'home' ? undefined : associations.contacts[workspace.group].metadata;
|
const metadata = workspace.type === 'home' ? undefined : associations.groups[workspace.group].metadata;
|
||||||
const navTo = (to: string) => `${props.baseUrl}${to}`;
|
const navTo = (to: string) => `${props.baseUrl}${to}`;
|
||||||
return (
|
return (
|
||||||
<Row width="100%" alignItems="center" height='48px' backgroundColor="white" zIndex="2" position="sticky" top="0px" pl='3' borderBottom='1px solid' borderColor='washedGray'>
|
<Row width="100%" alignItems="center" height='48px' backgroundColor="white" zIndex="2" position="sticky" top="0px" pl='3' borderBottom='1px solid' borderColor='washedGray'>
|
||||||
|
@ -14,7 +14,7 @@ const formSchema = Yup.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
interface FormSchema {
|
interface FormSchema {
|
||||||
group: string | null;
|
group: string[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GroupifyFormProps {
|
interface GroupifyFormProps {
|
||||||
@ -37,7 +37,7 @@ export function GroupifyForm(props: GroupifyFormProps) {
|
|||||||
await props.api.graph.groupifyGraph(
|
await props.api.graph.groupifyGraph(
|
||||||
ship,
|
ship,
|
||||||
name,
|
name,
|
||||||
values.group || undefined
|
values.group?.toString() || undefined
|
||||||
);
|
);
|
||||||
const mod = association.metadata.module || association['app-name'];
|
const mod = association.metadata.module || association['app-name'];
|
||||||
const newGroup = values.group || association.group;
|
const newGroup = values.group || association.group;
|
||||||
@ -79,6 +79,7 @@ export function GroupifyForm(props: GroupifyFormProps) {
|
|||||||
groups={props.groups}
|
groups={props.groups}
|
||||||
associations={props.associations}
|
associations={props.associations}
|
||||||
adminOnly
|
adminOnly
|
||||||
|
maxLength={1}
|
||||||
/>
|
/>
|
||||||
<AsyncButton primary loadingText="Groupifying..." border>
|
<AsyncButton primary loadingText="Groupifying..." border>
|
||||||
Groupify
|
Groupify
|
||||||
|
@ -43,7 +43,7 @@ export function GroupsPane(props: GroupsPaneProps) {
|
|||||||
const groupContacts = (groupPath && contacts[groupPath]) || undefined;
|
const groupContacts = (groupPath && contacts[groupPath]) || undefined;
|
||||||
const rootIdentity = contacts?.["/~/default"]?.[window.ship];
|
const rootIdentity = contacts?.["/~/default"]?.[window.ship];
|
||||||
const groupAssociation =
|
const groupAssociation =
|
||||||
(groupPath && associations.contacts[groupPath]) || undefined;
|
(groupPath && associations.groups[groupPath]) || undefined;
|
||||||
const group = (groupPath && groups[groupPath]) || undefined;
|
const group = (groupPath && groups[groupPath]) || undefined;
|
||||||
const [recentGroups, setRecentGroups] = useLocalStorageState<string[]>(
|
const [recentGroups, setRecentGroups] = useLocalStorageState<string[]>(
|
||||||
"recent-groups",
|
"recent-groups",
|
||||||
|
@ -65,7 +65,7 @@ export function NewGroup(props: NewGroupProps & RouteComponentProps) {
|
|||||||
await api.contacts.create(name, policy, title, description);
|
await api.contacts.create(name, policy, title, description);
|
||||||
const path = `/ship/~${window.ship}/${name}`;
|
const path = `/ship/~${window.ship}/${name}`;
|
||||||
await waiter(({ contacts, groups, associations }) => {
|
await waiter(({ contacts, groups, associations }) => {
|
||||||
return path in contacts && path in groups && path in associations.contacts;
|
return path in contacts && path in groups && path in associations.groups;
|
||||||
});
|
});
|
||||||
|
|
||||||
actions.setStatus({ success: null });
|
actions.setStatus({ success: null });
|
||||||
|
@ -37,8 +37,8 @@ export function Resource(props: ResourceProps) {
|
|||||||
const skelProps = { api, association };
|
const skelProps = { api, association };
|
||||||
let title = props.association.metadata.title;
|
let title = props.association.metadata.title;
|
||||||
if ('workspace' in props) {
|
if ('workspace' in props) {
|
||||||
if ('group' in props.workspace && props.workspace.group in props.associations.contacts) {
|
if ('group' in props.workspace && props.workspace.group in props.associations.groups) {
|
||||||
title = `${props.associations.contacts[props.workspace.group].metadata.title} - ${props.association.metadata.title}`;
|
title = `${props.associations.groups[props.workspace.group].metadata.title} - ${props.association.metadata.title}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -57,7 +57,7 @@ export function SidebarList(props: {
|
|||||||
const assoc = associations[a];
|
const assoc = associations[a];
|
||||||
return group
|
return group
|
||||||
? assoc.group === group
|
? assoc.group === group
|
||||||
: !(assoc.group in props.associations.contacts);
|
: !(assoc.group in props.associations.groups);
|
||||||
})
|
})
|
||||||
.sort(sidebarSort(associations, props.apps)[config.sortBy]);
|
.sort(sidebarSort(associations, props.apps)[config.sortBy]);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user