mirror of https://github.com/artifacthub/hub.git
Add option to report abuse (#1608)
Closes #1580 Signed-off-by: Sergio Castaño Arteaga <tegioz@icloud.com> Signed-off-by: Cintia Sanchez Garcia <cynthiasg@icloud.com> Co-authored-by: Sergio Castaño Arteaga <tegioz@icloud.com> Co-authored-by: Cintia Sanchez Garcia <cynthiasg@icloud.com>
This commit is contained in:
parent
81adbb28fb
commit
f86585a80d
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
name: Report abuse
|
||||
about: Report abuse or inappropriate content
|
||||
title: "[ABUSE-REPORT] Repository or package name"
|
||||
labels: abuse report
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the problem**
|
||||
Please explain why are you reporting this content.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
|
@ -2,7 +2,7 @@ apiVersion: v2
|
|||
name: artifact-hub
|
||||
description: Artifact Hub is a web-based application that enables finding, installing, and publishing Kubernetes packages.
|
||||
type: application
|
||||
version: 1.3.1-1
|
||||
version: 1.3.1-2
|
||||
appVersion: 1.3.0
|
||||
kubeVersion: ">= 1.14.0-0"
|
||||
home: https://artifacthub.io
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ stringData:
|
|||
openGraphImage: {{ .Values.hub.theme.images.openGraphImage | quote }}
|
||||
shortcutIcon: {{ .Values.hub.theme.images.shortcutIcon | quote }}
|
||||
websiteLogo: {{ .Values.hub.theme.images.websiteLogo | quote }}
|
||||
reportURL: {{ .Values.hub.theme.reportURL | quote }}
|
||||
sampleQueries:
|
||||
{{- range .Values.hub.theme.sampleQueries }}
|
||||
- name: {{ .name }}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ hub:
|
|||
enabled: true
|
||||
redirectURL: https://artifacthub.io/oauth/google/callback
|
||||
theme:
|
||||
reportURL: https://github.com/artifacthub/hub/issues/new?labels=abuse+report&template=report-abuse.md
|
||||
sampleQueries:
|
||||
- name: OLM operators for databases
|
||||
queryString: "kind=3&ts_query_web=database"
|
||||
|
|
|
|||
|
|
@ -588,6 +588,11 @@
|
|||
},
|
||||
"required": ["appleTouchIcon192", "appleTouchIcon512", "openGraphImage", "shortcutIcon", "websiteLogo"]
|
||||
},
|
||||
"reportURL": {
|
||||
"title": "Abuse report URL",
|
||||
"description": "URL to report abuses.",
|
||||
"type": "string"
|
||||
},
|
||||
"sampleQueries": {
|
||||
"title": "Sample search queries used in home and no results found pages",
|
||||
"type": "array",
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ func (h *Handlers) Index(w http.ResponseWriter, r *http.Request) {
|
|||
"oidcAuth": h.cfg.IsSet("server.oauth.oidc"),
|
||||
"openGraphImage": openGraphImage,
|
||||
"primaryColor": h.cfg.GetString("theme.colors.primary"),
|
||||
"reportURL": h.cfg.GetString("theme.reportURL"),
|
||||
"secondaryColor": h.cfg.GetString("theme.colors.secondary"),
|
||||
"shortcutIcon": h.cfg.GetString("theme.images.shortcutIcon"),
|
||||
"siteName": h.cfg.GetString("theme.siteName"),
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
<meta name="artifacthub:googleAuth" content="true" />
|
||||
<meta name="artifacthub:oidcAuth" content="false" />
|
||||
<meta name="artifacthub:sampleQueries" content='[{"name":"OLM operators for databases","queryString":"kind=3\u0026ts_query_web=database"},{"name":"Helm Charts provided by Bitnami","queryString":"kind=0\u0026org=bitnami"},{"name":"Packages of any kind related to etcd","queryString":"ts_query_web=etcd"},{"name":"Falco rules for CVE","queryString":"kind=1\u0026ts_query_web=cve"},{"name":"OLM operators in the monitoring category","queryString":"kind=3\u0026ts_query=monitoring"},{"name":"Packages from verified publishers","queryString":"verified_publisher=true"},{"name":"Official Prometheus packages","queryString":"ts_query_web=prometheus\u0026official=true"},{"name":"Operators with auto pilot capabilities","queryString":"capabilities=auto+pilot"},{"name":"Helm Charts in the storage category","queryString":"kind=0\u0026ts_query=storage"},{"name":"Packages with Apache-2.0 license","queryString":"license=Apache-2.0"},{"name":"OPA policies with MIT license","queryString":"kind=2\u0026license=MIT"},{"name":"Helm plugins","queryString":"kind=6"},{"name":"Kubectl plugins","queryString":"kind=5"},{"name":"Tekton tasks","queryString":"kind=7"}]' />
|
||||
<meta name="artifacthub:reportURL" content="https://github.com/artifacthub/hub/issues/new?labels=abuse+report&template=report-abuse.md" />
|
||||
<% } else { %>
|
||||
<title>{{ .title }}</title>
|
||||
<meta name="description" content="{{ .description }}" />
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
<meta name="artifacthub:gaTrackingID" content="{{ .gaTrackingID }}" />
|
||||
<meta name="artifacthub:motd" content="{{ .motd }}" />
|
||||
<meta name="artifacthub:motdSeverity" content="{{ .motdSeverity }}" />
|
||||
<meta name="artifacthub:reportURL" content="{{ .reportURL }}" />
|
||||
<% } %>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="{{ .title }}" />
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@
|
|||
right: 0.3rem !important;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767.98px) {
|
||||
.dropdown {
|
||||
width: 18rem;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ jest.mock('react-router-dom', () => ({
|
|||
}),
|
||||
}));
|
||||
|
||||
const openMock = jest.fn();
|
||||
window.open = openMock;
|
||||
|
||||
describe('MoreActionsButton', () => {
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
|
|
@ -78,5 +81,104 @@ describe('MoreActionsButton', () => {
|
|||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('report abuse', () => {
|
||||
it('opens url', () => {
|
||||
Object.defineProperty(document, 'querySelector', {
|
||||
value: (selector: any) => {
|
||||
switch (selector) {
|
||||
case `meta[name='artifacthub:reportURL']`:
|
||||
return {
|
||||
getAttribute: () => 'http://test.com',
|
||||
};
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
writable: true,
|
||||
});
|
||||
|
||||
render(<MoreActionsButton {...defaultProps} />);
|
||||
|
||||
const dropdown = screen.getByRole('menu');
|
||||
expect(dropdown).toBeInTheDocument();
|
||||
expect(dropdown).not.toHaveClass('show');
|
||||
|
||||
const btn = screen.getByRole('button', { name: 'Open menu' });
|
||||
expect(btn).toBeInTheDocument();
|
||||
|
||||
userEvent.click(btn);
|
||||
|
||||
expect(dropdown).toHaveClass('show');
|
||||
|
||||
const reportURLBtn = screen.getByRole('button', { name: 'Open report abuse url' });
|
||||
expect(reportURLBtn).toBeInTheDocument();
|
||||
|
||||
userEvent.click(reportURLBtn);
|
||||
|
||||
expect(openMock).toHaveBeenCalledTimes(1);
|
||||
expect(openMock).toHaveBeenCalledWith('http://test.com', '_blank');
|
||||
});
|
||||
|
||||
it('does not render when url is undefined', () => {
|
||||
Object.defineProperty(document, 'querySelector', {
|
||||
value: (selector: any) => {
|
||||
switch (selector) {
|
||||
case `meta[name='artifacthub:reportURL']`:
|
||||
return {
|
||||
getAttribute: () => null,
|
||||
};
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
writable: true,
|
||||
});
|
||||
|
||||
render(<MoreActionsButton {...defaultProps} />);
|
||||
|
||||
const dropdown = screen.getByRole('menu');
|
||||
expect(dropdown).toBeInTheDocument();
|
||||
expect(dropdown).not.toHaveClass('show');
|
||||
|
||||
const btn = screen.getByRole('button', { name: 'Open menu' });
|
||||
expect(btn).toBeInTheDocument();
|
||||
|
||||
userEvent.click(btn);
|
||||
|
||||
expect(dropdown).toHaveClass('show');
|
||||
expect(screen.queryByRole('button', { name: 'Open report abuse url' })).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it('does not render when url is an empty string', () => {
|
||||
Object.defineProperty(document, 'querySelector', {
|
||||
value: (selector: any) => {
|
||||
switch (selector) {
|
||||
case `meta[name='artifacthub:reportURL']`:
|
||||
return {
|
||||
getAttribute: () => '',
|
||||
};
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
writable: true,
|
||||
});
|
||||
|
||||
render(<MoreActionsButton {...defaultProps} />);
|
||||
|
||||
const dropdown = screen.getByRole('menu');
|
||||
expect(dropdown).toBeInTheDocument();
|
||||
expect(dropdown).not.toHaveClass('show');
|
||||
|
||||
const btn = screen.getByRole('button', { name: 'Open menu' });
|
||||
expect(btn).toBeInTheDocument();
|
||||
|
||||
userEvent.click(btn);
|
||||
|
||||
expect(dropdown).toHaveClass('show');
|
||||
expect(screen.queryByRole('button', { name: 'Open report abuse url' })).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import classnames from 'classnames';
|
||||
import { isNull } from 'lodash';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { BiCode } from 'react-icons/bi';
|
||||
import { GoStop } from 'react-icons/go';
|
||||
import { HiDotsVertical } from 'react-icons/hi';
|
||||
|
||||
import useOutsideClick from '../../hooks/useOutsideClick';
|
||||
import { SearchFiltersURL } from '../../types';
|
||||
import getMetaTag from '../../utils/getMetaTag';
|
||||
import styles from './MoreActionsButton.module.css';
|
||||
import WidgetModal from './WidgetModal';
|
||||
|
||||
|
|
@ -21,6 +24,7 @@ const MoreActionsButton = (props: Props) => {
|
|||
const [openStatus, setOpenStatus] = useState(false);
|
||||
const [visibleWidget, setVisibleWidget] = useState<boolean>(props.visibleWidget);
|
||||
const [currentPkgId, setCurrentPkgId] = useState<string>(props.packageId);
|
||||
const reportURL = getMetaTag('reportURL');
|
||||
|
||||
const ref = useRef(null);
|
||||
useOutsideClick([ref], openStatus, () => setOpenStatus(false));
|
||||
|
|
@ -69,10 +73,28 @@ const MoreActionsButton = (props: Props) => {
|
|||
aria-label="Open embed widget modal"
|
||||
>
|
||||
<div className="d-flex flex-row align-items-center">
|
||||
<BiCode className="mr-2" />
|
||||
<BiCode className={`mr-2 position-relative ${styles.icon}`} />
|
||||
<div>Embed widget</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{!isNull(reportURL) && reportURL !== '' && (
|
||||
<button
|
||||
className="dropdown-item btn btn-sm rounded-0 text-dark"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
window.open(reportURL, '_blank');
|
||||
setOpenStatus(false);
|
||||
}}
|
||||
aria-label="Open report abuse url"
|
||||
>
|
||||
<div className="d-flex flex-row align-items-center">
|
||||
<GoStop className={`mr-2 position-relative ${styles.icon}`} />
|
||||
<div>Report abuse</div>
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ exports[`MoreActionsButton creates snapshot 1`] = `
|
|||
class="d-flex flex-row align-items-center"
|
||||
>
|
||||
<svg
|
||||
class="mr-2"
|
||||
class="mr-2 position-relative icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
stroke="currentColor"
|
||||
|
|
|
|||
Loading…
Reference in New Issue