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

Added: more error notifications #17

Merged
merged 1 commit into from
Oct 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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