react-icons/fa#FaTrashAlt TypeScript Examples
The following examples show how to use
react-icons/fa#FaTrashAlt.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Page.tsx From freedeck-configurator with GNU General Public License v3.0 | 5 votes |
PageComponent: React.FC<IProps> = ({
brightness,
pageIndex,
deleteImage,
makeDefaultBackImage,
originalImages,
width,
height,
convertedImages,
setOriginalImage,
buttonSettingsPages,
displaySettingsPages,
deletePage,
addPage,
setButtonSettings,
setDisplaySettings,
pageCount,
switchDisplays,
}) => {
return (
<Wrapper id={`page_${pageIndex}`}>
<Header>
<PageIndicator>{pageIndex}</PageIndicator>
<DeletePage
onClick={() => {
const deleteConfirmed = window.confirm(
"Do you really want to delete this page forever?"
);
if (deleteConfirmed) deletePage(pageIndex);
}}
>
<FaTrashAlt size={18} color="white" />
</DeletePage>
</Header>
<Grid height={height} width={width}>
<DndProvider backend={Backend}>
{displaySettingsPages.map((imageDisplay, displayIndex) => (
<Display
brightness={brightness}
deleteImage={() => deleteImage(displayIndex)}
makeDefaultBackImage={() => makeDefaultBackImage(displayIndex)}
convertedImage={
convertedImages?.[displayIndex] ?? getEmptyConvertedImage()
}
setButtonSettings={(displayAction) =>
setButtonSettings(displayIndex, displayAction)
}
setDisplaySettings={(displayImage) =>
setDisplaySettings(displayIndex, displayImage)
}
actionDisplay={buttonSettingsPages[displayIndex]}
imageDisplay={displaySettingsPages[displayIndex]}
key={displayIndex}
displayIndex={displayIndex}
pageIndex={pageIndex}
setOriginalImage={(image) =>
setOriginalImage(displayIndex, image)
}
pages={[...Array(pageCount).keys()].filter(
(pageNumber) => pageNumber !== pageIndex
)}
addPage={(primary: boolean) => addPage(displayIndex, primary)}
originalImage={originalImages[displayIndex]}
switchDisplays={switchDisplays}
/>
))}
</DndProvider>
</Grid>
</Wrapper>
);
}
Example #2
Source File: Card.tsx From hub with Apache License 2.0 | 4 votes |
RepositoryCard = (props: Props) => {
const history = useHistory();
const { ctx } = useContext(AppCtx);
const [dropdownMenuStatus, setDropdownMenuStatus] = useState<boolean>(false);
const [transferModalStatus, setTransferModalStatus] = useState<boolean>(false);
const [deletionModalStatus, setDeletionModalStatus] = useState<boolean>(false);
const [badgeModalStatus, setBadgeModalStatus] = useState<boolean>(false);
const dropdownMenu = useRef(null);
const organizationName = ctx.prefs.controlPanel.selectedOrg;
const hasErrors = !isUndefined(props.repository.lastTrackingErrors) && !isNull(props.repository.lastTrackingErrors);
const hasScanningErrors =
!isUndefined(props.repository.lastScanningErrors) && !isNull(props.repository.lastScanningErrors);
const [openErrorsModal, setOpenErrorsModal] = useState<boolean>(false);
const [openScanningErrorsModal, setOpenScanningErrorsModal] = useState<boolean>(false);
const closeDropdown = () => {
setDropdownMenuStatus(false);
};
useOutsideClick([dropdownMenu], dropdownMenuStatus, closeDropdown);
useEffect(() => {
if (props.visibleModal) {
if (props.visibleModal === 'scanning') {
setOpenScanningErrorsModal(true);
} else {
setOpenErrorsModal(true);
}
history.replace({
search: '',
});
}
}, []); /* eslint-disable-line react-hooks/exhaustive-deps */
const getLastTracking = (): JSX.Element => {
const nextCheckTime: number = minutesToNearestInterval(30);
if (isUndefined(props.repository.lastTrackingTs) || isNull(props.repository.lastTrackingTs)) {
return (
<>
Not processed yet
{props.repository.disabled
? '.'
: nextCheckTime > 0
? `, it will be processed automatically in ~ ${nextCheckTime} minutes`
: ', it will be processed automatically in less than 30 minutes'}
</>
);
}
const content = (
<>
{!isFuture(props.repository.lastTrackingTs!) && (
<span>{moment.unix(props.repository.lastTrackingTs!).fromNow()}</span>
)}
{hasErrors ? (
<>
<FaExclamation className="mx-1 text-warning" />
<RepositoryWarningModal />
</>
) : (
<FaCheck className="mx-1 text-success" />
)}
</>
);
let nextCheckMsg: string = '';
if (nextCheckTime > 0 && !props.repository.disabled) {
nextCheckMsg = `(it will be checked for updates again in ~ ${nextCheckTime} minutes)`;
}
if (hasErrors) {
return (
<>
{content}
<Modal
modalDialogClassName={styles.modalDialog}
modalClassName="mh-100"
className={`d-inline-block ${styles.modal}`}
buttonType={`ms-1 btn badge btn-outline-secondary ${styles.btn}`}
buttonContent={
<div className="d-flex flex-row align-items-center">
<HiExclamation className="me-2" />
<span className="d-none d-xl-inline d-xxl-none d-xxxl-inline">Show tracking errors log</span>
<span className="d-inline d-xl-none d-xxl-inline d-xxxl-none">Logs</span>
</div>
}
header={
<div className={`h3 m-2 flex-grow-1 text-truncate ${styles.title}`}>
Tracking errors log - {props.repository.displayName || props.repository.name}
</div>
}
open={openErrorsModal}
onClose={() => setOpenErrorsModal(false)}
footerClassName={styles.modalFooter}
>
<div className="d-flex h-100 mw-100 overflow-hidden">
<div className="d-flex flex-column w-100">
<div className={`mb-2 ${styles.trackingTime}`}>
{moment.unix(props.repository.lastTrackingTs!).format('llll Z')}
</div>
<div
className={`position-relative flex-grow-1 mw-100 mh-100 overflow-hidden ${styles.modalSyntaxTrackerWrapper}`}
>
{props.repository.lastTrackingErrors && (
<SyntaxHighlighter
language="bash"
style={tomorrowNight}
customStyle={{ fontSize: '90%', height: '100%' }}
>
{props.repository.lastTrackingErrors}
</SyntaxHighlighter>
)}
</div>
</div>
</div>
</Modal>
<span className="ms-3 fst-italic text-muted">{nextCheckMsg}</span>
</>
);
} else {
return (
<>
{content}
{openErrorsModal && (
<Modal
className={`d-inline-block ${styles.modal}`}
header={<div className={`h3 m-2 flex-grow-1 ${styles.title}`}>Tracking errors log</div>}
open
>
<div className="h5 text-center my-5 mw-100">
It looks like the last tracking of this repository worked fine and no errors were produced.
<br />
<br />
If you have arrived to this screen from an email listing some errors, please keep in mind those may have
been already solved.
</div>
</Modal>
)}
<span className="ms-1 fst-italic text-muted">{nextCheckMsg}</span>
</>
);
}
};
const getLastScanning = (): JSX.Element => {
const nextCheckTime: number = minutesToNearestInterval(30, 15);
if (
props.repository.scannerDisabled ||
isUndefined(props.repository.lastTrackingTs) ||
isNull(props.repository.lastTrackingTs)
)
return <>-</>;
if (isUndefined(props.repository.lastScanningTs) || isNull(props.repository.lastScanningTs)) {
return (
<>
Not scanned yet
{props.repository.disabled
? '.'
: nextCheckTime > 0
? `, it will be scanned for security vulnerabilities in ~ ${nextCheckTime} minutes`
: ', it will be scanned for security vulnerabilities in less than 30 minutes'}
</>
);
}
const content = (
<>
{!isFuture(props.repository.lastScanningTs!) && (
<span>{moment.unix(props.repository.lastScanningTs!).fromNow()}</span>
)}
{hasScanningErrors ? (
<FaExclamation className="mx-2 text-warning" />
) : (
<FaCheck className="mx-2 text-success" />
)}
</>
);
let nextCheckMsg: string = '';
if (nextCheckTime > 0 && !props.repository.disabled) {
nextCheckMsg = `(it will be checked for updates again in ~ ${nextCheckTime} minutes)`;
}
if (hasScanningErrors) {
return (
<>
{content}
<Modal
modalDialogClassName={styles.modalDialog}
modalClassName="mh-100"
className={`d-inline-block ${styles.modal}`}
buttonType={`ms-1 btn badge btn-outline-secondary ${styles.btn}`}
buttonContent={
<div className="d-flex flex-row align-items-center">
<HiExclamation className="me-2" />
<span className="d-none d-sm-inline">Show scanning errors log</span>
<span className="d-inline d-sm-none">Logs</span>
</div>
}
header={
<div className={`h3 m-2 flex-grow-1 text-truncate ${styles.title}`}>
Scanning errors log - {props.repository.displayName || props.repository.name}
</div>
}
open={openScanningErrorsModal}
onClose={() => setOpenErrorsModal(false)}
footerClassName={styles.modalFooter}
>
<div className="d-flex h-100 mw-100 overflow-hidden">
<div className={`d-flex overflow-scroll ${styles.modalSyntaxWrapper}`}>
{props.repository.lastScanningErrors && (
<SyntaxHighlighter
language="bash"
style={tomorrowNight}
customStyle={{ fontSize: '90%', height: '100%', marginBottom: '0' }}
>
{props.repository.lastScanningErrors}
</SyntaxHighlighter>
)}
</div>
</div>
</Modal>
<span className="ms-3 fst-italic text-muted">{nextCheckMsg}</span>
</>
);
} else {
return (
<>
{content}
{openScanningErrorsModal && (
<Modal
className={`d-inline-block ${styles.modal}`}
header={<div className={`h3 m-2 flex-grow-1 ${styles.title}`}>Scanning errors log</div>}
open
>
<div className="h5 text-center my-5 mw-100">
It looks like the last security vulnerabilities scan of this repository worked fine and no errors were
produced.
<br />
<br />
If you have arrived to this screen from an email listing some errors, please keep in mind those may have
been already solved.
</div>
</Modal>
)}
<span className="ms-1 fst-italic text-muted">{nextCheckMsg}</span>
</>
);
}
};
return (
<div className="col-12 col-xxl-6 py-sm-3 py-2 px-0 px-xxl-3" data-testid="repoCard">
<div className="card h-100">
<div className="card-body d-flex flex-column h-100">
<div className="d-flex flex-row w-100 justify-content-between">
<div className={`text-truncate h5 mb-0 ${styles.titleCard}`}>
{props.repository.displayName || props.repository.name}
</div>
<OfficialBadge
official={props.repository.official}
className={`ms-3 d-none d-md-inline ${styles.labelWrapper}`}
type="repo"
/>
<VerifiedPublisherBadge
verifiedPublisher={props.repository.verifiedPublisher}
className={`ms-3 d-none d-md-inline ${styles.labelWrapper}`}
/>
<DisabledRepositoryBadge
disabled={props.repository.disabled!}
className={`ms-3 d-none d-md-inline ${styles.labelWrapper}`}
/>
<ScannerDisabledRepositoryBadge
scannerDisabled={props.repository.scannerDisabled!}
className={`ms-3 d-none d-md-inline ${styles.labelWrapper}`}
/>
{transferModalStatus && (
<TransferRepositoryModal
open={true}
repository={props.repository}
onSuccess={props.onSuccess}
onAuthError={props.onAuthError}
onClose={() => setTransferModalStatus(false)}
/>
)}
{deletionModalStatus && (
<DeletionModal
repository={props.repository}
organizationName={organizationName}
setDeletionModalStatus={setDeletionModalStatus}
onSuccess={props.onSuccess}
onAuthError={props.onAuthError}
/>
)}
{badgeModalStatus && (
<BadgeModal
repository={props.repository}
onClose={() => setBadgeModalStatus(false)}
open={badgeModalStatus}
/>
)}
<div className="ms-auto ps-3">
<RepositoryIconLabel kind={props.repository.kind} isPlural />
</div>
<div className="ms-3">
<div
ref={dropdownMenu}
className={classnames('dropdown-menu dropdown-menu-end p-0', styles.dropdownMenu, {
show: dropdownMenuStatus,
})}
>
<div className={`dropdown-arrow ${styles.arrow}`} />
<button
className="dropdown-item btn btn-sm rounded-0 text-dark"
onClick={(e: ReactMouseEvent<HTMLButtonElement>) => {
e.preventDefault();
closeDropdown();
setBadgeModalStatus(true);
}}
aria-label="Open badge modal"
>
<div className="d-flex flex-row align-items-center">
<MdLabel className={`me-2 ${styles.btnIcon}`} />
<span>Get badge</span>
</div>
</button>
<ActionBtn
className="dropdown-item btn btn-sm rounded-0 text-dark"
onClick={(e: ReactMouseEvent<HTMLButtonElement>) => {
e.preventDefault();
closeDropdown();
setTransferModalStatus(true);
}}
action={AuthorizerAction.TransferOrganizationRepository}
label="Open transfer repository modal"
>
<>
<RiArrowLeftRightLine className={`me-2 ${styles.btnIcon}`} />
<span>Transfer</span>
</>
</ActionBtn>
<ActionBtn
className="dropdown-item btn btn-sm rounded-0 text-dark"
onClick={(e: ReactMouseEvent<HTMLButtonElement>) => {
e.preventDefault();
closeDropdown();
props.setModalStatus({
open: true,
repository: props.repository,
});
}}
action={AuthorizerAction.UpdateOrganizationRepository}
label="Open update repository modal"
>
<>
<FaPencilAlt className={`me-2 ${styles.btnIcon}`} />
<span>Edit</span>
</>
</ActionBtn>
<ActionBtn
className="dropdown-item btn btn-sm rounded-0 text-dark"
onClick={(e: ReactMouseEvent<HTMLButtonElement>) => {
e.preventDefault();
closeDropdown();
setDeletionModalStatus(true);
}}
action={AuthorizerAction.DeleteOrganizationRepository}
label="Open delete repository modal"
>
<>
<FaTrashAlt className={`me-2 ${styles.btnIcon}`} />
<span>Delete</span>
</>
</ActionBtn>
</div>
<button
className={`btn btn-outline-secondary rounded-circle p-0 text-center ${styles.btnDropdown}`}
onClick={() => setDropdownMenuStatus(true)}
aria-label="Open menu"
aria-expanded={dropdownMenuStatus}
>
<BsThreeDotsVertical />
</button>
</div>
</div>
{props.repository.repositoryId && (
<div className="mt-2 d-flex flex-row align-items-baseline">
<div className="text-truncate">
<small className="text-muted text-uppercase me-1">ID: </small>
<small>{props.repository.repositoryId}</small>
</div>
<div className={`ms-1 ${styles.copyBtn}`}>
<div className={`position-absolute ${styles.copyBtnWrapper}`}>
<ButtonCopyToClipboard
text={props.repository.repositoryId}
className="btn-link border-0 text-dark fw-bold"
label="Copy repository ID to clipboard"
/>
</div>
</div>
</div>
)}
<div className="text-truncate">
<small className="text-muted text-uppercase me-1">Url: </small>
<small>{props.repository.url}</small>
</div>
<div>
<small className="text-muted text-uppercase me-1">Last processed: </small>
<small>{getLastTracking()}</small>
</div>
<div>
<small className="text-muted text-uppercase me-1">Last security scan: </small>
<small>{getLastScanning()}</small>
</div>
<div className="mt-3 m-md-0 d-flex flex-row d-md-none">
<OfficialBadge official={props.repository.official} className="me-3" type="repo" />
<VerifiedPublisherBadge verifiedPublisher={props.repository.verifiedPublisher} className="me-3" />
<DisabledRepositoryBadge disabled={props.repository.disabled!} />
</div>
</div>
</div>
</div>
);
}
Example #3
Source File: DeletionModal.tsx From hub with Apache License 2.0 | 4 votes |
DeletionModal = (props: Props) => {
const [isDeleting, setIsDeleting] = useState(false);
const [isValidInput, setIsValidInput] = useState<boolean>(false);
const onInputChange = (e: ChangeEvent<HTMLInputElement>) => {
setIsValidInput(e.target.value === props.repository.name);
};
async function deleteRepository() {
try {
setIsDeleting(true);
await API.deleteRepository(props.repository.name, props.organizationName);
setIsDeleting(false);
props.onSuccess();
} catch (err: any) {
setIsDeleting(false);
if (err.kind === ErrorKind.Unauthorized) {
props.onAuthError();
} else {
let errorMessage = 'An error occurred deleting the repository, please try again later.';
if (!isUndefined(props.organizationName) && err.kind === ErrorKind.Forbidden) {
errorMessage = 'You do not have permissions to delete the repository from the organization.';
}
alertDispatcher.postAlert({
type: 'danger',
message: errorMessage,
});
}
}
}
return (
<Modal
className="d-inline-block"
closeButton={
<>
<button
className="btn btn-sm btn-outline-secondary text-uppercase"
onClick={() => props.setDeletionModalStatus(false)}
aria-label="Cancel"
>
<div className="d-flex flex-row align-items-center">
<IoMdCloseCircle className="me-2" />
<span>Cancel</span>
</div>
</button>
<button
className="btn btn-sm btn-danger ms-3"
onClick={(e) => {
e.preventDefault();
deleteRepository();
}}
disabled={isDeleting || !isValidInput}
aria-label="Delete repository"
>
<div className="d-flex flex-row align-items-center text-uppercase">
{isDeleting ? (
<>
<span className="spinner-grow spinner-grow-sm" role="status" aria-hidden="true" />
<span className="ms-2">Deleting...</span>
</>
) : (
<>
<FaTrashAlt className="me-2" />
<span>Delete</span>
</>
)}
</div>
</button>
</>
}
header={<div className={`h3 m-2 flex-grow-1 ${styles.title}`}>Delete repository</div>}
onClose={() => props.setDeletionModalStatus(false)}
open
>
<div className="mw-100">
<div className="alert alert-warning my-4">
<span className="fw-bold text-uppercase">Important:</span> Please read this carefully.
</div>
<p>If you delete this repository all packages belonging to it will be deleted.</p>
<p>
All information related to your repository or packages will be permanently deleted as well. This includes
packages' stars, users subscriptions to packages, webhooks, events and notifications.
</p>
<p>
<span className="fw-bold">This operation cannot be undone</span>.
</p>
<p>
Please type <span className="fw-bold">{props.repository.name}</span> to confirm:
</p>
<InputField type="text" name="repoName" autoComplete="off" value="" onChange={onInputChange} />
</div>
</Modal>
);
}
Example #4
Source File: DeleteOrg.tsx From hub with Apache License 2.0 | 4 votes |
DeleteOrganization = (props: Props) => {
const { dispatch } = useContext(AppCtx);
const [openStatus, setOpenStatus] = useState<boolean>(false);
const [isDeleting, setIsDeleting] = useState(false);
const [isValidInput, setIsValidInput] = useState<boolean>(false);
const onInputChange = (e: ChangeEvent<HTMLInputElement>) => {
setIsValidInput(e.target.value === props.organization.name);
};
async function deleteOrganization() {
try {
setIsDeleting(true);
await API.deleteOrganization(props.organization.name);
dispatch(unselectOrg());
window.scrollTo(0, 0); // Scroll to top when org is deleted
setIsDeleting(false);
} catch (err: any) {
setIsDeleting(false);
if (err.kind === ErrorKind.Unauthorized) {
props.onAuthError();
} else {
let errorMessage = 'An error occurred deleting the organization, please try again later.';
if (err.kind === ErrorKind.Forbidden) {
errorMessage = 'You do not have permissions to delete the organization.';
}
alertDispatcher.postAlert({
type: 'danger',
message: errorMessage,
});
}
}
}
return (
<>
<div className="mt-4 mt-md-5">
<p className="mb-4">
Deleting your organization will also delete all the content that belongs to it. Please be certain as{' '}
<span className="fw-bold">this operation cannot be undone</span>.
</p>
<ActionBtn
className="btn btn-sm btn-danger"
onClick={(e: ReactMouseEvent<HTMLButtonElement>) => {
e.preventDefault();
setOpenStatus(true);
}}
action={AuthorizerAction.DeleteOrganization}
label="Open delete organization modal"
>
<div className="d-flex flex-row align-items-center text-uppercase">
<FaTrashAlt className="me-2" />
<div>Delete organization</div>
</div>
</ActionBtn>
</div>
<Modal
className="d-inline-block"
closeButton={
<>
<button
className="btn btn-sm btn-outline-secondary text-uppercase"
onClick={() => setOpenStatus(false)}
aria-label="Close"
>
<div className="d-flex flex-row align-items-center">
<IoMdCloseCircle className="me-2" />
<span>Cancel</span>
</div>
</button>
<button
className="btn btn-sm btn-danger ms-3"
onClick={(e) => {
e.preventDefault();
deleteOrganization();
}}
disabled={isDeleting || !isValidInput}
aria-label="Delete organization"
>
<div className="d-flex flex-row align-items-center text-uppercase">
{isDeleting ? (
<>
<span className="spinner-grow spinner-grow-sm" role="status" aria-hidden="true" />
<span className="ms-2">Deleting...</span>
</>
) : (
<>
<FaTrashAlt className="me-2" />
<span>Delete</span>
</>
)}
</div>
</button>
</>
}
header={<div className={`h3 m-2 flex-grow-1 ${styles.title}`}>Delete organization</div>}
onClose={() => setOpenStatus(false)}
open={openStatus}
>
<div className="mw-100">
<div className="alert alert-warning my-4">
<span className="fw-bold text-uppercase">Important:</span> Please read this carefully.
</div>
<p>
If you delete this organization all repositories belonging to it will be deleted. Please consider
transferring them to another organization or your personal account.
</p>
<p>
All information related to the repositories will be permanently deleted as well. This includes packages,
stars, users subscriptions, webhooks, events and notifications. Some of this information was created by
users and will be lost.
</p>
<p>
<span className="fw-bold">This operation cannot be undone</span>.
</p>
<p data-testid="confirmationText">
Please type <span className="fw-bold">{props.organization.name}</span> to confirm:
</p>
<InputField type="text" name="orgName" autoComplete="off" value="" onChange={onInputChange} />
</div>
</Modal>
</>
);
}
Example #5
Source File: Card.tsx From hub with Apache License 2.0 | 4 votes |
APIKeyCard = (props: Props) => {
const [isDeleting, setIsDeleting] = useState(false);
const [dropdownMenuStatus, setDropdownMenuStatus] = useState<boolean>(false);
const dropdownMenu = useRef(null);
const [deletionModalStatus, setDeletionModalStatus] = useState<boolean>(false);
const closeDropdown = () => {
setDropdownMenuStatus(false);
};
useOutsideClick([dropdownMenu], dropdownMenuStatus, closeDropdown);
async function deleteAPIKey() {
try {
setIsDeleting(true);
await API.deleteAPIKey(props.apiKey.apiKeyId!);
setIsDeleting(false);
props.onSuccess();
} catch (err: any) {
setIsDeleting(false);
if (err.kind === ErrorKind.Unauthorized) {
props.onAuthError();
} else {
alertDispatcher.postAlert({
type: 'danger',
message: 'An error occurred deleting the API key, please try again later.',
});
}
}
}
return (
<div className="col-12 col-xxl-6 py-sm-3 py-2 px-0 px-xxl-3" data-testid="APIKeyCard">
<div className="card h-100">
<div className="card-body d-flex flex-column h-100">
<div className="d-flex flex-row w-100 justify-content-between">
<div className={`h5 mb-1 me-2 text-break ${styles.titleCard}`}>{props.apiKey.name}</div>
{deletionModalStatus && (
<Modal
className={`d-inline-block ${styles.modal}`}
closeButton={
<>
<button
className="btn btn-sm btn-outline-secondary text-uppercase"
onClick={() => setDeletionModalStatus(false)}
aria-label="Cancel"
>
<div className="d-flex flex-row align-items-center">
<IoMdCloseCircle className="me-2" />
<span>Cancel</span>
</div>
</button>
<button
className="btn btn-sm btn-danger ms-3"
onClick={(e) => {
e.preventDefault();
closeDropdown();
deleteAPIKey();
}}
disabled={isDeleting}
aria-label="Delete API key"
>
<div className="d-flex flex-row align-items-center text-uppercase">
{isDeleting ? (
<>
<span className="spinner-grow spinner-grow-sm" role="status" aria-hidden="true" />
<span className="ms-2">Deleting...</span>
</>
) : (
<>
<FaTrashAlt className={`me-2 ${styles.btnDeleteIcon}`} />
<span>Delete</span>
</>
)}
</div>
</button>
</>
}
header={<div className={`h3 m-2 flex-grow-1 ${styles.title}`}>Delete API key</div>}
onClose={() => setDeletionModalStatus(false)}
open
>
<div className="mt-3 mw-100 text-center">
<p>Are you sure you want to remove this API key?</p>
</div>
</Modal>
)}
<div className="ms-auto">
<div
ref={dropdownMenu}
className={classnames('dropdown-menu dropdown-menu-end p-0', styles.dropdownMenu, {
show: dropdownMenuStatus,
})}
>
<div className={`dropdown-arrow ${styles.arrow}`} />
<button
className="dropdown-item btn btn-sm rounded-0 text-dark"
onClick={(e: ReactMouseEvent<HTMLButtonElement>) => {
e.preventDefault();
closeDropdown();
props.setModalStatus({
open: true,
apiKey: props.apiKey,
});
}}
aria-label="Open API key modal"
>
<div className="d-flex flex-row align-items-center">
<FaPencilAlt className={`me-2 ${styles.btnIcon}`} />
<span>Edit</span>
</div>
</button>
<button
className="dropdown-item btn btn-sm rounded-0 text-dark"
onClick={(e: ReactMouseEvent<HTMLButtonElement>) => {
e.preventDefault();
closeDropdown();
setDeletionModalStatus(true);
}}
aria-label="Open deletion modal"
>
<div className="d-flex flex-row align-items-center">
<FaTrashAlt className={`me-2 ${styles.btnIcon}`} />
<span>Delete</span>
</div>
</button>
</div>
<button
className={`btn btn-outline-secondary rounded-circle p-0 text-center ${styles.btnDropdown}`}
onClick={() => setDropdownMenuStatus(true)}
aria-label="Open menu"
aria-expanded={dropdownMenuStatus}
>
<BsThreeDotsVertical />
</button>
</div>
</div>
<div className="mt-2 d-flex flex-row align-items-baseline">
<div className="text-truncate">
<small className="text-muted text-uppercase me-1">API-KEY-ID: </small>
<small>{props.apiKey.apiKeyId}</small>
</div>
<div className={`ms-1 ${styles.copyBtn}`}>
<div className={`position-absolute ${styles.copyBtnWrapper}`}>
<ButtonCopyToClipboard
text={props.apiKey.apiKeyId!}
className="btn-link border-0 text-dark fw-bold"
label="Copy API key ID to clipboard"
/>
</div>
</div>
</div>
<div className="text-truncate">
<small className="text-muted text-uppercase me-1">Created at: </small>
<small>{moment.unix(props.apiKey.createdAt!).format('YYYY/MM/DD HH:mm:ss (Z)')}</small>
</div>
</div>
</div>
</div>
);
}
Example #6
Source File: DeleteAccount.tsx From hub with Apache License 2.0 | 4 votes |
DeleteAccount = (props: Props) => {
const { ctx } = useContext(AppCtx);
const [openStatus, setOpenStatus] = useState<boolean>(false);
const [isDeleting, setIsDeleting] = useState(false);
const [deleteSuccess, setDeleteSuccess] = useState<boolean>(false);
const [isValidInput, setIsValidInput] = useState<boolean>(false);
const onInputChange = (e: ChangeEvent<HTMLInputElement>) => {
setIsValidInput(e.target.value === ctx.user!.alias);
};
const onClose = () => {
setOpenStatus(false);
setDeleteSuccess(false);
setIsValidInput(false);
};
async function registerDeleteUserCode() {
try {
setIsDeleting(true);
await API.registerDeleteUserCode();
setIsDeleting(false);
setDeleteSuccess(true);
} catch (err: any) {
setIsDeleting(false);
if (err.kind === ErrorKind.Unauthorized) {
props.onAuthError();
} else {
alertDispatcher.postAlert({
type: 'danger',
message: 'An error occurred deleting your account, please try again later.',
});
}
}
}
return (
<>
<div className="mt-4 mt-md-5">
<p className="mb-4">
Deleting your account will also delete all the content that belongs to it (repositories, subscriptions,
webhooks, etc), as well as all organizations where you are the only member.
</p>
<button
className="btn btn-sm btn-danger"
onClick={() => setOpenStatus(true)}
aria-label="Open deletion account modal"
>
<div className="d-flex flex-row align-items-center text-uppercase">
<FaTrashAlt className="me-2" />
<div>Delete account</div>
</div>
</button>
</div>
<Modal
className="d-inline-block"
modalClassName={styles.modal}
closeButton={
deleteSuccess ? undefined : (
<>
<button
className="btn btn-sm btn-outline-secondary text-uppercase"
onClick={() => setOpenStatus(false)}
aria-label="Close"
>
<div className="d-flex flex-row align-items-center">
<IoMdCloseCircle className="me-2" />
<span>Cancel</span>
</div>
</button>
<button
className="btn btn-sm btn-danger ms-3"
onClick={(e) => {
e.preventDefault();
registerDeleteUserCode();
}}
disabled={isDeleting || !isValidInput}
aria-label="Delete account"
>
<div className="d-flex flex-row align-items-center text-uppercase">
{isDeleting ? (
<>
<span className="spinner-grow spinner-grow-sm" role="status" aria-hidden="true" />
<span className="ms-2">Deleting...</span>
</>
) : (
<>
<FaTrashAlt className="me-2" />
<span>Delete account</span>
</>
)}
</div>
</button>
</>
)
}
header={<div className={`h3 m-2 flex-grow-1 ${styles.title}`}>Delete account</div>}
onClose={onClose}
open={openStatus}
>
<div className="mw-100 h-100">
{deleteSuccess ? (
<div className="d-flex h-100 w-100 align-items-center justify-content-center">
<div className="alert" role="alert" aria-live="assertive" aria-atomic="true">
<div className="d-flex flex-sm-column flex-md-row align-items-center">
<div className="me-3">
<CgUserRemove className="h1 text-dark mb-3 mb-md-0" />
</div>
<h4 className="alert-heading mb-0">We've just sent you a confirmation email</h4>
</div>
<hr />
<p>
Please click on the link that has just been sent to your email account to delete your account and
complete the process.
</p>
<p className="mb-0">
Please note that the link <span className="fw-bold">is only valid for 15 minutes</span>. If you
haven't clicked the link by then you'll need to start the process from the beginning.
</p>
</div>
</div>
) : (
<>
<div className="alert alert-warning my-4">
<span className="fw-bold text-uppercase">Important:</span> Please read this carefully.
</div>
<p>
If you delete your account all repositories belonging to it will be deleted. Please consider
transferring them to another user.
</p>
<p>
All information related to the repositories will be permanently deleted as well. This includes packages,
stars, users subscriptions, webhooks, events and notifications. Some of this information was created by
users and will be lost. In addition to that, all organizations where you are the only member and all
content belonging to those organizations will be removed as well.
</p>
<p>
<span className="fw-bold">This operation cannot be undone</span>.
</p>
<p data-testid="confirmationText">
Please type <span className="fw-bold">{ctx.user!.alias}</span> to confirm:
</p>
<div className="pb-3">
<InputField type="text" name="alias" autoComplete="off" value="" onChange={onInputChange} />
</div>
</>
)}
</div>
</Modal>
</>
);
}
Example #7
Source File: Card.tsx From hub with Apache License 2.0 | 4 votes |
WebhookCard = (props: Props) => {
const { ctx } = useContext(AppCtx);
const [isDeleting, setIsDeleting] = useState<boolean>(false);
const [dropdownMenuStatus, setDropdownMenuStatus] = useState<boolean>(false);
const dropdownMenu = useRef(null);
const [deletionModalStatus, setDeletionModalStatus] = useState<boolean>(false);
const closeDropdown = () => {
setDropdownMenuStatus(false);
};
useOutsideClick([dropdownMenu], dropdownMenuStatus, closeDropdown);
async function deleteWebhook() {
try {
setIsDeleting(true);
await API.deleteWebhook(props.webhook.webhookId!, ctx.prefs.controlPanel.selectedOrg);
setIsDeleting(false);
props.onDeletion();
} catch (err: any) {
setIsDeleting(false);
if (err.kind === ErrorKind.Unauthorized) {
props.onAuthError();
} else {
alertDispatcher.postAlert({
type: 'danger',
message: 'An error occurred deleting the webhook, please try again later.',
});
}
}
}
return (
<div className="col-12 col-xxl-6 py-sm-3 py-2 px-0 px-xxl-3" role="listitem">
<div className={`card cardWithHover w-100 h-100 mw-100 bg-white ${styles.card}`}>
<div className="card-body position-relative">
<div className="d-flex flex-row">
<div className="h5 card-title mb-3 me-3 lh-1 text-break">
<div className="d-flex flex-row align-items-start">
<div>{props.webhook.name}</div>
{props.webhook.active ? (
<span
className={`ms-3 mt-1 fw-bold badge rounded-pill border border-success text-success text-uppercase ${styles.badge}`}
>
Active
</span>
) : (
<span
className={`ms-3 mt-1 fw-bold badge rounded-pill border border-dark text-dark text-uppercase ${styles.badge} ${styles.inactiveBadge}`}
>
Inactive
</span>
)}
</div>
</div>
{deletionModalStatus && (
<Modal
className={`d-inline-block ${styles.modal}`}
closeButton={
<>
<button
className="btn btn-sm btn-outline-secondary text-uppercase"
onClick={() => setDeletionModalStatus(false)}
aria-label="Close deletion modal"
>
<div className="d-flex flex-row align-items-center">
<IoMdCloseCircle className="me-2" />
<span>Cancel</span>
</div>
</button>
<button
className="btn btn-sm btn-danger ms-3"
onClick={(e) => {
e.preventDefault();
deleteWebhook();
}}
disabled={isDeleting}
aria-label="Delete webhook"
>
<div className="d-flex flex-row align-items-center text-uppercase">
{isDeleting ? (
<>
<span className="spinner-grow spinner-grow-sm" role="status" aria-hidden="true" />
<span className="ms-2">Deleting...</span>
</>
) : (
<>
<FaTrashAlt className={`me-2 ${styles.btnDeleteIcon}`} />
<span>Delete</span>
</>
)}
</div>
</button>
</>
}
header={<div className={`h3 m-2 flex-grow-1 ${styles.title}`}>Delete webhook</div>}
onClose={() => setDeletionModalStatus(false)}
open
>
<div className="mt-3 mw-100 text-center">
<p>Are you sure you want to delete this webhook?</p>
</div>
</Modal>
)}
<div className="ms-auto">
<div
ref={dropdownMenu}
className={classnames('dropdown-menu dropdown-menu-end p-0', styles.dropdownMenu, {
show: dropdownMenuStatus,
})}
>
<div className={`dropdown-arrow ${styles.arrow}`} />
<button
className="dropdown-item btn btn-sm rounded-0 text-dark"
onClick={(e: ReactMouseEvent<HTMLButtonElement>) => {
e.preventDefault();
closeDropdown();
props.onEdition();
}}
aria-label="Edit webhook"
>
<div className="d-flex flex-row align-items-center">
<FaPencilAlt className={`me-2 ${styles.btnIcon}`} />
<span>Edit</span>
</div>
</button>
<button
className="dropdown-item btn btn-sm rounded-0 text-dark"
onClick={(e: ReactMouseEvent<HTMLButtonElement>) => {
e.preventDefault();
closeDropdown();
setDeletionModalStatus(true);
}}
aria-label="Open deletion webhook modal"
>
<div className="d-flex flex-row align-items-center">
<FaTrashAlt className={`me-2 ${styles.btnIcon}`} />
<span>Delete</span>
</div>
</button>
</div>
<button
className={`btn btn-outline-secondary rounded-circle p-0 text-center ${styles.btnDropdown}`}
onClick={() => setDropdownMenuStatus(true)}
aria-label="Open menu"
aria-expanded={dropdownMenuStatus}
>
<BsThreeDotsVertical />
</button>
</div>
</div>
<div className="d-flex flex-column">
<div className="card-subtitle d-flex flex-column mw-100 mt-1">
<p className="card-text">{props.webhook.description}</p>
</div>
<div className="text-truncate">
<small className="text-muted text-uppercase me-2">Url:</small>
<small>{props.webhook.url}</small>
</div>
<div className="d-flex flex-row justify-content-between align-items-baseline">
{props.webhook.lastNotifications && (
<div className="d-none d-md-inline mt-2">
<LastNotificationsModal notifications={props.webhook.lastNotifications} />
</div>
)}
{(isUndefined(props.webhook.packages) || props.webhook.packages.length === 0) && (
<div className="ms-auto mt-2">
<ElementWithTooltip
element={
<span
className={`d-flex flex-row align-items-center badge bg-warning rounded-pill ${styles.badgeNoPackages}`}
>
<TiWarningOutline />
<span className="ms-1">No packages</span>
</span>
}
tooltipMessage="This webhook is not associated to any packages."
active
visibleTooltip
/>
</div>
)}
</div>
</div>
</div>
</div>
</div>
);
}
Example #8
Source File: index.tsx From postcode with MIT License | 4 votes |
KeyValueRow = (props) => {
const {
itemKey,
itemValue,
itemDescription,
itemDisabled,
actions,
onDelete,
onChange,
fixed,
} = props;
return (
<tr className={itemDisabled ? "kv-disabled" : null}>
{!fixed && (
<td className="kv-action-cell">
{actions && (
<input
type="checkbox"
checked={!itemDisabled}
onChange={(e) =>
onChange({
key: itemKey,
value: itemValue,
description: itemDescription,
disabled: !e.target.checked,
})
}
/>
)}
</td>
)}
<td>
<input
className="kv-input"
placeholder="Key"
value={itemKey}
disabled={fixed}
onChange={(e) =>
onChange({
key: e.target.value,
value: itemValue,
description: itemDescription,
disabled: itemDisabled,
})
}
/>
</td>
<td>
<input
className="kv-input"
placeholder="Value"
value={itemValue}
disabled={fixed}
onChange={(e) =>
onChange({
key: itemKey,
value: e.target.value,
description: itemDescription,
disabled: itemDisabled,
})
}
/>
</td>
{!fixed && (
<td>
<input
className="kv-input"
placeholder="Description"
value={itemDescription}
disabled={fixed}
onChange={(e) =>
onChange({
key: itemKey,
value: itemValue,
description: e.target.value,
disabled: itemDisabled,
})
}
/>
</td>
)}
{!fixed && (
<td className="kv-action-cell">
{actions && (
<FaTrashAlt className="kv-delete-button" onClick={onDelete} />
)}
</td>
)}
</tr>
);
}