diff --git a/src/components/home/RepositoryEntry.tsx b/src/components/home/RepositoryEntry.tsx
index 74c7448..44f717f 100644
--- a/src/components/home/RepositoryEntry.tsx
+++ b/src/components/home/RepositoryEntry.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { ListItemButton, Box, Typography, Grid, ListItemText } from "@mui/material";
+import { ListItemButton, Grid, ListItemText } from "@mui/material";
import Tag from "../../interfaces/Tag";
import Repository from "../../interfaces/Repositoriy";
import { printSize, printTimePassed } from "../../utils";
@@ -18,12 +18,10 @@ const RepositoryItem: React.FC
= (props: Props) => {
*/}
- (tag.label === "latest")).map((tag: Tag) => (tag.created ? printTimePassed(tag.created) : "")).join(" ")} />
- {/* {props.repository.name}
- {"Last updated: " + props.repository.tags.filter((tag: Tag) => (tag.label === "latest")).map((tag: Tag) => (tag.created ? printTimePassed(tag.created) : "")).join(" ")} */}
+ (tag.label === "latest")).map((tag: Tag) => (tag.created ? printTimePassed(tag.created) : "")).join(" ")} />
- (tag.label === "latest")).map((tag: Tag) => (tag.size ? printSize(tag.size) : "")).join(" ")} />
+ (tag.label === "latest")).map((tag: Tag) => (tag.size ? printSize(tag.size) : "")).join(" ")} />
diff --git a/src/components/navbar/NavBar.tsx b/src/components/navbar/NavBar.tsx
index f544f6f..0edf113 100644
--- a/src/components/navbar/NavBar.tsx
+++ b/src/components/navbar/NavBar.tsx
@@ -1,9 +1,17 @@
import React from "react";
+import { useEffect } from "react";
import { AppBar, Container, Toolbar, Typography, Box, IconButton, Menu, MenuItem , Tooltip, Avatar, Snackbar, Alert} from "@mui/material";
+import axios from "../../api/axios";
import useAuth from "../../hooks/useAuth";
+import useRepositories from "../../hooks/useRepositories";
+import { loginInfo } from "../../context/AuthProvider";
+import Tag from "../../interfaces/Tag";
+import Repository from "../../interfaces/Repositoriy";
+import Layer from "../../interfaces/Layer";
const NavBar: React.FC = () => {
- const auth = useAuth();
+ const { auth } = useAuth();
+ const { setRepositories } = useRepositories();
const [anchorElUser, setAnchorElUser] = React.useState<(EventTarget & HTMLButtonElement) | null>(null);
const [snackbarOpen, setSnackbarOpen] = React.useState(false);
@@ -21,6 +29,123 @@ const NavBar: React.FC = () => {
const handleClose = () => {
setSnackbarOpen(false);
};
+
+
+ const getTagInfo = async(newRepositories: Repository[], auth: loginInfo) => {
+ let promises: Promise[] = [];
+ newRepositories.forEach((repository: Repository) => {
+ repository.tags.forEach((tag: Tag) => {
+ let promise = axios.get(
+ "/" + repository.name + "/manifests/" + tag.label,
+ {
+ headers:{
+ Accept: "application/vnd.docker.distribution.manifest.v2+json",
+ },
+ auth: {
+ username: auth.username,
+ password: auth.password
+ }
+ }
+ ).then((response) => {
+ tag.schemaVersion = response?.data['schemaVersion'];
+ tag.mediaType = response?.data['mediaType'];
+ tag.digest = response?.headers['docker-content-digest'];
+ tag.config = response?.data?.config;
+ tag.layers = response?.data?.layers;
+ let size = 0;
+ response?.data?.layers.forEach((layer: Layer) => {
+ size += layer.size;
+ });
+ tag.size = size;
+ return axios.get(
+ "/" + repository.name + "/blobs/" + response?.data?.config['digest'],
+ {
+ headers:{
+ Accept: "application/vnd.docker.distribution.manifest.v2+json",
+ },
+ auth: {
+ username: auth.username,
+ password: auth.password
+ }
+ }
+ ).then((res) => {
+ tag.architecture = res?.data?.architecture;
+ tag.os = res?.data?.os;
+ tag.created = new Date(res?.data?.created);
+ });
+ });
+ promises.push(promise);
+ });
+ });
+ return Promise.all(promises);
+ };
+
+ const getTags = async(newRepositories: Repository[], auth: loginInfo) => {
+ let promises: Promise[] = [];
+ newRepositories.forEach((repository: Repository) => {
+ let promise = axios.get(
+ "/" + repository.name + "/tags/list",
+ {
+ auth: {
+ username: auth.username,
+ password: auth.password
+ }
+ }
+ ).then((res) => {
+ let tags: Tag[] = [];
+ res?.data?.tags.forEach((tagLabel: string) => {
+ let tag: Tag = {
+ label: tagLabel,
+ architecture: "",
+ os: "",
+ created: undefined,
+ schemaVersion: undefined,
+ mediaType: "",
+ config: undefined,
+ layers: undefined,
+ size: undefined,
+ digest: ""
+ }
+ tags.push(tag);
+ });
+ repository.tags = tags;
+ });
+ promises.push(promise);
+ });
+ await Promise.all(promises);
+ return getTagInfo(newRepositories, auth);
+ };
+
+ const listRepositories = async() => {
+
+ const response = await axios.get(
+ "/_catalog",
+ {
+ auth: {
+ username: auth.username,
+ password: auth.password
+ }
+ }
+ );
+
+ let newRepositories: Repository[] = [];
+ response?.data?.repositories.forEach((repositoriyName: string) => {
+ let newRepository: Repository = {
+ name: repositoriyName,
+ tags: []
+ }
+ newRepositories.push(newRepository);
+ });
+ await getTags(newRepositories, auth)
+
+ setRepositories(newRepositories);
+ // setRepositories(newRepositories);
+
+ };
+
+ useEffect(() => {
+ setInterval(() => listRepositories(), 1000);
+ }, []);
return (
diff --git a/src/components/repositoryInfo/RepositoryInfo.tsx b/src/components/repositoryInfo/RepositoryInfo.tsx
new file mode 100644
index 0000000..a31cdd8
--- /dev/null
+++ b/src/components/repositoryInfo/RepositoryInfo.tsx
@@ -0,0 +1,15 @@
+import React from "react";
+import { useLocation } from "react-router-dom";
+import { ListItemButton, Box, Typography, Grid, ListItemText } from "@mui/material";
+import Tag from "../../interfaces/Tag";
+import Repository from "../../interfaces/Repositoriy";
+
+const RepositoryInfo: React.FC = () => {
+ const location = useLocation()
+
+ return (
+ {location.pathname.slice(12,location.pathname.length)}
+ );
+}
+
+export default RepositoryInfo;
\ No newline at end of file
diff --git a/src/context/AuthProvider.tsx b/src/context/AuthProvider.tsx
index 2c99a2c..dc9c55c 100644
--- a/src/context/AuthProvider.tsx
+++ b/src/context/AuthProvider.tsx
@@ -1,26 +1,32 @@
import { createContext, useState } from "react";
-import Repository from "../interfaces/Repositoriy";
-interface loginInfo {
+export interface loginInfo {
loginNeeded: boolean;
isLoggedIn: boolean;
username: string;
password: string;
- repositories: Repository[];
}
-const AuthContext = createContext({
- loginNeeded: true,
- isLoggedIn: false,
- username: "",
- password: "",
- repositories: []
+interface MyAuthState {
+ auth: loginInfo;
+ setAuth: React.Dispatch>
+}
+
+
+const AuthContext = createContext({
+ auth: {
+ loginNeeded: true,
+ isLoggedIn: false,
+ username: "",
+ password: ""
+ },
+ setAuth: () => {}
});
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
- const [auth] = useState({ loginNeeded: true, isLoggedIn: false, username: "", password: "", repositories: [] });
+ const [auth, setAuth] = useState({ loginNeeded: true, isLoggedIn: false, username: "", password: "" });
- return {children};
+ return {children};
};
export default AuthContext;
diff --git a/src/context/RepositoriesProvider.tsx b/src/context/RepositoriesProvider.tsx
new file mode 100644
index 0000000..48743c2
--- /dev/null
+++ b/src/context/RepositoriesProvider.tsx
@@ -0,0 +1,21 @@
+import { createContext, useState } from "react";
+import Repository from "../interfaces/Repositoriy";
+
+
+interface MyRepositoriesState {
+ repositories: Repository[];
+ setRepositories: React.Dispatch>
+}
+
+const RepositoriesContext = createContext({
+ repositories: [],
+ setRepositories: () => {}
+});
+
+export const RepositoriesProvider = ({ children }: { children: React.ReactNode }) => {
+ const [repositories, setRepositories] = useState([]);
+
+ return {children};
+};
+
+export default RepositoriesContext;
\ No newline at end of file
diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx
index 32e8aee..e1d0b6d 100644
--- a/src/hooks/useAuth.tsx
+++ b/src/hooks/useAuth.tsx
@@ -1,17 +1,8 @@
import { useContext } from "react";
import AuthContext from "../context/AuthProvider";
-import Repository from "../interfaces/Repositoriy";
-
-interface loginInfo {
- loginNeeded: boolean;
- isLoggedIn: boolean;
- username: string;
- password: string;
- repositories: Repository[];
-}
const useAuth = () => {
- return useContext(AuthContext);
+ return useContext(AuthContext);
};
export default useAuth;
\ No newline at end of file
diff --git a/src/hooks/useRepositories.tsx b/src/hooks/useRepositories.tsx
new file mode 100644
index 0000000..5030ccf
--- /dev/null
+++ b/src/hooks/useRepositories.tsx
@@ -0,0 +1,8 @@
+import { useContext } from "react";
+import RepositoriesContext from "../context/RepositoriesProvider";
+
+const useRepositories = () => {
+ return useContext(RepositoriesContext);
+};
+
+export default useRepositories;
\ No newline at end of file
diff --git a/src/index.tsx b/src/index.tsx
index e838861..504e2b1 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -2,12 +2,15 @@ import ReactDOM from "react-dom";
import App from "./App";
import "./style/style.css";
import { AuthProvider } from "./context/AuthProvider";
+import { RepositoriesProvider } from "./context/RepositoriesProvider";
const Index: React.FC = () => {
return (
-
+
+
+
);
};