mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-06 18:21:12 +00:00
Merge pull request #463 from storytold/feature/page_st_filter
Feature/page st filter
This commit is contained in:
15 files changed
+463
-11
No files matched your search
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import { useLocalize } from "hooks";
|
||||
export default function Error({message}:{message?:string}){
|
||||
const {t} = useLocalize("App")
|
||||
return (
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<h1>{message ? message : t("error.unknownError")}</h1>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -21,12 +21,14 @@ interface SelectModalProps {
|
||||
label?: string;
|
||||
tabs: TabConfig[];
|
||||
modalTitle?: string;
|
||||
onSelect?: (token: string)=>void;
|
||||
}
|
||||
|
||||
const SelectModal = memo(
|
||||
({ label, tabs, modalTitle = "Select" }: SelectModalProps) => {
|
||||
({ label, tabs, modalTitle = "Select", onSelect }: SelectModalProps) => {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const { token, setToken, weightTitle, setWeightTitle } = useToken();
|
||||
const [selectedValue, setSelectedValue] = useState("");
|
||||
const [activeTab, setActiveTab] = useState(tabs[0].tabKey);
|
||||
const [mediaType, setMediaType] = useState(
|
||||
tabs[0].mediaTypeFilter || "all"
|
||||
@@ -42,6 +44,16 @@ const SelectModal = memo(
|
||||
setWeightType(currentTab?.mediaTypeFilter || "all");
|
||||
}, [activeTab, tabs]);
|
||||
|
||||
useEffect(()=>{
|
||||
if(token && token !== selectedValue && onSelect){
|
||||
setSelectedValue(token);
|
||||
onSelect(token);
|
||||
}else if(weightTitle && weightTitle !== selectedValue && onSelect){
|
||||
setSelectedValue(weightTitle);
|
||||
onSelect(weightTitle);
|
||||
}
|
||||
}, [token, weightTitle, selectedValue, onSelect]);
|
||||
|
||||
const openModal = () => {
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import Button from "./Button";
|
||||
import Checkbox from "./Checkbox";
|
||||
import Container from "./Container";
|
||||
import CoverImageInput from "./CoverImageInput";
|
||||
import ErrorMessage from "./ErrorMessage"
|
||||
import FileActions from "./FileActions";
|
||||
import FileDetails from "./FileDetails";
|
||||
import FileWrapper from "./FileWrapper";
|
||||
@@ -22,11 +23,13 @@ import Skeleton from "./Skeleton";
|
||||
import Slider from "./Slider";
|
||||
import Spinner from "./Spinner";
|
||||
import SplitPanel from "./SplitPanel";
|
||||
import Tabs from "./Tabs";
|
||||
import TempAudioPlayer from "./TempAudioPlayer";
|
||||
import TempInput from "./TempInput";
|
||||
import TempSelect from "./TempSelect";
|
||||
import TempTextArea from "./TempTextArea";
|
||||
import TintSpinner from "./TintSpinner";
|
||||
import VideoInput from "./VideoInput";
|
||||
|
||||
export {
|
||||
AudioBlobPreview,
|
||||
@@ -36,6 +39,7 @@ export {
|
||||
Checkbox,
|
||||
Container,
|
||||
CoverImageInput,
|
||||
ErrorMessage,
|
||||
FileActions,
|
||||
FileDetails,
|
||||
FileWrapper,
|
||||
@@ -53,9 +57,11 @@ export {
|
||||
Slider,
|
||||
Spinner,
|
||||
SplitPanel,
|
||||
Tabs,
|
||||
TempAudioPlayer,
|
||||
TempInput,
|
||||
TempSelect,
|
||||
TempTextArea,
|
||||
TintSpinner
|
||||
TintSpinner,
|
||||
VideoInput
|
||||
};
|
||||
@@ -108,6 +108,7 @@ import UploadSdWeightPage from "./pages/upload/UploadSdWeightPage";
|
||||
import { FooterNav } from "./nav/FooterNav";
|
||||
import FbxToGltfPage from "./pages/fbx_to_gltf/FbxToGltfPage";
|
||||
import UploadLoraWeightPage from "./pages/upload/UploadLoraWeightPage";
|
||||
import StorytellerFilterPage from "./pages/storyteller_filter/StorytellerFilter";
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper;
|
||||
@@ -818,6 +819,19 @@ class PageContainer extends React.Component<
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/storyteller-filter/:mediaToken?">
|
||||
<StorytellerFilterPage
|
||||
{...{
|
||||
enqueueInferenceJob: this.props.enqueueInferenceJob,
|
||||
sessionSubscriptionsWrapper:
|
||||
this.props.sessionSubscriptionsWrapper,
|
||||
inferenceJobs: this.props.inferenceJobs,
|
||||
inferenceJobsByCategory:
|
||||
this.props.inferenceJobsByCategory,
|
||||
}}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/character/donald-trump">
|
||||
<TrumpTtsPage
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import React, {useReducer } from 'react';
|
||||
|
||||
import { useLocalize } from "hooks";
|
||||
import { FrontendInferenceJobType, InferenceJob } from '@storyteller/components/src/jobs/InferenceJob';
|
||||
|
||||
import { Container, ErrorMessage } from "components/common";
|
||||
import PageHeader from "components/layout/PageHeader";
|
||||
|
||||
import PageVideoProvision from './components/pageVideoProvision';
|
||||
import PageFilterControls from './components/pageFilterControls';
|
||||
import { states, reducer } from "./storytellerFilterReducer";
|
||||
|
||||
|
||||
export default function StorytellerFilter(props:{
|
||||
enqueueInferenceJob: (
|
||||
jobToken: string,
|
||||
frontendInferenceJobType: FrontendInferenceJobType
|
||||
) => void;
|
||||
inferenceJobs: Array<InferenceJob>;
|
||||
inferenceJobsByCategory: Map<FrontendInferenceJobType, Array<InferenceJob>>;
|
||||
}){
|
||||
const debug=true;
|
||||
const { t } = useLocalize("StorytellerFilter");
|
||||
const { NO_FILE, FILE_STAGED, FILE_UPLOADING, FILE_UPLOADED, FILE_SELECTED, FILE_LOADING, FILE_LOADED } = states;
|
||||
const [pageState, dispatchPageState] = useReducer(reducer, {
|
||||
status: NO_FILE,
|
||||
});
|
||||
|
||||
const pagePicker = () => {
|
||||
switch (pageState.status){
|
||||
case NO_FILE:
|
||||
case FILE_STAGED:
|
||||
case FILE_UPLOADING:
|
||||
case FILE_SELECTED:
|
||||
return <PageVideoProvision {...{debug, t, pageState, dispatchPageState}}/>
|
||||
case FILE_UPLOADED:
|
||||
case FILE_LOADING:
|
||||
case FILE_LOADED:
|
||||
return <PageFilterControls {...{debug, t, pageState, dispatchPageState}}/>
|
||||
default:
|
||||
return <ErrorMessage/>
|
||||
}
|
||||
}
|
||||
const currPage = pagePicker();
|
||||
|
||||
return(
|
||||
<Container type="panel" className="mb-5">
|
||||
<PageHeader
|
||||
title={t("headings.title")}
|
||||
subText={t("headings.subtitle")}
|
||||
// imageUrl="/images/header/video-mocap.png"
|
||||
/>
|
||||
{currPage}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
import React from "react";
|
||||
import { useMedia } from "hooks";
|
||||
import { BucketConfig } from "@storyteller/components/src/api/BucketConfig";
|
||||
import { states, Action, State } from "../storytellerFilterReducer";
|
||||
import { BasicVideo, ErrorMessage, Panel, Spinner } from "components/common";
|
||||
|
||||
export default function PageFilterControls({
|
||||
debug=false, t, pageState, dispatchPageState
|
||||
}: {
|
||||
debug?: boolean;
|
||||
t: Function;
|
||||
pageState: State;
|
||||
dispatchPageState: (action: Action) => void;
|
||||
}) {
|
||||
useMedia({
|
||||
mediaToken: pageState.mediaFileToken,
|
||||
onSuccess: (res: any) => {
|
||||
// ratings.gather({ res, key: "token" });
|
||||
console.log(res)
|
||||
dispatchPageState({
|
||||
type: 'loadFileSuccess',
|
||||
payload: {mediaFile: res}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
if (pageState.mediaFile){
|
||||
const mediaLink = new BucketConfig().getGcsUrl(pageState.mediaFile.public_bucket_path);
|
||||
if (mediaLink)
|
||||
return(
|
||||
<Panel>
|
||||
<div className="row g-3 p-3">
|
||||
{/* <h1>{t("message.fileUploaded")}</h1> */}
|
||||
{debug && <p>{`File Token: ${pageState.mediaFileToken}`}</p> }
|
||||
<div className="col-6">
|
||||
<BasicVideo src={mediaLink} />
|
||||
</div>
|
||||
<div className="col-6">
|
||||
<BasicVideo src={mediaLink} />
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
);
|
||||
}else if (pageState.status <= states.FILE_LOADING){
|
||||
return (
|
||||
<Panel>
|
||||
{debug && <p>{`File Token: ${pageState.mediaFileToken}`}</p> }
|
||||
<p>Loading Files</p>
|
||||
<Spinner />
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
return <ErrorMessage />;
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
import React from "react";
|
||||
import { Redirect, useLocation } from "react-router-dom";
|
||||
|
||||
import { BasicVideo, Panel, Tabs } from "components/common";
|
||||
|
||||
import { Action, State } from "../storytellerFilterReducer";
|
||||
import TabContentUpload from "./tabContentUpload";
|
||||
import TabContentLibrary from "./tabContentLibrary";
|
||||
|
||||
export default function PageVideoProvision({
|
||||
debug=false, t, pageState, dispatchPageState
|
||||
}: {
|
||||
debug?: boolean;
|
||||
t: Function;
|
||||
pageState: State;
|
||||
dispatchPageState: (action: Action) => void;
|
||||
}) {
|
||||
const tabs = [
|
||||
{
|
||||
label: t("tabTitle.upload"),
|
||||
content: <TabContentUpload {...{
|
||||
debug, t, pageState, dispatchPageState
|
||||
}} />,
|
||||
to: "/storyteller-filter/upload",
|
||||
padding: true,
|
||||
},
|
||||
{
|
||||
label: t("tabTitle.library"),
|
||||
content: <TabContentLibrary {...{
|
||||
debug, t, pageState, dispatchPageState
|
||||
}} />,
|
||||
to: "/storyteller-filter/select-media",
|
||||
padding: true,
|
||||
},
|
||||
];
|
||||
|
||||
//pick default tab using pathname
|
||||
const { pathname } = useLocation();
|
||||
if (pathname === "/storyteller-filter" || pathname === "/storyteller-filter/") {
|
||||
return <Redirect to={"/storyteller-filter/upload"} />;
|
||||
}
|
||||
|
||||
return(
|
||||
<Panel>
|
||||
<div className="row g-0">
|
||||
<div className="col-12 col-md-6">
|
||||
<Tabs tabs={tabs} />
|
||||
</div>
|
||||
<div className="col-12 col-md-6">
|
||||
<Panel padding={true} clear={true}>
|
||||
<BasicVideo
|
||||
title={t("video.sample")}
|
||||
src="/videos/face-animator-instruction-en.mp4"
|
||||
/>
|
||||
</Panel>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
import SelectModal from "components/common/SelectModal/SelectModal";
|
||||
import React from "react";
|
||||
import { states, Action, State } from "../storytellerFilterReducer";
|
||||
import { Button } from "components/common";
|
||||
export default function TabContentLibrary({
|
||||
t, pageState, dispatchPageState
|
||||
}: {
|
||||
t: Function;
|
||||
pageState: State;
|
||||
dispatchPageState: (action: Action) => void;
|
||||
}){
|
||||
|
||||
const handleProceed = ()=>{
|
||||
dispatchPageState({type: "loadFile"})
|
||||
}
|
||||
const handleOnSelect = (token:string)=>{
|
||||
dispatchPageState({
|
||||
type: "selectedFile",
|
||||
payload: {mediaFileToken: token}
|
||||
});
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<SelectModal
|
||||
modalTitle="Select a Video"
|
||||
label="Select a Video"
|
||||
onSelect={handleOnSelect}
|
||||
tabs={[
|
||||
{
|
||||
label: "All Videos",
|
||||
tabKey: "allVideos",
|
||||
mediaTypeFilter: "video",
|
||||
searcher: false,
|
||||
type: "media",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{pageState.status === states.FILE_SELECTED &&
|
||||
<Button
|
||||
label={t("button.proceed")}
|
||||
onClick={handleProceed}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
import React from "react";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import { UploadMedia } from "@storyteller/components/src/api/media_files/UploadMedia";
|
||||
import { useFile } from "hooks";
|
||||
import { ErrorMessage, VideoInput, Spinner } from "components/common";
|
||||
import { states, Action, State } from "../storytellerFilterReducer";
|
||||
|
||||
export default function TabContentUpload({
|
||||
debug=false, t, pageState, dispatchPageState
|
||||
}: {
|
||||
debug?: boolean;
|
||||
t: Function;
|
||||
pageState: State;
|
||||
dispatchPageState: (action: Action) => void;
|
||||
}) {
|
||||
const videoProps = useFile({});
|
||||
const {NO_FILE, FILE_STAGED, FILE_UPLOADING} = states;
|
||||
|
||||
const makeVideoUploadRequest = () => ({
|
||||
uuid_idempotency_token: uuidv4(),
|
||||
file: videoProps.file,
|
||||
source: "file",
|
||||
type: "video",
|
||||
});
|
||||
|
||||
const handleUploadVideo = () => {
|
||||
dispatchPageState({type: 'uploadFile'});
|
||||
UploadMedia(makeVideoUploadRequest()).then(res => {
|
||||
if (res.success && res.media_file_token) {
|
||||
dispatchPageState({
|
||||
type: 'uploadFileSuccess',
|
||||
payload:{
|
||||
mediaFileToken :res.media_file_token
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// contains upload inout state and controls, see docs
|
||||
if (pageState.status === NO_FILE || pageState.status === FILE_STAGED) {
|
||||
return (
|
||||
<>
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<VideoInput
|
||||
{...{
|
||||
t,
|
||||
...videoProps,
|
||||
onStateChange: () =>{
|
||||
if (pageState.status === NO_FILE && videoProps.file)
|
||||
dispatchPageState({type: "stagedFile"})
|
||||
else if (pageState.status === FILE_STAGED && !videoProps.file)
|
||||
dispatchPageState({type: "clearedFile"})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row py-3">
|
||||
<div className="col-12">
|
||||
<div className="d-flex justify-content-end gap-3">
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
disabled={pageState.status !== FILE_STAGED}
|
||||
onClick={handleUploadVideo}
|
||||
>
|
||||
{t("button.upload")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}else if (pageState.status === FILE_UPLOADING){
|
||||
return(
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<h1>{t("message.fileUploading")}</h1>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<Spinner />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <ErrorMessage />;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './StorytellerFilter';
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
import { MediaFile } from "@storyteller/components/src/api/media_files/GetMediaFile";
|
||||
|
||||
export enum states{
|
||||
NO_FILE,
|
||||
FILE_STAGED,
|
||||
FILE_SELECTED,
|
||||
FILE_UPLOADING,
|
||||
FILE_UPLOADED,
|
||||
FILE_LOADING,
|
||||
FILE_LOADED,
|
||||
}
|
||||
|
||||
export type State = {
|
||||
status: number;
|
||||
mediaFileToken?: string;
|
||||
mediaFile?: MediaFile;
|
||||
inferenceJobToken?: string;
|
||||
}
|
||||
|
||||
export type Action =
|
||||
| {type: 'stagedFile'}
|
||||
| {type: 'clearedFile'}
|
||||
| {type: 'selectedFile', payload: { mediaFileToken: string}}
|
||||
| {type: 'uploadFile'}
|
||||
| {type: 'uploadFileSuccess', payload:{ mediaFileToken: string}}
|
||||
| {type: 'loadFile'}
|
||||
| {type: 'loadFileSuccess', payload:{mediaFile: MediaFile}}
|
||||
|
||||
|
||||
export function reducer (state: State, action: Action): State {
|
||||
console.log(action);
|
||||
switch(action.type){
|
||||
case 'stagedFile':
|
||||
return {...state, status: states.FILE_STAGED}
|
||||
case 'clearedFile':
|
||||
return {...state, status: states.NO_FILE}
|
||||
case 'selectedFile':
|
||||
return {
|
||||
...state,
|
||||
status: states.FILE_SELECTED,
|
||||
mediaFileToken: action.payload.mediaFileToken
|
||||
}
|
||||
case 'uploadFile':
|
||||
return {...state,status: states.FILE_UPLOADING};
|
||||
case 'uploadFileSuccess':
|
||||
return {
|
||||
...state,
|
||||
status: states.FILE_UPLOADED,
|
||||
mediaFileToken: action.payload.mediaFileToken
|
||||
}
|
||||
case 'loadFile':
|
||||
return {...state, status: states.FILE_LOADING}
|
||||
case 'loadFileSuccess':
|
||||
console.log("LOAD FILE SUCCESS");
|
||||
return {
|
||||
...state,
|
||||
status: states.FILE_LOADED,
|
||||
mediaFile: action.payload.mediaFile
|
||||
}
|
||||
default:
|
||||
return {status: states.NO_FILE};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,8 @@ import {
|
||||
InferenceJob,
|
||||
} from "@storyteller/components/src/jobs/InferenceJob";
|
||||
|
||||
import { BasicVideo, Button, Container, Panel } from "components/common";
|
||||
import { BasicVideo, Button, Container, Panel, Tabs } from "components/common";
|
||||
import PageHeader from "components/layout/PageHeader";
|
||||
import Tabs from "components/common/Tabs";
|
||||
import { useInferenceJobs, useLocalize } from "hooks";
|
||||
|
||||
import TabContentUpload from "./components/tabContentUpload";
|
||||
@@ -130,7 +129,9 @@ export default function VideoMotionCapture(props: {
|
||||
icon={faArrowRotateLeft}
|
||||
iconFlip={true}
|
||||
label="Generate Another"
|
||||
onClick={() => {}} //back to first state
|
||||
onClick={() => {
|
||||
dispatchPageState({type:"restart"})
|
||||
}} //back to first state
|
||||
variant="primary"
|
||||
/>
|
||||
</div>
|
||||
|
||||
+6
-2
@@ -21,8 +21,8 @@ export default function PageVideoMocapProgress({
|
||||
pageState: State;
|
||||
dispatchPageState: (action: Action) => void;
|
||||
}) {
|
||||
const { FILE_UPLOADING, FILE_UPLOADED, MOCAPNET_ENQUEUEING } = states;
|
||||
|
||||
const { FILE_UPLOADING, FILE_UPLOADED, FILE_SELECTED, MOCAPNET_ENQUEUEING } = states;
|
||||
|
||||
const handleEnqueueMocapNet = () => {
|
||||
if (pageState.mediaFileToken) {
|
||||
const request = {
|
||||
@@ -43,6 +43,10 @@ export default function PageVideoMocapProgress({
|
||||
}
|
||||
};
|
||||
|
||||
if (pageState.status === FILE_SELECTED){
|
||||
handleEnqueueMocapNet();
|
||||
}
|
||||
|
||||
if (pageState.status === FILE_UPLOADING) {
|
||||
return (
|
||||
<div className="d-flex flex-column p-4 gap-3 text-center align-items-center">
|
||||
|
||||
+24
-2
@@ -1,17 +1,33 @@
|
||||
import SelectModal from "components/common/SelectModal/SelectModal";
|
||||
import React from "react";
|
||||
import React, {useState} from "react";
|
||||
import { Action, State } from "../videoMocapReducer";
|
||||
import { Button } from "components/common";
|
||||
|
||||
export default function TabContentLibrary(props: {
|
||||
export default function TabContentLibrary({
|
||||
t, pageState, dispatchPageState
|
||||
}: {
|
||||
t: Function;
|
||||
pageState: State;
|
||||
dispatchPageState: (action: Action) => void;
|
||||
}){
|
||||
const [token, setToken] = useState<string|undefined>();
|
||||
const handleProceed = ()=>{
|
||||
if(token)
|
||||
dispatchPageState({
|
||||
type: "selectedFile",
|
||||
payload: {mediaFileToken: token}
|
||||
});
|
||||
}
|
||||
const handleOnSelect = (token:string)=>{
|
||||
setToken(token);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<SelectModal
|
||||
modalTitle="Select a Video"
|
||||
label="Select a Video"
|
||||
onSelect={handleOnSelect}
|
||||
tabs={[
|
||||
{
|
||||
label: "All Videos",
|
||||
@@ -22,6 +38,12 @@ export default function TabContentLibrary(props: {
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{token &&
|
||||
<Button
|
||||
label={t("button.proceed")}
|
||||
onClick={handleProceed}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ export enum states{
|
||||
FILE_STAGED,
|
||||
FILE_UPLOADING,
|
||||
FILE_UPLOADED,
|
||||
FILE_SELECTED,
|
||||
MOCAPNET_ENQUEUEING,
|
||||
MOCAPNET_ENQUEUED,
|
||||
}
|
||||
@@ -15,20 +16,29 @@ export type State = {
|
||||
}
|
||||
|
||||
export type Action =
|
||||
| {type: 'uploadFile'}
|
||||
| {type: 'restart'}
|
||||
| {type: 'stagedFile'}
|
||||
| {type: 'clearedFile'}
|
||||
| {type: 'selectedFile', payload:{ mediaFileToken: string}}
|
||||
| {type: 'uploadFile'}
|
||||
| {type: 'uploadFileSuccess', payload:{ mediaFileToken: string}}
|
||||
| {type: 'enqueueMocapNet'}
|
||||
| {type: 'enqueueMocapNetSuccess', payload: {inferenceJobToken: string|undefined}}
|
||||
|
||||
export function reducer (state: State, action: Action): State {
|
||||
console.log(action);
|
||||
switch(action.type){
|
||||
case 'restart':
|
||||
return { status: states.NO_FILE }
|
||||
case 'stagedFile':
|
||||
return {...state, status: states.FILE_STAGED}
|
||||
case 'clearedFile':
|
||||
return {...state, status: states.NO_FILE}
|
||||
case 'selectedFile':
|
||||
return {
|
||||
...state,
|
||||
status: states.FILE_SELECTED,
|
||||
mediaFileToken: action.payload.mediaFileToken
|
||||
}
|
||||
case 'uploadFile':
|
||||
return {...state,status: states.FILE_UPLOADING};
|
||||
case 'uploadFileSuccess':
|
||||
|
||||
Reference in new issue
Block a user