fix(web): download client table overflow, filter alerts, dubious wording (#521)

* fix table overflow in settings -> download client

* fixed uneven line height in CellLine component

* filters/details: rename "Cancel" to "Reset form values"
Added log level and log path to Application settings.
Added column truncation to Download Client settings.

* feat: change settings debug toggle wording

* fix: typo in irc add form
This commit is contained in:
stacksmash76 2022-11-10 12:27:09 +01:00 committed by GitHub
parent f811b80413
commit b6ba23d0ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 88 additions and 49 deletions

View file

@ -115,8 +115,7 @@ const CellLine = ({ title, children }: { title: string; children?: string; }) =>
return ( return (
<div className="mt-0.5"> <div className="mt-0.5">
<span className="font-bold">{title}</span> <span className="font-bold">{title}: </span>
{": "}
<span className="whitespace-pre-wrap break-words leading-5">{children}</span> <span className="whitespace-pre-wrap break-words leading-5">{children}</span>
</div> </div>
); );

View file

@ -1,11 +1,14 @@
import { FC } from "react"; import { FC } from "react";
import { SettingsContext } from "../utils/Context";
interface DebugProps { interface DebugProps {
values: unknown; values: unknown;
} }
const DEBUG: FC<DebugProps> = ({ values }) => { const DEBUG: FC<DebugProps> = ({ values }) => {
if (process.env.NODE_ENV !== "development") { const settings = SettingsContext.useValue();
if (process.env.NODE_ENV !== "development" || !settings.debug) {
return null; return null;
} }

View file

@ -163,7 +163,7 @@ export function IrcNetworkAddForm({ isOpen, toggle }: AddFormProps) {
> >
{(values) => ( {(values) => (
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0"> <div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
<div className="flex justify-center dark:bg-red-300 text-sm font-bold text-center p-4 py-8 dark:text-red-800"><span className="flex"><ExclamationTriangleIcon className="mr-2 h-6 w-6" /> ADD NETWORKS VIA INDEXERS! ONLY USE THIS IS YOU DELETED NETWORKS</span></div> <div className="flex justify-center dark:bg-red-300 text-sm font-bold text-center p-4 py-8 dark:text-red-800"><span className="flex"><ExclamationTriangleIcon className="mr-2 h-6 w-6" /> ADD NETWORKS VIA INDEXERS! ONLY USE THIS IF YOU DELETED NETWORKS</span></div>
<TextFieldWide <TextFieldWide
name="name" name="name"

View file

@ -80,7 +80,7 @@ function Table({ columns, data }: TableProps) {
// Render the UI for your table // Render the UI for your table
return ( return (
<div className="inline-block min-w-full mt-4 mb-2 align-middle"> <div className="inline-block min-w-full mt-4 mb-2 align-middle">
<div className="bg-white shadow-lg dark:bg-gray-800 rounded-md rounded-md overflow-auto"> <div className="bg-white shadow-lg dark:bg-gray-800 rounded-md overflow-auto">
<table {...getTableProps()} className="min-w-full divide-y divide-gray-200 dark:divide-gray-700"> <table {...getTableProps()} className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead className="bg-gray-50 dark:bg-gray-800"> <thead className="bg-gray-50 dark:bg-gray-800">
{headerGroups.map((headerGroup) => { {headerGroups.map((headerGroup) => {

View file

@ -108,17 +108,22 @@ const FormButtonsGroup = ({ values, deleteAction, reset }: FormButtonsGroupProps
className="inline-flex items-center justify-center px-4 py-2 rounded-md text-red-700 dark:text-red-500 light:bg-red-100 light:hover:bg-red-200 dark:hover:text-red-400 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:text-sm" className="inline-flex items-center justify-center px-4 py-2 rounded-md text-red-700 dark:text-red-500 light:bg-red-100 light:hover:bg-red-200 dark:hover:text-red-400 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:text-sm"
onClick={toggleDeleteModal} onClick={toggleDeleteModal}
> >
Remove Remove
</button> </button>
<div> <div>
{/* {dirty && <span className="mr-4 text-sm text-gray-500">Unsaved changes..</span>} */} {/* {dirty && <span className="mr-4 text-sm text-gray-500">Unsaved changes..</span>} */}
<button <button
type="button" type="button"
className="light:bg-white light:border light:border-gray-300 rounded-md py-2 px-4 inline-flex justify-center text-sm font-medium text-gray-700 dark:text-gray-500 light:hover:bg-gray-50 dark:hover:text-gray-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" className="bg-white dark:bg-gray-700 py-2 px-4 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:focus:ring-blue-500"
onClick={reset} onClick={(e) => {
e.preventDefault();
reset();
toast.custom((t) => <Toast type="success" body="Reset all filter values." t={t}/>);
}}
> >
Cancel Reset form values
</button> </button>
<button <button
type="submit" type="submit"
@ -292,10 +297,9 @@ export default function FilterDetails() {
<Route index element={<General />} /> <Route index element={<General />} />
<Route path="movies-tv" element={<MoviesTv />} /> <Route path="movies-tv" element={<MoviesTv />} />
<Route path="music" element={<Music />} /> <Route path="music" element={<Music />} />
<Route path="advanced" element={<Advanced />} /> <Route path="advanced" element={<Advanced values={values} />} />
<Route path="external" element={<External />} /> <Route path="external" element={<External />} />
<Route path="actions" element={<FilterActions filter={filter} values={values} />} <Route path="actions" element={<FilterActions filter={filter} values={values} />} />
/>
</Routes> </Routes>
<FormButtonsGroup values={values} deleteAction={deleteAction} dirty={dirty} reset={resetForm} /> <FormButtonsGroup values={values} deleteAction={deleteAction} dirty={dirty} reset={resetForm} />
<DEBUG values={values} /> <DEBUG values={values} />
@ -452,7 +456,11 @@ export function Music() {
); );
} }
export function Advanced() { interface AdvancedProps {
values: FormikValues;
}
export function Advanced({ values }: AdvancedProps) {
return ( return (
<div> <div>
<CollapsableSection defaultOpen={true} title="Releases" subtitle="Match only certain release names and/or ignore other release names"> <CollapsableSection defaultOpen={true} title="Releases" subtitle="Match only certain release names and/or ignore other release names">
@ -461,6 +469,24 @@ export function Advanced() {
<TextField name="match_releases" label="Match releases" columns={6} placeholder="eg. *some?movie*,*some?show*s01*" /> <TextField name="match_releases" label="Match releases" columns={6} placeholder="eg. *some?movie*,*some?show*s01*" />
<TextField name="except_releases" label="Except releases" columns={6} placeholder="" /> <TextField name="except_releases" label="Except releases" columns={6} placeholder="" />
{values.match_releases ? (
<WarningAlert
alert="Ask yourself:"
text={
<>Do you have a good reason to use <strong>Match releases</strong> instead of one of the other tabs?</>
}
colors="text-cyan-700 bg-cyan-100 dark:bg-cyan-200 dark:text-cyan-800"
/>
) : null}
{values.except_releases ? (
<WarningAlert
alert="Ask yourself:"
text={
<>Do you have a good reason to use <strong>Except releases</strong> instead of one of the other tabs?</>
}
colors="text-fuchsia-700 bg-fuchsia-100 dark:bg-fuchsia-200 dark:text-fuchsia-800"
/>
) : null}
<div className="col-span-6"> <div className="col-span-6">
<SwitchGroup name="use_regex" label="Use Regex" /> <SwitchGroup name="use_regex" label="Use Regex" />
</div> </div>
@ -514,13 +540,18 @@ export function Advanced() {
} }
interface WarningAlertProps { interface WarningAlertProps {
text: string; text: string | JSX.Element;
alert?: string;
colors?: string;
} }
function WarningAlert({ text }: WarningAlertProps) { function WarningAlert({ text, alert, colors }: WarningAlertProps) {
return ( return (
<div <div
className="col-span-12 flex p-4 text-sm text-yellow-700 bg-yellow-100 rounded-lg dark:bg-yellow-200 dark:text-yellow-800" className={classNames(
"col-span-12 flex p-4 text-sm rounded-lg",
colors ?? "text-yellow-700 bg-yellow-100 dark:bg-yellow-200 dark:text-yellow-800"
)}
role="alert"> role="alert">
<svg aria-hidden="true" className="flex-shrink-0 inline w-5 h-5 mr-3" fill="currentColor" <svg aria-hidden="true" className="flex-shrink-0 inline w-5 h-5 mr-3" fill="currentColor"
viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
@ -530,7 +561,8 @@ function WarningAlert({ text }: WarningAlertProps) {
</svg> </svg>
<span className="sr-only">Info</span> <span className="sr-only">Info</span>
<div> <div>
<span className="font-bold">Warning!</span> {text} <span className="font-bold">{alert ?? "Warning!"}</span>
{" "}{text}
</div> </div>
</div> </div>
); );

View file

@ -3,6 +3,26 @@ import { APIClient } from "../../api/APIClient";
import { Checkbox } from "../../components/Checkbox"; import { Checkbox } from "../../components/Checkbox";
import { SettingsContext } from "../../utils/Context"; import { SettingsContext } from "../../utils/Context";
interface RowItemProps {
label: string;
value?: string;
title?: string;
}
const RowItem = ({ label, value, title }: RowItemProps) => {
if (!value)
return null;
return (
<div className="py-4 sm:py-5 sm:grid sm:grid-cols-4 sm:gap-4 sm:px-6">
<dt className="font-medium text-gray-500 dark:text-white" title={title}>{label}:</dt>
<dd className="mt-1 text-gray-900 dark:text-white sm:mt-0 sm:col-span-2 break-all">
{value}
</dd>
</div>
);
};
function ApplicationSettings() { function ApplicationSettings() {
const [settings, setSettings] = SettingsContext.use(); const [settings, setSettings] = SettingsContext.use();
@ -31,7 +51,7 @@ function ApplicationSettings() {
<div className="mt-6 grid grid-cols-12 gap-6"> <div className="mt-6 grid grid-cols-12 gap-6">
<div className="col-span-6 sm:col-span-4"> <div className="col-span-6 sm:col-span-4">
<label htmlFor="host" className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide"> <label htmlFor="host" className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
Host Host
</label> </label>
<input <input
type="text" type="text"
@ -45,7 +65,7 @@ function ApplicationSettings() {
<div className="col-span-6 sm:col-span-4"> <div className="col-span-6 sm:col-span-4">
<label htmlFor="port" className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide"> <label htmlFor="port" className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
Port Port
</label> </label>
<input <input
type="text" type="text"
@ -59,7 +79,7 @@ function ApplicationSettings() {
<div className="col-span-6 sm:col-span-4"> <div className="col-span-6 sm:col-span-4">
<label htmlFor="base_url" className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide"> <label htmlFor="base_url" className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
Base url Base url
</label> </label>
<input <input
type="text" type="text"
@ -78,33 +98,18 @@ function ApplicationSettings() {
<div className="divide-y divide-gray-200 dark:divide-gray-700"> <div className="divide-y divide-gray-200 dark:divide-gray-700">
<div className="px-4 py-5 sm:p-0"> <div className="px-4 py-5 sm:p-0">
<dl className="sm:divide-y divide-gray-200 dark:divide-gray-700"> <dl className="sm:divide-y divide-gray-200 dark:divide-gray-700">
{data?.version ? ( <RowItem label="Version" value={data?.version} />
<div className="py-4 sm:py-5 sm:grid sm:grid-cols-4 sm:gap-4 sm:px-6"> <RowItem label="Commit" value={data?.commit} />
<dt className="font-medium text-gray-500 dark:text-white">Version:</dt> <RowItem label="Build date" value={data?.date} />
<dd className="mt-1 text-gray-900 dark:text-white sm:mt-0 sm:col-span-2 break-all"> <RowItem label="Log path" value={data?.log_path} title="Set in config.toml" />
{data?.version} <RowItem label="Log level" value={data?.log_level} title="Set in config.toml" />
</dd>
</div>
) : null}
{data?.commit ? (
<div className="py-4 sm:py-5 sm:grid sm:grid-cols-4 sm:gap-4 sm:px-6">
<dt className="font-medium text-gray-500 dark:text-white">Commit:</dt>
<dd className="mt-1 text-gray-900 dark:text-white sm:mt-0 sm:col-span-2 break-all">{data.commit}</dd>
</div>
) : null}
{data?.date ? (
<div className="py-4 sm:py-5 sm:grid sm:grid-cols-4 sm:gap-4 sm:px-6">
<dt className="font-medium text-gray-500 dark:text-white">Date:</dt>
<dd className="mt-1 text-gray-900 dark:text-white sm:mt-0 sm:col-span-2 break-all">{data?.date}</dd>
</div>
) : null}
</dl> </dl>
</div> </div>
<ul className="divide-y divide-gray-200 dark:divide-gray-700"> <ul className="divide-y divide-gray-200 dark:divide-gray-700">
<div className="px-4 sm:px-6 py-1"> <div className="px-4 sm:px-6 py-1">
<Checkbox <Checkbox
label="Debug" label="Debug mode"
description="Enable debug mode to get more logs." description="Frontend only. To change log level for backend, update config.toml"
value={settings.debug} value={settings.debug}
setValue={(newValue: boolean) => setSettings({ setValue={(newValue: boolean) => setSettings({
...settings, ...settings,

View file

@ -61,9 +61,9 @@ function DownloadClientSettingsListItem({ client, idx }: DLSettingsItemProps) {
/> />
</Switch> </Switch>
</td> </td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white">{client.name}</td> <td className="px-6 py-4 whitespace-nowrap text-sm truncate max-w-sm font-medium text-gray-900 dark:text-white">{client.name}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">{client.host}</td> <td className="px-6 py-4 whitespace-nowrap text-sm truncate max-w-sm text-gray-500 dark:text-gray-400">{client.host}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">{DownloadClientTypeNameMap[client.type]}</td> <td className="px-6 py-4 whitespace-nowrap text-sm truncate max-w-sm text-gray-500 dark:text-gray-400">{DownloadClientTypeNameMap[client.type]}</td>
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"> <td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<span className="text-blue-600 dark:text-gray-300 hover:text-blue-900 cursor-pointer" onClick={toggleUpdateClient}> <span className="text-blue-600 dark:text-gray-300 hover:text-blue-900 cursor-pointer" onClick={toggleUpdateClient}>
Edit Edit
@ -91,8 +91,8 @@ function DownloadClientSettings() {
<DownloadClientAddForm isOpen={addClientIsOpen} toggle={toggleAddClient} /> <DownloadClientAddForm isOpen={addClientIsOpen} toggle={toggleAddClient} />
<div className="py-6 px-4 sm:p-6 lg:pb-8"> <div className="py-6 px-2 lg:pb-8">
<div className="-ml-4 -mt-4 flex justify-between items-center flex-wrap sm:flex-nowrap"> <div className="px-4 -ml-4 -mt-4 flex justify-between items-center flex-wrap sm:flex-nowrap">
<div className="ml-4 mt-4"> <div className="ml-4 mt-4">
<h3 className="text-lg leading-6 font-medium text-gray-900 dark:text-white">Clients</h3> <h3 className="text-lg leading-6 font-medium text-gray-900 dark:text-white">Clients</h3>
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400"> <p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
@ -112,8 +112,8 @@ function DownloadClientSettings() {
<div className="flex flex-col mt-6"> <div className="flex flex-col mt-6">
{data && data.length > 0 ? {data && data.length > 0 ?
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"> <div className="-my-2 overflow-x-auto">
<div className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8"> <div className="py-2 align-middle inline-block min-w-full">
<div className="light:shadow overflow-hidden light:border-b light:border-gray-200 sm:rounded-lg"> <div className="light:shadow overflow-hidden light:border-b light:border-gray-200 sm:rounded-lg">
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700"> <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead className="light:bg-gray-50"> <thead className="light:bg-gray-50">