mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-08 02:52:12 +00:00
weight card revision/type consolidation
This commit is contained in:
1 parent
c0c98b4e35
commit
34849ab4ef
13 files changed
+137
-75
No files matched your search
@@ -14,24 +14,14 @@ export default function Label({
|
||||
required,
|
||||
disabled,
|
||||
}: Props) {
|
||||
return (
|
||||
<div
|
||||
{...{
|
||||
className: `fy-input-label ${disabled ? "opacity-50" : ""}`.trim(),
|
||||
}}
|
||||
>
|
||||
{label ? (
|
||||
<label
|
||||
{...{ className: `fw-medium ${required ? " required" : ""}`.trim() }}
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
) : null}
|
||||
{invalidReason ? (
|
||||
<span {...{ className: "label-error form-text red is-danger" }}>
|
||||
{invalidReason}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
return label ? <div {...{ className: `fy-input-label${disabled ? "opacity-50" : "" }` }}>
|
||||
<label {...{ className: `fw-medium${required ? " required" : "" }` }} >
|
||||
{label}
|
||||
</label>
|
||||
{ invalidReason ? (
|
||||
<span {...{ className: "label-error form-text red is-danger" }}>
|
||||
{invalidReason}
|
||||
</span>
|
||||
) : null }
|
||||
</div> : null;
|
||||
}
|
||||
@@ -106,4 +106,14 @@
|
||||
|
||||
label { }
|
||||
}
|
||||
|
||||
.fy-entity-input-upload-detail {
|
||||
span {
|
||||
opacity: .66;
|
||||
display: block;
|
||||
font-size: .75rem;
|
||||
line-height: 1em;
|
||||
height: .75rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import { FileWrapper, Label, Spinner } from "components/common";
|
||||
import { EntityType, MediaFilterProp, WeightFilterProp } from "components/entities/EntityTypes";
|
||||
import { useFile, useMedia, useModal, useSession } from "hooks";
|
||||
import { BucketConfig } from "@storyteller/components/src/api/BucketConfig";
|
||||
import { faFileArrowUp, faGrid, faPersonWalking } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { faDiagramSankey, faFile, faFileArrowUp, faGrid, faImage, faPersonWalking, faWaveform } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon as Icon } from "@fortawesome/react-fontawesome";
|
||||
import { UploadMedia, UploadMediaResponse } from "@storyteller/components/src/api/media_files/UploadMedia";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
@@ -17,6 +17,7 @@ import "./EntityInput.scss";
|
||||
interface Props {
|
||||
label?: string,
|
||||
onChange?: any,
|
||||
owner?: string,
|
||||
mediaType?: MediaFilterProp,
|
||||
aspectRatio?: "square" | "landscape" | "portrait",
|
||||
weightType?: WeightFilterProp,
|
||||
@@ -32,6 +33,7 @@ interface EmptySlideProps extends SlideProps {
|
||||
inputProps?: any,
|
||||
onSelect: any,
|
||||
open: any,
|
||||
owner: string,
|
||||
user: any
|
||||
};
|
||||
|
||||
@@ -64,24 +66,37 @@ const MocapInputFull = ({ media }: SlideProps) => {
|
||||
</>;
|
||||
};
|
||||
|
||||
const MediaPickerEmpty = ({ entityType, filterType, media, onSelect, open, inputProps, user }: EmptySlideProps) => {
|
||||
const MediaPickerEmpty = ({ entityType, filterType, media, onSelect, open, owner, inputProps, user }: EmptySlideProps) => {
|
||||
const browserClick = () => open({
|
||||
component: MediaBrowser,
|
||||
props: { entityType, filterType, onSelect, username: user?.username || "" }
|
||||
props: { entityType, filterType, onSelect, owner, username: user?.username || "" }
|
||||
});
|
||||
|
||||
const mediaIcons = () => {
|
||||
switch (filterType) {
|
||||
case "audio": return faWaveform;
|
||||
case "image": return faImage;
|
||||
case "bvh": return faPersonWalking;
|
||||
default: return faFile;
|
||||
}
|
||||
}
|
||||
|
||||
return <>
|
||||
<Icon {...{ className: "fy-entity-input-icon", icon: faPersonWalking }}/>
|
||||
<Icon {...{ className: "fy-entity-input-icon", icon: [faFile,mediaIcons(),faDiagramSankey][entityType] }}/>
|
||||
<div {...{ className: "fy-entity-input-empty-controls" }}>
|
||||
<FileWrapper {...{ containerClass: "fy-entity-input-row", panelClass: "fy-entity-input-button", noStyle: true, ...inputProps }}>
|
||||
<>
|
||||
<Icon {...{ className: "fy-entity-input-label-icon", icon: faFileArrowUp }}/>
|
||||
Upload, click or drag here
|
||||
</>
|
||||
</FileWrapper>
|
||||
{ entityType === EntityType.media &&
|
||||
<FileWrapper {...{ containerClass: "fy-entity-input-row", panelClass: "fy-entity-input-button", noStyle: true, ...inputProps }}>
|
||||
<>
|
||||
<Icon {...{ className: "fy-entity-input-label-icon", icon: faFileArrowUp }}/>
|
||||
<div {...{ className: "fy-entity-input-upload-detail" }}>
|
||||
Upload, click or drag here
|
||||
{ filterType !== "all" && <span>{ filterType } files supported</span> }
|
||||
</div>
|
||||
</>
|
||||
</FileWrapper> }
|
||||
<div {...{ className: "fy-entity-input-row fy-entity-input-button", onClick: browserClick }}>
|
||||
<Icon {...{ className: "fy-entity-input-label-icon", icon: faGrid }}/>
|
||||
Choose from your media
|
||||
Choose from your { ["","media","weights"][entityType] }
|
||||
</div>
|
||||
</div>
|
||||
</>;
|
||||
@@ -94,7 +109,7 @@ const AniMod = ({ animating, className, isLeaving, render: Render, style, ...res
|
||||
<Render {...{ ...rest, animating }} />
|
||||
</a.div>;
|
||||
|
||||
export default function EntityInput({ aspectRatio = "square", label, onChange, mediaType, weightType }: Props) {
|
||||
export default function EntityInput({ aspectRatio = "square", label, onChange, owner, mediaType, weightType }: Props) {
|
||||
const entityType = mediaType ? EntityType.media : weightType ? EntityType.weights : EntityType.unknown;
|
||||
const filterType = mediaType || weightType || "all";
|
||||
const { search } = useLocation();
|
||||
@@ -149,7 +164,7 @@ export default function EntityInput({ aspectRatio = "square", label, onChange, m
|
||||
return [
|
||||
<AniMod {...{ render: MediaBusy, className: "fy-entity-input-busy", ...sharedProps }}/>,
|
||||
<AniMod {...{ render: MocapInputFull, className: "fy-entity-input-full", ...sharedProps }}/>,
|
||||
<AniMod {...{ render: MediaPickerEmpty, className: "fy-entity-input-empty", entityType, filterType, inputProps, onSelect, open, user, ...sharedProps }}/>
|
||||
<AniMod {...{ render: MediaPickerEmpty, className: "fy-entity-input-empty", entityType, filterType, inputProps, onSelect, open, owner, user, ...sharedProps }}/>
|
||||
][i];
|
||||
|
||||
})
|
||||
|
||||
@@ -11,6 +11,7 @@ export enum MediaFilters {
|
||||
export enum WeightsFilters {
|
||||
all,
|
||||
hifigan_tt2,
|
||||
rvc_v2,
|
||||
sd_1,
|
||||
"sd_1.5",
|
||||
sdxl,
|
||||
@@ -35,6 +36,6 @@ export const EntityFilterOptions = ( mode: EntityType, t = (v:string) => v) => {
|
||||
.filter(val => isNaN(Number(val)))
|
||||
.map((value) => {
|
||||
if (typeof value === "string") return { value, label: t(value) }
|
||||
return { label: "", value: "" };
|
||||
return { label: "all", value: "all" };
|
||||
}) : [];
|
||||
};
|
||||
@@ -2,7 +2,7 @@ import React, { useRef } from "react";
|
||||
import { MediaFile } from "@storyteller/components/src/api/media_files/GetMedia";
|
||||
import MasonryGrid from "components/common/MasonryGrid/MasonryGrid";
|
||||
import { ImagePreview, MocapPreview, VideoPreview } from '../CardPreviews';
|
||||
import { AudioCard, OverlayCard, CardWrapper } from "components/entities";
|
||||
import { AudioCard, OverlayCard, CardWrapper, WeightCard } from "components/entities";
|
||||
import { EntityType } from "components/entities/EntityTypes";
|
||||
|
||||
interface MediaCardsProps {
|
||||
@@ -33,6 +33,10 @@ const MediaCards = ({ props, type }: MediaCardsProps) => {
|
||||
|
||||
const WeightsCards = ({ props, type }: MediaCardsProps) => {
|
||||
switch (type) {
|
||||
case "rvc_v2":
|
||||
return <CardWrapper {...{ ...props, card: WeightCard, padding: true }}/>;
|
||||
case "tt2":
|
||||
return <CardWrapper {...{ ...props, card: WeightCard, padding: true }}/>;
|
||||
default:
|
||||
return <div>Unsupported media type</div>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import React from "react";
|
||||
import moment from "moment";
|
||||
import { MakeRatingsProps } from "hooks/useRatings";
|
||||
import WeightCoverImage from "components/common/WeightCoverImage";
|
||||
import CardBadge from "../CardBadge";
|
||||
import CardFooter from "../CardFooter";
|
||||
import { BucketConfig } from "@storyteller/components/src/api/BucketConfig";
|
||||
|
||||
interface Props {
|
||||
data: any,
|
||||
makeRatingsProps?: MakeRatingsProps,
|
||||
showCover?: boolean
|
||||
showCreator?: boolean
|
||||
}
|
||||
|
||||
export default function WeightCard({ data, makeRatingsProps, showCover = true, showCreator }: Props) {
|
||||
const { cover_image, created_at, details, maybe_creator, title, token, weight_type } = data || {}
|
||||
const timeCreated = moment( created_at || "").fromNow();
|
||||
const path = cover_image.maybe_cover_image_public_bucket_path || details?.maybe_weight_data?.maybe_cover_image_public_bucket_path;
|
||||
const bucketConfig = new BucketConfig();
|
||||
const coverImage = bucketConfig.getCdnUrl(path, 110, 100);
|
||||
|
||||
return <>
|
||||
<div className="d-flex">
|
||||
{showCover && (
|
||||
<WeightCoverImage
|
||||
src={coverImage}
|
||||
height={110}
|
||||
width={110}
|
||||
coverIndex={cover_image?.default_cover?.image_index}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="flex-grow-1">
|
||||
<CardBadge {...{ className: `fy-entity-type${ weight_type ? "-" + weight_type : "" }`, label: weight_type }}/>
|
||||
|
||||
<div className="d-flex align-items-center mt-3">
|
||||
<div className="flex-grow-1">
|
||||
<h6 className="fw-semibold text-white mb-1">
|
||||
{ title || details.maybe_weight_data.title}
|
||||
</h6>
|
||||
<p className="fs-7 opacity-75">{ timeCreated }</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CardFooter {...{
|
||||
creator: maybe_creator,
|
||||
entityToken: token,
|
||||
entityType: "media_file",
|
||||
makeRatingsProps
|
||||
}}/>
|
||||
</>;
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./WeightCard";
|
||||
@@ -3,5 +3,6 @@ import CardWrapper from "./CardWrapper";
|
||||
import EntityInput from "./EntityInput";
|
||||
import MediaList from "./MediaList";
|
||||
import OverlayCard from "./OverlayCard";
|
||||
import WeightCard from "./WeightCard";
|
||||
|
||||
export { AudioCard, CardWrapper, EntityInput, MediaList, OverlayCard };
|
||||
export { AudioCard, CardWrapper, EntityInput, MediaList, OverlayCard, WeightCard };
|
||||
@@ -20,12 +20,12 @@ interface Props {
|
||||
handleClose: any,
|
||||
mediaToken: string,
|
||||
onSelect?: any,
|
||||
owner?: string,
|
||||
filterType?: MediaFilterProp | WeightFilterProp,
|
||||
username: string,
|
||||
}
|
||||
|
||||
export default function MediaBrowser({ entityType, filterType: inputFilter, mediaToken, handleClose = () => {}, onSelect, username }: Props) {
|
||||
console.log("😎",entityType);
|
||||
export default function MediaBrowser({ entityType, filterType: inputFilter, mediaToken, handleClose = () => {}, onSelect, owner, username }: Props) {
|
||||
const ratings = useRatings();
|
||||
const [showMasonryGrid, setShowMasonryGrid] = useState(true);
|
||||
const [filterType, filterTypeSet] = useState(inputFilter || "all");
|
||||
@@ -46,7 +46,7 @@ export default function MediaBrowser({ entityType, filterType: inputFilter, medi
|
||||
setShowMasonryGrid(true);
|
||||
},
|
||||
requestList: true,
|
||||
urlParam: "echelon",
|
||||
urlParam: owner || username,
|
||||
urlUpdate: false
|
||||
});
|
||||
|
||||
@@ -74,7 +74,7 @@ export default function MediaBrowser({ entityType, filterType: inputFilter, medi
|
||||
return <>
|
||||
<header {...{ className: "fy-media-browser-header" }}>
|
||||
<div {...{ className: "fy-media-browser-tools" }}>
|
||||
<h3>{ ["","Media","Weights"][entityType] }</h3>
|
||||
<h3>{ ["",`${ owner ? owner + "'s " : "" }Media`,"Weights"][entityType] }</h3>
|
||||
<Icon {...{ className: "icon-close-button", icon: faXmark, onClick: () => handleClose() }}/>
|
||||
</div>
|
||||
<div {...{ className: "fy-media-browser-tools" }}>
|
||||
|
||||
@@ -13,10 +13,7 @@ interface ModalConfig {
|
||||
|
||||
export default function ModalProvider({ children }: Props) {
|
||||
const [modalState,modalStateSet] = useState<ModalConfig | null>(null);
|
||||
const open = (cfg: ModalConfig) => {
|
||||
console.log("🪬",cfg);
|
||||
modalStateSet(cfg);
|
||||
};
|
||||
const open = (cfg: ModalConfig) => modalStateSet(cfg);
|
||||
const close = () => modalStateSet(null);
|
||||
|
||||
return <ModalContext.Provider {...{ value: { close, open, modalState } }}>
|
||||
|
||||
@@ -33,7 +33,6 @@ export default function useListContent({
|
||||
urlParam = "",
|
||||
urlUpdate = true
|
||||
}: Props) {
|
||||
console.log("💎",fetcher);
|
||||
const { pathname, search: locSearch } = useLocation();
|
||||
const history = useHistory();
|
||||
const urlQueries = new URLSearchParams(locSearch);
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
.fy-engine-compositor {
|
||||
// margin: 1rem;
|
||||
padding: 1rem;
|
||||
|
||||
.engine-compositor-container {
|
||||
padding: 1rem;
|
||||
|
||||
header {
|
||||
// background: blue;
|
||||
margin-bottom: 1.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -14,16 +12,12 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
h2 { margin-bottom: 0; }
|
||||
h2, .fy-temp-select, .fy-input { margin-bottom: 0; }
|
||||
}
|
||||
.compositor-content {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
// padding: 1rem;
|
||||
|
||||
> * {
|
||||
width: 100%;
|
||||
// background: red;
|
||||
}
|
||||
> * { width: 100%; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
import { EntityInput } from "components/entities";
|
||||
import { Button } from "components/common";
|
||||
// import { useInferenceJobs } from "hooks";
|
||||
// import InferenceJobsList from "components/layout/InferenceJobsList";
|
||||
// import { EnqueueEngineCompositing } from "@storyteller/components/src/api/engine_compositor/EnqueueEngineCompositing";
|
||||
// import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob";
|
||||
// import { v4 as uuidv4 } from "uuid";
|
||||
import { EntityFilterOptions, EntityType, MediaFilterProp, WeightFilterProp } from "components/entities/EntityTypes";
|
||||
import { Button, SegmentButtons, TempInput, TempSelect } from "components/common";
|
||||
|
||||
interface Props {
|
||||
value?: any;
|
||||
@@ -13,34 +9,34 @@ interface Props {
|
||||
|
||||
export default function DevMediaInput({ value }: Props) {
|
||||
const [mediaToken,mediaTokenSet] = useState();
|
||||
const [mediaType,mediaTypeSet] = useState<MediaFilterProp>("all");
|
||||
const [weightType,weightTypeSet] = useState<WeightFilterProp>("all");
|
||||
const [entityType,entityTypeSet] = useState(EntityType.media);
|
||||
const [owner,ownerSet] = useState("");
|
||||
const onChange = ({ target }: any) => mediaTokenSet(target.value);
|
||||
// const inferenceJobs = useInferenceJobs(FrontendInferenceJobType.EngineComposition);
|
||||
|
||||
// const failures = (fail = "") => {
|
||||
// switch (fail) {
|
||||
// default:
|
||||
// return "Uknown failure";
|
||||
// }
|
||||
// };
|
||||
const options = [{ label: "Media", value: EntityType.media },{ label: "Weights", value: EntityType.weights }];
|
||||
const changeFilter = ({ target }: { target: any }) => [mediaTypeSet,mediaTypeSet,weightTypeSet][entityType](target.value);
|
||||
|
||||
return <div {...{ className: "fy-engine-compositor"}}>
|
||||
<div {...{ className: "panel engine-compositor-container" }}>
|
||||
<header>
|
||||
<h2>{ [526,187].map((num = 0) => String.fromCodePoint(128000 + num)) }</h2>
|
||||
<SegmentButtons {...{ onChange: ({ target }: { target: any }) => entityTypeSet(target.value), options, value: entityType }}/>
|
||||
<TempInput {...{ value: owner, onChange: ({ target }: { target: any }) => ownerSet(target.value), placeholder: "User" }}/>
|
||||
<TempSelect {...{ options: EntityFilterOptions(entityType), value: ["",mediaType,weightType][entityType], onChange: changeFilter }}/>
|
||||
<Button {...{ label: "Enqueue", variant: "primary" }}/>
|
||||
</header>
|
||||
<EntityInput {...{ aspectRatio: "landscape", label: "Choose Media File", onChange, weightType: "sd_1.5" }}/>
|
||||
<EntityInput {...{
|
||||
aspectRatio: "landscape",
|
||||
label: `Choose ${ ["","media file","weight"][entityType] }`,
|
||||
onChange,
|
||||
owner,
|
||||
...([{},{ mediaType },{ weightType }][entityType])
|
||||
}}/>
|
||||
<div>
|
||||
{ mediaToken }
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
// <InferenceJobsList
|
||||
// {...{
|
||||
// failures,
|
||||
// jobType: FrontendInferenceJobType.EngineComposition,
|
||||
// }}
|
||||
// />
|
||||
}
|
||||
</div>;
|
||||
};
|
||||
Reference in new issue
Block a user