feat: Add lazy loading for images in PullRequestView

This commit adds lazy loading for images in the PullRequestView component. By implementing lazy loading, the images will only load when they are in the viewport, improving the page load performance and user experience.
This commit is contained in:
Simon Larsen 2024-07-12 21:13:05 +01:00
parent 4dacd9b8b4
commit 652e81e984
No known key found for this signature in database
GPG Key ID: 96C5DCA24769DBCA
5 changed files with 177 additions and 20 deletions

View File

@ -994,7 +994,7 @@ jobs:
needs: generate-build-number
strategy:
fail-fast: false
runs-on: ubuntu-large
runs-on: ubuntu-latest
steps:
# Docker compose needs a lot of space to build images, so we need to free up some space first in the GitHub Actions runner
@ -1031,12 +1031,12 @@ jobs:
with:
node-version: 18.3.0
- name: Setup Git LFS
run: git lfs install
# - name: Setup Git LFS
# run: git lfs install
# Cannot do this, no space on the gitHub standard runner. We need to use the large runner which is selfhosted
- name: Download the Model from Hugging Face
run: mkdir -p ./LLM/Models && cd ./LLM/Models && git clone https://${{ secrets.HUGGING_FACE_USERNAME }}:${{ secrets.HUGGING_FACE_PASSWORD }}@huggingface.co/meta-llama/Meta-Llama-3-8B-Instruct
# # Cannot do this, no space on the gitHub standard runner. We need to use the large runner which is selfhosted
# - name: Download the Model from Hugging Face
# run: mkdir -p ./LLM/Models && cd ./LLM/Models && git clone https://${{ secrets.HUGGING_FACE_USERNAME }}:${{ secrets.HUGGING_FACE_PASSWORD }}@huggingface.co/meta-llama/Meta-Llama-3-8B-Instruct
- name: Set up QEMU
uses: docker/setup-qemu-action@v2

View File

@ -23,7 +23,7 @@ jobs:
needs: generate-build-number
strategy:
fail-fast: false
runs-on: ubuntu-large
runs-on: ubuntu-latest
steps:
# Docker compose needs a lot of space to build images, so we need to free up some space first in the GitHub Actions runner
@ -60,12 +60,12 @@ jobs:
with:
node-version: 18.3.0
- name: Setup Git LFS
run: git lfs install
# - name: Setup Git LFS
# run: git lfs install
# Cannot do this, no space on the gitHub standard runner. We need to use the large runner which is selfhosted
- name: Download the Model from Hugging Face
run: mkdir -p ./LLM/Models && cd ./LLM/Models && git clone https://${{ secrets.HUGGING_FACE_USERNAME }}:${{ secrets.HUGGING_FACE_PASSWORD }}@huggingface.co/meta-llama/Meta-Llama-3-8B-Instruct
# # Cannot do this, no space on the gitHub standard runner. We need to use the large runner which is selfhosted
# - name: Download the Model from Hugging Face
# run: mkdir -p ./LLM/Models && cd ./LLM/Models && git clone https://${{ secrets.HUGGING_FACE_USERNAME }}:${{ secrets.HUGGING_FACE_PASSWORD }}@huggingface.co/meta-llama/Meta-Llama-3-8B-Instruct
- name: Set up QEMU
uses: docker/setup-qemu-action@v2

View File

@ -0,0 +1,30 @@
import Link from "CommonUI/src/Components/Link/Link";
import React, { FunctionComponent, ReactElement } from "react";
import CodeRepositoryType from "Common/Types/CodeRepository/CodeRepositoryType";
import URL from "Common/Types/API/URL";
export interface ComponentProps {
pullRequestId: string;
repoType: CodeRepositoryType;
organizationName: string;
repositoryName: string;
}
const PullRequestViewElement: FunctionComponent<ComponentProps> = (
props: ComponentProps,
): ReactElement => {
if (props.repoType === CodeRepositoryType.GitHub) {
const to: URL = URL.fromString(
`https://github.com/${props.organizationName}/${props.repositoryName}/pull/${props.pullRequestId}`,
);
return (
<Link to={to} openInNewTab={true}>
{props.pullRequestId}
</Link>
);
}
return <></>;
};
export default PullRequestViewElement;

View File

@ -1,25 +1,52 @@
import LabelsElement from "../../../../Components/Label/Labels";
import PageComponentProps from "../../../PageComponentProps";
import CodeRepositoryType from "Common/Types/CodeRepository/CodeRepositoryType";
import OneUptimeDate from "Common/Types/Date";
import ObjectID from "Common/Types/ObjectID";
import Alert, { AlertType } from "CommonUI/src/Components/Alerts/Alert";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import DropdownUtil from "CommonUI/src/Utils/Dropdown";
import Navigation from "CommonUI/src/Utils/Navigation";
import CodeRepository from "Model/Models/CopilotCodeRepository";
import CopilotCodeRepository from "Model/Models/CopilotCodeRepository";
import Label from "Model/Models/Label";
import React, { Fragment, FunctionComponent, ReactElement } from "react";
import React, {
Fragment,
FunctionComponent,
ReactElement,
useState,
} from "react";
const StatusPageView: FunctionComponent<
PageComponentProps
> = (): ReactElement => {
const modelId: ObjectID = Navigation.getLastParamAsObjectID();
const [codeRepository, setCodeRepository] =
useState<CopilotCodeRepository | null>(null);
return (
<Fragment>
{/* CodeRepository View */}
<CardModelDetail<CodeRepository>
{/* CopilotCodeRepository View */}
{codeRepository && codeRepository.lastCopilotRunDateTime && (
<Alert
type={AlertType.INFO}
strongTitle="Last Run At: "
title={`${OneUptimeDate.getDateAsLocalFormattedString(codeRepository.lastCopilotRunDateTime)}. Please re-run copilot to update data.`}
/>
)}
{codeRepository && !codeRepository.lastCopilotRunDateTime && (
<Alert
type={AlertType.INFO}
strongTitle="Last Run At: "
title={`No copilot run has been executed for this code repository. Please run copilot to update data.`}
/>
)}
<CardModelDetail<CopilotCodeRepository>
name="Git Repository > Repository Details"
cardProps={{
title: "Repository Details",
@ -129,8 +156,14 @@ const StatusPageView: FunctionComponent<
},
]}
modelDetailProps={{
selectMoreFields: {
lastCopilotRunDateTime: true,
},
onItemLoaded: (item: CopilotCodeRepository) => {
setCodeRepository(item);
},
showDetailsInNumberOfColumns: 2,
modelType: CodeRepository,
modelType: CopilotCodeRepository,
id: "model-detail-service-catalog",
fields: [
{
@ -154,7 +187,7 @@ const StatusPageView: FunctionComponent<
},
title: "Labels",
fieldType: FieldType.Element,
getElement: (item: CodeRepository): ReactElement => {
getElement: (item: CopilotCodeRepository): ReactElement => {
return <LabelsElement labels={item["labels"] || []} />;
},
},

View File

@ -5,18 +5,102 @@ import ModelTable from "CommonUI/src/Components/ModelTable/ModelTable";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import Navigation from "CommonUI/src/Utils/Navigation";
import CopilotPullRequest from "Model/Models/CopilotPullRequest";
import React, { Fragment, FunctionComponent, ReactElement } from "react";
import React, {
Fragment,
FunctionComponent,
ReactElement,
useEffect,
useState,
} from "react";
import DropdownUtil from "CommonUI/src/Utils/Dropdown";
import PullRequestState from "Common/Types/CodeRepository/PullRequestState";
import PullRequestStatusElement from "../../../../Components/CodeRepository/PullRequestStatus";
import CopilotCodeRepository from "Model/Models/CopilotCodeRepository";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import ErrorMessage from "CommonUI/src/Components/ErrorMessage/ErrorMessage";
import ModelAPI from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import API from "CommonUI/src/Utils/API/API";
import PullRequestViewElement from "../../../../Components/CodeRepository/PullRequestView";
import Alert, { AlertType } from "CommonUI/src/Components/Alerts/Alert";
import OneUptimeDate from "Common/Types/Date";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
const CopilotPullRequestPage: FunctionComponent<
PageComponentProps
> = (): ReactElement => {
const codeRepositoryId: ObjectID = Navigation.getLastParamAsObjectID(1);
const [codeRepository, setCodeRepository] =
useState<CopilotCodeRepository | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
const fetchCodeRepository: PromiseVoidFunction = async (): Promise<void> => {
// get item.
setIsLoading(true);
setError("");
try {
const item: CopilotCodeRepository | null = await ModelAPI.getItem({
modelType: CopilotCodeRepository,
id: codeRepositoryId,
select: {
repositoryHostedAt: true,
repositoryName: true,
organizationName: true,
lastCopilotRunDateTime: true,
},
});
if (!item) {
setError(`Code Repository not found`);
return;
}
setCodeRepository(item);
} catch (err) {
setError(API.getFriendlyMessage(err));
}
setIsLoading(false);
};
useEffect(() => {
fetchCodeRepository().catch((err: Error) => {
setError(API.getFriendlyMessage(err));
});
}, []);
if (isLoading) {
return <PageLoader isVisible={true} />;
}
if (error) {
return <ErrorMessage error={error} />;
}
if (!codeRepository) {
return <ErrorMessage error={"Code Repository not found"} />;
}
return (
<Fragment>
{codeRepository.lastCopilotRunDateTime && (
<Alert
type={AlertType.INFO}
strongTitle="Last Run At: "
title={`${OneUptimeDate.getDateAsLocalFormattedString(codeRepository.lastCopilotRunDateTime)}. Please re-run copilot to update data.`}
/>
)}
{!codeRepository.lastCopilotRunDateTime && (
<Alert
type={AlertType.INFO}
strongTitle="Last Run At: "
title={`No copilot run has been executed for this code repository. Please run copilot to update data.`}
/>
)}
<ModelTable<CopilotPullRequest>
modelType={CopilotPullRequest}
id="table-copiolt-pull-requests"
@ -71,7 +155,17 @@ const CopilotPullRequestPage: FunctionComponent<
pullRequestId: true,
},
title: "Pull Request ID",
type: FieldType.Text,
type: FieldType.Element,
getElement: (item: CopilotPullRequest): ReactElement => {
return (
<PullRequestViewElement
pullRequestId={item.pullRequestId!}
organizationName={codeRepository.organizationName!}
repositoryName={codeRepository.repositoryName!}
repoType={codeRepository.repositoryHostedAt!}
/>
);
},
},
{
field: {