Skip to content

Commit

Permalink
Feature automated artwork updates (#162)
Browse files Browse the repository at this point in the history
* add residency artwrok template

* added new review artwork step to submission form

* fix type error

* add alt layout for guest show and fix form submission types

* adjust artwork emailer to link to contentful asset and always run on shows that are two days away.

* move artwork-emails to cron and add to cron schedule

* update filename when saving to contentful

* update socialImage to showArtwork

* remove inaccessible colours from show artwork colour palette

* create extension for revalidation artwork in contentful, refactor contentful image upload functions to lib folder

* improve wording when regenreating artwork

* get field values from contentful as time of regeneration request

* add verification to artwork regeneration endpoint

* send artwork in jpg format in email

* move create client inside functions

* convert image from cloudinary to https

* dont allow form submission whilst images are uploading/processing

* move to new show artwork field in contentful

* add auth to artwork email endpoint

* reorder colours for artwork to be better distributed

* update working on artwork step and remove checkbox

* use preview client in show artwork url to get unpublished artists

* add preview watermark and text to artwork step

* Feature film screenings (#145)

* add film screening to events page filter

* fix film screening breaking event type pill, move event type to end of row

* add film screening to event type

* adjust event row date width so it fits onto one line

* Bugfix draft artists (#146)

* fix bug with draft artist being return from cms on published show

* remove unused code

* fix but with comma in second last artist name

* remove focus state from play buttons

* remove white outline from play button focus-within state

* Feature daily schedule artwork generator (#147)

* implmenent mvp for automated schedule artwork

* fix base url for stickers

* add don't cache response header

* add specific page for schedule artwork generation to solve transparent bg issue

* add border to img

* add download image button, fix sticker array length bug

* indicate to user when image is reloading

* adjust schedule so its only today and add to admin calendar additional menu

* remove some stickers

* fix bug with daily artwork generator times (#148)

* add loading state to daily artwork generator (#149)

* Bugfix long schedule (#150)

* adjust spacing for longer schedules

* adjust font size for longer schedules

* Feature/calendar updates (#151)

* add copy handles button to insta text popup

* add back button to daily schedule generator

* Feature/email updates (#152)

* refactor submission email and adjust wording

* update confirmation email text

* Bugfix/guests page (#153)

* add pagination to guests page

* animate load more button

* remove unused code from guest page

* bugfix same key for fetch with guests and news page (#154)

* make calendar additional menu available for mobile (#155)

* Bugfix show preview search (#156)

* make include play button in show preview on search page

* remove genres that don't have a name when parsing shows to correct format

* Feature/daily schedule updates (#157)

* add border and opaque background

* add responsive text size to schedule generator when schedule is long

* fix typo in show submission email (#158)

* Feature/show at time api endpoint (#159)

* create api endpoint for getting the show that took place at a specific time.

* move api endpoint to shows folder

* update website api secret

* add show artwork to show by timestamp api endpoint and make it preview temporarily for testing puroposes (#160)

* download todays artwork as zip

* take artists from title when regenerating artwork

* add missing dependencies

* better naming of show artwork field
  • Loading branch information
antiantivirus authored Jan 16, 2025
1 parent ae5a9e6 commit 351c5c6
Show file tree
Hide file tree
Showing 23 changed files with 885 additions and 331 deletions.
8 changes: 8 additions & 0 deletions components/formFields/filepondServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,12 @@ export const serverOptions = {
};
},
revert: null,
load: (source, load, error, progress, abort, headers) => {
var myRequest = new Request(source);
fetch(myRequest).then(function (response) {
response.blob().then(function (myBlob) {
load(myBlob);
});
});
},
};
46 changes: 42 additions & 4 deletions components/formFields/imageUploadField.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import { FilePond, registerPlugin } from "react-filepond";
import { useField, useFormikContext } from "formik";
import { serverOptions } from "./filepondServer";
Expand All @@ -24,23 +24,52 @@ export default function ImageUploadField({
label,
multi = false,
description,
value,
...props
}: {
label: string;
name: string;
multi?: boolean;
required?: boolean;
description?: string;
value?: any;
}) {
const [field, meta, helpers] = useField(props);
const { values, setFieldValue } = useFormikContext<any>();
const { values, setFieldValue, setSubmitting } = useFormikContext<any>();
const [files, setFiles] = useState([]);
const [uploading, setUploading] = useState(false);

useEffect(() => {
if (value) {
let initialImages;
if (multi) {
initialImages = value.map((image) => ({
source: image.url,
options: {
type: "local",
},
}));
} else {
initialImages = [
{
source: value.url,
options: {
type: "local",
},
},
];
}
setFiles(initialImages);
}
}, []);

// const setFieldValue(field, value){
const imageUploaded = (file) => {
const url = file.serverId.replace("http", "https");
const image = {
filename: file.filename,
type: file.fileType,
url: file.serverId,
url: url,
};
if (multi) {
let images = values[props.name];
Expand Down Expand Up @@ -78,7 +107,7 @@ export default function ImageUploadField({
{...field}
{...props}
className="min-h-36"
// files={files}
files={files}
allowMultiple={multi}
credits={false}
server={serverOptions}
Expand All @@ -91,11 +120,19 @@ export default function ImageUploadField({
}
}}
onupdatefiles={(files) => {
setFiles(files);
// only fire handler when image is removed.
if (files.length < values.image.length) {
_reorderDeleteHandler(files);
}
}}
onprocessfilestart={() => {
console.log("uploading");
setSubmitting(true);
}}
onprocessfiles={() => {
setSubmitting(false);
}}
allowReorder={multi}
labelIdle='Drag & Drop your image or <span class="filepond--label-action">Browse</span>'
acceptedFileTypes={["image/png", "image/jpeg"]}
Expand All @@ -117,6 +154,7 @@ export default function ImageUploadField({
className="pill-input"
required
/> */}
{uploading && <span className="text-sm text-gray-500">Uploading...</span>}
</div>
);
}
36 changes: 25 additions & 11 deletions components/submission/showSubmissionForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import ShowSubmissionStep1 from "./showSubmissionStep1";
import ShowSubmissionStep2 from "./showSubmissionStep2";
import ShowSubmissionStep3 from "./showSubmissionStep3";
import ShowSubmissionStep4 from "./showSubmissionStep4";
import ShowSubmissionStepInfo from "./showSubmissionStepInfo";
import ShowSubmissionStepForm from "./showSubmissionStepForm";
import ShowSubmissionStepArtwork from "./showSubmissionStepArtwork";
import ShowSubmissionStepSubmitted from "./showSubmissionStepSubmitted";
import {
Dropdown,
ShowInterface,
Expand Down Expand Up @@ -148,9 +149,10 @@ export default function ShowSubmissionForm({
},
[]
),
artwork: false,
};
const [currentStep, setCurrentStep] = useState<number>(1);
const isLastStep = currentStep === 2;
const isLastStep = currentStep === 3;
const currentValidationSchema = validationSchema[currentStep];
const [submissionError, setSubmissionError] = useState<boolean>(false);

Expand Down Expand Up @@ -215,22 +217,24 @@ export default function ShowSubmissionForm({
return <ShowSubmissionStep1 />;
case 1:
return (
<ShowSubmissionStep2
<ShowSubmissionStepInfo
importantInfo={importantInfo}
showType={values.showType}
/>
);
case 2:
return (
<ShowSubmissionStep3
<ShowSubmissionStepForm
initial={initial}
showType={values.showType}
genres={genres}
uploadLink={uploadLink}
/>
);
case 3:
return <ShowSubmissionStep4 initial={initial} />;
return <ShowSubmissionStepArtwork />;
case 4:
return <ShowSubmissionStepSubmitted initial={initial} />;
default:
return <ShowSubmissionStep1 />;
}
Expand All @@ -241,7 +245,7 @@ export default function ShowSubmissionForm({
{/* <pre className="text-white bg-black">
{JSON.stringify(initial, null, 2)}
</pre> */}
{currentStep != 3 && (
{currentStep != 4 && (
<div className="flex flex-col md:flex-row text-center items-center justify-center space-y sm:space-y-2 md:space-y-0 md:space-x-4">
{/* <button
onClick={() => setCurrentStep(0)}
Expand All @@ -259,8 +263,16 @@ export default function ShowSubmissionForm({
1. Important info
</button>
<Arrow className="hidden md:block" />
<span className={currentStep == 2 ? "font-medium" : ""}>
<button
onClick={() => setCurrentStep(2)}
disabled={currentStep <= 2}
className={currentStep == 2 ? "font-medium" : ""}
>
2. Submission
</button>
<Arrow className="hidden md:block" />
<span className={currentStep == 3 ? "font-medium" : ""}>
3. Artwork
</span>
</div>
)}
Expand All @@ -272,7 +284,7 @@ export default function ShowSubmissionForm({
{({ values, isSubmitting }) => (
<Form id="showSubmissionForm">
{step(values)}
{currentStep != 3 && (
{currentStep != 4 && (
<div>
<div className="flex space-x-6 mt-6">
{currentStep > 1 && (
Expand All @@ -297,7 +309,9 @@ export default function ShowSubmissionForm({
<span className="underline">
{!isSubmitting
? `${isLastStep ? "Submit" : "Next"}`
: "Submitting"}
: `${
isLastStep ? "Submitting" : "Processing images"
}`}
</span>
{!isSubmitting && <Arrow />}
{isSubmitting && (
Expand Down
67 changes: 67 additions & 0 deletions components/submission/showSubmissionStepArtwork.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useFormikContext, Field, ErrorMessage } from "formik";
import { useState, useEffect } from "react";
import { showArtworkURL } from "../../util";
import { SubmissionFormValues } from "../../types/shared";

export default function ShowSubmissionStepArtwork() {
const { values } = useFormikContext<SubmissionFormValues>();

const [imageUrl, setImageUrl] = useState<string | null>(null);
const [loading, setLoading] = useState<boolean>(false);

const fetchImage = async () => {
setLoading(true);
const surl = showArtworkURL(values, true);
console.log(surl);
const response = await fetch(surl);
const blob = await response.blob();
const url = URL.createObjectURL(blob);
setImageUrl(url);
setLoading(false);
};

useEffect(() => {
fetchImage();
}, []);

return (
// We pass the event to the handleSubmit() function on submit.
<div className="mt-16">
<legend className="font-sans mb-12 text-large font-medium text-center">
Preview artwork
</legend>
<div className="aspect-square max-w-3xl bg-black text-white flex items-center justify-center h-full w-full mx-auto">
{imageUrl ? (
<>
<div
className="border border-white bg-cover bg-center"
style={{
backgroundImage: `url(${imageUrl})`,
width: "100%",
height: "100%",
maxHeight: "80vh",
}}
></div>
<span className="absolute text-white opacity-50 text-[6rem] pointer-events-none">
PREVIEW
</span>
</>
) : (
<span className="animate-pulse">Generating preview artwork...</span>
)}
</div>
{imageUrl && (
<>
<p>
This is a preview only and your final artwork will be sent to you
via email.
</p>
<p>
Please press ‘submit’ if you’re happy with the artwork. If you need
to make changes please go back.
</p>
</>
)}
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dayjs.extend(utc);

const env = process.env.NODE_ENV;

export default function ShowSubmissionStep3({
export default function ShowSubmissionStepForm({
initial,
genres,
uploadLink,
Expand Down Expand Up @@ -130,7 +130,9 @@ export default function ShowSubmissionStep3({
description="No logos and no flyers. Minimum dimensions: 1000x1000px, maximum file size: 3MB."
required
name={`extraArtists.${index}.image`}
value={values.extraArtists[index].image}
/>

<div className="flex gap-2 md:gap-3 items-center border border-black p-3 md:p-6 bg-orange">
<AiOutlineInfoCircle className="w-5 sm:w-6 md:w-8 h-full" />
<span className="flex-1 text-small">
Expand Down Expand Up @@ -187,6 +189,7 @@ export default function ShowSubmissionStep3({
description="No logos and no flyers. Minimum dimensions: 1000x1000px, maximum file size: 3MB."
required
name={`artistsAdditionalInfo.${index}.image`}
value={values.artistsAdditionalInfo[index].image}
/>
)}
<div className="flex gap-2 md:gap-3 items-center border border-black p-3 md:p-6 bg-orange">
Expand Down Expand Up @@ -225,6 +228,7 @@ export default function ShowSubmissionStep3({
description="Please upload your show / artist image(s) below, including any guest images. No logos and no flyers. Minimum dimensions: 1000x1000px, maximum file size: 3MB."
required={true}
multi={true}
value={values.image}
/>
<div className="flex gap-2 md:gap-3 items-center border border-black p-3 md:p-6 mb-10 bg-orange">
<AiOutlineInfoCircle className="w-5 sm:w-6 md:w-8 h-full" />
Expand All @@ -249,6 +253,7 @@ export default function ShowSubmissionStep3({
required={true}
options={genres}
limit={3}
value={values.genres}
/>
<CheckboxField
name="hasNewGenres"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { documentToReactComponents } from "@contentful/rich-text-react-renderer"
import Prose from "../Prose";
import { Field, ErrorMessage } from "formik";

export default function ShowSubmissionStep2({ importantInfo, showType }) {
export default function ShowSubmissionStepInfo({ importantInfo, showType }) {
const importantInfoToShow = () => {
if (showType == "Live") {
return (
Expand Down
17 changes: 3 additions & 14 deletions emails/showArtwork.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,16 @@ const env = process.env.NODE_ENV;
interface EmailProps {
userName: string;
showDate: string;
artwork: string;
}

const artworkLinks = [
process.env.SHOW_ARTWORK_SUN,
process.env.SHOW_ARTWORK_MON,
process.env.SHOW_ARTWORK_TUES,
process.env.SHOW_ARTWORK_WED,
process.env.SHOW_ARTWORK_THURS,
process.env.SHOW_ARTWORK_FRI,
process.env.SHOW_ARTWORK_SAT,
];

const baseUrl = "https://refugeworldwide.com/";

export const ShowArtworkEmail = ({
userName = "Gramrcy",
showDate = "2024-05-15T15:00:00.000Z",
artwork = "https://res.cloudinary.com/dqjn26pey/image/upload/v1706278328/Refuge-pichi_mg1jge.jpg",
}: EmailProps) => {
const dayOfWeekNo = Number(dayjs(showDate).format("d"));
const dayOfWeek = dayjs(showDate).format("dddd");
const artworkLink = artworkLinks[dayOfWeekNo];
return (
<Html>
<Head />
Expand Down Expand Up @@ -76,7 +65,7 @@ export const ShowArtworkEmail = ({
</Heading>
<Text style={paragraph}>
You can find artwork for your show on {dayOfWeek}{" "}
<Link style={link} href={artworkLink}>
<Link style={link} href={artwork}>
here
</Link>
. If there are any issues please let us know asap!
Expand Down
Loading

0 comments on commit 351c5c6

Please sign in to comment.