Scraper and plugin manager (#4242)

* Add package manager
* Add SettingModal validate
* Reverse modal button order
* Add plugin package management
* Refactor ClearableInput
This commit is contained in:
WithoutPants
2023-11-22 10:01:11 +11:00
committed by GitHub
parent d95ef4059a
commit 987fa80786
42 changed files with 3484 additions and 35 deletions

View File

@@ -0,0 +1,33 @@
import React from "react";
import { Button, Modal } from "react-bootstrap";
import { FormattedMessage } from "react-intl";
export interface IAlertModalProps {
text: JSX.Element | string;
show?: boolean;
confirmButtonText?: string;
onConfirm: () => void;
onCancel: () => void;
}
export const AlertModal: React.FC<IAlertModalProps> = ({
text,
show,
confirmButtonText,
onConfirm,
onCancel,
}) => {
return (
<Modal show={show}>
<Modal.Body>{text}</Modal.Body>
<Modal.Footer>
<Button variant="danger" onClick={() => onConfirm()}>
{confirmButtonText ?? <FormattedMessage id="actions.confirm" />}
</Button>
<Button variant="secondary" onClick={() => onCancel()}>
<FormattedMessage id="actions.cancel" />
</Button>
</Modal.Footer>
</Modal>
);
};

View File

@@ -8,17 +8,23 @@ import useFocus from "src/utils/focus";
interface IClearableInput {
value: string;
setValue: (value: string) => void;
focus: ReturnType<typeof useFocus>;
focus?: ReturnType<typeof useFocus>;
placeholder?: string;
}
export const ClearableInput: React.FC<IClearableInput> = ({
value,
setValue,
focus,
placeholder,
}) => {
const intl = useIntl();
const [queryRef, setQueryFocus] = focus;
const [defaultQueryRef, setQueryFocusDefault] = useFocus();
const [queryRef, setQueryFocus] = focus || [
defaultQueryRef,
setQueryFocusDefault,
];
const queryClearShowing = !!value;
function onChangeQuery(event: React.FormEvent<HTMLInputElement>) {
@@ -34,7 +40,7 @@ export const ClearableInput: React.FC<IClearableInput> = ({
<div className="clearable-input-group">
<FormControl
ref={queryRef}
placeholder={`${intl.formatMessage({ id: "actions.search" })}…`}
placeholder={placeholder}
value={value}
onInput={onChangeQuery}
className="clearable-text-field"

View File

@@ -13,7 +13,7 @@ interface IButton {
interface IModal {
show: boolean;
onHide?: () => void;
header?: string;
header?: JSX.Element | string;
icon?: IconDefinition;
cancel?: IButton;
accept?: IButton;
@@ -59,24 +59,6 @@ export const ModalComponent: React.FC<IModal> = ({
<div>{leftFooterButtons}</div>
<div>
{footerButtons}
{cancel ? (
<Button
disabled={isRunning}
variant={cancel.variant ?? "primary"}
onClick={cancel.onClick}
className="ml-2"
>
{cancel.text ?? (
<FormattedMessage
id="actions.cancel"
defaultMessage="Cancel"
description="Cancels the current action and dismisses the modal."
/>
)}
</Button>
) : (
""
)}
<Button
disabled={isRunning || disabled}
variant={accept?.variant ?? "primary"}
@@ -95,6 +77,24 @@ export const ModalComponent: React.FC<IModal> = ({
)
)}
</Button>
{cancel ? (
<Button
disabled={isRunning}
variant={cancel.variant ?? "primary"}
onClick={cancel.onClick}
className="ml-2"
>
{cancel.text ?? (
<FormattedMessage
id="actions.cancel"
defaultMessage="Cancel"
description="Cancels the current action and dismisses the modal."
/>
)}
</Button>
) : (
""
)}
</div>
</Modal.Footer>
</Modal>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,100 @@
.package-manager {
padding: 1em;
.package-source {
font-weight: bold;
.source-controls {
align-items: center;
display: flex;
justify-content: end;
}
}
.package-cell,
.package-source {
cursor: pointer;
}
.package-collapse-button {
color: $text-color;
}
.package-manager-table-container {
max-height: 300px;
overflow-y: auto;
}
table thead {
background-color: $card-bg;
position: sticky;
top: 0;
z-index: 1;
.button-cell {
width: 40px;
}
}
table td {
vertical-align: middle;
}
.package-version,
.package-date,
.package-name,
.package-id {
display: block;
}
.package-date,
.package-id {
color: $muted-gray;
font-size: 0.8rem;
}
.package-manager-toolbar {
display: flex;
justify-content: space-between;
div {
display: flex;
}
.btn {
margin-left: 0.5em;
}
}
.package-required-by {
color: $warning;
font-size: 0.8rem;
}
.LoadingIndicator-message {
display: inline-block;
font-size: 1rem;
margin-left: 0.5em;
margin-top: 0;
}
.source-error {
& > .fa-icon {
color: $warning;
}
.btn {
margin-left: 0.5em;
}
}
}
.package-manager-no-results {
color: $text-muted;
padding: 1em;
text-align: center;
.btn {
margin-top: 0.5em;
}
}

View File

@@ -457,21 +457,31 @@ div.react-datepicker {
.clearable-text-field,
.clearable-text-field:active,
.clearable-text-field:focus {
background-color: #394b59;
background-color: $secondary;
border: 0;
border-color: #394b59;
border-color: $secondary;
color: #fff;
}
.clearable-text-field-clear {
background-color: #394b59;
color: #bfccd6;
background-color: $secondary;
color: $muted-gray;
font-size: 0.875rem;
margin: 0.375rem 0.75rem;
padding: 0;
position: absolute;
right: 0;
z-index: 4;
&:hover,
&:focus,
&:active,
&:not(:disabled):not(.disabled):active,
&:not(:disabled):not(.disabled):active:focus {
background-color: $secondary;
border-color: transparent;
box-shadow: none;
}
}
.string-list-row .input-group {