mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-11-13 08:38:43 +03:00
interface: storage prop unifying gcp and s3
N.B. this boldly assumes that store state will always contain a valid storage element that will contain gcp and s3 elements. This seems like a fair assumption.
This commit is contained in:
parent
ce1c69e0d1
commit
f85ef9fcb4
@ -64,7 +64,7 @@ class GcpManager {
|
|||||||
#consecutiveFailures: number = 0;
|
#consecutiveFailures: number = 0;
|
||||||
|
|
||||||
private isConfigured() {
|
private isConfigured() {
|
||||||
return this.#store.state.gcp.configured;
|
return this.#store.state.storage.gcp.configured;
|
||||||
}
|
}
|
||||||
|
|
||||||
private refreshLoop() {
|
private refreshLoop() {
|
||||||
@ -88,7 +88,7 @@ class GcpManager {
|
|||||||
}
|
}
|
||||||
this.#api.gcp.getToken()
|
this.#api.gcp.getToken()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const token = this.#store.state.gcp?.token;
|
const token = this.#store.state.storage.gcp?.token;
|
||||||
if (token) {
|
if (token) {
|
||||||
this.#consecutiveFailures = 0;
|
this.#consecutiveFailures = 0;
|
||||||
const interval = this.refreshInterval(token.expiresIn);
|
const interval = this.refreshInterval(token.expiresIn);
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import {useCallback, useMemo, useEffect, useRef, useState} from 'react';
|
import {useCallback, useMemo, useEffect, useRef, useState} from 'react';
|
||||||
import {S3State} from '../../types/s3-update';
|
import {
|
||||||
import {GcpState} from '../../types/gcp-state';
|
GcpState,
|
||||||
|
S3State,
|
||||||
|
StorageState
|
||||||
|
} from '../../types';
|
||||||
import S3 from "aws-sdk/clients/s3";
|
import S3 from "aws-sdk/clients/s3";
|
||||||
import GcpClient from './GcpClient';
|
import GcpClient from './GcpClient';
|
||||||
import {StorageClient, StorageAcl} from './StorageClient';
|
import {StorageClient, StorageAcl} from './StorageClient';
|
||||||
@ -15,7 +18,7 @@ export interface IuseStorage {
|
|||||||
promptUpload: () => Promise<string | undefined>;
|
promptUpload: () => Promise<string | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStorage = (s3: S3State, gcp: GcpState,
|
const useStorage = ({gcp, s3}: StorageState,
|
||||||
{ accept = '*' } = { accept: '*' }): IuseStorage => {
|
{ accept = '*' } = { accept: '*' }): IuseStorage => {
|
||||||
const [uploading, setUploading] = useState(false);
|
const [uploading, setUploading] = useState(false);
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ export default class GcpReducer<S extends GcpState>{
|
|||||||
reduceConfigured(json, state) {
|
reduceConfigured(json, state) {
|
||||||
let data = json['gcp-configured'];
|
let data = json['gcp-configured'];
|
||||||
if (data !== undefined) {
|
if (data !== undefined) {
|
||||||
state.gcp.configured = data;
|
state.storage.gcp.configured = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ export default class GcpReducer<S extends GcpState>{
|
|||||||
|
|
||||||
setToken(data: any, state: S) {
|
setToken(data: any, state: S) {
|
||||||
if (this.isToken(data)) {
|
if (this.isToken(data)) {
|
||||||
state.gcp.token = data;
|
state.storage.gcp.token = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,14 +23,14 @@ export default class S3Reducer<S extends S3State> {
|
|||||||
credentials(json: S3Update, state: S) {
|
credentials(json: S3Update, state: S) {
|
||||||
const data = _.get(json, 'credentials', false);
|
const data = _.get(json, 'credentials', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
state.s3.credentials = data;
|
state.storage.s3.credentials = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configuration(json: S3Update, state: S) {
|
configuration(json: S3Update, state: S) {
|
||||||
const data = _.get(json, 'configuration', false);
|
const data = _.get(json, 'configuration', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
state.s3.configuration = {
|
state.storage.s3.configuration = {
|
||||||
buckets: new Set(data.buckets),
|
buckets: new Set(data.buckets),
|
||||||
currentBucket: data.currentBucket
|
currentBucket: data.currentBucket
|
||||||
};
|
};
|
||||||
@ -39,44 +39,44 @@ export default class S3Reducer<S extends S3State> {
|
|||||||
|
|
||||||
currentBucket(json: S3Update, state: S) {
|
currentBucket(json: S3Update, state: S) {
|
||||||
const data = _.get(json, 'setCurrentBucket', false);
|
const data = _.get(json, 'setCurrentBucket', false);
|
||||||
if (data && state.s3) {
|
if (data && state.storage.s3) {
|
||||||
state.s3.configuration.currentBucket = data;
|
state.storage.s3.configuration.currentBucket = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addBucket(json: S3Update, state: S) {
|
addBucket(json: S3Update, state: S) {
|
||||||
const data = _.get(json, 'addBucket', false);
|
const data = _.get(json, 'addBucket', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
state.s3.configuration.buckets =
|
state.storage.s3.configuration.buckets =
|
||||||
state.s3.configuration.buckets.add(data);
|
state.storage.s3.configuration.buckets.add(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeBucket(json: S3Update, state: S) {
|
removeBucket(json: S3Update, state: S) {
|
||||||
const data = _.get(json, 'removeBucket', false);
|
const data = _.get(json, 'removeBucket', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
state.s3.configuration.buckets.delete(data);
|
state.storage.s3.configuration.buckets.delete(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint(json: S3Update, state: S) {
|
endpoint(json: S3Update, state: S) {
|
||||||
const data = _.get(json, 'setEndpoint', false);
|
const data = _.get(json, 'setEndpoint', false);
|
||||||
if (data && state.s3.credentials) {
|
if (data && state.storage.s3.credentials) {
|
||||||
state.s3.credentials.endpoint = data;
|
state.storage.s3.credentials.endpoint = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
accessKeyId(json: S3Update , state: S) {
|
accessKeyId(json: S3Update , state: S) {
|
||||||
const data = _.get(json, 'setAccessKeyId', false);
|
const data = _.get(json, 'setAccessKeyId', false);
|
||||||
if (data && state.s3.credentials) {
|
if (data && state.storage.s3.credentials) {
|
||||||
state.s3.credentials.accessKeyId = data;
|
state.storage.s3.credentials.accessKeyId = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
secretAccessKey(json: S3Update, state: S) {
|
secretAccessKey(json: S3Update, state: S) {
|
||||||
const data = _.get(json, 'setSecretAccessKey', false);
|
const data = _.get(json, 'setSecretAccessKey', false);
|
||||||
if (data && state.s3.credentials) {
|
if (data && state.storage.s3.credentials) {
|
||||||
state.s3.credentials.secretAccessKey = data;
|
state.storage.s3.credentials.secretAccessKey = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,13 +73,15 @@ export default class GlobalStore extends BaseStore<StoreState> {
|
|||||||
},
|
},
|
||||||
weather: {},
|
weather: {},
|
||||||
userLocation: null,
|
userLocation: null,
|
||||||
gcp: {},
|
storage: {
|
||||||
s3: {
|
gcp: {},
|
||||||
configuration: {
|
s3: {
|
||||||
buckets: new Set(),
|
configuration: {
|
||||||
currentBucket: ''
|
buckets: new Set(),
|
||||||
|
currentBucket: ''
|
||||||
|
},
|
||||||
|
credentials: null
|
||||||
},
|
},
|
||||||
credentials: null
|
|
||||||
},
|
},
|
||||||
isContactPublic: false,
|
isContactPublic: false,
|
||||||
contacts: {},
|
contacts: {},
|
||||||
|
@ -3,8 +3,7 @@ import { Invites } from '~/types/invite-update';
|
|||||||
import { Associations } from '~/types/metadata-update';
|
import { Associations } from '~/types/metadata-update';
|
||||||
import { Rolodex } from '~/types/contact-update';
|
import { Rolodex } from '~/types/contact-update';
|
||||||
import { Groups } from '~/types/group-update';
|
import { Groups } from '~/types/group-update';
|
||||||
import { GcpState } from '~/types/gcp-state';
|
import { StorageState } from '~/types/storage-state';
|
||||||
import { S3State } from '~/types/s3-update';
|
|
||||||
import { LaunchState, WeatherState } from '~/types/launch-update';
|
import { LaunchState, WeatherState } from '~/types/launch-update';
|
||||||
import { ConnectionStatus } from '~/types/connection';
|
import { ConnectionStatus } from '~/types/connection';
|
||||||
import {Graphs} from '~/types/graph-update';
|
import {Graphs} from '~/types/graph-update';
|
||||||
@ -32,8 +31,7 @@ export interface StoreState {
|
|||||||
groups: Groups;
|
groups: Groups;
|
||||||
groupKeys: Set<Path>;
|
groupKeys: Set<Path>;
|
||||||
nackedContacts: Set<Patp>
|
nackedContacts: Set<Patp>
|
||||||
s3: S3State;
|
storage: StorageState;
|
||||||
gcp: GcpState;
|
|
||||||
graphs: Graphs;
|
graphs: Graphs;
|
||||||
graphKeys: Set<string>;
|
graphKeys: Set<string>;
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ export * from './launch-update';
|
|||||||
export * from './local-update';
|
export * from './local-update';
|
||||||
export * from './metadata-update';
|
export * from './metadata-update';
|
||||||
export * from './noun';
|
export * from './noun';
|
||||||
|
export * from './storage-state';
|
||||||
export * from './gcp-state';
|
export * from './gcp-state';
|
||||||
export * from './s3-update';
|
export * from './s3-update';
|
||||||
export * from './workspace';
|
export * from './workspace';
|
||||||
|
8
pkg/interface/src/types/storage-state.ts
Normal file
8
pkg/interface/src/types/storage-state.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import {GcpState} from './gcp-state';
|
||||||
|
import {S3State} from './s3-update';
|
||||||
|
|
||||||
|
|
||||||
|
export interface StorageState {
|
||||||
|
gcp: GcpState;
|
||||||
|
s3: S3State;
|
||||||
|
};
|
@ -179,8 +179,7 @@ export function ChatResource(props: ChatResourceProps) {
|
|||||||
(!showBanner && hasLoadedAllowed) ? contacts : modifiedContacts
|
(!showBanner && hasLoadedAllowed) ? contacts : modifiedContacts
|
||||||
}
|
}
|
||||||
onUnmount={appendUnsent}
|
onUnmount={appendUnsent}
|
||||||
gcp={props.gcp}
|
storage={props.storage}
|
||||||
s3={props.s3}
|
|
||||||
placeholder="Message..."
|
placeholder="Message..."
|
||||||
message={unsent[station] || ''}
|
message={unsent[station] || ''}
|
||||||
deleteMessage={clearUnsent}
|
deleteMessage={clearUnsent}
|
||||||
|
@ -7,7 +7,7 @@ import { createPost } from '~/logic/api/graph';
|
|||||||
import tokenizeMessage, { isUrl } from '~/logic/lib/tokenizeMessage';
|
import tokenizeMessage, { isUrl } from '~/logic/lib/tokenizeMessage';
|
||||||
import GlobalApi from '~/logic/api/global';
|
import GlobalApi from '~/logic/api/global';
|
||||||
import { Envelope } from '~/types/chat-update';
|
import { Envelope } from '~/types/chat-update';
|
||||||
import { Contacts, Content } from '~/types';
|
import { StorageState, Contacts, Content } from '~/types';
|
||||||
import { Row, BaseImage, Box, Icon, LoadingSpinner } from '@tlon/indigo-react';
|
import { Row, BaseImage, Box, Icon, LoadingSpinner } from '@tlon/indigo-react';
|
||||||
import withStorage from '~/views/components/withStorage';
|
import withStorage from '~/views/components/withStorage';
|
||||||
import { withLocalState } from '~/logic/state/local';
|
import { withLocalState } from '~/logic/state/local';
|
||||||
@ -20,8 +20,7 @@ type ChatInputProps = IuseStorage & {
|
|||||||
envelopes: Envelope[];
|
envelopes: Envelope[];
|
||||||
contacts: Contacts;
|
contacts: Contacts;
|
||||||
onUnmount(msg: string): void;
|
onUnmount(msg: string): void;
|
||||||
gcp: any;
|
storage: StorageState;
|
||||||
s3: any;
|
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
message: string;
|
message: string;
|
||||||
deleteMessage(): void;
|
deleteMessage(): void;
|
||||||
|
@ -34,8 +34,7 @@ export function LinkResource(props: LinkResourceProps) {
|
|||||||
associations,
|
associations,
|
||||||
graphKeys,
|
graphKeys,
|
||||||
unreads,
|
unreads,
|
||||||
gcp,
|
storage,
|
||||||
s3,
|
|
||||||
history
|
history
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
@ -71,8 +70,7 @@ export function LinkResource(props: LinkResourceProps) {
|
|||||||
render={(props) => {
|
render={(props) => {
|
||||||
return (
|
return (
|
||||||
<LinkWindow
|
<LinkWindow
|
||||||
gcp={gcp}
|
storage={storage}
|
||||||
s3={s3}
|
|
||||||
association={resource}
|
association={resource}
|
||||||
contacts={contacts}
|
contacts={contacts}
|
||||||
resource={resourcePath}
|
resource={resourcePath}
|
||||||
|
@ -30,8 +30,7 @@ interface LinkWindowProps {
|
|||||||
group: Group;
|
group: Group;
|
||||||
path: string;
|
path: string;
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
}
|
}
|
||||||
export function LinkWindow(props: LinkWindowProps) {
|
export function LinkWindow(props: LinkWindowProps) {
|
||||||
const { graph, api, association } = props;
|
const { graph, api, association } = props;
|
||||||
@ -67,7 +66,7 @@ export function LinkWindow(props: LinkWindowProps) {
|
|||||||
return (
|
return (
|
||||||
<Col key={0} mx="auto" mt="4" maxWidth="768px" width="100%" flexShrink={0} px={3}>
|
<Col key={0} mx="auto" mt="4" maxWidth="768px" width="100%" flexShrink={0} px={3}>
|
||||||
{ canWrite ? (
|
{ canWrite ? (
|
||||||
<LinkSubmit gcp={props.gcp} s3={props.s3} name={name} ship={ship.slice(1)} api={api} />
|
<LinkSubmit storage={props.storage} name={name} ship={ship.slice(1)} api={api} />
|
||||||
) : (
|
) : (
|
||||||
<Text>There are no links here yet. You do not have permission to post to this collection.</Text>
|
<Text>There are no links here yet. You do not have permission to post to this collection.</Text>
|
||||||
)
|
)
|
||||||
@ -98,7 +97,7 @@ export function LinkWindow(props: LinkWindowProps) {
|
|||||||
return (
|
return (
|
||||||
<React.Fragment key={index.toString()}>
|
<React.Fragment key={index.toString()}>
|
||||||
<Col key={index.toString()} mx="auto" mt="4" maxWidth="768px" width="100%" flexShrink={0} px={3}>
|
<Col key={index.toString()} mx="auto" mt="4" maxWidth="768px" width="100%" flexShrink={0} px={3}>
|
||||||
<LinkSubmit gcp={props.gcp} s3={props.s3} name={name} ship={ship.slice(1)} api={api} />
|
<LinkSubmit storage={props.storage} name={name} ship={ship.slice(1)} api={api} />
|
||||||
</Col>
|
</Col>
|
||||||
<LinkItem {...linkProps} />
|
<LinkItem {...linkProps} />
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
@ -3,22 +3,21 @@ import React, { useCallback, useState } from "react";
|
|||||||
import GlobalApi from "~/logic/api/global";
|
import GlobalApi from "~/logic/api/global";
|
||||||
import { useFileDrag } from "~/logic/lib/useDrag";
|
import { useFileDrag } from "~/logic/lib/useDrag";
|
||||||
import useStorage from "~/logic/lib/useStorage";
|
import useStorage from "~/logic/lib/useStorage";
|
||||||
import { GcpState, S3State } from "~/types";
|
import { StorageState } from "~/types";
|
||||||
import SubmitDragger from "~/views/components/SubmitDragger";
|
import SubmitDragger from "~/views/components/SubmitDragger";
|
||||||
import { createPost } from "~/logic/api/graph";
|
import { createPost } from "~/logic/api/graph";
|
||||||
import { hasProvider } from "oembed-parser";
|
import { hasProvider } from "oembed-parser";
|
||||||
|
|
||||||
interface LinkSubmitProps {
|
interface LinkSubmitProps {
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
name: string;
|
name: string;
|
||||||
ship: string;
|
ship: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const LinkSubmit = (props: LinkSubmitProps) => {
|
const LinkSubmit = (props: LinkSubmitProps) => {
|
||||||
let { canUpload, uploadDefault, uploading, promptUpload } =
|
let { canUpload, uploadDefault, uploading, promptUpload } =
|
||||||
useStorage(props.s3, props.gcp);
|
useStorage(props.storage);
|
||||||
|
|
||||||
const [submitFocused, setSubmitFocused] = useState(false);
|
const [submitFocused, setSubmitFocused] = useState(false);
|
||||||
const [urlFocused, setUrlFocused] = useState(false);
|
const [urlFocused, setUrlFocused] = useState(false);
|
||||||
|
@ -114,15 +114,15 @@ export function EditProfile(props: any) {
|
|||||||
<Input id="nickname" label="Name" mb={3} />
|
<Input id="nickname" label="Name" mb={3} />
|
||||||
<Col width="100%">
|
<Col width="100%">
|
||||||
<Text mb={2}>Description</Text>
|
<Text mb={2}>Description</Text>
|
||||||
<MarkdownField id="bio" mb={3} gcp={props.gcp} s3={props.s3} />
|
<MarkdownField id="bio" mb={3} storage={props.storage} />
|
||||||
</Col>
|
</Col>
|
||||||
<ColorInput id="color" label="Sigil Color" mb={3} />
|
<ColorInput id="color" label="Sigil Color" mb={3} />
|
||||||
<Row mb={3} width="100%">
|
<Row mb={3} width="100%">
|
||||||
<Col pr={2} width="50%">
|
<Col pr={2} width="50%">
|
||||||
<ImageInput id="cover" label="Cover Image" gcp={props.gcp} s3={props.s3} />
|
<ImageInput id="cover" label="Cover Image" storage={props.storage} />
|
||||||
</Col>
|
</Col>
|
||||||
<Col pl={2} width="50%">
|
<Col pl={2} width="50%">
|
||||||
<ImageInput id="avatar" label="Profile Image" gcp={props.gcp} s3={props.s3} />
|
<ImageInput id="avatar" label="Profile Image" storage={props.storage} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Checkbox mb={3} id="isPublic" label="Public Profile" />
|
<Checkbox mb={3} id="isPublic" label="Public Profile" />
|
||||||
|
@ -107,8 +107,7 @@ export function Profile(props: any) {
|
|||||||
<EditProfile
|
<EditProfile
|
||||||
ship={ship}
|
ship={ship}
|
||||||
contact={contact}
|
contact={contact}
|
||||||
gcp={props.gcp}
|
storage={props.storage}
|
||||||
s3={props.s3}
|
|
||||||
api={props.api}
|
api={props.api}
|
||||||
groups={props.groups}
|
groups={props.groups}
|
||||||
associations={props.associations}
|
associations={props.associations}
|
||||||
|
@ -50,8 +50,7 @@ export default function ProfileScreen(props: any) {
|
|||||||
groups={props.groups}
|
groups={props.groups}
|
||||||
contact={contact}
|
contact={contact}
|
||||||
api={props.api}
|
api={props.api}
|
||||||
gcp={props.gcp}
|
storage={props.storage}
|
||||||
s3={props.s3}
|
|
||||||
isEdit={isEdit}
|
isEdit={isEdit}
|
||||||
isPublic={isPublic}
|
isPublic={isPublic}
|
||||||
nackedContacts={props.nackedContacts}
|
nackedContacts={props.nackedContacts}
|
||||||
|
@ -37,8 +37,7 @@ export function PublishResource(props: PublishResourceProps) {
|
|||||||
location={props.location}
|
location={props.location}
|
||||||
unreads={props.unreads}
|
unreads={props.unreads}
|
||||||
graphs={props.graphs}
|
graphs={props.graphs}
|
||||||
gcp={props.gcp}
|
storage={props.storage}
|
||||||
s3={props.s3}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -4,7 +4,7 @@ import { PostFormSchema, PostForm } from "./NoteForm";
|
|||||||
import { FormikHelpers } from "formik";
|
import { FormikHelpers } from "formik";
|
||||||
import GlobalApi from "~/logic/api/global";
|
import GlobalApi from "~/logic/api/global";
|
||||||
import { RouteComponentProps, useLocation } from "react-router-dom";
|
import { RouteComponentProps, useLocation } from "react-router-dom";
|
||||||
import { GraphNode, TextContent, Association, GcpState, S3State } from "~/types";
|
import { GraphNode, TextContent, Association, StorageState } from "~/types";
|
||||||
import { getLatestRevision, editPost } from "~/logic/lib/publish";
|
import { getLatestRevision, editPost } from "~/logic/lib/publish";
|
||||||
import {useWaitForProps} from "~/logic/lib/useWaitForProps";
|
import {useWaitForProps} from "~/logic/lib/useWaitForProps";
|
||||||
interface EditPostProps {
|
interface EditPostProps {
|
||||||
@ -13,12 +13,11 @@ interface EditPostProps {
|
|||||||
note: GraphNode;
|
note: GraphNode;
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
book: string;
|
book: string;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EditPost(props: EditPostProps & RouteComponentProps) {
|
export function EditPost(props: EditPostProps & RouteComponentProps) {
|
||||||
const { note, book, noteId, api, ship, history, gcp, s3 } = props;
|
const { note, book, noteId, api, ship, history, storage } = props;
|
||||||
const [revNum, title, body] = getLatestRevision(note);
|
const [revNum, title, body] = getLatestRevision(note);
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
@ -55,8 +54,7 @@ export function EditPost(props: EditPostProps & RouteComponentProps) {
|
|||||||
cancel
|
cancel
|
||||||
history={history}
|
history={history}
|
||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
gcp={gcp}
|
storage={storage}
|
||||||
s3={s3}
|
|
||||||
submitLabel="Update"
|
submitLabel="Update"
|
||||||
loadingText="Updating..."
|
loadingText="Updating..."
|
||||||
/>
|
/>
|
||||||
|
@ -17,7 +17,7 @@ import { Box } from "@tlon/indigo-react";
|
|||||||
import { useFileDrag } from "~/logic/lib/useDrag";
|
import { useFileDrag } from "~/logic/lib/useDrag";
|
||||||
import SubmitDragger from "~/views/components/SubmitDragger";
|
import SubmitDragger from "~/views/components/SubmitDragger";
|
||||||
import useStorage from "~/logic/lib/useStorage";
|
import useStorage from "~/logic/lib/useStorage";
|
||||||
import { GcpState, S3State } from "~/types";
|
import { StorageState } from "~/types";
|
||||||
|
|
||||||
const MARKDOWN_CONFIG = {
|
const MARKDOWN_CONFIG = {
|
||||||
name: "markdown",
|
name: "markdown",
|
||||||
@ -28,8 +28,7 @@ interface MarkdownEditorProps {
|
|||||||
value: string;
|
value: string;
|
||||||
onChange: (s: string) => void;
|
onChange: (s: string) => void;
|
||||||
onBlur?: (e: any) => void;
|
onBlur?: (e: any) => void;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PromptIfDirty = () => {
|
const PromptIfDirty = () => {
|
||||||
@ -75,7 +74,7 @@ export function MarkdownEditor(
|
|||||||
[onBlur]
|
[onBlur]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { uploadDefault, canUpload } = useStorage(props.s3, props.gcp);
|
const { uploadDefault, canUpload } = useStorage(props.storage);
|
||||||
|
|
||||||
const onFileDrag = useCallback(
|
const onFileDrag = useCallback(
|
||||||
async (files: FileList | File[], e: DragEvent) => {
|
async (files: FileList | File[], e: DragEvent) => {
|
||||||
|
@ -6,8 +6,7 @@ import { MarkdownEditor } from "./MarkdownEditor";
|
|||||||
|
|
||||||
export const MarkdownField = ({
|
export const MarkdownField = ({
|
||||||
id,
|
id,
|
||||||
gcp,
|
storage,
|
||||||
s3,
|
|
||||||
...rest
|
...rest
|
||||||
}: { id: string } & Parameters<typeof Box>[0]) => {
|
}: { id: string } & Parameters<typeof Box>[0]) => {
|
||||||
const [{ value, onBlur }, { error, touched }, { setValue }] = useField(id);
|
const [{ value, onBlur }, { error, touched }, { setValue }] = useField(id);
|
||||||
@ -36,8 +35,7 @@ export const MarkdownField = ({
|
|||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={setValue}
|
onChange={setValue}
|
||||||
gcp={gcp}
|
storage={storage}
|
||||||
s3={s3}
|
|
||||||
/>
|
/>
|
||||||
<ErrorLabel mt="2" hasError={!!(error && touched)}>
|
<ErrorLabel mt="2" hasError={!!(error && touched)}>
|
||||||
{error}
|
{error}
|
||||||
|
@ -21,8 +21,7 @@ interface PostFormProps {
|
|||||||
) => Promise<any>;
|
) => Promise<any>;
|
||||||
submitLabel: string;
|
submitLabel: string;
|
||||||
loadingText: string;
|
loadingText: string;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const formSchema = Yup.object({
|
const formSchema = Yup.object({
|
||||||
@ -36,7 +35,7 @@ export interface PostFormSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function PostForm(props: PostFormProps) {
|
export function PostForm(props: PostFormProps) {
|
||||||
const { initial, onSubmit, submitLabel, loadingText, gcp, s3, cancel, history } = props;
|
const { initial, onSubmit, submitLabel, loadingText, storage, cancel, history } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col width="100%" height="100%" p={[2, 4]}>
|
<Col width="100%" height="100%" p={[2, 4]}>
|
||||||
@ -67,7 +66,7 @@ export function PostForm(props: PostFormProps) {
|
|||||||
type="button">Cancel</Button>}
|
type="button">Cancel</Button>}
|
||||||
</Row>
|
</Row>
|
||||||
</Row>
|
</Row>
|
||||||
<MarkdownField flexGrow={1} id="body" gcp={gcp} s3={s3} />
|
<MarkdownField flexGrow={1} id="body" storage={storage} />
|
||||||
</Form>
|
</Form>
|
||||||
</Formik>
|
</Formik>
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -11,8 +11,7 @@ import {
|
|||||||
Graph,
|
Graph,
|
||||||
Contacts,
|
Contacts,
|
||||||
Association,
|
Association,
|
||||||
GcpState,
|
StorageState,
|
||||||
S3State,
|
|
||||||
Group
|
Group
|
||||||
} from "~/types";
|
} from "~/types";
|
||||||
|
|
||||||
@ -28,8 +27,7 @@ interface NoteRoutesProps {
|
|||||||
baseUrl?: string;
|
baseUrl?: string;
|
||||||
rootUrl?: string;
|
rootUrl?: string;
|
||||||
group: Group;
|
group: Group;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NoteRoutes(props: NoteRoutesProps & RouteComponentProps) {
|
export function NoteRoutes(props: NoteRoutesProps & RouteComponentProps) {
|
||||||
|
@ -9,8 +9,7 @@ import {
|
|||||||
Contacts,
|
Contacts,
|
||||||
Rolodex,
|
Rolodex,
|
||||||
Unreads,
|
Unreads,
|
||||||
GcpState,
|
StorageState
|
||||||
S3State
|
|
||||||
} from "~/types";
|
} from "~/types";
|
||||||
import { Center, LoadingSpinner } from "@tlon/indigo-react";
|
import { Center, LoadingSpinner } from "@tlon/indigo-react";
|
||||||
import bigInt from 'big-integer';
|
import bigInt from 'big-integer';
|
||||||
@ -34,8 +33,7 @@ interface NotebookRoutesProps {
|
|||||||
rootUrl: string;
|
rootUrl: string;
|
||||||
association: Association;
|
association: Association;
|
||||||
associations: Associations;
|
associations: Associations;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NotebookRoutes(
|
export function NotebookRoutes(
|
||||||
@ -82,8 +80,7 @@ export function NotebookRoutes(
|
|||||||
association={props.association}
|
association={props.association}
|
||||||
graph={graph}
|
graph={graph}
|
||||||
baseUrl={baseUrl}
|
baseUrl={baseUrl}
|
||||||
gcp={props.gcp}
|
storage={props.storage}
|
||||||
s3={props.s3}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -115,8 +112,7 @@ export function NotebookRoutes(
|
|||||||
contacts={notebookContacts}
|
contacts={notebookContacts}
|
||||||
association={props.association}
|
association={props.association}
|
||||||
group={group}
|
group={group}
|
||||||
gcp={props.gcp}
|
storage={props.storage}
|
||||||
s3={props.s3}
|
|
||||||
{...routeProps}
|
{...routeProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -16,8 +16,7 @@ interface NewPostProps {
|
|||||||
graph: Graph;
|
graph: Graph;
|
||||||
association: Association;
|
association: Association;
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function NewPost(props: NewPostProps & RouteComponentProps) {
|
export default function NewPost(props: NewPostProps & RouteComponentProps) {
|
||||||
@ -54,8 +53,7 @@ export default function NewPost(props: NewPostProps & RouteComponentProps) {
|
|||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
submitLabel="Publish"
|
submitLabel="Publish"
|
||||||
loadingText="Posting..."
|
loadingText="Posting..."
|
||||||
gcp={props.gcp}
|
storage={props.storage}
|
||||||
s3={props.s3}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
} from "@tlon/indigo-react";
|
} from "@tlon/indigo-react";
|
||||||
|
|
||||||
import GlobalApi from "~/logic/api/global";
|
import GlobalApi from "~/logic/api/global";
|
||||||
import { GcpState, S3State } from "~/types";
|
import { StorageState, } from "~/types";
|
||||||
import { ImageInput } from "~/views/components/ImageInput";
|
import { ImageInput } from "~/views/components/ImageInput";
|
||||||
import {ColorInput} from "~/views/components/ColorInput";
|
import {ColorInput} from "~/views/components/ColorInput";
|
||||||
|
|
||||||
@ -19,14 +19,12 @@ export function BackgroundPicker({
|
|||||||
bgType,
|
bgType,
|
||||||
bgUrl,
|
bgUrl,
|
||||||
api,
|
api,
|
||||||
gcp,
|
storage,
|
||||||
s3,
|
|
||||||
}: {
|
}: {
|
||||||
bgType: BgType;
|
bgType: BgType;
|
||||||
bgUrl?: string;
|
bgUrl?: string;
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
const rowSpace = { my: 0, alignItems: 'center' };
|
const rowSpace = { my: 0, alignItems: 'center' };
|
||||||
@ -40,8 +38,7 @@ export function BackgroundPicker({
|
|||||||
<ImageInput
|
<ImageInput
|
||||||
ml="3"
|
ml="3"
|
||||||
api={api}
|
api={api}
|
||||||
gcp={gcp}
|
storage={storage}
|
||||||
s3={s3}
|
|
||||||
id="bgUrl"
|
id="bgUrl"
|
||||||
name="bgUrl"
|
name="bgUrl"
|
||||||
label="URL"
|
label="URL"
|
||||||
|
@ -10,7 +10,7 @@ import * as Yup from 'yup';
|
|||||||
|
|
||||||
import GlobalApi from '~/logic/api/global';
|
import GlobalApi from '~/logic/api/global';
|
||||||
import { uxToHex } from '~/logic/lib/util';
|
import { uxToHex } from '~/logic/lib/util';
|
||||||
import { GcpState, S3State, BackgroundConfig } from '~/types';
|
import { StorageState, BackgroundConfig } from '~/types';
|
||||||
import { BackgroundPicker, BgType } from './BackgroundPicker';
|
import { BackgroundPicker, BgType } from './BackgroundPicker';
|
||||||
import useLocalState, { LocalState } from '~/logic/state/local';
|
import useLocalState, { LocalState } from '~/logic/state/local';
|
||||||
|
|
||||||
@ -34,12 +34,11 @@ interface FormSchema {
|
|||||||
|
|
||||||
interface DisplayFormProps {
|
interface DisplayFormProps {
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DisplayForm(props: DisplayFormProps) {
|
export default function DisplayForm(props: DisplayFormProps) {
|
||||||
const { api, gcp, s3 } = props;
|
const { api, storage } = props;
|
||||||
|
|
||||||
const { hideAvatars, hideNicknames, background, set: setLocalState } = useLocalState();
|
const { hideAvatars, hideNicknames, background, set: setLocalState } = useLocalState();
|
||||||
|
|
||||||
@ -95,8 +94,7 @@ export default function DisplayForm(props: DisplayFormProps) {
|
|||||||
bgType={props.values.bgType}
|
bgType={props.values.bgType}
|
||||||
bgUrl={props.values.bgUrl}
|
bgUrl={props.values.bgUrl}
|
||||||
api={api}
|
api={api}
|
||||||
gcp={gcp}
|
storage={storage}
|
||||||
s3={s3}
|
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Disable avatars"
|
label="Disable avatars"
|
||||||
|
@ -13,8 +13,7 @@ type ProfileProps = StoreState & { api: GlobalApi; ship: string };
|
|||||||
|
|
||||||
export default function Settings({
|
export default function Settings({
|
||||||
api,
|
api,
|
||||||
gcp,
|
storage,
|
||||||
s3
|
|
||||||
}: ProfileProps) {
|
}: ProfileProps) {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -28,11 +27,10 @@ export default function Settings({
|
|||||||
>
|
>
|
||||||
<DisplayForm
|
<DisplayForm
|
||||||
api={api}
|
api={api}
|
||||||
gcp={gcp}
|
storage={storage}
|
||||||
s3={s3}
|
|
||||||
/>
|
/>
|
||||||
<RemoteContentForm api={api} />
|
<RemoteContentForm api={api} />
|
||||||
<S3Form api={api} s3={s3} />
|
<S3Form api={api} s3={storage.s3} />
|
||||||
<SecuritySettings api={api} />
|
<SecuritySettings api={api} />
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -10,22 +10,20 @@ import {
|
|||||||
BaseInput
|
BaseInput
|
||||||
} from "@tlon/indigo-react";
|
} from "@tlon/indigo-react";
|
||||||
import { useField } from "formik";
|
import { useField } from "formik";
|
||||||
import { S3State } from "~/types/s3-update";
|
import { StorageState } from "~/types/storage-state";
|
||||||
import { GcpState } from "~/types/gcp-state";
|
|
||||||
import useStorage from "~/logic/lib/useStorage";
|
import useStorage from "~/logic/lib/useStorage";
|
||||||
|
|
||||||
type ImageInputProps = Parameters<typeof Box>[0] & {
|
type ImageInputProps = Parameters<typeof Box>[0] & {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
s3: S3State;
|
storage: StorageState;
|
||||||
gcp: GcpState;
|
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function ImageInput(props: ImageInputProps) {
|
export function ImageInput(props: ImageInputProps) {
|
||||||
const { id, label, s3, gcp, caption, placeholder, ...rest } = props;
|
const { id, label, storage, caption, placeholder, ...rest } = props;
|
||||||
|
|
||||||
const { uploadDefault, canUpload, uploading } = useStorage(s3, gcp);
|
const { uploadDefault, canUpload, uploading } = useStorage(storage);
|
||||||
|
|
||||||
const [field, meta, { setValue, setError }] = useField(id);
|
const [field, meta, { setValue, setError }] = useField(id);
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import useStorage from "~/logic/lib/useStorage";
|
|||||||
|
|
||||||
const withStorage = (Component, params = {}) => {
|
const withStorage = (Component, params = {}) => {
|
||||||
return React.forwardRef((props: any, ref) => {
|
return React.forwardRef((props: any, ref) => {
|
||||||
const storage = useStorage(props.s3, props.gcp, params);
|
const storage = useStorage(props.storage, params);
|
||||||
|
|
||||||
return <Component ref={ref} {...storage} {...props} />;
|
return <Component ref={ref} {...storage} {...props} />;
|
||||||
});
|
});
|
||||||
|
@ -22,7 +22,7 @@ import { ColorInput } from "~/views/components/ColorInput";
|
|||||||
import { useHistory } from "react-router-dom";
|
import { useHistory } from "react-router-dom";
|
||||||
|
|
||||||
import { uxToHex } from "~/logic/lib/util";
|
import { uxToHex } from "~/logic/lib/util";
|
||||||
import {GcpState, S3State} from "~/types";
|
import {StorageState} from "~/types";
|
||||||
import {ImageInput} from "~/views/components/ImageInput";
|
import {ImageInput} from "~/views/components/ImageInput";
|
||||||
|
|
||||||
interface FormSchema {
|
interface FormSchema {
|
||||||
@ -46,12 +46,11 @@ interface GroupAdminSettingsProps {
|
|||||||
group: Group;
|
group: Group;
|
||||||
association: Association;
|
association: Association;
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GroupAdminSettings(props: GroupAdminSettingsProps) {
|
export function GroupAdminSettings(props: GroupAdminSettingsProps) {
|
||||||
const { group, association, gcp, s3 } = props;
|
const { group, association, storage } = props;
|
||||||
const { metadata } = association;
|
const { metadata } = association;
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const currentPrivate = "invite" in props.group.policy;
|
const currentPrivate = "invite" in props.group.policy;
|
||||||
@ -133,8 +132,7 @@ export function GroupAdminSettings(props: GroupAdminSettingsProps) {
|
|||||||
caption="A picture for your group"
|
caption="A picture for your group"
|
||||||
placeholder="Enter URL"
|
placeholder="Enter URL"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
gcp={gcp}
|
storage={storage}
|
||||||
s3={s3}
|
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="isPrivate"
|
id="isPrivate"
|
||||||
|
@ -6,7 +6,7 @@ import GlobalApi from "~/logic/api/global";
|
|||||||
|
|
||||||
import { GroupAdminSettings } from "./Admin";
|
import { GroupAdminSettings } from "./Admin";
|
||||||
import { GroupPersonalSettings } from "./Personal";
|
import { GroupPersonalSettings } from "./Personal";
|
||||||
import { GroupNotificationsConfig, GcpState, S3State } from "~/types";
|
import { GroupNotificationsConfig, StorageState } from "~/types";
|
||||||
import { GroupChannelSettings } from "./Channels";
|
import { GroupChannelSettings } from "./Channels";
|
||||||
import { useHistory } from "react-router-dom";
|
import { useHistory } from "react-router-dom";
|
||||||
import {resourceFromPath, roleForShip} from "~/logic/lib/group";
|
import {resourceFromPath, roleForShip} from "~/logic/lib/group";
|
||||||
@ -21,8 +21,7 @@ interface GroupSettingsProps {
|
|||||||
associations: Associations;
|
associations: Associations;
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
notificationsGroupConfig: GroupNotificationsConfig;
|
notificationsGroupConfig: GroupNotificationsConfig;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
}
|
}
|
||||||
export function GroupSettings(props: GroupSettingsProps) {
|
export function GroupSettings(props: GroupSettingsProps) {
|
||||||
|
@ -71,8 +71,7 @@ export function GroupsPane(props: GroupsPaneProps) {
|
|||||||
association={groupAssociation!}
|
association={groupAssociation!}
|
||||||
group={group!}
|
group={group!}
|
||||||
api={api}
|
api={api}
|
||||||
gcp={props.gcp}
|
storage={props.storage}
|
||||||
s3={props.s3}
|
|
||||||
notificationsGroupConfig={props.notificationsGroupConfig}
|
notificationsGroupConfig={props.notificationsGroupConfig}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
|
|
||||||
|
@ -6,12 +6,7 @@ import { Contacts, Contact } from "~/types/contact-update";
|
|||||||
import { Group } from "~/types/group-update";
|
import { Group } from "~/types/group-update";
|
||||||
import { Association } from "~/types/metadata-update";
|
import { Association } from "~/types/metadata-update";
|
||||||
import GlobalApi from "~/logic/api/global";
|
import GlobalApi from "~/logic/api/global";
|
||||||
import {
|
import { GroupNotificationsConfig, StorageState, Associations } from "~/types";
|
||||||
GroupNotificationsConfig,
|
|
||||||
GcpState,
|
|
||||||
S3State,
|
|
||||||
Associations
|
|
||||||
} from "~/types";
|
|
||||||
|
|
||||||
import { GroupSettings } from "./GroupSettings/GroupSettings";
|
import { GroupSettings } from "./GroupSettings/GroupSettings";
|
||||||
import { Participants } from "./Participants";
|
import { Participants } from "./Participants";
|
||||||
@ -28,8 +23,7 @@ export function PopoverRoutes(
|
|||||||
group: Group;
|
group: Group;
|
||||||
association: Association;
|
association: Association;
|
||||||
associations: Associations;
|
associations: Associations;
|
||||||
gcp: GcpState;
|
storage: StorageState;
|
||||||
s3: S3State;
|
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
notificationsGroupConfig: GroupNotificationsConfig;
|
notificationsGroupConfig: GroupNotificationsConfig;
|
||||||
rootIdentity: Contact;
|
rootIdentity: Contact;
|
||||||
@ -133,8 +127,7 @@ export function PopoverRoutes(
|
|||||||
api={props.api}
|
api={props.api}
|
||||||
notificationsGroupConfig={props.notificationsGroupConfig}
|
notificationsGroupConfig={props.notificationsGroupConfig}
|
||||||
associations={props.associations}
|
associations={props.associations}
|
||||||
gcp={props.gcp}
|
storage={props.storage}
|
||||||
s3={props.s3}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{view === "participants" && (
|
{view === "participants" && (
|
||||||
|
Loading…
Reference in New Issue
Block a user