autobrr/web/src/screens/settings/Irc.tsx
stacksmash76 20138030e1
refactor: various frontend improvements (#101)
* Removed recoil and replaced it with react-ridge-state, a 0.4kb alternative.

* Added AuthContext and SettingsContext persistent localStorage states.

* Fixed tailwind.config.js incorrect key directive. See https://tailwindcss.com/docs/content-configuration#safelisting-classes.

* Changed darkMode in Tailwind to "class" and started manually adjusting the theme according to the appropriate media query.

* Added possibility of changing the theme manually via the Settings tab.

* Changed Releases.tsx behavior to show the UI only when the HTTP request succeeded and there is some data (i.e. table is non-empty).

* Changed the table color of screens/filters/list.tsx to a one notch lighter shade of gray for eye-comfort.

* Replaced "User" in the header, with the users real username.

* Made data version, commit and date fields optional in settings/Application.tsx.

* Started working on a RegExp playground, which works fine, but JS won't cooperate and return the right match length. Either way, the RegExp must be implemented on backend and then must be communicated with the frontend. Otherwise a potential for incorrect results exists.

* Removed Layout.tsx, since it was redundant.

* Created a Checkbox component class for easier and consistent future use.

* Rewritten App.tsx, Login.tsx, Logout.tsx to accomodate for new changes.

* Fixed previous mistake regarding tailwind.config.js purge key, since we're still using old postcss7 from October last year

* Removed package-lock.json from both root and web directories.

* Refresh TypeScript configuration to support a types/ directory containing d.ts. The effect of this is that types don't have to be imported anymore and are at all times available globally. This also unifies them into a single source of truth, which will be a lot easier to manage in the future. Note: Only certain interop types have been moved at the time of writing.

* Fixed minor Checkbox argument mistake.

* fix: remove length from data check

* chore: lock files are annoying

* fix: select

* fix: wip release filtering
2022-01-26 23:54:29 +01:00

182 lines
11 KiB
TypeScript

import { useQuery } from "react-query";
import { formatDistanceToNowStrict, formatISO9075 } from "date-fns";
import APIClient from "../../api/APIClient";
import { useToggle } from "../../hooks/hooks";
import { EmptySimple } from "../../components/emptystates";
import { IrcNetworkAddForm, IrcNetworkUpdateForm } from "../../forms";
function IsEmptyDate(date: string) {
if (date !== "0001-01-01T00:00:00Z") {
return formatDistanceToNowStrict(
new Date(date),
{ addSuffix: true }
)
}
return "n/a"
}
function simplifyDate(date: string) {
if (date !== "0001-01-01T00:00:00Z") {
return formatISO9075(new Date(date))
}
return "n/a"
}
function IrcSettings() {
const [addNetworkIsOpen, toggleAddNetwork] = useToggle(false)
const { data } = useQuery<IrcNetwork[], Error>('networks', APIClient.irc.getNetworks,
{
refetchOnWindowFocus: false
}
)
return (
<div className="divide-y divide-gray-200 lg:col-span-9">
<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 dark:text-white">IRC</h3>
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
IRC networks and channels. Click on a network to view channel status.
</p>
</div>
<div className="ml-4 mt-4 flex-shrink-0">
<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 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>
</div>
</div>
{data && data.length > 0 ?
<section className="mt-6 light:bg-white dark:bg-gray-800 light:shadow sm:rounded-md">
<ol className="min-w-full">
<li className="grid grid-cols-12 gap-4 border-b border-gray-200 dark:border-gray-700">
{/* <div className="col-span-1 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Enabled</div> */}
<div className="col-span-3 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Network</div>
<div className="col-span-4 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Server</div>
<div className="col-span-4 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Nick</div>
</li>
{data && data.map((network: IrcNetwork, idx) => (
<LiItem key={idx} idx={idx} network={network} />
))}
</ol>
</section>
: <EmptySimple title="No networks" subtitle="Add a new network" buttonText="New network" buttonAction={toggleAddNetwork} />}
</div>
</div>
)
}
interface LiItemProps {
idx: number;
network: IrcNetwork;
}
const LiItem = ({ idx, network }: LiItemProps) => {
const [updateIsOpen, toggleUpdate] = useToggle(false)
const [edit, toggleEdit] = useToggle(false);
return (
<li key={idx} >
<div className="grid grid-cols-12 gap-4 items-center hover:bg-gray-50 dark:hover:bg-gray-700 py-4">
<IrcNetworkUpdateForm isOpen={updateIsOpen} toggle={toggleUpdate} network={network} />
{/* <div className="col-span-1 flex items-center sm:px-6">
<Switch
checked={network.enabled}
onChange={toggleUpdate}
className={classNames(
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>
<span
aria-hidden="true"
className={classNames(
network.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>
</div> */}
<div className="col-span-3 items-center sm:px-6 text-sm font-medium text-gray-900 dark:text-white cursor-pointer" onClick={toggleEdit}>
<span className="relative inline-flex items-center">
{
network.enabled ? (
network.connected ? (
<span className="mr-3 flex h-3 w-3 relative" title={`Connected since: ${simplifyDate(network.connected_since)}`}>
<span className="animate-ping inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
<span className="inline-flex absolute rounded-full h-3 w-3 bg-green-500"></span>
</span>
) : <span className="mr-3 flex h-3 w-3 rounded-full opacity-75 bg-red-400" />
) : <span className="mr-3 flex h-3 w-3 rounded-full opacity-75 bg-gray-500" />
}
{network.name}
</span>
</div>
<div className="col-span-4 flex justify-between items-center sm:px-6 text-sm text-gray-500 dark:text-gray-400 cursor-pointer" onClick={toggleEdit}>{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 dark:bg-green-300 text-green-800 dark:text-green-900">TLS</span>}</div>
<div className="col-span-4 items-center sm:px-6 text-sm text-gray-500 dark:text-gray-400 cursor-pointer" onClick={toggleEdit}>{network.nickserv.account}</div>
<div className="col-span-1 text-sm text-gray-500 dark:text-gray-400">
<span className="text-indigo-600 dark:text-gray-300 hover:text-indigo-900 cursor-pointer" onClick={toggleUpdate}>
Edit
</span>
</div>
</div>
{edit && (
<div className="px-4 py-4 flex border-b border-x-0 dark:border-gray-600 dark:bg-gray-700">
<div className="min-w-full">
<ol>
<li className="grid grid-cols-12 gap-4 border-b border-gray-200 dark:border-gray-700">
<div className="col-span-4 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Channel</div>
<div className="col-span-4 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Monitoring since</div>
<div className="col-span-4 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Last announce</div>
</li>
{network.channels.map(c => (
<li key={c.id} className="text-gray-500 dark:text-gray-400">
<div className="grid grid-cols-12 gap-4 items-center py-4">
<div className="col-span-4 flex items-center sm:px-6 ">
<span className="relative inline-flex items-center">
{
network.enabled ? (
c.monitoring ? (
<span className="mr-3 flex h-3 w-3 relative" title="monitoring">
<span className="animate-ping inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
<span className="inline-flex absolute rounded-full h-3 w-3 bg-green-500"></span>
</span>
) : <span className="mr-3 flex h-3 w-3 rounded-full opacity-75 bg-red-400" />
) : <span className="mr-3 flex h-3 w-3 rounded-full opacity-75 bg-gray-500" />
}
{c.name}
</span>
</div>
<div className="col-span-4 flex items-center sm:px-6 ">
<span className="" title={simplifyDate(c.monitoring_since)}>{IsEmptyDate(c.monitoring_since)}</span>
</div>
<div className="col-span-4 flex items-center sm:px-6 ">
<span className="" title={simplifyDate(c.last_announce)}>{IsEmptyDate(c.last_announce)}</span>
</div>
</div>
</li>
))}
</ol>
</div>
</div>
)}
</li>
)
}
export default IrcSettings;