1- import React , { useEffect } from 'react' ;
1+ import React , { useEffect , useState } from 'react' ;
22import tw from 'twin.macro' ;
33import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' ;
44import { faNetworkWired } from '@fortawesome/free-solid-svg-icons' ;
@@ -14,28 +14,45 @@ import { Allocation } from '@/api/server/getServer';
1414import Spinner from '@/components/elements/Spinner' ;
1515import setPrimaryServerAllocation from '@/api/server/network/setPrimaryServerAllocation' ;
1616import useFlash from '@/plugins/useFlash' ;
17+ import { Textarea } from '@/components/elements/Input' ;
18+ import setServerAllocationNotes from '@/api/server/network/setServerAllocationNotes' ;
19+ import { debounce } from 'debounce' ;
20+ import InputSpinner from '@/components/elements/InputSpinner' ;
1721
1822const Code = styled . code `${ tw `font-mono py-1 px-2 bg-neutral-900 rounded text-sm block` } ` ;
1923const Label = styled . label `${ tw `uppercase text-xs mt-1 text-neutral-400 block px-1 select-none transition-colors duration-150` } ` ;
2024
2125const NetworkContainer = ( ) => {
22- const server = useServer ( ) ;
26+ const { uuid , allocations } = useServer ( ) ;
2327 const { clearFlashes, clearAndAddHttpError } = useFlash ( ) ;
24- const { data, error, mutate } = useSWR < Allocation [ ] > ( server . uuid , key => getServerAllocations ( key ) , { initialData : server . allocations } ) ;
28+ const [ loading , setLoading ] = useState < false | number > ( false ) ;
29+ const { data, error, mutate } = useSWR < Allocation [ ] > ( uuid , key => getServerAllocations ( key ) , { initialData : allocations } ) ;
2530
2631 const setPrimaryAllocation = ( id : number ) => {
2732 clearFlashes ( 'server:network' ) ;
2833
2934 const initial = data ;
3035 mutate ( data ?. map ( a => a . id === id ? { ...a , isDefault : true } : { ...a , isDefault : false } ) , false ) ;
3136
32- setPrimaryServerAllocation ( server . uuid , id )
37+ setPrimaryServerAllocation ( uuid , id )
3338 . catch ( error => {
3439 clearAndAddHttpError ( { key : 'server:network' , error } ) ;
3540 mutate ( initial , false ) ;
3641 } ) ;
3742 } ;
3843
44+ const setAllocationNotes = debounce ( ( id : number , notes : string ) => {
45+ setLoading ( id ) ;
46+ clearFlashes ( 'server:network' ) ;
47+
48+ setServerAllocationNotes ( uuid , id , notes )
49+ . then ( ( ) => mutate ( data ?. map ( a => a . id === id ? { ...a , notes } : a ) , false ) )
50+ . catch ( error => {
51+ clearAndAddHttpError ( { key : 'server:network' , error } ) ;
52+ } )
53+ . then ( ( ) => setLoading ( false ) ) ;
54+ } , 750 ) ;
55+
3956 useEffect ( ( ) => {
4057 if ( error ) {
4158 clearAndAddHttpError ( { key : 'server:network' , error } ) ;
@@ -47,8 +64,8 @@ const NetworkContainer = () => {
4764 { ! data ?
4865 < Spinner size = { 'large' } centered />
4966 :
50- data . map ( ( { id, ip, port, alias, isDefault } , index ) => (
51- < GreyRowBox key = { `${ ip } :${ port } ` } css = { index > 0 ? tw `mt-2` : undefined } >
67+ data . map ( ( { id, ip, port, alias, notes , isDefault } , index ) => (
68+ < GreyRowBox key = { `${ ip } :${ port } ` } css = { index > 0 ? tw `mt-2` : undefined } $hoverable = { false } >
5269 < div css = { tw `pl-4 pr-6 text-neutral-400` } >
5370 < FontAwesomeIcon icon = { faNetworkWired } />
5471 </ div >
@@ -60,7 +77,17 @@ const NetworkContainer = () => {
6077 < Code > :{ port } </ Code >
6178 < Label > Port</ Label >
6279 </ div >
63- < div css = { tw `flex-1 text-right` } >
80+ < div css = { tw `px-8 flex-1 self-start` } >
81+ < InputSpinner visible = { loading === id } >
82+ < Textarea
83+ css = { tw `bg-neutral-800 hover:border-neutral-600 border-transparent` }
84+ placeholder = { 'Notes' }
85+ defaultValue = { notes || undefined }
86+ onChange = { e => setAllocationNotes ( id , e . currentTarget . value ) }
87+ />
88+ </ InputSpinner >
89+ </ div >
90+ < div css = { tw `w-32 text-right` } >
6491 { isDefault ?
6592 < span css = { tw `bg-green-500 py-1 px-2 rounded text-green-50 text-xs` } >
6693 Primary
0 commit comments