mirror of
https://github.com/idanoo/autobrr
synced 2025-07-25 17:59:14 +00:00
feat: dark mode (#32)
This commit is contained in:
parent
974ca95d80
commit
66048c5533
49 changed files with 1736 additions and 1992 deletions
|
@ -17,7 +17,7 @@ export default function Base() {
|
|||
|
||||
return (
|
||||
<div className="">
|
||||
<Disclosure as="nav" className="bg-gray-800 pb-48">
|
||||
<Disclosure as="nav" className="bg-gray-900 pb-48">
|
||||
{({ open }) => (
|
||||
<>
|
||||
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||
|
@ -40,11 +40,34 @@ export default function Base() {
|
|||
<div className="flex items-baseline space-x-4">
|
||||
{nav.map((item, itemIdx) =>
|
||||
<NavLink
|
||||
key={itemIdx}
|
||||
key={item.name + itemIdx}
|
||||
to={item.path}
|
||||
exact={true}
|
||||
activeClassName="bg-gray-900 text-white "
|
||||
className="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium"
|
||||
strict={true}
|
||||
isActive={(match, location) => {
|
||||
if (match?.url === "/" && item.path === "/" && location.pathname === "/") {
|
||||
return true
|
||||
}
|
||||
|
||||
// if (item.path ==="/" && location.pathname ==="/") {
|
||||
// console.log("match base");
|
||||
|
||||
// return true
|
||||
// }
|
||||
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (match.url === "/") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}}
|
||||
activeClassName="bg-gray-900 dark:bg-gray-700 text-white "
|
||||
className={classNames(
|
||||
"text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium"
|
||||
)}
|
||||
>
|
||||
{item.name}
|
||||
</NavLink>
|
||||
|
@ -59,7 +82,7 @@ export default function Base() {
|
|||
<>
|
||||
<div>
|
||||
<Menu.Button
|
||||
className="max-w-xs bg-gray-800 rounded-full flex items-center text-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white">
|
||||
className="max-w-xs rounded-full flex items-center text-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white">
|
||||
<span
|
||||
className="hidden text-gray-300 text-sm font-medium sm:block">
|
||||
<span className="sr-only">Open user menu for </span>User
|
||||
|
@ -82,15 +105,15 @@ export default function Base() {
|
|||
>
|
||||
<Menu.Items
|
||||
static
|
||||
className="origin-top-right absolute right-0 mt-2 w-48 z-10 rounded-md shadow-lg py-1 bg-white ring-1 ring-black ring-opacity-5 focus:outline-none"
|
||||
className="origin-top-right absolute right-0 mt-2 w-48 z-10 rounded-md shadow-lg py-1 bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 focus:outline-none"
|
||||
>
|
||||
<Menu.Item>
|
||||
{({ active }) => (
|
||||
<Link
|
||||
to="settings"
|
||||
className={classNames(
|
||||
active ? 'bg-gray-100' : '',
|
||||
'block px-4 py-2 text-sm text-gray-700'
|
||||
active ? 'bg-gray-100 dark:bg-gray-600' : '',
|
||||
'block px-4 py-2 text-sm text-gray-700 dark:text-gray-200'
|
||||
)}
|
||||
>
|
||||
Settings
|
||||
|
@ -102,8 +125,8 @@ export default function Base() {
|
|||
<Link
|
||||
to="/logout"
|
||||
className={classNames(
|
||||
active ? 'bg-gray-100' : '',
|
||||
'block px-4 py-2 text-sm text-gray-700'
|
||||
active ? 'bg-gray-100 dark:bg-gray-600' : '',
|
||||
'block px-4 py-2 text-sm text-gray-700 dark:text-gray-200'
|
||||
)}
|
||||
>
|
||||
Logout
|
||||
|
@ -138,7 +161,6 @@ export default function Base() {
|
|||
{nav.map((item, itemIdx) =>
|
||||
itemIdx === 0 ? (
|
||||
<Fragment key={item.path}>
|
||||
{/* Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" */}
|
||||
<Link to={item.path}
|
||||
className="bg-gray-900 text-white block px-3 py-2 rounded-md text-base font-medium">
|
||||
{item.name}
|
||||
|
|
|
@ -7,12 +7,10 @@ export function Dashboard() {
|
|||
</div>
|
||||
</header>
|
||||
<div className="max-w-7xl mx-auto pb-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="bg-white rounded-lg shadow px-5 py-6 sm:px-6">
|
||||
<div className="border-4 border-dashed border-gray-200 rounded-lg h-96" />
|
||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow px-5 py-6 sm:px-6">
|
||||
<div className="border-4 border-dashed border-gray-200 dark:border-gray-700 rounded-lg h-96" />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -38,7 +38,7 @@ export default function Logs() {
|
|||
</div>
|
||||
</header>
|
||||
<div className="max-w-7xl mx-auto pb-12 px-2 sm:px-4 lg:px-8">
|
||||
<div className="bg-white rounded-lg shadow px-2 sm:px-4 py-3 sm:py-4">
|
||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow px-2 sm:px-4 py-3 sm:py-4">
|
||||
<div className=" overflow-y-auto p-2 rounded-lg h-96 bg-gray-900">
|
||||
{logs.map((a, idx) => (
|
||||
<p key={idx}>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import React from 'react'
|
||||
import {CogIcon, DownloadIcon, KeyIcon} from '@heroicons/react/outline'
|
||||
import {NavLink, Route, Switch as RouteSwitch, useLocation, useRouteMatch} from "react-router-dom";
|
||||
import IndexerSettings from "./settings/Indexer";
|
||||
|
@ -33,17 +32,17 @@ function SubNavLink({item, url}: any) {
|
|||
key={item.name}
|
||||
to={too}
|
||||
exact={true}
|
||||
activeClassName="bg-teal-50 border-teal-500 text-teal-700 hover:bg-teal-50 hover:text-teal-700"
|
||||
activeClassName="bg-teal-50 dark:bg-gray-700 border-teal-500 dark:border-blue-500 text-teal-700 dark:text-white hover:bg-teal-50 dark:hover:bg-gray-500 hover:text-teal-700 dark:hover:text-gray-200"
|
||||
className={classNames(
|
||||
'border-transparent text-gray-900 hover:bg-gray-50 hover:text-gray-900 group border-l-4 px-3 py-2 flex items-center text-sm font-medium'
|
||||
'border-transparent text-gray-900 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 hover:text-gray-900 dark:hover:text-gray-300 group border-l-4 px-3 py-2 flex items-center text-sm font-medium'
|
||||
)}
|
||||
aria-current={splitLocation[2] === item.href ? 'page' : undefined}
|
||||
>
|
||||
<item.icon
|
||||
className={classNames(
|
||||
splitLocation[2] === item.href
|
||||
? 'text-teal-500 group-hover:text-teal-500'
|
||||
: 'text-gray-400 group-hover:text-gray-500',
|
||||
? 'text-teal-500 dark:text-blue-600 group-hover:text-teal-500 dark:group-hover:text-blue-600'
|
||||
: 'text-gray-400 group-hover:text-gray-500 dark:group-hover:text-gray-300',
|
||||
'flex-shrink-0 -ml-1 mr-3 h-6 w-6'
|
||||
)}
|
||||
aria-hidden="true"
|
||||
|
@ -77,8 +76,8 @@ export default function Settings() {
|
|||
</header>
|
||||
|
||||
<div className="max-w-screen-xl mx-auto pb-6 px-4 sm:px-6 lg:pb-16 lg:px-8">
|
||||
<div className="bg-white rounded-lg shadow overflow-hidden">
|
||||
<div className="divide-y divide-gray-200 lg:grid lg:grid-cols-12 lg:divide-y-0 lg:divide-x">
|
||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
|
||||
<div className="divide-y divide-gray-200 dark:divide-gray-700 lg:grid lg:grid-cols-12 lg:divide-y-0 lg:divide-x">
|
||||
<SidebarNav url={url} subNavigation={subNavigation}/>
|
||||
|
||||
<RouteSwitch>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import {useMutation} from "react-query";
|
||||
import { useMutation } from "react-query";
|
||||
import APIClient from "../../api/APIClient";
|
||||
import {Form} from "react-final-form";
|
||||
import {PasswordField, TextField} from "../../components/inputs";
|
||||
import {useRecoilState} from "recoil";
|
||||
import {isLoggedIn} from "../../state/state";
|
||||
import {useHistory} from "react-router-dom";
|
||||
import {useEffect} from "react";
|
||||
import { Form } from "react-final-form";
|
||||
import { PasswordField, TextField } from "../../components/inputs";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { isLoggedIn } from "../../state/state";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useEffect } from "react";
|
||||
import logo from "../../logo.png"
|
||||
|
||||
interface loginData {
|
||||
|
@ -18,7 +18,7 @@ function Login() {
|
|||
let history = useHistory();
|
||||
|
||||
useEffect(() => {
|
||||
if(loggedIn) {
|
||||
if (loggedIn) {
|
||||
// setLoading(false);
|
||||
history.push('/');
|
||||
} else {
|
||||
|
@ -38,7 +38,7 @@ function Login() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
||||
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
||||
<div className="sm:mx-auto sm:w-full sm:max-w-md mb-6">
|
||||
<img
|
||||
className="mx-auto h-12 w-auto"
|
||||
|
@ -48,7 +48,7 @@ function Login() {
|
|||
</div>
|
||||
|
||||
<div className="sm:mx-auto sm:w-full sm:max-w-md">
|
||||
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
|
||||
<div className="bg-white dark:bg-gray-800 py-8 px-4 shadow sm:rounded-lg sm:px-10">
|
||||
|
||||
<Form
|
||||
initialValues={{
|
||||
|
@ -57,11 +57,11 @@ function Login() {
|
|||
}}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
{({handleSubmit, values}) => {
|
||||
{({ handleSubmit, values }) => {
|
||||
return (
|
||||
<form className="space-y-6" onSubmit={handleSubmit}>
|
||||
<TextField name="username" label="Username" autoComplete="username" />
|
||||
<PasswordField name="password" label="password" autoComplete="current-password"/>
|
||||
<PasswordField name="password" label="password" autoComplete="current-password" />
|
||||
|
||||
{/*<div className="flex items-center justify-between">*/}
|
||||
{/* <div className="flex items-center">*/}
|
||||
|
@ -86,7 +86,7 @@ function Login() {
|
|||
<div>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 dark:bg-blue-600 hover:bg-indigo-700 dark:hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-blue-500"
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
|
|
|
@ -9,18 +9,18 @@ function Logout() {
|
|||
const [loggedIn, setLoggedIn] = useRecoilState(isLoggedIn);
|
||||
let history = useHistory();
|
||||
|
||||
const [_, removeCookie] = useCookies(['user_session']);
|
||||
const [,, removeCookie] = useCookies(['user_session']);
|
||||
|
||||
useEffect(() => {
|
||||
APIClient.auth.logout().then(r => {
|
||||
removeCookie("user_session", "")
|
||||
removeCookie("user_session")
|
||||
setLoggedIn(false);
|
||||
history.push('/login');
|
||||
})
|
||||
}, [loggedIn, history, removeCookie, setLoggedIn])
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
||||
<div className="min-h-screen bg-gray-50 dark:bg-gray-800 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
||||
<p>Logged out</p>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Fragment, useRef } from "react";
|
||||
import { Fragment, useRef } from "react";
|
||||
import { Dialog, Transition, Switch as SwitchBasic } from "@headlessui/react";
|
||||
import { ChevronDownIcon, ChevronRightIcon, ExclamationIcon, } from '@heroicons/react/solid'
|
||||
import { EmptyListState } from "../../components/EmptyListState";
|
||||
|
@ -55,9 +55,9 @@ function TabNavLink({ item, url }: any) {
|
|||
key={item.name}
|
||||
to={too}
|
||||
exact={true}
|
||||
activeClassName="border-purple-600 text-purple-600"
|
||||
activeClassName="border-purple-600 dark:border-blue-500 text-purple-600 dark:text-white"
|
||||
className={classNames(
|
||||
'border-transparent text-gray-500 hover:text-purple-600 hover:border-purple-600 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm'
|
||||
'border-transparent text-gray-500 hover:text-purple-600 dark:hover:text-white hover:border-purple-600 dark:hover:border-blue-500 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm'
|
||||
)}
|
||||
aria-current={splitLocation[2] === item.href ? 'page' : undefined}
|
||||
>
|
||||
|
@ -72,7 +72,7 @@ const FormButtonsGroup = ({ deleteAction, reset, dirty }: any) => {
|
|||
const cancelButtonRef = useRef(null)
|
||||
|
||||
return (
|
||||
<div className="pt-6 divide-y divide-gray-200">
|
||||
<div className="pt-6 divide-y divide-gray-200 dark:divide-gray-700">
|
||||
|
||||
<Transition.Root show={deleteModalIsOpen} as={Fragment}>
|
||||
<Dialog
|
||||
|
@ -97,7 +97,6 @@ const FormButtonsGroup = ({ deleteAction, reset, dirty }: any) => {
|
|||
<Dialog.Overlay className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
|
||||
</Transition.Child>
|
||||
|
||||
{/* This element is to trick the browser into centering the modal contents. */}
|
||||
<span className="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">
|
||||
​
|
||||
</span>
|
||||
|
@ -142,7 +141,7 @@ const FormButtonsGroup = ({ deleteAction, reset, dirty }: any) => {
|
|||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
className="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 light:bg-white text-base font-medium text-gray-700 dark:text-red-500 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
onClick={toggleDeleteModal}
|
||||
ref={cancelButtonRef}
|
||||
>
|
||||
|
@ -158,7 +157,7 @@ const FormButtonsGroup = ({ deleteAction, reset, dirty }: any) => {
|
|||
<div className="mt-4 pt-4 flex justify-between">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-md text-red-700 bg-red-100 hover:bg-red-200 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 border border-transparent font-medium 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}
|
||||
>
|
||||
Remove
|
||||
|
@ -168,14 +167,14 @@ const FormButtonsGroup = ({ deleteAction, reset, dirty }: any) => {
|
|||
{/* {dirty && <span className="mr-4 text-sm text-gray-500">Unsaved changes..</span>} */}
|
||||
<button
|
||||
type="button"
|
||||
className="bg-white border border-gray-300 rounded-md shadow-sm py-2 px-4 inline-flex justify-center text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-light-blue-500"
|
||||
className="light:bg-white light:border light:border-gray-300 rounded-md shadow-sm 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"
|
||||
onClick={reset}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="ml-4 relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
className="ml-4 relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 dark:bg-blue-600 hover:bg-indigo-700 dark:hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
|
@ -266,7 +265,7 @@ export default function FilterDetails() {
|
|||
</div>
|
||||
</header>
|
||||
<div className="max-w-7xl mx-auto pb-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="bg-white rounded-lg shadow">
|
||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow">
|
||||
<div className="relative mx-auto md:px-6 xl:px-4">
|
||||
<div className="px-4 sm:px-6 md:px-0">
|
||||
<div className="pt-2 pb-6">
|
||||
|
@ -278,7 +277,7 @@ export default function FilterDetails() {
|
|||
<select
|
||||
id="selected-tab"
|
||||
name="selected-tab"
|
||||
className="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm rounded-md"
|
||||
className="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-700 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm rounded-md"
|
||||
>
|
||||
{tabs.map((tab) => (
|
||||
<option key={tab.name} onClick={(e) => handleMobileNav(e, tab.href)}>
|
||||
|
@ -288,7 +287,7 @@ export default function FilterDetails() {
|
|||
</select>
|
||||
</div>
|
||||
<div className="hidden sm:block">
|
||||
<div className="border-b border-gray-200">
|
||||
<div className="border-b border-gray-200 dark:border-gray-700">
|
||||
<nav className="-mb-px flex space-x-8">
|
||||
{tabs.map((tab) => (
|
||||
<TabNavLink item={tab} url={url} key={tab.href} />
|
||||
|
@ -385,7 +384,7 @@ function General({ indexers }: GeneralProps) {
|
|||
<TextField name="name" label="Filter name" columns={6} placeholder="eg. Filter 1" />
|
||||
|
||||
<div className="col-span-6">
|
||||
<label htmlFor="indexers" className="block text-xs font-bold text-gray-700 uppercase tracking-wide">
|
||||
<label htmlFor="indexers" className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||
Indexers
|
||||
</label>
|
||||
|
||||
|
@ -409,7 +408,7 @@ function General({ indexers }: GeneralProps) {
|
|||
isClearable={true}
|
||||
isMulti={true}
|
||||
placeholder="Choose indexers"
|
||||
className="mt-2 block w-full focus:outline-none focus:ring-light-blue-500 focus:border-light-blue-500 sm:text-sm"
|
||||
className="mt-2 block w-full focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
||||
options={opts}
|
||||
/>
|
||||
)
|
||||
|
@ -429,7 +428,7 @@ function General({ indexers }: GeneralProps) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t">
|
||||
<div className="border-t dark:border-gray-700">
|
||||
<SwitchGroup name="enabled" label="Enabled" description="Enabled or disable filter." />
|
||||
</div>
|
||||
|
||||
|
@ -485,11 +484,11 @@ function Advanced() {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<div className="mt-6 lg:pb-8 border-b border-gray-200">
|
||||
<div className="mt-6 lg:pb-8 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="flex justify-between items-center cursor-pointer" onClick={toggleReleases}>
|
||||
<div className="-ml-2 -mt-2 flex flex-wrap items-baseline">
|
||||
<h3 className="ml-2 mt-2 text-lg leading-6 font-medium text-gray-900">Releases</h3>
|
||||
<p className="ml-2 mt-1 text-sm text-gray-500 truncate">Match or ignore</p>
|
||||
<h3 className="ml-2 mt-2 text-lg leading-6 font-medium text-gray-900 dark:text-gray-200">Releases</h3>
|
||||
<p className="ml-2 mt-1 text-sm text-gray-500 dark:text-gray-400 truncate">Match or ignore</p>
|
||||
</div>
|
||||
<div className="mt-3 sm:mt-0 sm:ml-4">
|
||||
<button
|
||||
|
@ -508,11 +507,11 @@ function Advanced() {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-6 lg:pb-8 border-b border-gray-200">
|
||||
<div className="mt-6 lg:pb-8 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="flex justify-between items-center cursor-pointer" onClick={toggleGroups}>
|
||||
<div className="-ml-2 -mt-2 flex flex-wrap items-baseline">
|
||||
<h3 className="ml-2 mt-2 text-lg leading-6 font-medium text-gray-900">Groups</h3>
|
||||
<p className="ml-2 mt-1 text-sm text-gray-500 truncate">Match or ignore</p>
|
||||
<h3 className="ml-2 mt-2 text-lg leading-6 font-medium text-gray-900 dark:text-gray-200">Groups</h3>
|
||||
<p className="ml-2 mt-1 text-sm text-gray-500 dark:text-gray-400 truncate">Match or ignore</p>
|
||||
</div>
|
||||
<div className="mt-3 sm:mt-0 sm:ml-4">
|
||||
<button
|
||||
|
@ -531,11 +530,11 @@ function Advanced() {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-6 lg:pb-8 border-b border-gray-200">
|
||||
<div className="mt-6 lg:pb-8 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="flex justify-between items-center cursor-pointer" onClick={toggleCategories}>
|
||||
<div className="-ml-2 -mt-2 flex flex-wrap items-baseline">
|
||||
<h3 className="ml-2 mt-2 text-lg leading-6 font-medium text-gray-900">Categories and tags</h3>
|
||||
<p className="ml-2 mt-1 text-sm text-gray-500 truncate">Match or ignore categories or tags</p>
|
||||
<h3 className="ml-2 mt-2 text-lg leading-6 font-medium text-gray-900 dark:text-gray-200">Categories and tags</h3>
|
||||
<p className="ml-2 mt-1 text-sm text-gray-500 dark:text-gray-400 truncate">Match or ignore categories or tags</p>
|
||||
</div>
|
||||
<div className="mt-3 sm:mt-0 sm:ml-4">
|
||||
<button
|
||||
|
@ -557,11 +556,11 @@ function Advanced() {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-6 lg:pb-8 border-b border-gray-200">
|
||||
<div className="mt-6 lg:pb-8 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="flex justify-between items-center cursor-pointer" onClick={toggleUploaders}>
|
||||
<div className="-ml-2 -mt-2 flex flex-wrap items-baseline">
|
||||
<h3 className="ml-2 mt-2 text-lg leading-6 font-medium text-gray-900">Uploaders</h3>
|
||||
<p className="ml-2 mt-1 text-sm text-gray-500 truncate">Match or ignore uploaders</p>
|
||||
<h3 className="ml-2 mt-2 text-lg leading-6 font-medium text-gray-900 dark:text-gray-200">Uploaders</h3>
|
||||
<p className="ml-2 mt-1 text-sm text-gray-500 dark:text-gray-400 truncate">Match or ignore uploaders</p>
|
||||
</div>
|
||||
<div className="mt-3 sm:mt-0 sm:ml-4">
|
||||
<button
|
||||
|
@ -580,11 +579,11 @@ function Advanced() {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-6 lg:pb-8 border-b border-gray-200">
|
||||
<div className="mt-6 lg:pb-8 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="flex justify-between items-center cursor-pointer" onClick={toggleFreeleech}>
|
||||
<div className="-ml-2 -mt-2 flex flex-wrap items-baseline">
|
||||
<h3 className="ml-2 mt-2 text-lg leading-6 font-medium text-gray-900">Freeleech</h3>
|
||||
<p className="ml-2 mt-1 text-sm text-gray-500 truncate">Match only freeleech and freeleech percent</p>
|
||||
<h3 className="ml-2 mt-2 text-lg leading-6 font-medium text-gray-900 dark:text-gray-200">Freeleech</h3>
|
||||
<p className="ml-2 mt-1 text-sm text-gray-500 dark:text-gray-400 truncate">Match only freeleech and freeleech percent</p>
|
||||
</div>
|
||||
<div className="mt-3 sm:mt-0 sm:ml-4">
|
||||
<button
|
||||
|
@ -615,8 +614,6 @@ interface FilterActionsProps {
|
|||
}
|
||||
|
||||
function FilterActions({ filter, values }: FilterActionsProps) {
|
||||
// const [addActionIsOpen, toggleAddAction] = useToggle(false)
|
||||
|
||||
const { data } = useQuery<DownloadClient[], Error>('downloadClients', APIClient.download_clients.getAll,
|
||||
{
|
||||
refetchOnWindowFocus: false
|
||||
|
@ -644,36 +641,35 @@ function FilterActions({ filter, values }: FilterActionsProps) {
|
|||
|
||||
return (
|
||||
<div className="mt-10">
|
||||
{/* {addActionIsOpen &&
|
||||
<FilterActionAddForm filter={filter} clients={data || []} isOpen={addActionIsOpen} toggle={toggleAddAction} />
|
||||
} */}
|
||||
<FieldArray name="actions">
|
||||
{({ remove, push }) => (
|
||||
<Fragment>
|
||||
<div className="-ml-4 -mt-4 mb-6 flex justify-between items-center flex-wrap sm:flex-nowrap">
|
||||
<div className="ml-4 mt-4">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900">Actions</h3>
|
||||
<p className="mt-1 text-sm text-gray-500">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900 dark:text-gray-200">Actions</h3>
|
||||
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||
Add to download clients or run custom commands.
|
||||
</p>
|
||||
</div>
|
||||
<div className="ml-4 mt-4 flex-shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
className="relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
className="relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 dark:bg-blue-600 hover:bg-indigo-700 dark:hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-blue-500"
|
||||
onClick={() => push(newAction)}
|
||||
>
|
||||
Add new
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-white shadow sm:rounded-md">
|
||||
|
||||
<div className="light:bg-white dark:bg-gray-800 light:shadow sm:rounded-md">
|
||||
{values.actions.length > 0 ?
|
||||
values.actions.map((action: any, index: any) => (
|
||||
<ul className="divide-y divide-gray-200" key={index}>
|
||||
<ul className="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
{values.actions.map((action: any, index: any) => (
|
||||
<FilterActionsItem action={action} clients={data!} idx={index} remove={remove} />
|
||||
</ul>
|
||||
)) : <EmptyListState text="No actions yet!" />
|
||||
))}
|
||||
</ul>
|
||||
: <EmptyListState text="No actions yet!" />
|
||||
}
|
||||
</div>
|
||||
</Fragment>
|
||||
|
@ -867,8 +863,8 @@ function FilterActionsItem({ action, clients, idx, remove }: FilterActionsItemPr
|
|||
<li>
|
||||
<div
|
||||
className={classNames(
|
||||
idx % 2 === 0 ? "bg-white" : "bg-gray-50",
|
||||
"flex items-center sm:px-6 hover:bg-gray-50"
|
||||
idx % 2 === 0 ? "bg-white dark:bg-gray-800" : "bg-gray-50 dark:bg-gray-700",
|
||||
"flex items-center sm:px-6 hover:bg-gray-50 dark:hover:bg-gray-600"
|
||||
)}
|
||||
>
|
||||
<Field name={`actions.${idx}.enabled`} type="checkbox">
|
||||
|
@ -885,8 +881,8 @@ function FilterActionsItem({ action, clients, idx, remove }: FilterActionsItemPr
|
|||
setFieldValue(field?.name ?? '', value)
|
||||
}}
|
||||
className={classNames(
|
||||
field.value ? 'bg-teal-500' : 'bg-gray-200',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-light-blue-500'
|
||||
field.value ? 'bg-teal-500 dark:bg-blue-500' : 'bg-gray-200 dark:bg-gray-600',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500'
|
||||
)}
|
||||
>
|
||||
<span className="sr-only">toggle enabled</span>
|
||||
|
@ -905,14 +901,14 @@ function FilterActionsItem({ action, clients, idx, remove }: FilterActionsItemPr
|
|||
<div className="min-w-0 flex-1 sm:flex sm:items-center sm:justify-between">
|
||||
<div className="truncate">
|
||||
<div className="flex text-sm">
|
||||
<p className="ml-4 font-medium text-indigo-600 truncate">
|
||||
<p className="ml-4 font-medium text-indigo-600 dark:text-gray-100 truncate">
|
||||
{action.name}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 flex-shrink-0 sm:mt-0 sm:ml-5">
|
||||
<div className="flex overflow-hidden -space-x-1">
|
||||
<span className="text-sm font-normal text-gray-500">
|
||||
<span className="text-sm font-normal text-gray-500 dark:text-gray-400">
|
||||
{ActionTypeNameMap[action.type]}
|
||||
</span>
|
||||
</div>
|
||||
|
@ -928,7 +924,7 @@ function FilterActionsItem({ action, clients, idx, remove }: FilterActionsItemPr
|
|||
|
||||
</div>
|
||||
{edit && (
|
||||
<div className="px-4 py-4 flex items-center sm:px-6">
|
||||
<div className="px-4 py-4 flex items-center sm:px-6 border dark:border-gray-600">
|
||||
<Transition.Root show={deleteModalIsOpen} as={Fragment}>
|
||||
<Dialog
|
||||
as="div"
|
||||
|
@ -968,7 +964,7 @@ function FilterActionsItem({ action, clients, idx, remove }: FilterActionsItemPr
|
|||
<div className="mt-4 pt-4 flex justify-between">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center py-2 border border-transparent font-medium rounded-md text-red-700 hover:text-red-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:text-sm"
|
||||
className="inline-flex items-center justify-center py-2 border border-transparent font-medium rounded-md text-red-700 dark:text-red-500 hover:text-red-500 dark:hover:text-red-400 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:text-sm"
|
||||
onClick={toggleDeleteModal}
|
||||
>
|
||||
Remove
|
||||
|
@ -977,7 +973,7 @@ function FilterActionsItem({ action, clients, idx, remove }: FilterActionsItemPr
|
|||
<div>
|
||||
<button
|
||||
type="button"
|
||||
className="bg-white border border-gray-300 rounded-md shadow-sm py-2 px-4 inline-flex justify-center text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-light-blue-500"
|
||||
className="light:bg-white light:border light:border-gray-300 rounded-md shadow-sm 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"
|
||||
onClick={toggleEdit}
|
||||
>
|
||||
Close
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Fragment } from "react";
|
||||
import { Fragment } from "react";
|
||||
import { Transition, Listbox } from "@headlessui/react";
|
||||
import { CheckIcon, SelectorIcon } from '@heroicons/react/solid';
|
||||
import { Action, DownloadClient } from "../../../domain/interfaces";
|
||||
|
@ -21,17 +21,17 @@ export default function DownloadClientSelect({
|
|||
field,
|
||||
form: { setFieldValue },
|
||||
}: any) => (
|
||||
<Listbox
|
||||
value={field.value}
|
||||
<Listbox
|
||||
value={field.value}
|
||||
onChange={(value: any) => setFieldValue(field?.name, value)}
|
||||
>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Listbox.Label className="block text-xs font-bold text-gray-700 uppercase tracking-wide">
|
||||
<Listbox.Label className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||
Client
|
||||
</Listbox.Label>
|
||||
<div className="mt-2 relative">
|
||||
<Listbox.Button className="bg-white relative w-full border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
|
||||
<Listbox.Button className="bg-white dark:bg-gray-800 relative w-full border border-gray-300 dark:border-gray-700 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 dark:focus:ring-blue-500 focus:border-indigo-500 dark:focus:border-blue-500 dark:text-gray-200 sm:text-sm">
|
||||
<span className="block truncate">
|
||||
{field.value
|
||||
? clients.find((c) => c.id === field.value)!.name
|
||||
|
@ -40,7 +40,7 @@ export default function DownloadClientSelect({
|
|||
{/*<span className="block truncate">Choose a client</span>*/}
|
||||
<span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
||||
<SelectorIcon
|
||||
className="h-5 w-5 text-gray-400"
|
||||
className="h-5 w-5 text-gray-400 dark:text-gray-300"
|
||||
aria-hidden="true" />
|
||||
</span>
|
||||
</Listbox.Button>
|
||||
|
@ -54,7 +54,7 @@ export default function DownloadClientSelect({
|
|||
>
|
||||
<Listbox.Options
|
||||
static
|
||||
className="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
|
||||
className="absolute z-10 mt-1 w-full bg-white dark:bg-gray-800 shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
|
||||
>
|
||||
{clients
|
||||
.filter((c) => c.type === action.type)
|
||||
|
@ -63,8 +63,8 @@ export default function DownloadClientSelect({
|
|||
key={client.id}
|
||||
className={({ active }) => classNames(
|
||||
active
|
||||
? "text-white bg-indigo-600"
|
||||
: "text-gray-900",
|
||||
? "text-white dark:text-gray-100 bg-indigo-600 dark:bg-gray-800"
|
||||
: "text-gray-900 dark:text-gray-300",
|
||||
"cursor-default select-none relative py-2 pl-3 pr-9"
|
||||
)}
|
||||
value={client.id}
|
||||
|
@ -83,7 +83,7 @@ export default function DownloadClientSelect({
|
|||
{selected ? (
|
||||
<span
|
||||
className={classNames(
|
||||
active ? "text-white" : "text-indigo-600",
|
||||
active ? "text-white dark:text-gray-100" : "text-indigo-600 dark:text-gray-700",
|
||||
"absolute inset-y-0 right-0 flex items-center pr-4"
|
||||
)}
|
||||
>
|
||||
|
|
|
@ -24,7 +24,7 @@ const MultiSelect: React.FC<Props> = ({
|
|||
)}
|
||||
>
|
||||
<label
|
||||
className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
|
||||
className="block uppercase tracking-wide text-gray-700 dark:text-gray-200 text-xs font-bold mb-2"
|
||||
htmlFor={label}
|
||||
>
|
||||
{label}
|
||||
|
@ -34,22 +34,21 @@ const MultiSelect: React.FC<Props> = ({
|
|||
{({
|
||||
field,
|
||||
form: { setFieldValue },
|
||||
}: any) => {
|
||||
return (
|
||||
<RMSC
|
||||
{...field}
|
||||
type="select"
|
||||
options={options}
|
||||
labelledBy={name}
|
||||
value={field.value && field.value.map((item: any) => options.find((o: any) => o.value === item))}
|
||||
onChange={(values: any) => {
|
||||
let am = values && values.map((i: any) => i.value)
|
||||
}: any) => (
|
||||
<RMSC
|
||||
{...field}
|
||||
type="select"
|
||||
options={options}
|
||||
labelledBy={name}
|
||||
value={field.value && field.value.map((item: any) => options.find((o: any) => o.value === item))}
|
||||
onChange={(values: any) => {
|
||||
let am = values && values.map((i: any) => i.value)
|
||||
|
||||
setFieldValue(field.name, am)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
setFieldValue(field.name, am)
|
||||
}}
|
||||
className="dark:bg-gray-700"
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Field } from "formik";
|
||||
import React from "react";
|
||||
import { Field } from "formik";
|
||||
import { classNames } from "../../../styles/utils";
|
||||
|
||||
interface Props {
|
||||
|
@ -18,14 +18,13 @@ const NumberField: React.FC<Props> = ({
|
|||
className,
|
||||
}) => (
|
||||
<div className="col-span-12 sm:col-span-6">
|
||||
<label htmlFor={name} className="block text-sm font-medium text-gray-700">
|
||||
<label htmlFor={name} className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||
{label}
|
||||
</label>
|
||||
|
||||
<Field name={name} type="number">
|
||||
{({
|
||||
field,
|
||||
form: { touched, errors },
|
||||
meta,
|
||||
}: any) => (
|
||||
<div className="sm:col-span-2">
|
||||
|
@ -35,8 +34,8 @@ const NumberField: React.FC<Props> = ({
|
|||
className={classNames(
|
||||
meta.touched && meta.error
|
||||
? "focus:ring-red-500 focus:border-red-500 border-red-500"
|
||||
: "focus:ring-indigo-500 focus:border-indigo-500 border-gray-300",
|
||||
"block w-full shadow-sm sm:text-sm rounded-md"
|
||||
: "focus:ring-indigo-500 dark:focus:ring-blue-500 focus:border-indigo-500 dark:focus:border-blue-500 border-gray-300",
|
||||
"mt-2 block w-full dark:bg-gray-800 border border-gray-300 dark:border-gray-700 shadow-sm dark:text-gray-100 sm:text-sm rounded-md"
|
||||
)}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
|
|
|
@ -30,11 +30,11 @@ function Select({ name, label, optionDefaultText, options }: props) {
|
|||
>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Listbox.Label className="block text-xs font-bold text-gray-700 uppercase tracking-wide">
|
||||
<Listbox.Label className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||
{label}
|
||||
</Listbox.Label>
|
||||
<div className="mt-2 relative">
|
||||
<Listbox.Button className="bg-white relative w-full border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
|
||||
<Listbox.Button className="bg-white dark:bg-gray-800 relative w-full border border-gray-300 dark:border-gray-700 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 dark:focus:ring-blue-500 focus:border-indigo-500 dark:focus:border-blue-500 dark:text-gray-200 sm:text-sm">
|
||||
<span className="block truncate">
|
||||
{field.value
|
||||
? options.find((c) => c.value === field.value)!.label
|
||||
|
@ -43,7 +43,7 @@ function Select({ name, label, optionDefaultText, options }: props) {
|
|||
</span>
|
||||
<span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
||||
<SelectorIcon
|
||||
className="h-5 w-5 text-gray-400"
|
||||
className="h-5 w-5 text-gray-400 dark:text-gray-300"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</span>
|
||||
|
@ -58,7 +58,7 @@ function Select({ name, label, optionDefaultText, options }: props) {
|
|||
>
|
||||
<Listbox.Options
|
||||
static
|
||||
className="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
|
||||
className="absolute z-10 mt-1 w-full bg-white dark:bg-gray-800 shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
|
||||
>
|
||||
{options.map((opt) => (
|
||||
<Listbox.Option
|
||||
|
@ -66,8 +66,8 @@ function Select({ name, label, optionDefaultText, options }: props) {
|
|||
className={({ active }) =>
|
||||
classNames(
|
||||
active
|
||||
? "text-white bg-indigo-600"
|
||||
: "text-gray-900",
|
||||
? "text-white dark:text-gray-100 bg-indigo-600 dark:bg-gray-800"
|
||||
: "text-gray-900 dark:text-gray-300",
|
||||
"cursor-default select-none relative py-2 pl-3 pr-9"
|
||||
)
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ function Select({ name, label, optionDefaultText, options }: props) {
|
|||
{selected ? (
|
||||
<span
|
||||
className={classNames(
|
||||
active ? "text-white" : "text-indigo-600",
|
||||
active ? "text-white dark:text-gray-100" : "text-indigo-600 dark:text-gray-700",
|
||||
"absolute inset-y-0 right-0 flex items-center pr-4"
|
||||
)}
|
||||
>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { InputHTMLAttributes } from 'react'
|
||||
import { Switch as HeadlessSwitch } from '@headlessui/react'
|
||||
import { FieldInputProps, FieldMetaProps, FieldProps, FormikProps, FormikValues } from 'formik'
|
||||
import React, { InputHTMLAttributes } from 'react'
|
||||
import { classNames } from "../../../styles/utils";
|
||||
|
||||
type SwitchProps<V = any> = {
|
||||
|
@ -37,8 +37,8 @@ export const Switch: React.FC<SwitchProps> = ({
|
|||
}}
|
||||
|
||||
className={classNames(
|
||||
checked ? 'bg-teal-500' : 'bg-gray-200',
|
||||
'ml-4 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-light-blue-500'
|
||||
checked ? 'bg-teal-500 dark:bg-blue-500' : 'bg-gray-200 dark:bg-gray-600',
|
||||
'ml-4 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500'
|
||||
)}
|
||||
>
|
||||
{({ checked }) => (
|
||||
|
|
|
@ -15,12 +15,12 @@ const SwitchGroup: React.FC<Props> = ({ name, label, description, defaultValue }
|
|||
<ul className="mt-2 divide-y divide-gray-200">
|
||||
<Switch.Group as="li" className="py-4 flex items-center justify-between">
|
||||
{label && <div className="flex flex-col">
|
||||
<Switch.Label as="p" className="text-sm font-medium text-gray-900"
|
||||
<Switch.Label as="p" className="text-sm font-medium text-gray-900 dark:text-gray-100"
|
||||
passive>
|
||||
{label}
|
||||
</Switch.Label>
|
||||
{description && (
|
||||
<Switch.Description className="text-sm text-gray-500">
|
||||
<Switch.Description className="text-sm text-gray-500 dark:text-gray-400">
|
||||
{description}
|
||||
</Switch.Description>
|
||||
)}
|
||||
|
@ -41,8 +41,8 @@ const SwitchGroup: React.FC<Props> = ({ name, label, description, defaultValue }
|
|||
setFieldValue(field?.name ?? '', value)
|
||||
}}
|
||||
className={classNames(
|
||||
field.value ? 'bg-teal-500' : 'bg-gray-200',
|
||||
'ml-4 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-light-blue-500'
|
||||
field.value ? 'bg-teal-500 dark:bg-blue-500' : 'bg-gray-200',
|
||||
'ml-4 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500'
|
||||
)}
|
||||
>
|
||||
{/* <span className="sr-only">{label}</span> */}
|
||||
|
@ -68,7 +68,7 @@ const SwitchGroup: React.FC<Props> = ({ name, label, description, defaultValue }
|
|||
onChange={onChange}
|
||||
className={classNames(
|
||||
value ? 'bg-teal-500' : 'bg-gray-200',
|
||||
'ml-4 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-light-blue-500'
|
||||
'ml-4 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500'
|
||||
)}
|
||||
>
|
||||
<span className="sr-only">Use setting</span>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Field } from "formik";
|
||||
import React from "react";
|
||||
import { Field } from "formik";
|
||||
import { classNames } from "../../../styles/utils";
|
||||
|
||||
type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
||||
|
@ -20,7 +20,7 @@ const TextField: React.FC<Props> = ({ name, label, placeholder, columns, classNa
|
|||
)}
|
||||
>
|
||||
{label && (
|
||||
<label htmlFor={name} className="block text-xs font-bold text-gray-700 uppercase tracking-wide">
|
||||
<label htmlFor={name} className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
|
@ -35,7 +35,7 @@ const TextField: React.FC<Props> = ({ name, label, placeholder, columns, classNa
|
|||
id={name}
|
||||
type="text"
|
||||
autoComplete={autoComplete}
|
||||
className="mt-2 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-light-blue-500 focus:border-light-blue-500 sm:text-sm"
|
||||
className="mt-2 block w-full dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:text-gray-100 sm:text-sm"
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { Switch } from "@headlessui/react";
|
||||
import { EmptyListState } from "../../components/EmptyListState";
|
||||
|
||||
|
@ -38,7 +38,7 @@ export default function Filters() {
|
|||
<div className="flex-shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
className="relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
className="relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 dark:bg-blue-600 hover:bg-indigo-700 dark:hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-blue-500"
|
||||
onClick={toggleCreateFilter}
|
||||
>
|
||||
Add new
|
||||
|
@ -48,8 +48,8 @@ export default function Filters() {
|
|||
</header>
|
||||
|
||||
<div className="max-w-7xl mx-auto pb-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="bg-white rounded-lg shadow">
|
||||
<div className="relative inset-0 py-3 px-3 sm:px-3 lg:px-3 h-full">
|
||||
<div className="bg-white dark:bg-gray-900 light:rounded-lg light:shadow">
|
||||
<div className="relative inset-0 light:py-3 light:px-3 light:sm:px-3 light:lg:px-3 h-full">
|
||||
{data && data.length > 0 ? <FilterList filters={data} /> :
|
||||
<EmptyListState text="No filters here.." buttonText="Add new" buttonOnClick={toggleCreateFilter} />}
|
||||
</div>
|
||||
|
@ -67,26 +67,26 @@ function FilterList({ filters }: FilterListProps) {
|
|||
return (
|
||||
<div className="flex flex-col">
|
||||
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
|
||||
<div className="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-gray-50">
|
||||
<div className="light:py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
|
||||
<div className="shadow overflow-hidden border-b border-gray-200 dark:border-gray-800 sm:rounded-lg">
|
||||
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-800">
|
||||
<thead className="bg-gray-50 dark:bg-gray-900 text-gray-500 dark:text-gray-400">
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider"
|
||||
>
|
||||
Enabled
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider"
|
||||
>
|
||||
Indexers
|
||||
</th>
|
||||
|
@ -95,7 +95,7 @@ function FilterList({ filters }: FilterListProps) {
|
|||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
<tbody className="bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-800">
|
||||
{filters.map((filter: Filter, idx) => (
|
||||
<FilterListItem filter={filter} key={idx} idx={idx} />
|
||||
))}
|
||||
|
@ -124,14 +124,14 @@ function FilterListItem({ filter, idx }: FilterListItemProps) {
|
|||
|
||||
return (
|
||||
<tr key={filter.name}
|
||||
className={idx % 2 === 0 ? 'bg-white' : 'bg-gray-50'}>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||
className={idx % 2 === 0 ? 'bg-white dark:bg-gray-900' : 'bg-gray-50 dark:bg-gray-900'}>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-100">
|
||||
<Switch
|
||||
checked={enabled}
|
||||
onChange={toggleActive}
|
||||
className={classNames(
|
||||
enabled ? 'bg-teal-500' : 'bg-gray-200',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-light-blue-500'
|
||||
enabled ? 'bg-teal-500 dark:bg-blue-500' : 'bg-gray-200 dark:bg-gray-700',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500'
|
||||
)}
|
||||
>
|
||||
<span className="sr-only">Use setting</span>
|
||||
|
@ -139,16 +139,16 @@ function FilterListItem({ filter, idx }: FilterListItemProps) {
|
|||
aria-hidden="true"
|
||||
className={classNames(
|
||||
enabled ? 'translate-x-5' : 'translate-x-0',
|
||||
'inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200'
|
||||
'inline-block h-5 w-5 rounded-full bg-white dark:bg-gray-200 shadow transform ring-0 transition ease-in-out duration-200'
|
||||
)}
|
||||
/>
|
||||
</Switch>
|
||||
</td>
|
||||
<td className="px-6 py-4 w-full whitespace-nowrap text-sm font-medium text-gray-900">{filter.name}</td>
|
||||
<td className="px-6 py-4 w-full whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">{filter.name}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{filter.indexers && filter.indexers.map(t =>
|
||||
<span key={t.id} className="mr-2 inline-flex items-center px-2.5 py-0.5 rounded-md text-sm font-medium bg-gray-100 text-gray-800">{t.name}</span>)}</td>
|
||||
<span key={t.id} className="mr-2 inline-flex items-center px-2.5 py-0.5 rounded-md text-sm font-medium bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-400">{t.name}</span>)}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<Link to={`filters/${filter.id.toString()}`} className="text-indigo-600 hover:text-indigo-900">
|
||||
<Link to={`filters/${filter.id.toString()}`} className="text-indigo-600 dark:text-gray-200 hover:text-indigo-900 dark:hover:text-gray-400">
|
||||
Edit
|
||||
</Link>
|
||||
</td>
|
||||
|
|
|
@ -22,11 +22,11 @@ function ApplicationSettings() {
|
|||
)
|
||||
|
||||
return (
|
||||
<form className="divide-y divide-gray-200 lg:col-span-9" action="#" method="POST">
|
||||
<form className="divide-y divide-gray-200 dark:divide-gray-700 lg:col-span-9" action="#" method="POST">
|
||||
<div className="py-6 px-4 sm:p-6 lg:pb-8">
|
||||
<div>
|
||||
<h2 className="text-lg leading-6 font-medium text-gray-900">Application</h2>
|
||||
<p className="mt-1 text-sm text-gray-500">
|
||||
<h2 className="text-lg leading-6 font-medium text-gray-900 dark:text-white">Application</h2>
|
||||
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||
Application settings. Change in config.toml and restart to take effect.
|
||||
</p>
|
||||
</div>
|
||||
|
@ -35,7 +35,7 @@ function ApplicationSettings() {
|
|||
|
||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||
<div className="col-span-6 sm:col-span-4">
|
||||
<label htmlFor="host" className="block text-sm font-medium text-gray-700">
|
||||
<label htmlFor="host" className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||
Host
|
||||
</label>
|
||||
<input
|
||||
|
@ -44,12 +44,12 @@ function ApplicationSettings() {
|
|||
id="host"
|
||||
value={data.host}
|
||||
disabled={true}
|
||||
className="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-light-blue-500 focus:border-light-blue-500 sm:text-sm"
|
||||
className="mt-2 block w-full dark:bg-gray-800 border border-gray-300 dark:border-gray-700 border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:text-gray-100 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="col-span-6 sm:col-span-4">
|
||||
<label htmlFor="port" className="block text-sm font-medium text-gray-700">
|
||||
<label htmlFor="port" className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||
Port
|
||||
</label>
|
||||
<input
|
||||
|
@ -58,12 +58,12 @@ function ApplicationSettings() {
|
|||
id="port"
|
||||
value={data.port}
|
||||
disabled={true}
|
||||
className="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-light-blue-500 focus:border-light-blue-500 sm:text-sm"
|
||||
className="mt-2 block w-full dark:bg-gray-800 border border-gray-300 dark:border-gray-700 border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:text-gray-100 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="col-span-6 sm:col-span-4">
|
||||
<label htmlFor="base_url" className="block text-sm font-medium text-gray-700">
|
||||
<label htmlFor="base_url" className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||
Base url
|
||||
</label>
|
||||
<input
|
||||
|
@ -72,23 +72,23 @@ function ApplicationSettings() {
|
|||
id="base_url"
|
||||
value={data.base_url}
|
||||
disabled={true}
|
||||
className="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-light-blue-500 focus:border-light-blue-500 sm:text-sm"
|
||||
className="mt-2 block w-full dark:bg-gray-800 border border-gray-300 dark:border-gray-700 border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:text-gray-100 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="pt-6 pb-6 divide-y divide-gray-200">
|
||||
<div className="pt-6 pb-6 divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<div className="px-4 sm:px-6">
|
||||
<ul className="mt-2 divide-y divide-gray-200">
|
||||
<Switch.Group as="li" className="py-4 flex items-center justify-between">
|
||||
<div className="flex flex-col">
|
||||
<Switch.Label as="p" className="text-sm font-medium text-gray-900"
|
||||
<Switch.Label as="p" className="text-sm font-medium text-gray-900 dark:text-white"
|
||||
passive>
|
||||
Debug
|
||||
</Switch.Label>
|
||||
<Switch.Description className="text-sm text-gray-500">
|
||||
<Switch.Description className="text-sm text-gray-500 dark:text-gray-400">
|
||||
Enable debug mode to get more logs.
|
||||
</Switch.Description>
|
||||
</div>
|
||||
|
@ -96,8 +96,8 @@ function ApplicationSettings() {
|
|||
checked={isDebug}
|
||||
onChange={setIsDebug}
|
||||
className={classNames(
|
||||
isDebug ? 'bg-teal-500' : 'bg-gray-200',
|
||||
'ml-4 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-light-blue-500'
|
||||
isDebug ? 'bg-teal-500 dark:bg-blue-500' : 'bg-gray-200 dark:bg-gray-700',
|
||||
'ml-4 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500'
|
||||
)}
|
||||
>
|
||||
<span className="sr-only">Use setting</span>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import {useState} from "react";
|
||||
import {DownloadClient} from "../../domain/interfaces";
|
||||
import {useToggle} from "../../hooks/hooks";
|
||||
import {Switch} from "@headlessui/react";
|
||||
import {useQuery} from "react-query";
|
||||
import {classNames} from "../../styles/utils";
|
||||
import { DownloadClient } from "../../domain/interfaces";
|
||||
import { useToggle } from "../../hooks/hooks";
|
||||
import { Switch } from "@headlessui/react";
|
||||
import { useQuery } from "react-query";
|
||||
import { classNames } from "../../styles/utils";
|
||||
import { DownloadClientAddForm, DownloadClientUpdateForm } from "../../forms";
|
||||
import EmptySimple from "../../components/empty/EmptySimple";
|
||||
import APIClient from "../../api/APIClient";
|
||||
import {DownloadClientTypeNameMap} from "../../domain/constants";
|
||||
import { DownloadClientTypeNameMap } from "../../domain/constants";
|
||||
|
||||
interface DownloadLClientSettingsListItemProps {
|
||||
client: DownloadClient;
|
||||
|
@ -18,17 +17,17 @@ function DownloadClientSettingsListItem({ client, idx }: DownloadLClientSettings
|
|||
const [updateClientIsOpen, toggleUpdateClient] = useToggle(false)
|
||||
|
||||
return (
|
||||
<tr key={client.name} className={idx % 2 === 0 ? 'bg-white' : 'bg-gray-50'}>
|
||||
<tr key={client.name} className={idx % 2 === 0 ? 'light:bg-white' : 'light:bg-gray-50'}>
|
||||
{updateClientIsOpen &&
|
||||
<DownloadClientUpdateForm client={client} isOpen={updateClientIsOpen} toggle={toggleUpdateClient}/>
|
||||
<DownloadClientUpdateForm client={client} isOpen={updateClientIsOpen} toggle={toggleUpdateClient} />
|
||||
}
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||
<Switch
|
||||
checked={client.enabled}
|
||||
onChange={toggleUpdateClient}
|
||||
className={classNames(
|
||||
client.enabled ? 'bg-teal-500' : 'bg-gray-200',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-light-blue-500'
|
||||
client.enabled ? 'bg-teal-500 dark:bg-blue-500' : 'bg-gray-200 dark:bg-gray-600',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500'
|
||||
)}
|
||||
>
|
||||
<span className="sr-only">Use setting</span>
|
||||
|
@ -41,11 +40,11 @@ function DownloadClientSettingsListItem({ client, idx }: DownloadLClientSettings
|
|||
/>
|
||||
</Switch>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{client.name}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{client.host}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{DownloadClientTypeNameMap[client.type]}</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 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-right text-sm font-medium">
|
||||
<span className="text-indigo-600 hover:text-indigo-900 cursor-pointer" onClick={toggleUpdateClient}>
|
||||
<span className="text-indigo-600 dark:text-gray-300 hover:text-indigo-900 cursor-pointer" onClick={toggleUpdateClient}>
|
||||
Edit
|
||||
</span>
|
||||
</td>
|
||||
|
@ -67,21 +66,21 @@ function DownloadClientSettings() {
|
|||
<div className="divide-y divide-gray-200 lg:col-span-9">
|
||||
|
||||
{addClientIsOpen &&
|
||||
<DownloadClientAddForm isOpen={addClientIsOpen} toggle={toggleAddClient}/>
|
||||
<DownloadClientAddForm isOpen={addClientIsOpen} toggle={toggleAddClient} />
|
||||
}
|
||||
|
||||
<div className="py-6 px-4 sm:p-6 lg:pb-8">
|
||||
<div className="-ml-4 -mt-4 flex justify-between items-center flex-wrap sm:flex-nowrap">
|
||||
<div className="ml-4 mt-4">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900">Clients</h3>
|
||||
<p className="mt-1 text-sm text-gray-500">
|
||||
<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">
|
||||
Manage download clients.
|
||||
</p>
|
||||
</div>
|
||||
<div className="ml-4 mt-4 flex-shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
className="relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
className="relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 dark:bg-blue-600 hover:bg-indigo-700 dark:hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
onClick={toggleAddClient}
|
||||
>
|
||||
Add new
|
||||
|
@ -93,43 +92,43 @@ function DownloadClientSettings() {
|
|||
{data && data.length > 0 ?
|
||||
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
|
||||
<div className="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-gray-50">
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
Enabled
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
Host
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
Type
|
||||
</th>
|
||||
<th scope="col" className="relative px-6 py-3">
|
||||
<span className="sr-only">Edit</span>
|
||||
</th>
|
||||
</tr>
|
||||
<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">
|
||||
<thead className="light:bg-gray-50">
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
||||
>
|
||||
Enabled
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
||||
>
|
||||
Host
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
||||
>
|
||||
Type
|
||||
</th>
|
||||
<th scope="col" className="relative px-6 py-3">
|
||||
<span className="sr-only">Edit</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data && data.map((client, idx) => (
|
||||
<DownloadClientSettingsListItem client={client} idx={idx} key={idx} />
|
||||
))}
|
||||
<tbody className="light:bg-white divide-y divide-gray-200 dark:divide-gray-700">
|
||||
{data && data.map((client, idx) => (
|
||||
<DownloadClientSettingsListItem client={client} idx={idx} key={idx} />
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -1,52 +1,53 @@
|
|||
import {useToggle} from "../../hooks/hooks";
|
||||
import {useQuery} from "react-query";
|
||||
import React, {useEffect} from "react";
|
||||
import {IndexerAddForm, IndexerUpdateForm} from "../../forms";
|
||||
import {Indexer} from "../../domain/interfaces";
|
||||
import {Switch} from "@headlessui/react";
|
||||
import {classNames} from "../../styles/utils";
|
||||
import { useEffect } from "react";
|
||||
import { useToggle } from "../../hooks/hooks";
|
||||
import { useQuery } from "react-query";
|
||||
import { IndexerAddForm, IndexerUpdateForm } from "../../forms";
|
||||
import { Indexer } from "../../domain/interfaces";
|
||||
import { Switch } from "@headlessui/react";
|
||||
import { classNames } from "../../styles/utils";
|
||||
import EmptySimple from "../../components/empty/EmptySimple";
|
||||
import APIClient from "../../api/APIClient";
|
||||
|
||||
const ListItem = ({ indexer }: any) => {
|
||||
const [updateIsOpen, toggleUpdate] = useToggle(false)
|
||||
|
||||
return (
|
||||
<tr key={indexer.name}>
|
||||
{updateIsOpen && <IndexerUpdateForm isOpen={updateIsOpen} toggle={toggleUpdate} indexer={indexer} />}
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<Switch
|
||||
checked={indexer.enabled}
|
||||
onChange={toggleUpdate}
|
||||
className={classNames(
|
||||
indexer.enabled ? 'bg-teal-500' : 'bg-gray-200',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-light-blue-500'
|
||||
)}
|
||||
>
|
||||
<span className="sr-only">Enable</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
return (
|
||||
<tr key={indexer.name}>
|
||||
<IndexerUpdateForm isOpen={updateIsOpen} toggle={toggleUpdate} indexer={indexer} />
|
||||
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<Switch
|
||||
checked={indexer.enabled}
|
||||
onChange={toggleUpdate}
|
||||
className={classNames(
|
||||
indexer.enabled ? 'translate-x-5' : 'translate-x-0',
|
||||
'inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200'
|
||||
indexer.enabled ? 'bg-teal-500 dark:bg-blue-500' : 'bg-gray-200 dark:bg-gray-600',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500'
|
||||
)}
|
||||
/>
|
||||
</Switch>
|
||||
</td>
|
||||
<td className="px-6 py-4 w-full whitespace-nowrap text-sm font-medium text-gray-900">{indexer.name}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<span className="text-indigo-600 hover:text-indigo-900 cursor-pointer" onClick={toggleUpdate}>
|
||||
Edit
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
>
|
||||
<span className="sr-only">Enable</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className={classNames(
|
||||
indexer.enabled ? 'translate-x-5' : 'translate-x-0',
|
||||
'inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200'
|
||||
)}
|
||||
/>
|
||||
</Switch>
|
||||
</td>
|
||||
<td className="px-6 py-4 w-full whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white">{indexer.name}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<span className="text-indigo-600 dark:text-gray-300 hover:text-indigo-900 dark:hover:text-blue-500 cursor-pointer" onClick={toggleUpdate}>
|
||||
Edit
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
|
||||
function IndexerSettings() {
|
||||
const [addIndexerIsOpen, toggleAddIndexer] = useToggle(false)
|
||||
|
||||
const {error, data} = useQuery<any[], Error>('indexer', APIClient.indexers.getAll,
|
||||
const { error, data } = useQuery<any[], Error>('indexer', APIClient.indexers.getAll,
|
||||
{
|
||||
refetchOnWindowFocus: false
|
||||
}
|
||||
|
@ -65,8 +66,8 @@ function IndexerSettings() {
|
|||
<div className="py-6 px-4 sm:p-6 lg:pb-8">
|
||||
<div className="-ml-4 -mt-4 flex justify-between items-center flex-wrap sm:flex-nowrap">
|
||||
<div className="ml-4 mt-4">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900">Indexers</h3>
|
||||
<p className="mt-1 text-sm text-gray-500">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900 dark:text-white">Indexers</h3>
|
||||
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||
Indexer settings.
|
||||
</p>
|
||||
</div>
|
||||
|
@ -74,7 +75,7 @@ function IndexerSettings() {
|
|||
<button
|
||||
type="button"
|
||||
onClick={toggleAddIndexer}
|
||||
className="relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
className="relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 dark:bg-blue-600 hover:bg-indigo-700 dark:hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-blue-500"
|
||||
>
|
||||
Add new
|
||||
</button>
|
||||
|
@ -85,37 +86,37 @@ function IndexerSettings() {
|
|||
{data && data.length > 0 ?
|
||||
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
|
||||
<div className="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-gray-50">
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
Enabled
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th scope="col" className="relative px-6 py-3">
|
||||
<span className="sr-only">Edit</span>
|
||||
</th>
|
||||
</tr>
|
||||
<div className="light:shadow overflow-hidden light:border-b light:border-gray-200 dark:border-gray-700 sm:rounded-lg">
|
||||
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead className="light:bg-gray-50">
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
||||
>
|
||||
Enabled
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th scope="col" className="relative px-6 py-3">
|
||||
<span className="sr-only">Edit</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{data && data.map((indexer: Indexer, idx: number) => (
|
||||
<ListItem indexer={indexer} key={idx}/>
|
||||
))}
|
||||
<tbody className="light:bg-white divide-y divide-gray-200 dark:divide-gray-700">
|
||||
{data && data.map((indexer: Indexer, idx: number) => (
|
||||
<ListItem indexer={indexer} key={idx} />
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
: <EmptySimple title="No indexers" subtitle="Add a new indexer" buttonText="New indexer" buttonAction={toggleAddIndexer}/>
|
||||
: <EmptySimple title="No indexers" subtitle="Add a new indexer" buttonText="New indexer" buttonAction={toggleAddIndexer} />
|
||||
}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import React, {useEffect} from "react";
|
||||
import {IrcNetworkAddForm} from "../../forms";
|
||||
import {useToggle} from "../../hooks/hooks";
|
||||
import {useQuery} from "react-query";
|
||||
import IrcNetworkUpdateForm from "../../forms/settings/IrcNetworkUpdateForm";
|
||||
import {Switch} from "@headlessui/react";
|
||||
import {classNames} from "../../styles/utils";
|
||||
import { useEffect } from "react";
|
||||
import { IrcNetworkAddForm, IrcNetworkUpdateForm } from "../../forms";
|
||||
import { useToggle } from "../../hooks/hooks";
|
||||
import { useQuery } from "react-query";
|
||||
import { Switch } from "@headlessui/react";
|
||||
import { classNames } from "../../styles/utils";
|
||||
import EmptySimple from "../../components/empty/EmptySimple";
|
||||
import APIClient from "../../api/APIClient";
|
||||
|
||||
|
@ -34,16 +33,13 @@ function IrcSettings() {
|
|||
|
||||
return (
|
||||
<div className="divide-y divide-gray-200 lg:col-span-9">
|
||||
|
||||
{addNetworkIsOpen &&
|
||||
<IrcNetworkAddForm isOpen={addNetworkIsOpen} toggle={toggleAddNetwork}/>
|
||||
}
|
||||
<IrcNetworkAddForm isOpen={addNetworkIsOpen} toggle={toggleAddNetwork} />
|
||||
|
||||
<div className="py-6 px-4 sm:p-6 lg:pb-8">
|
||||
<div className="-ml-4 -mt-4 flex justify-between items-center flex-wrap sm:flex-nowrap">
|
||||
<div className="ml-4 mt-4">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900">IRC</h3>
|
||||
<p className="mt-1 text-sm text-gray-500">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900 dark:text-white">IRC</h3>
|
||||
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||
IRC networks and channels.
|
||||
</p>
|
||||
</div>
|
||||
|
@ -51,7 +47,7 @@ function IrcSettings() {
|
|||
<button
|
||||
type="button"
|
||||
onClick={toggleAddNetwork}
|
||||
className="relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
className="relative inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 dark:bg-blue-600 hover:bg-indigo-700 dark:hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
>
|
||||
Add new
|
||||
</button>
|
||||
|
@ -62,49 +58,49 @@ function IrcSettings() {
|
|||
{data && data.length > 0 ?
|
||||
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
|
||||
<div className="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-gray-50">
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
Enabled
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
Network
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
Server
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
Nick
|
||||
</th>
|
||||
<th scope="col" className="relative px-6 py-3">
|
||||
<span className="sr-only">Edit</span>
|
||||
</th>
|
||||
</tr>
|
||||
<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">
|
||||
<thead className="light:bg-gray-50">
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
||||
>
|
||||
Enabled
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
||||
>
|
||||
Network
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
||||
>
|
||||
Server
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
||||
>
|
||||
Nick
|
||||
</th>
|
||||
<th scope="col" className="relative px-6 py-3">
|
||||
<span className="sr-only">Edit</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data && data.map((network: IrcNetwork, idx) => (
|
||||
<ListItem key={idx} idx={idx} network={network}/>
|
||||
))}
|
||||
<tbody className="light:bg-white divide-y divide-gray-200 dark:divide-gray-700">
|
||||
{data && data.map((network: IrcNetwork, idx) => (
|
||||
<ListItem key={idx} idx={idx} network={network} />
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
: <EmptySimple title="No networks" subtitle="Add a new network" buttonText="New network" buttonAction={toggleAddNetwork}/>
|
||||
: <EmptySimple title="No networks" subtitle="Add a new network" buttonText="New network" buttonAction={toggleAddNetwork} />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -116,15 +112,16 @@ const ListItem = ({ idx, network }: any) => {
|
|||
const [updateIsOpen, toggleUpdate] = useToggle(false)
|
||||
|
||||
return (
|
||||
<tr key={network.name} className={idx % 2 === 0 ? 'bg-white' : 'bg-gray-50'}>
|
||||
{updateIsOpen && <IrcNetworkUpdateForm isOpen={updateIsOpen} toggle={toggleUpdate} network={network} />}
|
||||
<tr key={network.name} className={idx % 2 === 0 ? 'light:bg-white' : 'light:bg-gray-50'}>
|
||||
<IrcNetworkUpdateForm isOpen={updateIsOpen} toggle={toggleUpdate} network={network} />
|
||||
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<Switch
|
||||
checked={network.enabled}
|
||||
onChange={toggleUpdate}
|
||||
className={classNames(
|
||||
network.enabled ? 'bg-teal-500' : 'bg-gray-200',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-light-blue-500'
|
||||
network.enabled ? 'bg-teal-500 dark:bg-blue-500' : 'bg-gray-200 dark:bg-gray-600',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500'
|
||||
)}
|
||||
>
|
||||
<span className="sr-only">Enable</span>
|
||||
|
@ -137,11 +134,11 @@ const ListItem = ({ idx, network }: any) => {
|
|||
/>
|
||||
</Switch>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{network.name}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{network.server}:{network.port} {network.tls && <span className="ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800">TLS</span>}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{network.nickserv?.account}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white">{network.name}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><span>{network.server}:{network.port}</span> {network.tls && <span className="ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-green-100 dark:bg-green-300 text-green-800 dark:text-green-900">TLS</span>}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">{network.nickserv?.account}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<span className="text-indigo-600 hover:text-indigo-900 cursor-pointer" onClick={toggleUpdate}>
|
||||
<span className="text-indigo-600 dark:text-gray-300 hover:text-indigo-900 cursor-pointer" onClick={toggleUpdate}>
|
||||
Edit
|
||||
</span>
|
||||
</td>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue