Skip to content

Commit

Permalink
Backend Upload/Load for new post images
Browse files Browse the repository at this point in the history
  • Loading branch information
maxtyson123 committed Sep 26, 2024
1 parent 657c66a commit 1e052a1
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 91 deletions.
110 changes: 28 additions & 82 deletions website/src/components/plant_sections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
import {IconDefinition} from "@fortawesome/fontawesome-svg-core";
import {CreditedImage} from "@/components/credits";
import {ModalImage} from "@/components/modal";
import {getPostImage} from "@/lib/data";

interface AutoSectionProps{
section: any
Expand All @@ -42,7 +43,6 @@ interface AutoSectionProps{
*
* @param {Object} props - Component props.
* @param {Object} props.section - The section data.
* @param {AttachmentData[]} props.images - The images for the plant.
* @param {boolean} props.isLeft - Whether the image should be on the left or right side of the page.
*
* @see {@link EdibleSection} - The edible section.
Expand All @@ -54,14 +54,14 @@ interface AutoSectionProps{
*
* @returns {JSX.Element} The rendered section component.
*/
export function AutoSection({section, images, isLeft} : AutoSectionProps){
export function AutoSection({section, isLeft} : AutoSectionProps){
switch (section.type){
case "edible":
return <EdibleSection section={section} images={images} isLeft={isLeft}/>
return <EdibleSection section={section} isLeft={isLeft}/>
case "medical":
return <MedicalSection section={section} images={images} isLeft={isLeft}/>
return <MedicalSection section={section} isLeft={isLeft}/>
case "craft":
return <CraftSection section={section} images={images} isLeft={isLeft}/>
return <CraftSection section={section} isLeft={isLeft}/>
case "custom":
return <CustomSection section={section}/>
default:
Expand All @@ -72,7 +72,6 @@ export function AutoSection({section, images, isLeft} : AutoSectionProps){

interface EdibleSectionProps{
section: EdibleSectionData;
images: AttachmentData[]
isLeft: boolean
}

Expand All @@ -81,43 +80,28 @@ interface EdibleSectionProps{
*
* @param {Object} props - Component props.
* @param {EdibleSectionData} props.section - The section data.
* @param {AttachmentData} props.images - The images for the plant.
* @param {boolean} props.isLeft - Whether the image should be on the left or right side of the page.
*
* @see {@link AdvancedTextArea} - The advanced text area component.
*
* @returns {JSX.Element} The rendered section component.
*/
export function EdibleSection({section, images, isLeft} : EdibleSectionProps){
export function EdibleSection({section, isLeft} : EdibleSectionProps){

// Store the nutrition amd preparation section in a ref
const nutritionRef = useRef<HTMLParagraphElement>(null)
const preparationRef = useRef<HTMLParagraphElement>(null)
const [imageState, setImageState] = useState<string>("/media/images/loading.gif")
const [altState, setAltState] = useState<string>("Loading")
const [creditsState, setCreditsState] = useState<string>("Loading")

useEffect(() => {
// Get the image of the part of the plant
if(section.image_of_part == "Default"){
setImageState("/media/images/default_noImage.png")
setAltState("No Image")
setCreditsState("")
}else{
let image_index = images.findIndex((image) => {
return (image.meta as ImageMetaData).name == section.image_of_part
})
setImageState(images[image_index].path)
setAltState((images[image_index].meta as ImageMetaData).name)
setCreditsState((images[image_index].meta as ImageMetaData).credits)
}
}, [])
const hasImage = section.images.length > 0
const imageURI = hasImage ? getPostImage(section.images[0]) : "/media/images/default_noImage.png"
const imageAlt = hasImage ? section.images[0].post_title : "No Image"
const imageCredits = hasImage ? section.images[0].post_user_id.toString() : ""

const imageDiv = (
<>
<div className={styles.imageContainer}>
<ModalImage url={imageState} description={altState}>
<CreditedImage url={imageState} alt={altState} credits={creditsState}/>
<ModalImage url={imageURI} description={imageAlt}>
<CreditedImage url={imageURI} alt={imageAlt} credits={imageCredits}/>
</ModalImage>
</div>
</>
Expand Down Expand Up @@ -160,7 +144,6 @@ export function EdibleSection({section, images, isLeft} : EdibleSectionProps){

interface MedicalSectionProps{
section: MedicalSectionData;
images: AttachmentData[]
isLeft: boolean
}

Expand All @@ -169,45 +152,28 @@ interface MedicalSectionProps{
*
* @param {Object} props - Component props.
* @param {MedicalSectionData} props.section - The section data.
* @param {AttachmentData} props.images - The images for the plant.
* @param {boolean} props.isLeft - Whether the image should be on the left or right side of the page.
*
* @see {@link AdvancedTextArea} - The advanced text area component.
* @param {boolean} props.isLeft - Whether the image should be on the left or right side of the page..
*
* @returns {JSX.Element} The rendered section component.
*/
export function MedicalSection({section, images, isLeft} : MedicalSectionProps){
export function MedicalSection({section, isLeft} : MedicalSectionProps){

// Store the use and preparation in a ref to set the contents with html later
const medUseRef = useRef<HTMLDivElement>(null)
const preparationRef = useRef<HTMLDivElement>(null)
const restrictedRef = useRef<HTMLDivElement>(null)

const [imageState, setImageState] = useState<string>("/media/images/loading.gif")
const [altState, setAltState] = useState<string>("Loading")
const [creditsState, setCreditsState] = useState<string>("Loading")

useEffect(() => {
// Get the image of the part of the plant
if(section.image == "Default"){
setImageState("/media/images/default_noImage.png")
setAltState("No Image")
setCreditsState("")
}else{
let image_index = images.findIndex((image) => {
return (image.meta as ImageMetaData).name == section.image
})
setImageState(images[image_index].path)
setAltState((images[image_index].meta as ImageMetaData).name)
setCreditsState((images[image_index].meta as ImageMetaData).credits)
}
}, [])
// TODO COMPONETIZE THIS
const hasImage = section.images.length > 0
const imageURI = hasImage ? getPostImage(section.images[0]) : "/media/images/default_noImage.png"
const imageAlt = hasImage ? section.images[0].post_title : "No Image"
const imageCredits = hasImage ? section.images[0].post_user_id.toString() : ""

const imageDiv = (
<>
<div className={styles.imageContainer}>
<ModalImage url={imageState} description={altState}>
<CreditedImage url={imageState} alt={altState} credits={creditsState}/>
<ModalImage url={imageURI} description={imageAlt}>
<CreditedImage url={imageURI} alt={imageAlt} credits={imageCredits}/>
</ModalImage>
</div>
</>
Expand Down Expand Up @@ -253,7 +219,6 @@ export function MedicalSection({section, images, isLeft} : MedicalSectionProps){

interface CraftSectionProps{
section: CraftSectionData;
images: AttachmentData[]
isLeft: boolean
}

Expand All @@ -262,45 +227,26 @@ interface CraftSectionProps{
*
* @param {Object} props - Component props.
* @param {CraftSectionData} props.section - The section data.
* @param {AttachmentData} props.images - The images for the plant.
* @param {boolean} props.isLeft - Whether the image should be on the left or right side of the page.
*
* @see {@link AdvancedTextArea} - The advanced text area component.
*
* @returns {JSX.Element} The rendered section component.
*/
export function CraftSection({section, images, isLeft} : CraftSectionProps){
export function CraftSection({section, isLeft} : CraftSectionProps){

// Store the use and additional info in a ref to set the contents with html later
const craft_useRef = useRef<HTMLDivElement>(null)
const additional_infoRef = useRef<HTMLDivElement>(null)

const [imageState, setImageState] = useState<string>("/media/images/loading.gif")
const [altState, setAltState] = useState<string>("Loading")
const [creditsState, setCreditsState] = useState<string>("Loading")

useEffect(() => {

// Get the image of the part of the plant
if(section.image == "Default"){
setImageState("/media/images/default_noImage.png")
setAltState("No Image")
setCreditsState("")
}else{
let image_index = images.findIndex((image) => {
return (image.meta as ImageMetaData).name == section.image
})
setImageState(images[image_index].path)
setAltState((images[image_index].meta as ImageMetaData).name)
setCreditsState((images[image_index].meta as ImageMetaData).credits)
}
}, [])
const hasImage = section.images.length > 0
const imageURI = hasImage ? getPostImage(section.images[0]) : "/media/images/default_noImage.png"
const imageAlt = hasImage ? section.images[0].post_title : "No Image"
const imageCredits = hasImage ? section.images[0].post_user_id.toString() : ""

const imageDiv = (
<>
<div className={styles.imageContainer}>
<ModalImage url={imageState} description={altState}>
<CreditedImage url={imageState} alt={altState} credits={creditsState}/>
<ModalImage url={imageURI} description={imageAlt}>
<CreditedImage url={imageURI} alt={imageAlt} credits={imageCredits}/>
</ModalImage>
</div>
</>
Expand Down
40 changes: 38 additions & 2 deletions website/src/pages/api/plants/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export default async function handler(

}



export async function downloadPlantData(table: any, id: any, client: any, restrictedData: boolean) {
const tables = USE_POSTGRES ? new PostgresSQL() : new SQLDatabase();

Expand Down Expand Up @@ -252,7 +254,7 @@ export async function downloadPlantData(table: any, id: any, client: any, restri
joiner += ` WHERE plants.id = ${id}`;

// Create the query
const query = `
let query = `
SELECT
${selector}
FROM ${process.env.MYSQL_DATABASE}.plants
Expand All @@ -266,13 +268,47 @@ export async function downloadPlantData(table: any, id: any, client: any, restri
if(!data)
return ["error", "No data found"];

// Get the post ids
data[0].medical_images = parseImageIds(data[0].medical_images);
data[0].edible_images = parseImageIds(data[0].edible_images);
data[0].craft_images = parseImageIds(data[0].craft_images);

// Remove duplicates
let allPostIds: any = [];
for (let i = 0; i < data[0].medical_images.length; i++) { allPostIds = allPostIds.concat(data[0].medical_images[i]); }
for (let i = 0; i < data[0].edible_images.length; i++) { allPostIds = allPostIds.concat(data[0].edible_images[i]); }
for (let i = 0; i < data[0].craft_images.length; i++) { allPostIds = allPostIds.concat(data[0].craft_images[i]); }
allPostIds = allPostIds.filter((id: any, index: any) => allPostIds.indexOf(id) === index);

// Make sure that allPostIds is not empty
if(allPostIds.length === 0) return ["success", data];

// Get the post data
query = `SELECT * FROM posts WHERE id IN (${allPostIds.join(",")})`;
const postData = await makeQuery(query, client);

// Add the post data to the data
for (let i = 0; i < data[0].medical_images.length; i++) { data[0].medical_images[i] = data[0].medical_images[i].map((id: any) => postData.find((post: any) => post.id === id)); }
for (let i = 0; i < data[0].edible_images.length; i++) { data[0].edible_images[i] = data[0].edible_images[i].map((id: any) => postData.find((post: any) => post.id === id)); }
for (let i = 0; i < data[0].craft_images.length; i++) { data[0].craft_images[i] = data[0].craft_images[i].map((id: any) => postData.find((post: any) => post.id === id)); }

// If the data is not empty, return the data
return ["success", data];

} catch (error) {
// If there is an error, return the error
console.error(error);
return ["error", error];
}
}

// TODO: medical_images, craft_images and edible_images all return an array of strings. These strings are ids seperated by a comma or null. For example: "craft_images":[ null, "31,32,33,34" ]. If it is null create an empty array in place otherwise create an array of posts by fetching all from the posts table where the id is the same. The example would return: "craft_images":[ [], [{id: 31, ...}, {id: 32, ...}, {id: 33, ...}, {id: 34, ...},], "31,32,33,34" ],
const parseImageIds = (imageData: string) => {
if(imageData === null) return [[]];
return JSON.parse(imageData).map((imageIds: string) => {
if(imageIds === null || imageIds == "") return [];
return imageIds.split(",").map((id: string) => {
return parseInt(id.trim().split("\n")[0])
})
}
)
}
2 changes: 0 additions & 2 deletions website/src/pages/api/plants/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ export default async function handler(
selector = "AND";
}

console.log(query)

// Filter mushrooms
if (!mushrooms){
mushrooms = "exclude"
Expand Down
6 changes: 3 additions & 3 deletions website/src/pages/api/plants/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export default async function handler(
if(edible_parts.length > 0) {

// Tell the query that we are adding to the edible parts table
query += `INSERT INTO edible (plant_id, ${tables.edible_part_of_plant}, ${tables.edible_use_identifier}, ${tables.edible_image_of_part}, ${tables.edible_nutrition}, ${tables.edible_preparation}, ${tables.edible_preparation_type}) VALUES `;
query += `INSERT INTO edible (plant_id, ${tables.edible_part_of_plant}, ${tables.edible_use_identifier}, ${tables.edible_images}, ${tables.edible_nutrition}, ${tables.edible_preparation}, ${tables.edible_preparation_type}) VALUES `;

// Loop through each of the edible parts
for(let i = 0; i < edible_parts.length; i++) {
Expand All @@ -150,7 +150,7 @@ export default async function handler(
if(medical_types.length > 0) {

// Tell the query that we are adding to the medical types table
query += `INSERT INTO medical (plant_id, ${tables.medical_type}, ${tables.medical_use_identifier}, ${tables.medical_use}, ${tables.medical_image}, ${tables.medical_preparation}, ${tables.medical_restricted}) VALUES `;
query += `INSERT INTO medical (plant_id, ${tables.medical_type}, ${tables.medical_use_identifier}, ${tables.medical_use}, ${tables.medical_images}, ${tables.medical_preparation}, ${tables.medical_restricted}) VALUES `;

// Loop through each of the medical types
for(let i = 0; i < medical_types.length; i++) {
Expand All @@ -170,7 +170,7 @@ export default async function handler(
if(craft_parts.length > 0) {

// Tell the query that we are adding to the craft parts table
query += `INSERT INTO craft (plant_id, ${tables.craft_part_of_plant}, ${tables.craft_use_identifier}, ${tables.craft_use}, ${tables.craft_image}, ${tables.craft_additional_info}) VALUES `;
query += `INSERT INTO craft (plant_id, ${tables.craft_part_of_plant}, ${tables.craft_use_identifier}, ${tables.craft_use}, ${tables.craft_images}, ${tables.craft_additional_info}) VALUES `;


// Loop through each of the craft parts
Expand Down
1 change: 1 addition & 0 deletions website/src/pages/api/posts/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export default async function handler(
const specificQuery = plant_id ? ` AND ${tables.post_plant_id} = ${plant_id}` : ""

// Get the latest posts
// todo: GET The plant names here please
query = `SELECT * FROM posts WHERE ${tables.post_approved} = 1 ${specificQuery} ORDER BY ${tables.post_date} DESC`;


Expand Down
1 change: 0 additions & 1 deletion website/src/pages/plants/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,6 @@ export default function PlantPage() {
{plantData?.sections.map((section, index) => (
<AutoSection
section={section}
images={plantData?.attachments.filter((attachment) => attachment.type === "image")}
isLeft={isMobile ? true : index % 2 === 0}
key={index}
/>
Expand Down
2 changes: 1 addition & 1 deletion website/src/pages/plants/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2382,7 +2382,7 @@ export default function CreatePlant() {

return (
<>
<Layout pageName={"Create Plant"} loginRequired header={"Creating plant: " + plantName} loadingMessage={progressMessage} permissionRequired={"pages:plants:edit"}>
<Layout pageName={"Create Plant"} loginRequired header={"Editing plant: " + plantName} loadingMessage={progressMessage} permissionRequired={"pages:plants:edit"}>
<div className={"row"}>

{/* If there is an error then show it */}
Expand Down

0 comments on commit 1e052a1

Please sign in to comment.