Skip to content

Commit

Permalink
Merge pull request #87 from KelvinTegelaar/dev
Browse files Browse the repository at this point in the history
[pull] dev from KelvinTegelaar:dev
  • Loading branch information
pull[bot] authored Feb 11, 2025
2 parents dbe0495 + b8957ba commit ef17d84
Show file tree
Hide file tree
Showing 2 changed files with 198 additions and 44 deletions.
171 changes: 136 additions & 35 deletions src/pages/tools/community-repos/repo.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useRouter } from "next/router";
import { Layout as DashboardLayout } from "/src/layouts";
import { CippTablePage } from "/src/components/CippComponents/CippTablePage.jsx";
import { useState, useEffect } from "react";
import { ApiPostCall } from "/src/api/ApiCall";
import { ApiPostCall, ApiGetCall } from "/src/api/ApiCall";
import {
Button,
Dialog,
Expand All @@ -11,67 +11,179 @@ import {
DialogActions,
Box,
Skeleton,
Alert,
} from "@mui/material";
import { OpenInNew } from "@mui/icons-material";
import { Grid } from "@mui/system";
import CippJSONView from "/src/components/CippFormPages/CippJSONView";
import { EyeIcon } from "@heroicons/react/24/outline";
import { CippAutoComplete } from "/src/components/CippComponents/CippAutocomplete";
import React from "react";

const Page = () => {
const router = useRouter();
const { name } = router.query;
const [openJsonDialog, setOpenJsonDialog] = useState(false);
const [fileResults, setFileResults] = useState([]);
const [jsonContent, setJsonContent] = useState({});
const [branches, setBranches] = useState([]);
const [selectedBranch, setSelectedBranch] = useState("");
const [selectedRepo, setSelectedRepo] = useState(name);

const searchMutation = ApiPostCall({
onResult: (resp) => {
if (resp?.Results === null || resp?.Results?.[0] === null) return;
setFileResults(resp?.Results || []);
},
});

const fileMutation = ApiPostCall({
const fileQuery = ApiPostCall({
onResult: (resp) => {
setJsonContent(JSON.parse(resp?.Results?.content || "{}"));
},
});

const branchQuery = ApiGetCall({
url: "/api/ExecGitHubAction",
data: {
Action: "GetBranches",
FullName: selectedRepo,
},
onResult: (resp) => {
const branchList = resp?.Results || [];
setBranches(branchList);
if (branchList.length === 1) {
setSelectedBranch(branchList[0].name);
fetchFileTree(branchList[0].name);
}
const mainBranch = branchList.find((branch) => ["main", "master"].includes(branch.name));
if (mainBranch) {
setSelectedBranch(mainBranch.name);
fetchFileTree(mainBranch.name);
}
},
queryKey: `${selectedRepo}-branches`,
waiting: selectedRepo !== "",
});

const fileTreeQuery = ApiGetCall({
url: "/api/ExecGitHubAction",
data: {
Action: "GetFileTree",
FullName: selectedRepo,
Branch: selectedBranch,
},
onResult: (resp) => {
setFileResults(resp?.Results || []);
},
queryKey: `${selectedRepo}-${selectedBranch}-filetree`,
waiting: selectedRepo !== "" && selectedBranch !== "",
});

const fetchFileTree = (branch) => {
if (selectedRepo !== "" && branch !== "") {
if (!fileTreeQuery.waiting) {
fileTreeQuery.waiting = true;
}
fileTreeQuery.refetch();
}
};

const handleJsonView = (url) => {
fileMutation.mutate({
fileQuery.mutate({
url: "/api/ExecGitHubAction",
data: {
GetFileContents: {
Url: url,
},
Action: "GetFileContents",
Url: url,
},
});
setOpenJsonDialog(true);
};

useEffect(() => {
if (name) {
searchMutation.mutate({
url: "/api/ExecGitHubAction",
data: {
Search: {
Repository: [name],
Type: "code",
Language: "json",
},
if (selectedRepo) {
branchQuery.refetch();
}
}, [selectedRepo]);

useEffect(() => {
if (selectedBranch) {
fetchFileTree(selectedBranch);
}
}, [selectedBranch]);

const updateQueryParams = (newRepo) => {
const query = { ...router.query };
if (query.name !== newRepo) {
query.name = newRepo;
router.replace(
{
pathname: router.pathname,
query: query,
},
});
undefined,
{ shallow: true }
);
}
}, [name]);
};

const MemoizedCippAutoComplete = React.memo((props) => {
return <CippAutoComplete {...props} />;
});

return (
<>
<CippTablePage
title={`Templates for ${name}`}
title={`Templates for ${selectedRepo}`}
tenantInTitle={false}
tableFilter={
<Grid container spacing={2}>
<Grid item size={{ xs: 12, md: 4 }}>
<MemoizedCippAutoComplete
fullWidth
value={{
label: selectedRepo,
value: selectedRepo,
}}
onChange={(newValue) => {
if (newValue.value === selectedRepo) return;
setSelectedRepo(newValue.value);
updateQueryParams(newValue.value);
}}
api={{
url: "/api/ListCommunityRepos",
queryKey: "CommunityRepos",
dataKey: "Results",
valueField: "FullName",
labelField: "FullName",
}}
multiple={false}
label="Select Repository"
placeholder="Select Repository"
disableClearable
/>
</Grid>
<Grid item size={{ xs: 12, md: 3 }}>
<MemoizedCippAutoComplete
fullWidth
value={
selectedBranch
? { label: selectedBranch, value: selectedBranch }
: { label: "Loading branches", value: "" }
}
onChange={(event, newValue) => setSelectedBranch(newValue.value)}
options={branches.map((branch) => ({ label: branch.name, value: branch.name }))}
multiple={false}
label="Select Branch"
placeholder="Select Branch"
disableClearable
isFetching={branchQuery.isPending}
/>
</Grid>
</Grid>
}
data={fileResults}
apiDataKey="Results"
queryKey="JsonTemplates"
simpleColumns={["name", "html_url"]}
simpleColumns={["path", "html_url"]}
actions={[
{
label: "View Template",
Expand All @@ -81,19 +193,8 @@ const Page = () => {
hideBulk: true,
},
]}
isFetching={searchMutation.isPending}
refreshFunction={() =>
searchMutation.mutate({
url: "/api/ExecGitHubAction",
data: {
Search: {
Repository: [name],
Type: "code",
Language: "json",
},
},
})
}
isFetching={fileTreeQuery.isFetching}
refreshFunction={() => fetchFileTree(selectedBranch)}
/>
<Dialog
fullWidth
Expand All @@ -103,7 +204,7 @@ const Page = () => {
>
<DialogTitle>Template Details</DialogTitle>
<DialogContent>
{fileMutation.isPending ? (
{fileQuery.isPending ? (
<Box>
<Skeleton height={300} />
</Box>
Expand Down
71 changes: 62 additions & 9 deletions src/pages/tools/templatelib/index.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React from "react";
import { Grid, Divider, Typography, CircularProgress, Alert, Chip } from "@mui/material";
import { useForm } from "react-hook-form";
import { Grid, Divider, Typography, CircularProgress, Alert, Chip, Link } from "@mui/material";
import { useForm, useWatch } from "react-hook-form";
import { Layout as DashboardLayout } from "/src/layouts/index.js";
import CippFormPage from "/src/components/CippFormPages/CippFormPage";
import CippFormComponent from "/src/components/CippComponents/CippFormComponent";
import { useSettings } from "/src/hooks/use-settings";
import { CippFormTenantSelector } from "../../../components/CippComponents/CippFormTenantSelector";
import { Box } from "@mui/system";
import { CippFormCondition } from "../../../components/CippComponents/CippFormCondition";
import { ApiGetCall } from "/src/api/ApiCall";
import NextLink from "next/link";

const TemplateLibrary = () => {
const currentTenant = useSettings().currentTenant;
Expand All @@ -22,6 +24,13 @@ const TemplateLibrary = () => {
},
});

const integrations = ApiGetCall({
url: "/api/ListExtensionsConfig",
queryKey: "Integrations",
});

const templateRepo = useWatch({ control: formControl.control, name: "templateRepo" });

const customDataFormatter = (values) => {
const startDate = new Date();
startDate.setHours(0, 0, 0, 0);
Expand All @@ -43,7 +52,7 @@ const TemplateLibrary = () => {
<CippFormPage
formControl={formControl}
queryKey="TemplateLibrary"
title="Add Template Library"
title="Template Library"
hideBackButton
postUrl="/api/AddScheduledItem?DisallowDuplicateName=true"
customDataformatter={customDataFormatter}
Expand All @@ -63,15 +72,27 @@ const TemplateLibrary = () => {
<Alert severity="warning" sx={{ my: 2 }}>
Enabling this feature will overwrite templates with the same name.
</Alert>

{integrations.isSuccess && !integrations.data?.GitHub?.Enabled && (
<Alert severity="info">
The community repositories feature requires the GitHub Integration to be enabled. Go
to the{" "}
<Link component={NextLink} href={"/cipp/integrations/configure?id=GitHub"}>
GitHub Integration
</Link>{" "}
page to enable it.
</Alert>
)}
</Grid>

<Divider sx={{ my: 2, width: "100%" }} />
<Divider sx={{ mt: 2, width: "100%" }} />
<Grid
container
spacing={2}
sx={{
alignItems: "center",
m: 3,
my: 1,
mx: 1,
}}
>
<Grid item xs={12} md={5}>
Expand Down Expand Up @@ -103,19 +124,47 @@ const TemplateLibrary = () => {
}}
formControl={formControl}
multiple={false}
disabled={!integrations.data?.GitHub?.Enabled}
/>
</Box>
</Grid>
</Grid>
<Divider sx={{ my: 2, width: "100%" }} />
<Divider sx={{ mt: 2, width: "100%" }} />
{templateRepo?.value && (
<Grid item xs={12} md={5}>
<Typography variant="h6" sx={{ mb: 2 }}>
Repository Branch
</Typography>
<CippFormComponent
type="autoComplete"
name="templateRepoBranch"
label="Select Branch"
formControl={formControl}
api={{
url: "/api/ExecGitHubAction",
data: {
Action: "GetBranches",
FullName: templateRepo?.value,
},
queryKey: `${templateRepo?.value}-Branches`,
dataKey: "Results",
valueField: "name",
labelField: "name",
}}
multiple={false}
/>
</Grid>
)}
<CippFormCondition
formControl={formControl}
field="templateRepo"
compareType="doesNotContain"
compareValue={"CIPP"}
>
<Grid item xs={12}>
<Typography variant="h6">Conditional Access</Typography>
<Typography variant="h6" sx={{ mb: 1 }}>
Conditional Access
</Typography>
<CippFormComponent
type="switch"
name="ca"
Expand All @@ -125,7 +174,9 @@ const TemplateLibrary = () => {
</Grid>

<Grid item xs={12}>
<Typography variant="h6">Intune</Typography>
<Typography variant="h6" sx={{ mb: 1 }}>
Intune
</Typography>
<CippFormComponent
type="switch"
name="intuneconfig"
Expand Down Expand Up @@ -153,7 +204,9 @@ const TemplateLibrary = () => {
compareValue={"CIPP-"}
>
<Grid item xs={12}>
<Typography variant="h6">Template Repository files</Typography>
<Typography variant="h6" sx={{ mb: 1 }}>
Template Repository files
</Typography>
<CippFormComponent
type="switch"
name="standardsconfig"
Expand Down

0 comments on commit ef17d84

Please sign in to comment.