Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

Commit

Permalink
Merge pull request #17 from containerish/image-detail-page
Browse files Browse the repository at this point in the history
Added: more error notifications
  • Loading branch information
guacamole authored Oct 25, 2021
2 parents 44a4a59 + a88de06 commit 17bc274
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 49 deletions.
10 changes: 6 additions & 4 deletions src/components/card.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ export const Tile = ({ repoName, author, updatedAt }) => {
<Card
hoverable
headStyle={{ background: 'rgba(204,215,227,0.61)', fontWeight: "bold" }}
title={author + "/" + repoName}
title={<Typography.Title level={4}>
{author + "/" + repoName}
</Typography.Title>}
bordered={true}
style={{ width: "100%", borderRadius: 8 }}
extra={(
<div>
<Text style={{ marginRight: "12px" }} copyable={{
text: `docker pull ${author}/${repoName}`,
text: `docker pull openregistry.dev/${author}/${repoName}`,
tooltips: [<Tooltip>copy pull command</Tooltip>]
}}
/>
Expand All @@ -24,8 +26,8 @@ export const Tile = ({ repoName, author, updatedAt }) => {
</div>
)}
>
<p>Author: {author}</p>
<p>Updated At: {updatedAt}</p>
<Typography.Paragraph style={{fontWeight: "bold"}}>Author: {author}</Typography.Paragraph>
<Typography.Text>Updated At: {updatedAt}</Typography.Text>
</Card>
</div>
)
Expand Down
18 changes: 18 additions & 0 deletions src/components/notify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {Alert, message} from "antd";
import React from "react";

message.config({
icon: null,
})

export const Notify = (kind, msg) => {
return message[kind]({
content: <Alert
message={msg}
type={kind}
closable={false}
icon={null}
/>,
duration: 2,
})
}
4 changes: 2 additions & 2 deletions src/components/signin.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from "react";
import '../styles/landingpage.css'
import { Form, Input, Button, Typography, message, Alert } from 'antd';
import { LoadingOutlined, CheckCircleTwoTone, CloseCircleOutlined, } from '@ant-design/icons';
import { LoadingOutlined } from '@ant-design/icons';
import { useHistory, } from "react-router";
import axios from 'axios';

Expand Down Expand Up @@ -64,7 +64,7 @@ const SignIn = ({ handleSignUp, handleModalClose, }) => {
loc.push('/repositories')
}).catch(err => {
setShowLoader(false)
setSignInError(err.response.data.error)
setSignInError(err.message)
setShowNotification(true)
})
}
Expand Down
24 changes: 24 additions & 0 deletions src/components/table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Button, Table, Typography } from 'antd';
const { Column, } = Table;

export const CustomTable = (
{ onChange, data = [], loading = false, pagination = { pageSize: 5, current: 1 } }
) => {

return <Table
title={() => <Typography.Title level={3}>Tags and additional info</Typography.Title>}
loading={loading}
pagination={pagination}
bordered
dataSource={data}
onChange={onChange}
>
<Column title="Tag" dataIndex="reference" key="reference" />
<Column title="Skylink (Skynet)" dataIndex="skynetLink" key="skynetLink" render={(text, record, index) => {
return <Button type="link" onClick={() => window.open(`https://siasky.net/${text.replace('sia://', '')}`)}>Link</Button>
}} />
{/*<Column title="Pulled" dataIndex="pulled" key="digest"/>*/}
{/*<Column title="Pushed" key="action" dataIndex="mediatype" />*/}
<Column title="Size (in MBs)" key="size" dataIndex="size" />
</Table>
}
19 changes: 17 additions & 2 deletions src/pages/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React, { useState, useEffect } from 'react';
import dashboardBgImage from "../styles/pictures/dashboard-bg.svg"
import { RenderTileList } from "../components/card";
import axios from 'axios';
import jwtDecode from "jwt-decode";
import {Notify} from "../components/notify";

const styles = {
dashboard: {
Expand All @@ -22,9 +24,15 @@ const styles = {

const PersonalDashboard = () => {
const [repoData, setRepoData] = useState([]);
const [showNotification, setShowNotification] = useState(false);
const [notificationKind, setNotificationKind] = useState('info');
const [notificationMsg, setNotificationMsg] = useState('');

useEffect(() => {
axios.get(`${process.env.REACT_APP_API_BASE_URL}/internal/metadata`).then(res => {
const token = jwtDecode(localStorage.getItem('token'))

// token.sub (short for subject) is the username for the logged-in user
axios.get(`${process.env.REACT_APP_API_BASE_URL}/internal/metadata?namespace=${token.sub}`).then(res => {
if (typeof (res.data) === 'object') {
if (res.data && res.data.Namespace && res.data.Namespace.length > 0) {
setRepoData([res.data])
Expand All @@ -37,10 +45,14 @@ const PersonalDashboard = () => {
setRepoData(data)
}

}).catch(_ => {
}).catch(err => {
// set it to empty, so that RenderList can display no data message
// @TODO - maybe we can display an error warning
setRepoData([])
setNotificationKind('error')
setNotificationMsg(err.message)
setShowNotification(true)
setShowNotification(false)
})
}, [])

Expand All @@ -49,6 +61,9 @@ const PersonalDashboard = () => {
<div style={{ display: 'flex', alignItems: "center", flexDirection: "column", justifyContent: 'center' }}>
<RenderTileList data={repoData}/>
</div>
{
showNotification ? Notify(notificationKind, notificationMsg) : null
}
</div>
);
}
Expand Down
47 changes: 29 additions & 18 deletions src/pages/explore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React, { useEffect, useState } from 'react';
import { Typography, Card } from 'antd';
import dashboardBgImage from "../styles/pictures/dashboard-bg.svg"
import { RenderTileList } from "../components/card";
import jwtDecode from "jwt-decode";
import axios from "axios";
import {Notify} from "../components/notify";

const styles = {
dashboard: {
Expand All @@ -29,32 +29,43 @@ const styles = {

const ExploreContainerImages = () => {
const [repoData, setRepoData] = useState([]);
const [showNotification, setShowNotification] = useState(false);
const [notificationKind, setNotificationKind] = useState('info');
const [notificationMsg, setNotificationMsg] = useState('');

useEffect(() => {
const token = jwtDecode(localStorage.getItem('token'))
// token.sub is the username
axios.get(`${process.env.REACT_APP_API_BASE_URL}/internal/metadata?namespace=${token.sub}`).then(res => {
if (typeof res.data === 'object') {
if (res.data && res.data.Namespace && res.data.Namespace.length > 0) {
setRepoData([res.data])
return
useEffect( async () => {
let repos = await fetchAllRepositories()
setRepoData(repos)
}, [])

const fetchAllRepositories = async () => {
try {
const resp = await axios.get(`${process.env.REACT_APP_API_BASE_URL}/internal/metadata`)
if (typeof resp.data === 'object') {
if (resp.data && resp.data.Namespace && resp.data.Namespace.length > 0) {
return [resp.data]
}
}

if (res.data) {
const data = res.data.filter(el => el && el.Namespace && el.Namespace.length > 0)
setRepoData(data)
if (resp.data) {
return resp.data.filter(el => el && el.Namespace && el.Namespace.length > 0)
}

}).catch(_ => {
// set it to empty, so that RenderList can display no data message
// @TODO - maybe we can display an error warning
setRepoData([])
})
}, [])
return []
} catch (err) {
setNotificationKind('error')
setNotificationMsg(err.message)
setShowNotification(true)
setShowNotification(false)
return []
}
}

return (
<Card style={repoData.length === 0 ? {...styles.dashboard, ...styles.flexboxCenter} : styles.dashboard}>
{
showNotification ? Notify(notificationKind, notificationMsg) : null
}
<div style={styles.inner}>
<Typography.Title level={3}>
Search for your or public container images
Expand Down
106 changes: 83 additions & 23 deletions src/pages/image_detail.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,110 @@
import NavBar from "../components/menu";
import {Typography, Badge, Card} from "antd";
import {Typography, Badge, Card, Button, Tooltip} from "antd";
import ReactMarkdown from "react-markdown";
import containerLogo from "../styles/pictures/container-logo.png";
import {useParams} from "react-router-dom";
import { EditTwoTone } from '@ant-design/icons'
import {CustomTable} from "../components/table";
import dashboardBgImage from "../styles/pictures/dashboard-bg.svg";
import {useEffect, useState} from "react";
import axios from "axios";
import jwtDecode from "jwt-decode";
import {Notify} from "../components/notify";

const { Title, Paragraph, Text, Link } = Typography;

export const ImageDetail = () => {
let { username, imagename } = useParams();

let desc = `Params are placeholders in the URL that begin
with a colon, like the \`:id\` param defined in`
let tags = ["latest", "beta", "heko"]

const [activeUser, setActiveUser] = useState({});
const [imageDetail, setImageDetail] = useState([])
const [isTableLoading, setIsTableLoading] = useState(false)
const [showNotification, setShowNotification] = useState(false);
const [notificationKind, setNotificationKind] = useState('info');
const [notificationMsg, setNotificationMsg] = useState('');

const [pagination, setPagination] = useState({
pageSize: 5,
current: 1,
})

let desc = `No description found`
let markdownDetails = `# Nothing to see here :(`

return(
<div style={{display: "flex", justifyContent: "center", flexDirection: "column", alignItems: "center"}}>
useEffect(() => {
const token = jwtDecode(localStorage.getItem('token'))
setActiveUser(token)

setIsTableLoading(true)
axios.get(`${process.env.REACT_APP_API_BASE_URL}/internal/metadata?namespace=${username}/${imagename}`)
.then(resp => {
setImageDetail(resp.data)
setIsTableLoading(false)
setPagination({...pagination, total: resp.data.Manifest.config.length})
}).catch(err => {
setIsTableLoading(false)
setNotificationKind('error')
setNotificationMsg(err.message)
setShowNotification(true)
setShowNotification(false)
})
}, [])

const onTableChange = (paginate, filters, sorters) => {
setPagination(paginate)
}

return (
<div style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
backgroundRepeat: "no-repeat",
backgroundSize: "cover",
height: "100vh",
overflowY: "scroll",
paddingBottom: "10%",
backgroundImage: `url(${dashboardBgImage})`,
// backgroundColor: '#f4f3f6'
}}>

<Card style={{width: "90%", marginTop: "2%"}}>
<div style={{flexDirection: "row", display: "flex", alignItems: "center"}}>
<img src={containerLogo} style={{height: 100, }} alt="container-image-logo"/>
<img src={containerLogo} style={{height: 85, }} alt="container-image-logo"/>
<div style={{marginLeft: "2%"}}>
<Typography.Title level={2}>{username+"/"+imagename}</Typography.Title>
<p>{desc}</p>
</div>
</div>

<div style={{display: "flex", justifyContent: "space-between", marginTop: "1%"}}>
<div>
{
tags.map((t) => {
return <Badge
count={t}
style={{ margin: "0 2px", backgroundColor: '#7c8fa9', color: "#fff", fontWeight: "bold"}}

/>
})
}
</div>
<div style={{display: "flex", justifyContent: "flex-end", marginTop: "1%"}}>
<Text strong copyable code>{`docker pull openregistry.dev/${username}/${imagename}`}</Text>
</div>
</Card>
<Card style={{width: "90%", marginTop: "2%"}}>
<ReactMarkdown>
{markdownDetails}
</ReactMarkdown>

{/*<Card style={{width: "90%", margin: "2% 0"}}>*/}
{/* <CustomTable onChange={onTableChange} data={imageDetail} loading={isTableLoading} pagination={pagination}/>*/}
{/*</Card>*/}

{
showNotification ? Notify(notificationKind, notificationMsg) : null
}
<Card style={{width: "90%", margin: "2% 0"}}>
{
activeUser.sub === username ?
<div style={{ display: "flex", justifyContent: "flex-end",}}>
<Tooltip placement="bottom" title={"coming soon"}>
<Button disabled icon={<EditTwoTone />}>Edit</Button>
</Tooltip>
</div>
: null
}
<div>
<ReactMarkdown>
{markdownDetails}
</ReactMarkdown>
</div>
</Card>
</div>
)
Expand Down

0 comments on commit 17bc274

Please sign in to comment.