mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 09:48:44 +00:00
added cover image edit link to media pages
This commit is contained in:
1 parent
8f0d41a53c
commit
519a6c6b73
6 files changed
+129
-39
No files matched your search
@@ -8,14 +8,47 @@
|
||||
position: relative;
|
||||
background-color: #57577d;
|
||||
|
||||
img {
|
||||
img, .cover-img-edit {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
img {
|
||||
object-fit: cover;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
}
|
||||
|
||||
.cover-img-edit {
|
||||
padding: .25rem;
|
||||
font-size: .75rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all .25s ease-in-out;
|
||||
color: transparent;
|
||||
|
||||
span { text-align: center }
|
||||
|
||||
svg {
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
transition: background .25s ease-in-out;
|
||||
background: rgba(#000, .5);
|
||||
border-radius: .25rem;
|
||||
padding: .5rem;
|
||||
right: .25rem;
|
||||
bottom: .25rem;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: rgba(#000, .5);
|
||||
svg { background: none }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,15 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faPen } from "@fortawesome/pro-solid-svg-icons";
|
||||
import "./WeightCoverImage.scss";
|
||||
|
||||
interface WeightCoverImageProps {
|
||||
src?: string;
|
||||
alt?: string;
|
||||
height?: number;
|
||||
onClick?: (e: any) => any;
|
||||
to?: string,
|
||||
width?: number;
|
||||
coverIndex?: number;
|
||||
}
|
||||
@@ -12,9 +18,12 @@ export default function WeightCoverImage({
|
||||
src,
|
||||
alt,
|
||||
height = 100,
|
||||
onClick,
|
||||
to,
|
||||
width = 100,
|
||||
coverIndex,
|
||||
}: WeightCoverImageProps) {
|
||||
console.log("👕",onClick);
|
||||
const containerStyle = {
|
||||
height: `${height}px`,
|
||||
width: `${width}px`,
|
||||
@@ -27,8 +36,15 @@ export default function WeightCoverImage({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="cover-img" style={containerStyle}>
|
||||
<div {...{
|
||||
className: "cover-img",
|
||||
style: containerStyle
|
||||
}}>
|
||||
<img src={image} alt={alt || "Model Weight Cover"} />
|
||||
{ to ? <Link {...{ className: "cover-img-edit", to }}>
|
||||
<span>Edit cover image</span>
|
||||
<FontAwesomeIcon icon={faPen}/>
|
||||
</Link> : null }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -43,7 +43,13 @@ const EntityInputFull = ({ media, clear }: SlideProps) => {
|
||||
const mediaType = mediaCategoryfromString(media?.media_type || "");
|
||||
|
||||
switch (mediaType) {
|
||||
case MediaFilters.image: return <img {...{ src: mediaUrl, alt: "Selected media file" }}/>
|
||||
case MediaFilters.image: return <>
|
||||
<img {...{ src: mediaUrl, alt: "Selected media file" }}/>
|
||||
<div {...{ className: "fy-entity-input-full-controls" }}>
|
||||
Your file
|
||||
<Button {...{ label: "Clear", variant: "secondary", onClick: () => clear() }}/>
|
||||
</div>
|
||||
</>;
|
||||
case MediaFilters.video: return <>
|
||||
<video controls {...{ src: mediaUrl }}/>
|
||||
<div {...{ className: "fy-entity-input-full-controls" }}>
|
||||
|
||||
@@ -1,30 +1,41 @@
|
||||
.cover-image-page {
|
||||
header {
|
||||
display: flex;
|
||||
margin-bottom: 1rem;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
h1 {
|
||||
display: inline;
|
||||
}
|
||||
header {
|
||||
display: flex;
|
||||
margin-bottom: 1rem;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
h1 {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.cover-image-panel {
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
grid-auto-columns: 1fr;
|
||||
}
|
||||
.cover-image-panel {
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
grid-auto-columns: 50%;
|
||||
|
||||
.cover-image-empty {
|
||||
background-color: rgba(#000,.33);
|
||||
border-radius: .5rem;
|
||||
color: rgba(#fff, .5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: .5rem 0;
|
||||
aspect-ratio: 4/3;
|
||||
}
|
||||
.cover-image-current {
|
||||
border-radius: .5rem;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
margin: .5rem 0;
|
||||
}
|
||||
|
||||
.fy-entity-input-square {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.cover-image-empty {
|
||||
background-color: rgba(#000,.33);
|
||||
border-radius: .5rem;
|
||||
color: rgba(#fff, .5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: .5rem 0;
|
||||
aspect-ratio: 4/3;
|
||||
}
|
||||
}
|
||||
@@ -5,25 +5,24 @@ import { EntityInput } from "components/entities";
|
||||
import { EditCoverImage, EditCoverImageResponse } from "@storyteller/components/src/api/media_files/EditCoverImage";
|
||||
import { BucketConfig } from "@storyteller/components/src/api/BucketConfig";
|
||||
import "./EditCoverImage.scss";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useHistory, useParams } from "react-router-dom";
|
||||
|
||||
export default function EditCoverImagePage() {
|
||||
const { token: targetToken } = useParams<{ token: string }>();
|
||||
const { studioAccessCheck } = useSession();
|
||||
const history = useHistory();
|
||||
const [coverToken, coverTokenSet] = useState("");
|
||||
const { media } = useMedia({ mediaToken: targetToken });
|
||||
const bucketConfig = new BucketConfig();
|
||||
const currentSrc = bucketConfig.getGcsUrl(media?.cover_image?.maybe_cover_image_public_bucket_path || "");
|
||||
|
||||
console.log("😎 loaded target media",media);
|
||||
|
||||
const onClick = () => {
|
||||
if (coverToken) {
|
||||
EditCoverImage(targetToken,{
|
||||
cover_image_media_file_token: coverToken,
|
||||
})
|
||||
.then((res: EditCoverImageResponse) => {
|
||||
|
||||
history.push(`/media/${targetToken}`);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -50,14 +49,18 @@ export default function EditCoverImagePage() {
|
||||
Current cover image
|
||||
{
|
||||
media?.cover_image?.maybe_cover_image_public_bucket_path ?
|
||||
<img {...{ alt: "cover art", src: currentSrc }}/> :
|
||||
<img {...{
|
||||
alt: "cover art",
|
||||
className: "cover-image-current",
|
||||
src: currentSrc
|
||||
}}/> :
|
||||
<div {...{ className: "cover-image-empty" }}>No cover image</div>
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
<EntityInput {...{
|
||||
accept: ["image"],
|
||||
aspectRatio: "landscape",
|
||||
aspectRatio: "square",
|
||||
label: "Choose a cover image",
|
||||
name: "coverToken",
|
||||
value: coverToken,
|
||||
|
||||
@@ -66,6 +66,9 @@ export default function MediaPage() {
|
||||
const [copyPositiveButtonText, setCopyPositiveButtonText] = useState("Copy");
|
||||
const [copyNegativeButtonText, setCopyNegativeButtonText] = useState("Copy");
|
||||
const [activeSlide, setActiveSlide] = useState({ url: "", token: "" });
|
||||
const viewerCanEdit = canEditMediaFile(
|
||||
mediaFile?.maybe_creator_user?.user_token || ""
|
||||
);
|
||||
|
||||
// Inside MediaPage.tsx
|
||||
|
||||
@@ -471,11 +474,31 @@ export default function MediaPage() {
|
||||
|
||||
const title = GetMediaFileTitle(mediaFile);
|
||||
|
||||
const showEngineCover = () => {
|
||||
const coverMediaPath = mediaFile?.cover_image?.maybe_cover_image_public_bucket_path || "";
|
||||
if (mediaFile) {
|
||||
switch (mediaFile.media_type) {
|
||||
case MediaFileType.BVH:
|
||||
case MediaFileType.GLB:
|
||||
case MediaFileType.GLTF:
|
||||
case MediaFileType.SceneRon: return <WeightCoverImage {...{
|
||||
...coverMediaPath ? { src: bucketConfig.getGcsUrl(coverMediaPath) } : {},
|
||||
...viewerCanEdit ? { to: `/edit-cover-image/${ token }` } : {},
|
||||
coverIndex: mediaFile.cover_image.default_cover.image_index,
|
||||
}}/>;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Container type="panel" className="mb-5">
|
||||
<Panel clear={true} className="py-4">
|
||||
<div className="d-flex flex-column flex-lg-row gap-3 gap-lg-2">
|
||||
{
|
||||
showEngineCover()
|
||||
}
|
||||
<div>
|
||||
<div className="d-flex gap-2 align-items-center flex-wrap">
|
||||
<h1 className="fw-bold mb-2">{title}</h1>
|
||||
@@ -790,9 +813,7 @@ export default function MediaPage() {
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
{canEditMediaFile(
|
||||
mediaFile?.maybe_creator_user?.user_token || ""
|
||||
) && (
|
||||
{ viewerCanEdit && (
|
||||
<>
|
||||
<div className="d-flex gap-2">
|
||||
<Button
|
||||
|
||||
Reference in new issue
Block a user