Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/guest-app/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<div id="__filepicker"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
Expand Down
72 changes: 37 additions & 35 deletions examples/guest-app/src/App.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,33 @@
import React from 'react';
import { AppProvider, gql } from '8base-react-sdk';
import { Query } from 'react-apollo';
import { AppProvider, FileInput } from '8base-react-sdk';
import { ApolloLink } from 'apollo-link';

// 8base api endpoint
const API_ENDPOINT_URI = 'https://api.8base.com/cjxotvdpv006501l68k94dz80';

// Guest can query specific tables if he is allowed
const CAT_BREEDS_LIST_QUERY = gql`
query CatBreedsList {
catBreedsList {
items {
id
name
}
}
}
`;

const CatBreeds = ({ loading, data }) => {
if (loading) {
return <p>Loading...</p>;
}

return (
<div>
<h2>Cat breeds</h2>
<ul>
{ data.catBreedsList.items.map(
({ id, name }) => <li><p key={ id }>{ name }</p></li>
) }
</ul>
</div>
);
};
// const API_ENDPOINT_URI = 'https://api.8base.com/cjxotvdpv006501l68k94dz80';
// AWS
const API_ENDPOINT_URI = 'https://staging-api.8basedev.com/ckol7pw34004008k174kfhmt4';
const TOKENT = '83cd5898-0b2e-42df-a3ff-3139d435758b';

// FILESTACK
// const API_ENDPOINT_URI = 'https://staging-api.8basedev.com/ckpcn6bqx092g08mihor93cru';
// const TOKENT = '1e3493c8-0ce6-4c5e-88e0-f6ca195f8cc1';


const muLink = new ApolloLink((operation, forward) => {
operation.setContext(({ headers = {} }) => {
return {
headers: {
...headers,
authorization: TOKENT,
},
};
});

return forward && forward(operation);
});

const App = () => (
<AppProvider uri={ API_ENDPOINT_URI }>
<AppProvider uri={ API_ENDPOINT_URI } extendLinks={(links) => [muLink, ...links,]} >
{ ({ loading }) => {
if (loading) {
return <p>Loading...</p>;
Expand All @@ -44,9 +36,19 @@ const App = () => (
return (
<React.Fragment>
<h1>Guest App</h1>
<Query query={ CAT_BREEDS_LIST_QUERY }>
{/* <Query query={ CAT_BREEDS_LIST_QUERY }>
{ ({ loading, data }) => <CatBreeds loading={ loading } data={ data } /> }
</Query>
</Query> */}
<FileInput onUploadDone={(val) => console.log('onUploadDone', val)} >
{({pick, value}) => (
<>
<button onClick={() => pick({})}>CLICK</button>
<pre>
{Array.isArray(value) ? value.map(el => <div><a href={el.downloadUrl} >{el.filename}</a></div>) : value && <a href={value.downloadUrl} >{value.filename}</a>}
</pre>
</>
)}
</FileInput>
</React.Fragment>
);
} }
Expand Down
4 changes: 3 additions & 1 deletion packages/file-input/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
"react-dom": "^16.8.6"
},
"dependencies": {
"@emotion/css": "^11.1.3",
"filestack-js": "3.7.0",
"graphql-tag": "^2.10.0"
"graphql-tag": "^2.10.0",
"react-dropzone": "^11.3.4"
},
"devDependencies": {
"@babel/core": "^7.4.3",
Expand Down
135 changes: 135 additions & 0 deletions packages/file-input/src/FileInput.aws.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import React, { useCallback, useEffect, useState } from 'react';

import { PickerOptions } from 'filestack-js';

import { AWSFileInputProps } from 'src/types';

import { Modal, FilePickerContent } from './components';
import { useFilePicker } from './hooks';

const UNSUPPORTED_OPTIONS = [
'allowManualRetry',
'fromSources',
'container',
'cleanupImageExif',
'customAuthText',
'displayMode', // may be implemented in the future
'customSourceContainer',
'customSourcePath',
'customSourceName',
'customText',
'disableStorageKey',
'disableTransformer', // true by default
'disableThumbnails', // false by default, may be implemented in the future
'dropPane',
'exposeOriginalFile',
'globalDropZone',
'hideModalWhenUploading', // may be implemented in the future
'imageDim',
'imageMax',
'imageMin',
'lang', // may be implemented in the future
'viewType', // may be implemented in the future
'errorsTimeout',
'modalSize', // may be implemented in the future
'rootId',
'startUploadingWhenMaxFilesReached', // may be implemented in the future
'storeTo',
'transformations', // may be implemented in the future
'uploadConfig',
'uploadInBackground', // may be implemented in the future
'videoResolution', // may be implemented in the future
'minFiles', // may be implemented in the future
];

const warnAboutOptions = (options: PickerOptions = {}) => {
if ('maxFiles' in options) {
console.warn('@8base-react/file-input: Specify "maxFiles" as a prop for FileInput component');
}

if ('onUploadDone' in options) {
console.warn(
'@8base-react/file-input: Specify "onUploadDone" as a prop for FileInput component',
);
}

setTimeout(() => {
UNSUPPORTED_OPTIONS.forEach(optionKey => {
if (optionKey in options) {
console.warn(`@8base-react/file-input: ${optionKey} option is not supported yet`);
}
});
}, 0);
};

export const FileInputAws: React.FC<AWSFileInputProps> = ({
children,
maxFiles,
fallbackOptions,
value: controlledValue = null,
onUploadDone: uploadCallback,
onChange,
}) => {
const [calledFallback, setCalledFallback] = useState<boolean>(false);
const {
fileList,
fileProgressList,
isOpen,
hideFilePicker,
showFilePicker,
addFiles,
removeFile,
step,
setUploadMoreStep,
setUploadStep,
upload,
getRootProps,
getInputProps,
options,
value,
originalFile,
error,
} = useFilePicker({ uploadCallback, controlledValue, onChange });

const pick = useCallback(
(pickerOptions: PickerOptions = {}) => {
warnAboutOptions(options);
showFilePicker({ ...pickerOptions, maxFiles });
},
[showFilePicker, maxFiles, options],
);

useEffect(() => {
if (calledFallback) {
return;
}

if (fallbackOptions) {
pick(fallbackOptions);
}

setCalledFallback(true);
}, [fallbackOptions, calledFallback, pick]);

return (
<>
<Modal isOpen={isOpen} onClose={hideFilePicker}>
<FilePickerContent
step={step}
hideFilePicker={hideFilePicker}
addFiles={addFiles}
fileList={fileList}
setUploadStep={setUploadStep}
removeFile={removeFile}
setUploadMoreStep={setUploadMoreStep}
upload={upload}
fileProgressList={fileProgressList}
getInputProps={getInputProps}
getRootProps={getRootProps}
options={options}
/>
</Modal>
{children({ pick, value, originalFile, error })}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { withApollo, WithApolloClient } from 'react-apollo';
import { ApolloClient } from 'apollo-client';
import * as filestack from 'filestack-js';
import gql from 'graphql-tag';
import { FileInputProps, FileInputState } from './types';
import { FilestackFileInputProps as FileInputProps, FileInputState } from './types';

const FILE_UPLOAD_INFO_QUERY = gql`
query FileUploadInfo {
Expand All @@ -16,7 +16,7 @@ const FILE_UPLOAD_INFO_QUERY = gql`
}
`;

const FileInput: React.ComponentType<FileInputProps> = withApollo(
const FileInputFilestack: React.ComponentType<FileInputProps> = withApollo(
// @ts-ignore
class FileInput extends React.Component<WithApolloClient<FileInputProps>, FileInputState> {
public static defaultProps = {
Expand Down Expand Up @@ -51,6 +51,9 @@ const FileInput: React.ComponentType<FileInputProps> = withApollo(

public componentDidMount() {
this.filestackPromise = this.initFilestack();
if (this.props.fallbackOptions) {
this.pick(this.props.fallbackOptions);
}
}

public async initFilestack() {
Expand Down Expand Up @@ -169,4 +172,4 @@ const FileInput: React.ComponentType<FileInputProps> = withApollo(
},
);

export { FileInput };
export { FileInputFilestack };
71 changes: 71 additions & 0 deletions packages/file-input/src/FileInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useState } from 'react';

import { PickerOptions } from 'filestack-js';
import gql from 'graphql-tag';
import { useQuery } from 'react-apollo';

import { FileInputAws } from './FileInput.aws';
import { FileInputFilestack } from './FileInput.filestack';
import { AWSFileInputProps, CommonFileInputProps, RenderPropType } from './types';

type FileManagementProviderResponse = {
system: {
environmentSettings: {
fileManagementProvider: string;
};
};
};

const FALLBACK_PROPS = {
value: null,
originalFile: null,
error: null,
loading: true,
};

const FILE_MANAGEMENT_PROVIDER_QUERY = gql`
query FileManagementProvider {
system {
environmentSettings {
fileManagementProvider
}
}
}
`;

const AWS_PROVIDER_NAME = 'aws';

const checkAWSProvider = (data: FileManagementProviderResponse | undefined) => {
const provider =
data &&
data.system &&
data.system.environmentSettings &&
data.system.environmentSettings.fileManagementProvider;
return provider === AWS_PROVIDER_NAME;
};

/**
* This component check the workspace file provider
* and selects which type of filepicker to use - filestack or 8base
*/
export const FileInput: React.FC<CommonFileInputProps | AWSFileInputProps> = props => {
// need to open picker after finish query
const [fallbackOptions, setFallbackOptions] = useState<PickerOptions | undefined>();
const { data, loading } = useQuery<FileManagementProviderResponse>(
FILE_MANAGEMENT_PROVIDER_QUERY,
{ fetchPolicy: props.fetchPolicy },
);

if (loading) {
return props.children({
...FALLBACK_PROPS,
pick: setFallbackOptions as RenderPropType['pick'],
});
}

if (checkAWSProvider(data)) {
return <FileInputAws {...(props as AWSFileInputProps)} fallbackOptions={fallbackOptions} />;
}

return <FileInputFilestack {...props} fallbackOptions={fallbackOptions} />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const STEPS = {
select: 'select',
upload: 'upload',
uploadMore: 'uploadMore',
uploading: 'uploading',
} as const;

export type StepType = keyof typeof STEPS;
1 change: 1 addition & 0 deletions packages/file-input/src/components/FilePicker/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { FilePickerContent } from './view/FilePicker.content'
22 changes: 22 additions & 0 deletions packages/file-input/src/components/FilePicker/view/CloseIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';

import { css } from '@emotion/css';

const closeIconCss = css`
width: 24px;
height: 24px;
display: block;
`;

export const CloseIcon = () => (
<i className={closeIconCss}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path
d="m23.542371 10.62753-1.491936-1.4919365-5.914843 5.9148425-5.914843-5.9148425-1.4919365 1.4919365 5.9148425 5.914843-5.9148425 5.914843 1.4919365 1.491936 5.914843-5.914842 5.914843 5.914842 1.491936-1.491936-5.914842-5.914843z"
fill="#656565"
fillRule="evenodd"
strokeWidth="1.058111"
/>
</svg>
</i>
);
Loading