Refactor irc client (#19)

* refactor: update http handlers

* feat: add trace log level

* refactir: irc handler

* refactor(definitions): add irc settings and invite cmd:

* feat: add dft values to inputs

* refactor: indexer irc forms

* refactor(definitions): fix nickserv.password var:

* feat: pre fill indexer name field

* refactor: handle stopping and updates
This commit is contained in:
Ludvig Lundgren 2021-08-29 23:23:02 +02:00 committed by GitHub
parent 5f69ae9380
commit 4d40d41628
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 1380 additions and 943 deletions

View file

@ -1,23 +1,24 @@
import React, {Fragment} from "react";
import {useMutation, useQuery} from "react-query";
import {Indexer} from "../../domain/interfaces";
import {sleep} from "../../utils/utils";
import {XIcon} from "@heroicons/react/solid";
import {Dialog, Transition} from "@headlessui/react";
import {Field, Form} from "react-final-form";
import React, { Fragment } from "react";
import { useMutation, useQuery } from "react-query";
import { Channel, Indexer, IndexerSchema, IndexerSchemaSettings, Network } from "../../domain/interfaces";
import { sleep } from "../../utils/utils";
import { XIcon } from "@heroicons/react/solid";
import { Dialog, Transition } from "@headlessui/react";
import { Field, Form } from "react-final-form";
import DEBUG from "../../components/debug";
import Select from "react-select";
import {queryClient} from "../../App";
import { SwitchGroup } from "../../components/inputs";
import { queryClient } from "../../App";
import { SwitchGroup, TextFieldWide } from "../../components/inputs";
import APIClient from "../../api/APIClient";
import { NumberFieldWide, PasswordFieldWide } from "../../components/inputs/wide";
interface props {
isOpen: boolean;
toggle: any;
}
function IndexerAddForm({isOpen, toggle}: props) {
const {data} = useQuery<any[], Error>('indexerSchema', APIClient.indexers.getSchema,
function IndexerAddForm({ isOpen, toggle }: props) {
const { data } = useQuery<IndexerSchema[], Error>('indexerSchema', APIClient.indexers.getSchema,
{
enabled: isOpen,
refetchOnWindowFocus: false
@ -33,59 +34,122 @@ function IndexerAddForm({isOpen, toggle}: props) {
}
})
const onSubmit = (data: any) => {
mutation.mutate(data)
const ircMutation = useMutation((network: Network) => APIClient.irc.createNetwork(network), {
onSuccess: (data) => {
console.log("irc mutation: ", data);
// queryClient.invalidateQueries(['indexer']);
// sleep(1500)
// toggle()
}
})
const onSubmit = (formData: any) => {
let ind = data && data.find(i => i.identifier === formData.identifier)
if (!ind) {
return
}
let channels: Channel[] = []
if (ind.irc.channels.length) {
ind.irc.channels.forEach(element => {
channels.push({ name: element })
});
}
const network: Network = {
name: ind.name,
enabled: false,
server: formData.irc.server,
port: formData.irc.port,
tls: formData.irc.tls,
nickserv: formData.irc.nickserv,
invite_command: formData.irc.invite_command,
settings: formData.irc.settings,
channels: channels,
}
console.log("network: ", network);
mutation.mutate(formData, {
onSuccess: (data) => {
// create irc
ircMutation.mutate(network)
}
})
};
const renderSettingFields = (indexer: string) => {
if (indexer !== "") {
// let ind = data.find(i => i.implementation_name === indexer)
let ind = data && data.find(i => i.identifier === indexer)
return (
<div key="opt">
{ind && ind.settings && ind.settings.map((f: any, idx: number) => {
switch (f.type) {
case "text":
return (
<div className="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5" key={idx}>
<div>
<label
htmlFor={f.name}
className="block text-sm font-medium text-gray-900 sm:mt-px sm:pt-2"
>
{f.label}
</label>
</div>
<div className="sm:col-span-2">
<Field name={"settings."+f.name}>
{({input, meta}) => (
<div className="sm:col-span-2">
<input
type="text"
{...input}
className="block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md"
/>
{meta.touched && meta.error &&
<span>{meta.error}</span>}
</div>
)}
</Field>
</div>
</div>
)
}
})}
{ind && ind.settings && ind.settings.map((f: any, idx: number) => {
switch (f.type) {
case "text":
return (
<TextFieldWide name={`settings.${f.name}`} label={f.label} key={idx} help={f.help} defaultValue=""/>
)
case "secret":
return (
<PasswordFieldWide name={`settings.${f.name}`} label={f.label} key={idx} help={f.help} defaultValue="" />
)
}
})}
<div hidden={true}>
<TextFieldWide name={`name`} label="Name" defaultValue={ind?.name} />
</div>
</div>
)
}
}
const renderIrcSettingFields = (indexer: string) => {
if (indexer !== "") {
let ind = data && data.find(i => i.identifier === indexer)
return (
<Fragment>
{ind && ind.irc && ind.irc.settings && (
<div className="border-t border-gray-200 py-5">
<div className="px-6 space-y-1">
<Dialog.Title className="text-lg font-medium text-gray-900">IRC</Dialog.Title>
<p className="text-sm text-gray-500">
Networks, channels and invite commands are configured automatically.
</p>
</div>
{ind.irc.settings.map((f: IndexerSchemaSettings, idx: number) => {
switch (f.type) {
case "text":
return <TextFieldWide name={`irc.${f.name}`} label={f.label} required={f.required} key={idx} help={f.help} />
case "secret":
return <PasswordFieldWide name={`irc.${f.name}`} label={f.label} required={f.required} key={idx} help={f.help} defaultValue={f.default} />
}
})}
<div hidden={true}>
<TextFieldWide name={`irc.server`} label="Server" defaultValue={ind.irc.server} />
<NumberFieldWide name={`irc.port`} label="Port" defaultValue={ind.irc.port} />
<SwitchGroup name="irc.tls" label="TLS" defaultValue={ind.irc.tls} />
</div>
</div>
)}
</Fragment>
)
}
}
return (
<Transition.Root show={isOpen} as={Fragment}>
<Dialog as="div" static className="fixed inset-0 overflow-hidden" open={isOpen} onClose={toggle}>
<div className="absolute inset-0 overflow-hidden">
<Dialog.Overlay className="absolute inset-0"/>
<Dialog.Overlay className="absolute inset-0" />
<div className="fixed inset-y-0 right-0 pl-10 max-w-full flex sm:pl-16">
<Transition.Child
@ -100,18 +164,17 @@ function IndexerAddForm({isOpen, toggle}: props) {
<div className="w-screen max-w-2xl">
<Form
initialValues={{
name: "",
enabled: true,
identifier: "",
irc: {}
}}
onSubmit={onSubmit}
>
{({handleSubmit, values}) => {
{({ handleSubmit, values }) => {
return (
<form className="h-full flex flex-col bg-white shadow-xl overflow-y-scroll"
onSubmit={handleSubmit}>
onSubmit={handleSubmit}>
<div className="flex-1">
{/* Header */}
<div className="px-4 py-6 bg-gray-50 sm:px-6">
<div className="flex items-start justify-between space-x-3">
<div className="space-y-1">
@ -129,43 +192,14 @@ function IndexerAddForm({isOpen, toggle}: props) {
onClick={toggle}
>
<span className="sr-only">Close panel</span>
<XIcon className="h-6 w-6" aria-hidden="true"/>
<XIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
</div>
</div>
{/* Divider container */}
<div
className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<div
className="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5">
<div>
<label
htmlFor="name"
className="block text-sm font-medium text-gray-900 sm:mt-px sm:pt-2"
>
Name
</label>
</div>
<Field name="name">
{({input, meta}) => (
<div className="sm:col-span-2">
<input
type="text"
{...input}
className="block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md"
/>
{meta.touched && meta.error &&
<span>{meta.error}</span>}
</div>
)}
</Field>
</div>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroup name="enabled" label="Enabled" />
</div>
<div
className="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5">
@ -182,26 +216,32 @@ function IndexerAddForm({isOpen, toggle}: props) {
name="identifier"
parse={val => val && val.value}
format={val => data && data.find((o: any) => o.value === val)}
render={({input, meta}) => (
render={({ input, meta }) => (
<React.Fragment>
<Select {...input}
isClearable={true}
placeholder="Choose an indexer"
options={data && data.sort((a,b): any => a.name.localeCompare(b.name)).map(v => ({
label: v.name,
value: v.identifier
// value: v.implementation_name
}))}/>
{/*<Error name={input.name} classNames="text-red mt-2 block" />*/}
isClearable={true}
placeholder="Choose an indexer"
options={data && data.sort((a, b): any => a.name.localeCompare(b.name)).map(v => ({
label: v.name,
value: v.identifier
}))} />
</React.Fragment>
)}
/>
</div>
</div>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroup name="enabled" label="Enabled" />
</div>
{renderSettingFields(values.identifier)}
</div>
{renderIrcSettingFields(values.identifier)}
</div>
<div
@ -223,7 +263,7 @@ function IndexerAddForm({isOpen, toggle}: props) {
</div>
</div>
<DEBUG values={values}/>
<DEBUG values={values} />
</form>
)
}}