Skip to content

Commit

Permalink
feat: added button to delete tag
Browse files Browse the repository at this point in the history
Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
  • Loading branch information
Petu Eusebiu committed Dec 11, 2023
1 parent d9370fb commit b07cc59
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 9 deletions.
3 changes: 2 additions & 1 deletion src/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,13 @@ const endpoints = {
authConfig: `/v2/_zot/ext/mgmt`,
openidAuth: `/zot/auth/login`,
logout: `/zot/auth/logout`,
deleteImage: (name, tag) => `/v2/${name}/manifests/${tag}`,

Check warning on line 84 in src/api.js

View check run for this annotation

Codecov / codecov/patch

src/api.js#L84

Added line #L84 was not covered by tests
repoList: ({ pageNumber = 1, pageSize = 15 } = {}) =>
`/v2/_zot/ext/search?query={RepoListWithNewestImage(requestedPage: {limit:${pageSize} offset:${
(pageNumber - 1) * pageSize
}}){Results {Name LastUpdated Size Platforms {Os Arch} NewestImage { Tag Vulnerabilities {MaxSeverity Count} Description Licenses Title Source IsSigned SignatureInfo { Tool IsTrusted Author } Documentation Vendor Labels} IsStarred IsBookmarked StarCount DownloadCount}}}`,
detailedRepoInfo: (name) =>
`/v2/_zot/ext/search?query={ExpandedRepoInfo(repo:"${name}"){Images {Manifests {Digest Platform {Os Arch} Size} Vulnerabilities {MaxSeverity Count} Tag LastUpdated Vendor } Summary {Name LastUpdated Size Platforms {Os Arch} Vendors IsStarred IsBookmarked NewestImage {RepoName IsSigned SignatureInfo { Tool IsTrusted Author } Vulnerabilities {MaxSeverity Count} Manifests {Digest} Tag Vendor Title Documentation DownloadCount Source Description Licenses}}}}`,
`/v2/_zot/ext/search?query={ExpandedRepoInfo(repo:"${name}"){Images {Manifests {Digest Platform {Os Arch} Size} Vulnerabilities {MaxSeverity Count} Tag LastUpdated Vendor IsDeletable } Summary {Name LastUpdated Size Platforms {Os Arch} Vendors IsStarred IsBookmarked NewestImage {RepoName IsSigned SignatureInfo { Tool IsTrusted Author } Vulnerabilities {MaxSeverity Count} Manifests {Digest} Tag Vendor Title Documentation DownloadCount Source Description Licenses}}}}`,
detailedImageInfo: (name, tag) =>
`/v2/_zot/ext/search?query={Image(image: "${name}:${tag}"){RepoName IsSigned SignatureInfo { Tool IsTrusted Author } Vulnerabilities {MaxSeverity Count} Referrers {MediaType ArtifactType Size Digest Annotations{Key Value}} Tag Manifests {History {Layer {Size Digest} HistoryDescription {CreatedBy EmptyLayer}} Digest ConfigDigest LastUpdated Size Platform {Os Arch}} Vendor Licenses }}`,
vulnerabilitiesForRepo: (name, { pageNumber = 1, pageSize = 15 }, searchTerm = '') => {
Expand Down
9 changes: 7 additions & 2 deletions src/components/Repo/RepoDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ function RepoDetails() {
};
}, [name]);

const handleDeleteTag = (removed) => {
let newTags = tags.filter((tag) => tag.tag !== removed);
setTags(newTags);

Check warning on line 202 in src/components/Repo/RepoDetails.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Repo/RepoDetails.jsx#L201-L202

Added lines #L201 - L202 were not covered by tests
};

const handlePlatformChipClick = (event) => {
const { textContent } = event.target;
event.stopPropagation();
Expand All @@ -223,7 +228,7 @@ function RepoDetails() {

const handleBookmarkClick = () => {
api.put(`${host()}${endpoints.bookmarkToggle(name)}`, abortController.signal).then((response) => {
if (response.status === 200) {
if (response && response.status === 200) {
setRepoDetailData((prevState) => ({
...prevState,
isBookmarked: !prevState.isBookmarked
Expand Down Expand Up @@ -341,7 +346,7 @@ function RepoDetails() {
<Grid item xs={12} md={8} className={classes.tags}>
<Card className={classes.cardRoot}>
<CardContent className={classes.tagsContent}>
<Tags tags={tags} />
<Tags tags={tags} repoName={name} handleDeleteTag={handleDeleteTag} />
</CardContent>
</Card>
</Grid>
Expand Down
5 changes: 4 additions & 1 deletion src/components/Repo/Tabs/Tags.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const useStyles = makeStyles(() => ({

export default function Tags(props) {
const classes = useStyles();
const { tags } = props;
const { tags, repoName, handleDeleteTag } = props;
const [tagsFilter, setTagsFilter] = useState('');
const [sortFilter, setSortFilter] = useState(tagsSortByCriteria.updateTimeDesc.value);

Expand All @@ -59,10 +59,13 @@ export default function Tags(props) {
return (
<TagCard
key={tag.tag}
repoName={repoName}
tag={tag.tag}
lastUpdated={tag.lastUpdated}
vendor={tag.vendor}
manifests={tag.manifests}
handleDeleteTag={handleDeleteTag}
isDeletable={tag.isDeletable}
/>
);
})
Expand Down
29 changes: 29 additions & 0 deletions src/components/Shared/ConfirmDialog.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from 'react';

// components
import { Button, Dialog, DialogTitle, DialogActions } from '@mui/material';

export default function ConfirmDialog(props) {
const { onClose, open, title, onConfirm } = props;

Check warning on line 7 in src/components/Shared/ConfirmDialog.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/ConfirmDialog.jsx#L6-L7

Added lines #L6 - L7 were not covered by tests

return (

Check warning on line 9 in src/components/Shared/ConfirmDialog.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/ConfirmDialog.jsx#L9

Added line #L9 was not covered by tests
<Dialog onClose={onClose} open={open} color="primary">
<DialogTitle> {title} </DialogTitle>
<DialogActions style={{ justifyContent: 'center' }}>
<Button variant="contained" onClick={() => onClose()} color="primary">

Check warning on line 13 in src/components/Shared/ConfirmDialog.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/ConfirmDialog.jsx#L13

Added line #L13 was not covered by tests
Cancel
</Button>
<Button
color="error"
variant="contained"
onClick={() => {
onConfirm();
onClose();

Check warning on line 21 in src/components/Shared/ConfirmDialog.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/ConfirmDialog.jsx#L19-L21

Added lines #L19 - L21 were not covered by tests
}}
>
Delete
</Button>
</DialogActions>
</Dialog>
);
}
54 changes: 54 additions & 0 deletions src/components/Shared/DeleteTag.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as React from 'react';
import { IconButton } from '@mui/material';
import DeleteIcon from '@mui/icons-material/Delete';

// utility
import { api, endpoints } from '../../api';

// components
import ConfirmDialog from 'components/Shared/ConfirmDialog';
import { host } from '../../host';

export default function DeleteTag(props) {
const { repo, tag, handleDeleteTag } = props;
const [open, setOpen] = React.useState(false);

Check warning on line 14 in src/components/Shared/DeleteTag.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/DeleteTag.jsx#L12-L14

Added lines #L12 - L14 were not covered by tests

const handleClickOpen = () => {
setOpen(true);

Check warning on line 17 in src/components/Shared/DeleteTag.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/DeleteTag.jsx#L16-L17

Added lines #L16 - L17 were not covered by tests
};

const handleClose = () => {
setOpen(false);

Check warning on line 21 in src/components/Shared/DeleteTag.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/DeleteTag.jsx#L20-L21

Added lines #L20 - L21 were not covered by tests
};

const deleteTag = (repo, tag) => {
api

Check warning on line 25 in src/components/Shared/DeleteTag.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/DeleteTag.jsx#L24-L25

Added lines #L24 - L25 were not covered by tests
.delete(`${host()}${endpoints.deleteImage(repo, tag)}`)
.then((response) => {

Check warning on line 27 in src/components/Shared/DeleteTag.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/DeleteTag.jsx#L27

Added line #L27 was not covered by tests
if (response && response.status == 202) {
handleDeleteTag(tag);

Check warning on line 29 in src/components/Shared/DeleteTag.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/DeleteTag.jsx#L29

Added line #L29 was not covered by tests
}
})
.catch((err) => {
console.error(err);

Check warning on line 33 in src/components/Shared/DeleteTag.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/DeleteTag.jsx#L32-L33

Added lines #L32 - L33 were not covered by tests
});
};

const onConfirm = () => {
deleteTag(repo, tag);

Check warning on line 38 in src/components/Shared/DeleteTag.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/DeleteTag.jsx#L37-L38

Added lines #L37 - L38 were not covered by tests
};

return (

Check warning on line 41 in src/components/Shared/DeleteTag.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Shared/DeleteTag.jsx#L41

Added line #L41 was not covered by tests
<div>
<IconButton onClick={handleClickOpen}>
<DeleteIcon />
</IconButton>
<ConfirmDialog
onClose={handleClose}
open={open}
title={`Permanently delete ${repo}:${tag} image`}
onConfirm={onConfirm}
/>
</div>
);
}
14 changes: 9 additions & 5 deletions src/components/Shared/TagCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Markdown } from 'utilities/MarkdowntojsxWrapper';
import transform from 'utilities/transform';
import { DateTime } from 'luxon';
import { KeyboardArrowDown, KeyboardArrowRight } from '@mui/icons-material';
import DeleteTag from 'components/Shared/DeleteTag';

const useStyles = makeStyles((theme) => ({
card: {
Expand Down Expand Up @@ -78,9 +79,9 @@ const useStyles = makeStyles((theme) => ({
}));

export default function TagCard(props) {
const { repoName, tag, lastUpdated, vendor, manifests } = props;

const { repoName, tag, lastUpdated, vendor, manifests, handleDeleteTag, isDeletable } = props;
const [open, setOpen] = useState(false);

const classes = useStyles();

const lastDate = lastUpdated
Expand All @@ -99,9 +100,12 @@ export default function TagCard(props) {
return (
<Card className={classes.card} raised>
<CardContent className={classes.content}>
<Typography variant="body1" align="left" className={classes.tagHeading}>
Tag
</Typography>
<Stack direction="row" spacing={2} justifyContent="space-between">
<Typography variant="body1" align="left" className={classes.tagHeading}>
Tag
</Typography>
{isDeletable && <DeleteTag repo={repoName} tag={tag} handleDeleteTag={handleDeleteTag} />}
</Stack>
<Typography variant="body1" align="left" className={classes.tagName} onClick={() => goToTags()}>
{repoName && `${repoName}:`}
{tag}
Expand Down
1 change: 1 addition & 0 deletions src/utilities/objectModels.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const mapToImage = (responseImage) => {
authors: responseImage.Authors,
vulnerabiltySeverity: responseImage.Vulnerabilities?.MaxSeverity,
vulnerabilityCount: responseImage.Vulnerabilities?.Count,
isDeletable: responseImage.IsDeletable,
// frontend only prop to increase interop with Repo objects and code reusability
name: `${responseImage.RepoName}:${responseImage.Tag}`
};
Expand Down

0 comments on commit b07cc59

Please sign in to comment.