Skip to content

Commit

Permalink
feat: added kpi stats to homepage
Browse files Browse the repository at this point in the history
  • Loading branch information
jeafreezy committed Oct 22, 2024
1 parent 6baf05b commit 2ae23a8
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 60 deletions.
17 changes: 12 additions & 5 deletions frontend/src/app/routes/models/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,12 @@ const LayoutToggle = ({
query,
updateQuery,
isMobile,
disabled=false
disabled = false,
}: {
updateQuery: (params: TQueryParams) => void;
query: TQueryParams;
isMobile?: boolean;
disabled?:boolean
disabled?: boolean;
}) => {
const activeLayout = query[SEARCH_PARAMS.layout];
return (
Expand All @@ -134,7 +134,7 @@ const LayoutToggle = ({
disabled={disabled}
>
{activeLayout !== LayoutView.LIST ? (
<ListIcon className="icon-lg"/>
<ListIcon className="icon-lg" />
) : (
<CategoryIcon className="icon-lg" />
)}
Expand Down Expand Up @@ -295,7 +295,10 @@ export const ModelsPage = () => {
<div className="w-full grid md:grid-cols-4 md:border rounded-md p-2 md:border-gray-border gap-x-2 mt-10 grid-rows-2 md:grid-rows-1 gap-y-6 md:gap-y-0 h-screen">
<div className="overflow-scroll md:row-start-1 col-span-1 md:col-span-2">
<div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-x-4 gap-y-10">
<ModelListGridLayout models={data?.results} isPending={isPending} />
<ModelListGridLayout
models={data?.results}
isPending={isPending}
/>
</div>
</div>
<div className="col-span-2 md:col-span-2 row-start-1 ">
Expand Down Expand Up @@ -360,7 +363,11 @@ export const ModelsPage = () => {
<div className="md:flex items-center gap-x-10 hidden">
{/* Desktop */}
<SetMapToggle updateQuery={updateQuery} query={query} />
<LayoutToggle updateQuery={updateQuery} query={query} disabled={mapViewIsActive as boolean}/>
<LayoutToggle
updateQuery={updateQuery}
query={query}
disabled={mapViewIsActive as boolean}
/>
</div>
</div>
{/* Mobile */}
Expand Down
19 changes: 11 additions & 8 deletions frontend/src/components/landing/cta/cta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ import HOTTeam from "@/assets/images/hot_team_2.jpg";
import styles from "./cta.module.css";
import { APP_CONTENT } from "@/utils";
import { Image } from "@/components/ui/image";
import { Link } from "@/components/ui/link";

const CallToAction = () => {
const joinTheCommunityClick = () =>
{
window.open("https://slack.hotosm.org/")
}
return (
<section className={styles.container}>
<div className={styles.cta}>
Expand All @@ -17,10 +14,16 @@ const CallToAction = () => {
<p>{APP_CONTENT.homepage.callToAction.paragraph}</p>
</div>
<div className={styles.ctaButtonContainer}>
<Button variant="primary" onClick={joinTheCommunityClick}>
{" "}
{APP_CONTENT.homepage.callToAction.ctaButton}
</Button>
<Link
href={APP_CONTENT.homepage.callToAction.ctaLink}
title={APP_CONTENT.homepage.callToAction.ctaButton}
nativeAnchor
blank
>
<Button variant="primary">
{APP_CONTENT.homepage.callToAction.ctaButton}
</Button>
</Link>
</div>
</div>
<div className={styles.imageBlock}>
Expand Down
77 changes: 52 additions & 25 deletions frontend/src/components/landing/kpi/kpi.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,68 @@
import { APP_CONTENT } from "@/utils";
import styles from "./kpi.module.css";
import { API_ENDPOINTS, apiClient } from "@/services";
import { useQuery } from "@tanstack/react-query";

type TKPIS = {
figure: string;
figure?: number;
label: string;
}[];

const KPIs: TKPIS = [
{
figure: "15",
label: APP_CONTENT.homepage.kpi.publishedAIModels,
},
{
figure: "120",
label: APP_CONTENT.homepage.kpi.totalUsers,
},
{
figure: "100",
label: APP_CONTENT.homepage.kpi.humanFeedback,
},
{
figure: "15",
label: APP_CONTENT.homepage.kpi.acceptedPrediction,
}
// ,
// {
// figure: "86",
// label: "Mappers",
// },
];
type TKPIResponse = {
total_accepted_predictions: number;
total_feedback_labels: number;
total_models_published: number;
total_registered_users: number;
};

const fetchKPIStats = async (): Promise<TKPIResponse> => {
const { data } = await apiClient.get(API_ENDPOINTS.GET_KPI_STATS);
return data;
};

const Kpi = () => {
const { data, isLoading,isError,error} = useQuery({
queryKey: ["kpis"],
queryFn: fetchKPIStats,
});

if (isError) {
return (
<section className={styles.kpiContainer}>
<div>
<h2>Error fetching KPI Stats</h2>
<p>{(error as Error)?.message || 'An unknown error occurred.'}</p>
</div>
</section>
);
}

const KPIs: TKPIS = [
{
figure: data?.total_models_published ?? 0,
label: APP_CONTENT.homepage.kpi.publishedAIModels,
},
{
figure: data?.total_registered_users ?? 0,
label: APP_CONTENT.homepage.kpi.totalUsers,
},
{
figure: data?.total_feedback_labels ?? 0,
label: APP_CONTENT.homepage.kpi.humanFeedback,
},
{
figure: data?.total_accepted_predictions ?? 0,
label: APP_CONTENT.homepage.kpi.acceptedPrediction,
},
];

return (
<section className={styles.kpiContainer}>
{KPIs.map((kpi, id) => (
<div key={`kpi-${id}`} className={styles.kpiItem}>
<h1>{kpi.figure}</h1>
<h1 className={`${isLoading ? "animate-pulse" : ""}`}>
{kpi.figure}
</h1>
<h3>{kpi.label}</h3>
</div>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ type TrainingDetailsDialogProps = {
isOpened: boolean;
closeDialog: () => void;
trainingId: number;
datasetId:number
datasetId: number;
};

const TrainingDetailsDialog: React.FC<TrainingDetailsDialogProps> = ({
isOpened,
closeDialog,
trainingId,datasetId
trainingId,
datasetId,
}) => {
const isMobile = useDevice();

Expand All @@ -23,7 +24,11 @@ const TrainingDetailsDialog: React.FC<TrainingDetailsDialogProps> = ({
label={`Training ${trainingId}`}
size={isMobile ? "extra-large" : "medium"}
>
<ModelProperties trainingId={trainingId} isTrainingDetailsDialog datasetId={datasetId}/>
<ModelProperties
trainingId={trainingId}
isTrainingDetailsDialog
datasetId={datasetId}
/>
</Dialog>
);
};
Expand Down
7 changes: 2 additions & 5 deletions frontend/src/features/models/components/model-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ import { Link } from "@/components/ui/link";
import { truncateString } from "@/utils";
import { roundNumber } from "@/utils/number-utils";


type ModelCardProps = {
model: TModel;
};


const ModelCard: React.FC<ModelCardProps> = ({ model }) => {

return (
<div className="flex items-center w-full">
<Link
Expand All @@ -25,8 +22,8 @@ const ModelCard: React.FC<ModelCardProps> = ({ model }) => {
>
<div className="h-[200px] w-full">
<Image
height='256px'
width='256px'
height="256px"
width="256px"
src={
model.thumbnail_url
? `${model.thumbnail_url}.png`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,8 @@ const ModelProperties: React.FC<ModelPropertiesProps> = ({
source_imagery,
} = data || {};


const trainingResultsGraph = `${ENVS.BASE_API_URL}workspace/download/dataset_${datasetId}/output/training_${data?.id}/graphs/training_validation_sparse_categorical_accuracy.png`

const trainingResultsGraph = `${ENVS.BASE_API_URL}workspace/download/dataset_${datasetId}/output/training_${data?.id}/graphs/training_validation_sparse_categorical_accuracy.png`;

const content = useMemo(() => {
if (isPending) {
return <ModelPropertiesSkeleton isTrainingDetailsDialog />;
Expand Down Expand Up @@ -201,9 +200,11 @@ const ModelProperties: React.FC<ModelPropertiesProps> = ({
isTMS
/>
</div>

<div className={`col-span-3 lg:col-span-2 ${isTrainingDetailsDialog && 'lg:col-span-3'}`}>
<Image src={trainingResultsGraph} alt={""} />

<div
className={`col-span-3 lg:col-span-2 ${isTrainingDetailsDialog && "lg:col-span-3"}`}
>
<Image src={trainingResultsGraph} alt={""} />
</div>
{/* Show logs only in modal and when status failed */}
{isTrainingDetailsDialog && data?.status === TrainingStatus.FAILED && (
Expand All @@ -221,7 +222,7 @@ const ModelProperties: React.FC<ModelPropertiesProps> = ({
input_contact_spacing,
input_boundary_width,
source_imagery,
trainingResultsGraph
trainingResultsGraph,
]);

return isError ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type TrainingHistoryTableProps = {
modelId: string;
trainingId: number;
modelOwner: string;
datasetId:number
datasetId: number;
};

const columnDefinitions = (
Expand Down Expand Up @@ -226,7 +226,7 @@ const TrainingHistoryTable: React.FC<TrainingHistoryTableProps> = ({
trainingId,
modelId,
modelOwner,
datasetId
datasetId,
}) => {
const [offset, setOffset] = useState(0);
const { data, isPending, isPlaceholderData } = useTrainingHistory(
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/services/api-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export const API_ENDPOINTS = {
AUTH_CALLBACK: "auth/callback/",
USER: "auth/me/",

//KPIs

GET_KPI_STATS: "kpi/stats/ ",

//Models
GET_MODELS: "model/",
GET_MODEL_DETAILS: (id: string) => `model/${id}`,
Expand Down
12 changes: 7 additions & 5 deletions frontend/src/utils/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ export const APP_CONTENT = {
ctaSecondaryButton: "Start Mapping",
jumbotronImageAlt: "A user engaging in a mapping activity",
kpi: {
publishedAIModels:"Published AI Models",
totalUsers:"Total Registered Users",
publishedAIModels: "Published AI Models",
totalUsers: "Total Registered Users",
humanFeedback: "Human Feedbacks",
acceptedPrediction: "Accepted Prediction"
acceptedPrediction: "Accepted Prediction",
},
aboutTitle: "WHAT IS fAIr?",
aboutContent: `fAIr is an open AI-assisted mapping service developed by the Humanitarian OpenStreetMap Team (HOT) that aims to improve the efficiency and accuracy of mapping efforts for humanitarian purposes. The service uses AI models, specifically computer vision techniques, to detect objects in satellite and UAV imagery.`,
Expand Down Expand Up @@ -144,7 +144,7 @@ export const APP_CONTENT = {
{
question: "Can I use fAIr without having a sound knowledge of AI?",
answer:
"fAIr is design for users without the need for python or any programming skills. However, basic knowledge in humanitarian mapping and Geographical Information Systems (GIS) would be sufficient for self exploration.",
"fAIr is designed for users without the need for Python or any programming skills. However, basic knowledge in humanitarian mapping and Geographical Information Systems (GIS) would be sufficient for self exploration.",
},
],
},
Expand All @@ -158,7 +158,9 @@ export const APP_CONTENT = {
callToAction: {
title: `We can't do it without you`,
ctaButton: "Join The Community",
paragraph: "fAIr is a collaborative project. We welcome all types of experience to join our community on HOTOSM Slack. There is always a room for AI/ML for earth observation expertise, community engagement enthusiastic, academic researcher or student looking for an academic challenge around social impact."
ctaLink: "https://slack.hotosm.org",
paragraph:
"fAIr is a collaborative project. We welcome all types of experience to join our community on HOTOSM Slack. There is always a room for AI/ML for earth observation expertise, community engagement enthusiastic, academic researcher or student looking for an academic challenge around social impact.",
},
},
pageNotFound: {
Expand Down

0 comments on commit 2ae23a8

Please sign in to comment.