Skip to content

Commit

Permalink
Merge branch '9.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
himeshr committed Aug 8, 2024
2 parents d4d9b58 + d7014b3 commit 8b67df6
Show file tree
Hide file tree
Showing 16 changed files with 201 additions and 4,387 deletions.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
Connecting local avni-media to server/etl on another environment like staging leads to CORS errors.

Thus, for local development on avni-media, other avni components like `avni-server` and `avni-etl` need to be running locally with an IDP enabled i.e. Cognito or Keycloak.

### Other Avni Components

#### Environment Variables
Ensure that local `avni-server` and `avni-etl` have the following environment variables set
I. Ensure that local `avni-server` and `avni-etl` have the following environment variables set
```
AVNI_IDP_TYPE
OPENCHS_CLIENT_ID
Expand All @@ -21,6 +23,19 @@ OPENCHS_KEYCLOAK_CLIENT_SECRET
OPENCHS_KEYCLOAK_ENABLED
```

II. Alternately, to work with Staging env IDP and Storage, you may use the following Make command in both avni-server and avni-etl. If required, override the DB and other details, Ex: OPENCHS_DATABASE_NAME=avni_org

```
## Init below fields in env variables
OPENCHS_STAGING_APP_CLIENT_ID
OPENCHS_STAGING_USER_POOL_ID
OPENCHS_STAGING_IAM_USER
OPENCHS_STAGING_IAM_USER_ACCESS_KEY
OPENCHS_STAGING_IAM_USER_SECRET_ACCESS_KEY
make start_server_staging OPENCHS_DATABASE_NAME=<your_db_name>
```

### Avni Media
There is a `local.staging` environment template configured for `client` and `server` that help with running `avni-media` locally.
Look at `client/middleware.js` which takes care of routing the request to local `avni-server` and `avni-etl` in this mode.
Expand Down
24 changes: 14 additions & 10 deletions client/components/ImageCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import {Carousel} from "react-responsive-carousel";
import CheckButton from "./CheckButton";
import {useEffect, useState} from "react";
import axios from "axios";
import {redirectIfNotValid, operationalModuleData} from '@/utils/helpers'
import {redirectIfNotValid, operationalModuleData, fetchAuthHeaders} from '@/utils/helpers'
import {imageType, getImageName, getImage, imageMetadata, getMetadata, getImageNameWithoutNewLines} from '../model/ImageType';
import {Button} from "@mui/material";
import {MediaSearchService} from "@/service/MediaSearchService";
import Loading from '@/components/loading';

interface Props {
imageList: object[];
totalRecords: any;
carouselImage: any;
pagination: any;
currentPage: any;
showPerpage: any,
onClose: () => void;
onSelectImage: (value: string, checked: boolean) => void;
checkedImage: string[];
Expand All @@ -26,7 +28,8 @@ const ImageCarousel = ({
imageList,
totalRecords,
carouselImage,
pagination,
currentPage,
showPerpage,
onClose,
onSelectImage,
checkedImage,
Expand All @@ -35,7 +38,7 @@ const ImageCarousel = ({
const ci = carouselImage as never;
const index = imageList.indexOf(ci);
const [images, setImages] = useState([]);

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

useEffect(() => {
Expand All @@ -49,8 +52,10 @@ const ImageCarousel = ({
useEffect(() => {
redirectIfNotValid();
const fetchImages = async () => {
const responseData = await MediaSearchService.searchMedia(dataBody, pagination.page, pagination.size);
setShowLoader(true);
const responseData = await MediaSearchService.searchMedia(dataBody, currentPage, showPerpage);
setImages(responseData.data);
setShowLoader(false);
};
fetchImages();
}, [totalRecords]);
Expand All @@ -65,10 +70,8 @@ const ImageCarousel = ({

const redirectToSubjectDashboardURL = async (imgMetadata: imageMetadata) => {
const options = {
headers: {
"AUTH-TOKEN": localStorage.getItem("authToken"),
},
params : imgMetadata
headers: fetchAuthHeaders(),
params: imgMetadata
};
const response = await axios.get(
`${process.env.NEXT_PUBLIC_WEB}/web/individual/byMetadata`,
Expand Down Expand Up @@ -113,7 +116,8 @@ const ImageCarousel = ({
</svg>
</button>
</div>
<div className="flex w-full h-full">
<div className="flex w-full h-full" style={{position: "relative",width: "500px", height: "500px"}}>
{showLoader && <Loading />}
<Carousel
renderArrowPrev={(clickHandler, hasPrev) => {
return (
Expand Down
129 changes: 57 additions & 72 deletions client/components/ImageList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import CheckButton from "./CheckButton";
import {Key, useEffect, useState} from "react";
import {Fragment, Key, useEffect, useState} from "react";
import Pagination from "@/components/Pagination";
import ImageCarousel from "./ImageCarousel";
import axios from "axios";
Expand All @@ -13,8 +12,8 @@ import Program from "./FilterComponent/Program";
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, getImageNameWithoutNewLines} from '../model/ImageType';
import {fetchAuthHeaders, getUserUuidFromToken, operationalModuleData, redirectIfNotValid} from "@/utils/helpers";
import {imageType} from '../model/ImageType';
import CodedConceptFilter from "./FilterComponent/CodedConceptFilter";
import DateConceptFilter from "./FilterComponent/DateConceptFilter";
import TimeStampConceptFilter from "./FilterComponent/TimeStampConceptFilter";
Expand All @@ -23,6 +22,8 @@ import NumericConceptFilter from "./FilterComponent/NumericConceptFilter";
import {Checkbox, Divider, FormControlLabel, Button as MUIButton} from "@mui/material";
import _ from 'lodash';
import {MediaSearchService} from "@/service/MediaSearchService";
import MediaViewItem from '@/components/MediaViewItem';
import Loading from './loading';

export default function ImageList() {
const [parentId, setParentId] = useState<any[]>([])
Expand All @@ -33,9 +34,8 @@ export default function ImageList() {
const [selectedParentId, setSelectedParentId] = useState<any>([]);
const [fromDate, setFromDate] = useState(null);
const [toDate, setToDate] = useState(null);
const [imageList, setImageList] = useState<any>({page: 0, data: []});
const [imageList, setImageList] = useState<any>({total: 0, data: []});
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>();
const [locationFilter, setLocation] = useState<any>([]);
Expand Down Expand Up @@ -299,15 +299,17 @@ export default function ImageList() {
useEffect(() => {
redirectIfNotValid();
const fetchImages = async () => {
const responseData = await MediaSearchService.searchMedia(dataBody, pagination.page, showPerpage);
const nextPageResponseData = await MediaSearchService.searchMedia(dataBody, pagination.page + 1, showPerpage);
setShowLoader(true);
const responseData = await MediaSearchService.searchMedia(dataBody, currentPage, showPerpage);
const nextPageResponseData = await MediaSearchService.searchMedia(dataBody, currentPage + 1, showPerpage);

setImageList(responseData);
setShowLoader(false);
setNextPageData(nextPageResponseData);
};

fetchImages();
}, [pagination, showPerpage]);
}, [currentPage, showPerpage]);

const [carouselImage, setCarouselImage] = useState<{
uuid: string;
Expand Down Expand Up @@ -377,8 +379,7 @@ export default function ImageList() {
}, [checkedImage, imageList]);


const pageChange = (size: number, page: number) => {
setPagination({size: size, page: page});
const pageChange = (page: number) => {
setCurrentPage(page);
if (selectAllPages) {
setSelectAllInPage((oldValue: any) => {
Expand All @@ -388,15 +389,12 @@ export default function ImageList() {
}
};
const [showModal, setShowModal] = useState(false);
const [showLoader, setShowLoader] = useState(false);

const handleSendSelectedImages = async (inputValue: any) => {
alert(`We are processing your download request. Once the download is ready, it will be available under Available Downloads. At most 1000 media items will be included in the download bundle.`);
if (selectAllPages) {
const options = {
headers: {
"AUTH-TOKEN": localStorage.getItem("authToken"),
},
};
const options = {headers: fetchAuthHeaders()};
await axios.post(
`${process.env.NEXT_PUBLIC_ETL}/requestDownloadAll`,
{mediaSearchRequest: dataBody, username: userName, description: inputValue, addressLevelTypes: locationFilter},
Expand Down Expand Up @@ -717,8 +715,10 @@ export default function ImageList() {

const handleApplyFilter = async () => {
redirectIfNotValid();
const responseData = await MediaSearchService.searchMedia(dataBody, 0, pagination.size);
setShowLoader(true);
const responseData = await MediaSearchService.searchMedia(dataBody, 0, showPerpage);
setImageList(responseData);
setShowLoader(false);
};

const handleNumberChange = (value: number) => {
Expand Down Expand Up @@ -873,6 +873,9 @@ export default function ImageList() {
subject={subject}
/>
)}
{showLoader && (
<Loading />
)}
<Button name="Apply Filter" onClick={handleApplyFilter}/>
<Button onClick={handleOpenModal} name=" Download"/>
<Link href="./downloadList">
Expand Down Expand Up @@ -909,62 +912,44 @@ export default function ImageList() {
}
</div>
<Divider style={{paddingTop: "24px"}}/>
<div className="max-w-2xl mx-auto py-16 px-4 sm:py-24 sm:px-6 lg:max-w-7xl lg:px-8">
<div className="-mt-16 grid grid-cols-1 gap-y-12 sm:grid-cols-2 sm:gap-x-6 lg:grid-cols-5 xl:gap-x-8">
{imageList.data.map(
(image: imageType) => {
return (
<div key={`${image.uuid}-${Math.random()}`}>
<div className="relative">
<div className="relative w-full h-50 rounded-lg overflow-hidden">
<button>
<img
src={getImage(image, true)}
alt={image?.subjectTypeName}
onClick={() => setCarouselImage(image)}
className="thumb"
/>
</button>
</div>
<CheckButton
imageNameWithoutNewLines={getImageNameWithoutNewLines(image, minLevelName)}
unSignedUrl={image.url}
name={getImageName(image, minLevelName)}
id={image.uuid}
onSelectImage={onSelectImage}
checkedImage={checkedImage}
imageDetail={image}
image_url={image.signedUrl}
flag="list"
onSelectImageCarousel={function (): void {
throw new Error("Function not implemented.");
}}
/>
</div>
</div>
);
}
{imageList.total === 0 ? (showLoader ? <></>: (<p style={{
display: "flex",
justifyContent: "center",
alignItems: "center", paddingTop: "24px", fontSize: "1rem"
}}>No results to display</p>)) :
<Fragment>
<div className="max-w-2xl mx-auto py-16 px-4 sm:py-24 sm:px-6 lg:max-w-7xl lg:px-8">
<div
className="-mt-16 grid grid-cols-1 gap-y-12 sm:grid-cols-2 sm:gap-x-6 lg:grid-cols-5 xl:gap-x-8">
{imageList.data.map(
(image: imageType) =>
<MediaViewItem key={image.uuid} image={image}
setCarouselImage={setCarouselImage}
minLevelName={minLevelName} onSelectImage={onSelectImage}
checkedImage={checkedImage}/>
)}
</div>
</div>
{carouselImage && (
<ImageCarousel
imageList={imageList.data}
totalRecords={imageList.total}
carouselImage={carouselImage}
onClose={() => setCarouselImage(null)}
onSelectImage={onSelectImage}
currentPage={currentPage}
showPerpage={showPerpage}
checkedImage={checkedImage}
setCheckedImage={[]}
dataBody={dataBody}
/>
)}
</div>
</div>
{carouselImage && (
<ImageCarousel
imageList={imageList.data}
totalRecords={imageList.total}
carouselImage={carouselImage}
onClose={() => setCarouselImage(null)}
onSelectImage={onSelectImage}
pagination={pagination}
checkedImage={checkedImage}
setCheckedImage={[]}
dataBody={dataBody}
/>
)}
<Pagination
showperpage={showPerpage}
pagechange={pageChange}
nextPageData={nextPageData.data}
/>
<Pagination
showperpage={showPerpage}
pagechange={pageChange}
nextPageData={nextPageData.data}
/>
</Fragment>}
</div>
</>
);
Expand Down
45 changes: 45 additions & 0 deletions client/components/MediaViewItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {getImage, getImageName, getImageNameWithoutNewLines, imageType} from '@/model/ImageType';
import CheckButton from '@/components/CheckButton';

interface Props {
image: imageType,
setCarouselImage: (value: (((prevState: ({ uuid: string; signedUrl: string; signedThumbnailUrl: string; subjectTypeName: string } | null)) => ({ uuid: string; signedUrl: string; signedThumbnailUrl: string; subjectTypeName: string } | null)) | { uuid: string; signedUrl: string; signedThumbnailUrl: string; subjectTypeName: string } | null)) => void,
minLevelName: string,
onSelectImage: (value: string, checked: boolean) => void,
checkedImage: string[]
}

const MediaViewItem = ({image, setCarouselImage, minLevelName, onSelectImage, checkedImage}: Props) => {
return (
<div key={`${image.uuid}-${Math.random()}`}>
<div className="relative">
<div className="relative w-full h-50 rounded-lg overflow-hidden">
<button>
<img
src={getImage(image, true)}
alt={image?.subjectTypeName}
onClick={() => setCarouselImage(image)}
className="thumb"
/>
</button>
</div>
<CheckButton
imageNameWithoutNewLines={getImageNameWithoutNewLines(image, minLevelName)}
unSignedUrl={image.url}
name={getImageName(image, minLevelName)}
id={image.uuid}
onSelectImage={onSelectImage}
checkedImage={checkedImage}
imageDetail={image}
image_url={image.signedUrl}
flag="list"
onSelectImageCarousel={function (): void {
throw new Error("Function not implemented.");
}}
/>
</div>
</div>
);
}

export default MediaViewItem;
6 changes: 3 additions & 3 deletions client/components/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useState, useEffect } from 'react';

interface Props {
showperpage: number;
pagechange: (size: number, pageNumber: number) => void;
pagechange: (pageNumber: number) => void;
nextPageData: any[];

}
Expand All @@ -15,10 +15,10 @@ interface Props {
useEffect(() => {

if (counter == page) {
pagechange(showperpage, counter - 1)
pagechange(counter - 1)
}
else {
pagechange(showperpage, counter -1 )
pagechange(counter -1 )
}
}, [counter, showperpage])

Expand Down
Loading

0 comments on commit 8b67df6

Please sign in to comment.