mirror of
https://github.com/urbit/shrub.git
synced 2025-01-04 10:32:34 +03:00
publish: choose group for groupify
This commit is contained in:
parent
73881aa25f
commit
f320631230
@ -82,11 +82,11 @@ export default class PublishApi extends BaseApi {
|
|||||||
return this.action('publish', 'publish-action', act);
|
return this.action('publish', 'publish-action', act);
|
||||||
}
|
}
|
||||||
|
|
||||||
groupify(bookId: string) {
|
groupify(bookId: string, group: Path | null) {
|
||||||
return this.publishAction({
|
return this.publishAction({
|
||||||
groupify: {
|
groupify: {
|
||||||
book: bookId,
|
book: bookId,
|
||||||
target: null,
|
target: group,
|
||||||
inclusive: false
|
inclusive: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -163,6 +163,7 @@ export default function PublishApp(props: PublishAppProps) {
|
|||||||
hideNicknames={hideNicknames}
|
hideNicknames={hideNicknames}
|
||||||
hideAvatars={hideAvatars}
|
hideAvatars={hideAvatars}
|
||||||
remoteContentPolicy={remoteContentPolicy}
|
remoteContentPolicy={remoteContentPolicy}
|
||||||
|
associations={associations}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
import React, { useEffect } from "react";
|
||||||
|
import { Box, Col, Button, InputLabel, InputCaption } from "@tlon/indigo-react";
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import GlobalApi from "~/logic/api/global";
|
||||||
|
import { Notebook } from "~/types/publish-update";
|
||||||
|
import { Contacts } from "~/types/contact-update";
|
||||||
|
|
||||||
|
import { MetadataForm } from "./MetadataForm";
|
||||||
|
import { Groups, Associations } from "~/types";
|
||||||
|
import { Formik, FormikHelpers, Form } from "formik";
|
||||||
|
import GroupSearch from "~/views/components/GroupSearch";
|
||||||
|
import { AsyncButton } from "~/views/components/AsyncButton";
|
||||||
|
|
||||||
|
const formSchema = Yup.object({
|
||||||
|
group: Yup.string().nullable(),
|
||||||
|
});
|
||||||
|
|
||||||
|
interface FormSchema {
|
||||||
|
group: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GroupifyFormProps {
|
||||||
|
host: string;
|
||||||
|
book: string;
|
||||||
|
notebook: Notebook;
|
||||||
|
groups: Groups;
|
||||||
|
api: GlobalApi;
|
||||||
|
associations: Associations;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GroupifyForm(props: GroupifyFormProps) {
|
||||||
|
const onGroupify = async (
|
||||||
|
values: FormSchema,
|
||||||
|
actions: FormikHelpers<FormSchema>
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
await props.api.publish.groupify(props.book, values.group);
|
||||||
|
actions.setStatus({ success: null });
|
||||||
|
} catch (e) {
|
||||||
|
actions.setStatus({ error: e.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const groupPath = props.notebook?.["writers-group-path"];
|
||||||
|
|
||||||
|
const isUnmanaged = props.groups?.[groupPath]?.hidden || false;
|
||||||
|
|
||||||
|
if (!isUnmanaged) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialValues: FormSchema = {
|
||||||
|
group: null
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Formik
|
||||||
|
validationSchema={formSchema}
|
||||||
|
initialValues={initialValues}
|
||||||
|
onSubmit={onGroupify}
|
||||||
|
>
|
||||||
|
<Form style={{ display: "contents" }}>
|
||||||
|
<GroupSearch
|
||||||
|
id="group"
|
||||||
|
label="Group"
|
||||||
|
caption="What group should this notebook be added to? If blank, a new group will be made for the notebook"
|
||||||
|
associations={props.associations}
|
||||||
|
/>
|
||||||
|
<AsyncButton loadingText="Groupifying..." border>
|
||||||
|
Groupify
|
||||||
|
</AsyncButton>
|
||||||
|
</Form>
|
||||||
|
</Formik>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GroupifyForm;
|
@ -50,7 +50,6 @@ const ResetOnPropsChange = (props: { init: FormSchema; book: string }) => {
|
|||||||
|
|
||||||
export function MetadataForm(props: MetadataFormProps) {
|
export function MetadataForm(props: MetadataFormProps) {
|
||||||
const { host, notebook, api, book } = props;
|
const { host, notebook, api, book } = props;
|
||||||
const history = useHistory();
|
|
||||||
const initialValues: FormSchema = {
|
const initialValues: FormSchema = {
|
||||||
name: notebook?.title,
|
name: notebook?.title,
|
||||||
description: notebook?.about,
|
description: notebook?.about,
|
||||||
@ -72,11 +71,6 @@ export function MetadataForm(props: MetadataFormProps) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDelete = async () => {
|
|
||||||
await api.publish.delBook(book);
|
|
||||||
history.push("/~publish");
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Formik
|
<Formik
|
||||||
validationSchema={formSchema}
|
validationSchema={formSchema}
|
||||||
@ -84,16 +78,6 @@ export function MetadataForm(props: MetadataFormProps) {
|
|||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
>
|
>
|
||||||
<Form style={{ display: "contents" }}>
|
<Form style={{ display: "contents" }}>
|
||||||
<Col mb={4}>
|
|
||||||
<InputLabel>Delete Notebook</InputLabel>
|
|
||||||
<InputCaption>
|
|
||||||
Permanently delete this notebook. (All current members will no
|
|
||||||
longer see this notebook.)
|
|
||||||
</InputCaption>
|
|
||||||
<Button onClick={onDelete} mt={1} border error>
|
|
||||||
Delete this notebook
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
<Input
|
<Input
|
||||||
id="name"
|
id="name"
|
||||||
label="Rename"
|
label="Rename"
|
||||||
|
@ -20,6 +20,7 @@ import { Groups } from "~/types/group-update";
|
|||||||
import { Contacts, Rolodex } from "~/types/contact-update";
|
import { Contacts, Rolodex } from "~/types/contact-update";
|
||||||
import GlobalApi from "~/logic/api/global";
|
import GlobalApi from "~/logic/api/global";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
import {Associations} from "~/types";
|
||||||
|
|
||||||
const TabList = styled(_TabList)`
|
const TabList = styled(_TabList)`
|
||||||
margin-bottom: ${(p) => p.theme.space[4]}px;
|
margin-bottom: ${(p) => p.theme.space[4]}px;
|
||||||
@ -38,6 +39,7 @@ interface NotebookProps {
|
|||||||
contacts: Rolodex;
|
contacts: Rolodex;
|
||||||
groups: Groups;
|
groups: Groups;
|
||||||
hideNicknames: boolean;
|
hideNicknames: boolean;
|
||||||
|
associations: Associations;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Notebook(props: NotebookProps & RouteComponentProps) {
|
export function Notebook(props: NotebookProps & RouteComponentProps) {
|
||||||
@ -130,6 +132,7 @@ export function Notebook(props: NotebookProps & RouteComponentProps) {
|
|||||||
api={api}
|
api={api}
|
||||||
notebook={notebook}
|
notebook={notebook}
|
||||||
contacts={notebookContacts}
|
contacts={notebookContacts}
|
||||||
|
associations={props.associations}
|
||||||
groups={groups}
|
groups={groups}
|
||||||
/>
|
/>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
@ -9,7 +9,7 @@ import { Contacts, Rolodex } from "../../../../types/contact-update";
|
|||||||
import Notebook from "./Notebook";
|
import Notebook from "./Notebook";
|
||||||
import NewPost from "./new-post";
|
import NewPost from "./new-post";
|
||||||
import { NoteRoutes } from './NoteRoutes';
|
import { NoteRoutes } from './NoteRoutes';
|
||||||
import { LocalUpdateRemoteContentPolicy } from "~/types";
|
import { LocalUpdateRemoteContentPolicy, Associations } from "~/types";
|
||||||
|
|
||||||
interface NotebookRoutesProps {
|
interface NotebookRoutesProps {
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
@ -23,6 +23,7 @@ interface NotebookRoutesProps {
|
|||||||
hideAvatars: boolean;
|
hideAvatars: boolean;
|
||||||
hideNicknames: boolean;
|
hideNicknames: boolean;
|
||||||
remoteContentPolicy: LocalUpdateRemoteContentPolicy;
|
remoteContentPolicy: LocalUpdateRemoteContentPolicy;
|
||||||
|
associations: Associations;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NotebookRoutes(
|
export function NotebookRoutes(
|
||||||
|
@ -5,7 +5,9 @@ import { Notebook } from "~/types/publish-update";
|
|||||||
import { Contacts } from "~/types/contact-update";
|
import { Contacts } from "~/types/contact-update";
|
||||||
|
|
||||||
import { MetadataForm } from "./MetadataForm";
|
import { MetadataForm } from "./MetadataForm";
|
||||||
import { Groups } from "~/types";
|
import { Groups, Associations } from "~/types";
|
||||||
|
import GroupifyForm from "./GroupifyForm";
|
||||||
|
import { useHistory } from "react-router-dom";
|
||||||
|
|
||||||
interface SettingsProps {
|
interface SettingsProps {
|
||||||
host: string;
|
host: string;
|
||||||
@ -14,13 +16,18 @@ interface SettingsProps {
|
|||||||
contacts: Contacts;
|
contacts: Contacts;
|
||||||
groups: Groups;
|
groups: Groups;
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
|
associations: Associations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Divider = (props) => (
|
||||||
|
<Box {...props} mb={4} borderBottom={1} borderBottomColor="lightGray" />
|
||||||
|
);
|
||||||
export function Settings(props: SettingsProps) {
|
export function Settings(props: SettingsProps) {
|
||||||
const onGroupify = () => {
|
const history = useHistory();
|
||||||
return props.api.publish.groupify(props.book);
|
const onDelete = async () => {
|
||||||
|
await props.api.publish.delBook(props.book);
|
||||||
|
history.push("/~publish");
|
||||||
};
|
};
|
||||||
|
|
||||||
const groupPath = props.notebook?.["writers-group-path"];
|
const groupPath = props.notebook?.["writers-group-path"];
|
||||||
|
|
||||||
const isUnmanaged = props.groups?.[groupPath]?.hidden || false;
|
const isUnmanaged = props.groups?.[groupPath]?.hidden || false;
|
||||||
@ -36,17 +43,22 @@ export function Settings(props: SettingsProps) {
|
|||||||
>
|
>
|
||||||
{isUnmanaged && (
|
{isUnmanaged && (
|
||||||
<>
|
<>
|
||||||
<Col mb={4}>
|
<GroupifyForm {...props} />
|
||||||
<InputLabel>Groupify</InputLabel>
|
<Divider mt={4} />
|
||||||
<InputCaption>Turn this notebook into a group</InputCaption>
|
|
||||||
<Button onClick={onGroupify} border>
|
|
||||||
Groupify
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
<Box mb={4} borderBottom={1} borderBottomColor="washedGray" />
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<MetadataForm {...props} />
|
<MetadataForm {...props} />
|
||||||
|
<Divider />
|
||||||
|
<Col mb={4}>
|
||||||
|
<InputLabel>Delete Notebook</InputLabel>
|
||||||
|
<InputCaption>
|
||||||
|
Permanently delete this notebook. (All current members will no longer
|
||||||
|
see this notebook.)
|
||||||
|
</InputCaption>
|
||||||
|
<Button onClick={onDelete} mt={1} border error>
|
||||||
|
Delete this notebook
|
||||||
|
</Button>
|
||||||
|
</Col>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ export function GroupSearch(props: InviteSearchProps) {
|
|||||||
caption={props.caption}
|
caption={props.caption}
|
||||||
candidates={groups}
|
candidates={groups}
|
||||||
renderCandidate={renderCandidate}
|
renderCandidate={renderCandidate}
|
||||||
disabled={value.length !== 0}
|
disabled={value && value.length !== 0}
|
||||||
search={(s: string, a: Association) =>
|
search={(s: string, a: Association) =>
|
||||||
a.metadata.title.toLowerCase().startsWith(s.toLowerCase())
|
a.metadata.title.toLowerCase().startsWith(s.toLowerCase())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user