Skip to content

Commit

Permalink
#174 - Download file working (added extension to the downloaded file)…
Browse files Browse the repository at this point in the history
…. removed duplicate code for media search into service. use middleware specific environment variables for middleware.js.
  • Loading branch information
petmongrels committed May 10, 2024
1 parent d02b62f commit d1e3c7b
Show file tree
Hide file tree
Showing 12 changed files with 367 additions and 1,426 deletions.
4 changes: 4 additions & 0 deletions client/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ start-local-staging:
$(call _create_env,local.staging)
npm run dev

start-with-prod:
$(call _create_env,development.production)
npm run dev

_build-app:
$(call _create_env,)
npm run build
Expand Down
95 changes: 50 additions & 45 deletions client/components/CheckButton.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,56 @@
import{DownloadOutlined} from '@ant-design/icons';
import {DownloadOutlined} from '@ant-design/icons';
import {getDownloadFileName} from "@/model/ImageType";

interface prop {
name: string,
id: string,
onSelectImage: (value: string, checked: boolean) => void,
checkedImage: string[],
onSelectImageCarousel: (value: string, checked: boolean) => void,
flag: string,
imageDetail: any
image_url: string
name: string,
id: string,
onSelectImage: (value: string, checked: boolean) => void,
checkedImage: string[],
onSelectImageCarousel: (value: string, checked: boolean) => void,
flag: string,
imageDetail: any
image_url: string,
unSignedUrl: string,
imageNameWithoutNewLines: string
}

export default function CheckButton({ name, id, onSelectImage, checkedImage, onSelectImageCarousel, flag,image_url }: prop) {
const handleChecked = (e: any) => {
const { value, checked } = e.target;
if (flag == 'list') {
onSelectImage(value, checked)
} else {
const { value, checked } = e.target;
onSelectImageCarousel(value, checked)
export default function CheckButton({name, id, onSelectImage, checkedImage, onSelectImageCarousel, flag, image_url, unSignedUrl, imageNameWithoutNewLines}: prop) {
const handleChecked = (e: any) => {
const {value, checked} = e.target;
if (flag == 'list') {
onSelectImage(value, checked)
} else {
const {value, checked} = e.target;
onSelectImageCarousel(value, checked)
}
}
}

const isChecked = checkedImage.includes(id.toString());

return (
<fieldset className="mt-5">
<div className="flex justify-between">
<div className="">
<input
id={id.toString()}
value={id}
aria-describedby="comments-description"
type="checkbox"
checked={isChecked}
className="focus:ring-teal-500 h-4 w-4 text-teal-600 border-gray-300 rounded"
onChange={(e) => handleChecked(e)}
/>
</div>
<div className="mr-8">
<a href={image_url} target ="_blank" >
<DownloadOutlined />
</a>
</div>
</div>
<div className="mt-1 text-sm">
<label className="font-medium text-gray-700">{name}</label>
</div>
</fieldset>
);
const isChecked = checkedImage.includes(id.toString());
const downloadUrl = `/web/media/downloadStream?s3Url=${unSignedUrl}&fileName=${getDownloadFileName(name, unSignedUrl)}`;

return (
<fieldset className="mt-5">
<div className="flex justify-between">
<div className="">
<input
id={id.toString()}
value={id}
aria-describedby="comments-description"
type="checkbox"
checked={isChecked}
className="focus:ring-teal-500 h-4 w-4 text-teal-600 border-gray-300 rounded"
onChange={(e) => handleChecked(e)}
/>
</div>
<div className="mr-8">
<a href={downloadUrl} download>
<DownloadOutlined/>
</a>
</div>
</div>
<div className="mt-1 text-sm">
<label className="font-medium text-gray-700"><a href={image_url} target="_blank">{name}</a></label>
</div>
</fieldset>
);
}
27 changes: 9 additions & 18 deletions client/components/ImageCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import CheckButton from "./CheckButton";
import {useEffect, useState} from "react";
import axios from "axios";
import {redirectIfNotValid, operationalModuleData} from '@/utils/helpers'
import {imageType, getImageName, getImage, imageMetadata, getMetadata} from '../model/ImageType';
import {imageType, getImageName, getImage, imageMetadata, getMetadata, getImageNameWithoutNewLines} from '../model/ImageType';
import {Button} from "@mui/material";
import {MediaSearchService} from "@/service/MediaSearchService";

interface Props {
imageList: object[];
Expand All @@ -33,10 +34,7 @@ const ImageCarousel = ({
}: Props) => {
const ci = carouselImage as never;
const index = imageList.indexOf(ci);
const [imageCarousel, setImageCarousel] = useState({
page: 0,
data: []
});
const [images, setImages] = useState([]);

const [minLevelName, setMinLevelName] = useState<string>('');

Expand All @@ -51,17 +49,8 @@ const ImageCarousel = ({
useEffect(() => {
redirectIfNotValid();
const fetchImages = async () => {
const options = {
headers: {
"AUTH-TOKEN": localStorage.getItem("authToken"),
},
};
const response = await axios.post(
`${process.env.NEXT_PUBLIC_ETL}/media/search?page=${pagination.page}&size=${pagination.size}`,
dataBody,
options
);
setImageCarousel(response.data);
const responseData = await MediaSearchService.searchMedia(dataBody, pagination.page, pagination.size);
setImages(responseData.data);
};
fetchImages();
}, [totalRecords]);
Expand Down Expand Up @@ -158,15 +147,17 @@ const ImageCarousel = ({
dynamicHeight={false}
useKeyboardArrows={true}
>
{imageCarousel.data.map(
{images.map(
(
img: imageType,
index
) => (
<div key={index}>
<img src={getImage(img, true)} className="carousel-image"/>
<img src={getImage(img, false)} className="carousel-image"/>
<div className="checkbox">
<CheckButton
imageNameWithoutNewLines={getImageNameWithoutNewLines(img, minLevelName)}
unSignedUrl={img.url}
image_url={getImage(img)}
name={getImageName(img, minLevelName)}
id={img.uuid}
Expand Down
88 changes: 36 additions & 52 deletions client/components/ImageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import SubjectType from "./FilterComponent/SubjectType";
import NumberDropdown from "./FilterComponent/ImageSize";
import Button from "./DownloadComponent/Button";
import {getUserUuidFromToken, operationalModuleData, redirectIfNotValid} from "@/utils/helpers";
import {imageType, getImageName, getImage} from '../model/ImageType';
import {imageType, getImageName, getImage, getImageNameWithoutNewLines} from '../model/ImageType';
import CodedConceptFilter from "./FilterComponent/CodedConceptFilter";
import DateConceptFilter from "./FilterComponent/DateConceptFilter";
import TimeStampConceptFilter from "./FilterComponent/TimeStampConceptFilter";
import TexConceptFilter from "./FilterComponent/TextConceptFilter";
import NumericConceptFilter from "./FilterComponent/NumericConceptFilter";
import {Checkbox, Divider, FormControlLabel, Button as MUIButton} from "@mui/material";
import _ from 'lodash';
import {MediaSearchService} from "@/service/MediaSearchService";

export default function ImageList() {
const [parentId, setParentId] = useState<any[]>([])
Expand All @@ -33,7 +34,7 @@ export default function ImageList() {
const [fromDate, setFromDate] = useState(null);
const [toDate, setToDate] = useState(null);
const [imageList, setImageList] = useState<any>({page: 0, data: []});
const MIN_PAGE_SIZE = 10, MAX_PAGE_SIZE= 100, PAGE_SIZE_STEP = 10;
const MIN_PAGE_SIZE = 10, MAX_PAGE_SIZE = 100, PAGE_SIZE_STEP = 10;
const [pagination, setPagination] = useState({size: MIN_PAGE_SIZE, page: 0});
const [showPerpage, setShowperpage] = useState(PAGE_SIZE_STEP);
const [userName, setUserName] = useState<string | string[] | undefined>();
Expand Down Expand Up @@ -76,7 +77,7 @@ export default function ImageList() {
const [selectedMediaConcepts, setSelectedMediaConcepts] = useState<any>([]);
const selectedFieldConcept = selectedFieldConcepts && selectedFieldConcepts.length > 0 && selectedFieldConcepts[0];
const ALL_SELECTED = "ALL", SOME_SELECTED = "SOME", NONE_SELECTED = "NONE";
const [selectAllInPage, setSelectAllInPage] = useState<any>({0:NONE_SELECTED});
const [selectAllInPage, setSelectAllInPage] = useState<any>({0: NONE_SELECTED});
const [selectAllPages, setSelectAllPages] = useState<boolean>(false);
const [currentPage, setCurrentPage] = useState<number>(0);
useEffect(() => {
Expand Down Expand Up @@ -107,10 +108,9 @@ export default function ImageList() {
}, []);



const getConceptData = async (formUUID: any, filteredConcept: any[]) => {
const formData = await axios.get(
`${process.env.NEXT_PUBLIC_WEB}/web/form/${formUUID}`
`${process.env.NEXT_PUBLIC_WEB}/web/form/${formUUID}`
);
const forms = formData.data;
const formElementGroups = forms.formElementGroups;
Expand Down Expand Up @@ -299,24 +299,11 @@ export default function ImageList() {
useEffect(() => {
redirectIfNotValid();
const fetchImages = async () => {
const options = {
headers: {
"AUTH-TOKEN": localStorage.getItem("authToken"),
},
};
const responseData = await MediaSearchService.searchMedia(dataBody, pagination.page, showPerpage);
const nextPageResponseData = await MediaSearchService.searchMedia(dataBody, pagination.page + 1, showPerpage);

const response = await axios.post(
`${process.env.NEXT_PUBLIC_ETL}/media/search?page=${pagination.page}&size=${showPerpage}`,
dataBody,
options
);
const nextPageResponse = await axios.post(
`${process.env.NEXT_PUBLIC_ETL}/media/search?page=${pagination.page + 1}&size=${showPerpage}`,
dataBody,
options
);
setImageList(response.data);
setNextPageData(nextPageResponse.data);
setImageList(responseData);
setNextPageData(nextPageResponseData);
};

fetchImages();
Expand All @@ -335,7 +322,7 @@ export default function ImageList() {
const onSelectImage = (value: string, checked: boolean) => {
if (checked) {
setCheckedImage((prevCheckedImage) => {
return (prevCheckedImage.indexOf(value) == -1) ? [...prevCheckedImage, value] : prevCheckedImage
return (prevCheckedImage.indexOf(value) == -1) ? [...prevCheckedImage, value] : prevCheckedImage
});
} else {
setCheckedImage((prevCheckedImage) =>
Expand Down Expand Up @@ -364,16 +351,16 @@ export default function ImageList() {
const toggleCheckAllImagesInCurrentPage = () => {
setSelectAllInPage((oldValue: any) => {
const currentValue = oldValue[currentPage] || NONE_SELECTED;
const nextValue = (currentValue === NONE_SELECTED || currentValue === SOME_SELECTED) ? ALL_SELECTED: NONE_SELECTED;
const nextValue = (currentValue === NONE_SELECTED || currentValue === SOME_SELECTED) ? ALL_SELECTED : NONE_SELECTED;
return {...oldValue, [currentPage]: nextValue}
});
}

useEffect(() => {
if(selectAllInPage[currentPage] === ALL_SELECTED){
imageList.data.forEach((image : any) => onSelectImage(image.uuid, true));
} else if(selectAllInPage[currentPage] === NONE_SELECTED) {
imageList.data.forEach((image : any) => onSelectImage(image.uuid, false));
if (selectAllInPage[currentPage] === ALL_SELECTED) {
imageList.data.forEach((image: any) => onSelectImage(image.uuid, true));
} else if (selectAllInPage[currentPage] === NONE_SELECTED) {
imageList.data.forEach((image: any) => onSelectImage(image.uuid, false));
}
}, [imageList, selectAllInPage])

Expand All @@ -393,7 +380,7 @@ export default function ImageList() {
const pageChange = (size: number, page: number) => {
setPagination({size: size, page: page});
setCurrentPage(page);
if(selectAllPages) {
if (selectAllPages) {
setSelectAllInPage((oldValue: any) => {
oldValue[page] = ALL_SELECTED;
return oldValue;
Expand Down Expand Up @@ -730,18 +717,8 @@ export default function ImageList() {

const handleApplyFilter = async () => {
redirectIfNotValid();
const options = {
headers: {
"AUTH-TOKEN": localStorage.getItem("authToken"),
"Content-Type": "application/json",
},
};
const response = await axios.post(
`${process.env.NEXT_PUBLIC_ETL}/media/search?page=${pagination.page}&size=${pagination.size}`,
dataBody,
options
);
setImageList(response.data);
const responseData = await MediaSearchService.searchMedia(dataBody, 0, pagination.size);
setImageList(responseData);
};

const handleNumberChange = (value: number) => {
Expand All @@ -755,16 +732,16 @@ export default function ImageList() {
const toggleSelectAllPages = () => {
setSelectAllPages(oldValue => {
const newValue = !oldValue;
if(!newValue) {
setSelectAllInPage({[currentPage]:NONE_SELECTED})
if (!newValue) {
setSelectAllInPage({[currentPage]: NONE_SELECTED})
setCheckedImage([]);
}
return newValue
});
}

const resetSelections = () => {
setSelectAllInPage({[currentPage]:NONE_SELECTED});
setSelectAllInPage({[currentPage]: NONE_SELECTED});
setSelectAllPages(false);
setCheckedImage([]);
}
Expand Down Expand Up @@ -827,7 +804,9 @@ export default function ImageList() {
)}
<Daterange dateRange={dateRange}/>

<Concepts setConceptsFunction={(x:string[]) => {setSelectedMediaConcepts(x)}} concepts={mediaConcepts} title={"Media Types"} multiSelect={true} searchable={false}/>
<Concepts setConceptsFunction={(x: string[]) => {
setSelectedMediaConcepts(x)
}} concepts={mediaConcepts} title={"Media Types"} multiSelect={true} searchable={false}/>

{subjectFilter && subjectFilter.length > 0 && (
<SubjectType
Expand All @@ -851,7 +830,7 @@ export default function ImageList() {
)}

{selectedFormSubject && selectedFormSubject.length > 0 && conceptData &&
<Concepts setConceptsFunction={setConcepts} concepts={conceptData} title="Fields" multiSelect={false} searchable={true}/>
<Concepts setConceptsFunction={setConcepts} concepts={conceptData} title="Fields" multiSelect={false} searchable={true}/>
}
{showCodedFilter ? (
<CodedConceptFilter concepts={selectedFieldConcept.conceptAnswers}
Expand Down Expand Up @@ -906,24 +885,27 @@ export default function ImageList() {
onClick={restFilters}
name="Reset Filters"
/>
<FormControlLabel style={{paddingLeft:"48px"}} label={"Select All"}
<FormControlLabel style={{paddingLeft: "48px"}} label={"Select All"}
control={<Checkbox
onChange={toggleCheckAllImagesInCurrentPage}
checked={selectAllInPage[currentPage] === ALL_SELECTED}
indeterminate={selectAllInPage[currentPage] === SOME_SELECTED}
disabled={selectAllPages}
/>} />
/>}/>
{(selectAllInPage[currentPage] === ALL_SELECTED) && <>
<MUIButton variant="text" onClick={toggleSelectAllPages} style={{textTransform:"capitalize", fontSize:"1rem"}}>{selectAllPages ? "Clear selection" : "Select all media matching filter"}</MUIButton>
<MUIButton variant="text" onClick={toggleSelectAllPages} style={{
textTransform: "capitalize",
fontSize: "1rem"
}}>{selectAllPages ? "Clear selection" : "Select all media matching filter"}</MUIButton>
</>}
{
(selectAllPages || checkedImage.length > 0) && <Divider style={{paddingTop:"24px"}}/>
(selectAllPages || checkedImage.length > 0) && <Divider style={{paddingTop: "24px"}}/>
}
{
(!selectAllPages && checkedImage.length > 0) && <p style={{paddingTop:"24px", fontSize:"1rem"}}>Selected {checkedImage.length} media items</p>
(!selectAllPages && checkedImage.length > 0) && <p style={{paddingTop: "24px", fontSize: "1rem"}}>Selected {checkedImage.length} media items</p>
}
{
selectAllPages && <p style={{paddingTop:"24px", fontSize:"1rem"}}>Selected all media items in all pages</p>
selectAllPages && <p style={{paddingTop: "24px", fontSize: "1rem"}}>Selected all media items in all pages</p>
}
</div>
<Divider style={{paddingTop: "24px"}}/>
Expand All @@ -945,6 +927,8 @@ export default function ImageList() {
</button>
</div>
<CheckButton
imageNameWithoutNewLines={getImageNameWithoutNewLines(image, minLevelName)}
unSignedUrl={image.url}
name={getImageName(image, minLevelName)}
id={image.uuid}
onSelectImage={onSelectImage}
Expand Down
Loading

0 comments on commit d1e3c7b

Please sign in to comment.