Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/variables-redux #157

Merged
merged 14 commits into from
Feb 10, 2023
Merged
3 changes: 2 additions & 1 deletion schemas/tdp-server_0.1.0_openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1473,10 +1473,11 @@
"schemas": {
"Component": {
"title": "Component",
"required": ["id", "version"],
"required": ["id", "service_id", "version"],
"type": "object",
"properties": {
"id": { "title": "Id", "type": "string" },
"service_id": { "title": "Service Id", "type": "string" },
"variables": { "$ref": "#/components/schemas/Variables" },
"version": { "title": "Version", "type": "string" }
},
Expand Down
12 changes: 0 additions & 12 deletions src/app/dashboard/services/layout.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/clients/tdpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
} from '@/client-sdk'

export type {
Component,
ComponentUpdate,
DeploymentLog,
DeploymentLogWithOperations,
Expand All @@ -39,7 +40,6 @@ export function createTdpClientInstance(configuration?: Configuration) {
const planApi = new PlanApi(configuration)
const schemaApi = new SchemaApi(configuration)

//TODO: export API and refactor function in hooks
return {
getServices: () => serviceApi.getServicesApiV1ServiceGet(),
getService: (serviceId: string) =>
Expand Down
32 changes: 17 additions & 15 deletions src/components/Layout/Menu.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,9 @@
import Link from 'next/link'
import { useRouter } from 'next/router'
import { BeakerIcon, Cog6ToothIcon } from '@heroicons/react/24/solid'
import { useServicesList } from 'src/hooks'
import { HeroIcon } from 'src/types'
import { classNames } from 'src/utils'

const baseMenuItems = [
{
name: 'Services',
href: '#',
icon: BeakerIcon,
},
{
name: 'Deployments',
href: '/deploy',
icon: Cog6ToothIcon,
},
]
import { useSelectServices } from 'src/features/variables'

export type TNavItem = {
name: string
Expand All @@ -26,7 +13,22 @@ export type TNavItem = {
}

export function Menu() {
const menuItems = useServicesList(baseMenuItems)
const menuItems = [
{
name: 'Services',
href: '#',
icon: BeakerIcon,
children: useSelectServices().value.map((v) => ({
name: v.value.id,
href: `/services/${v.value.id}`,
})),
},
{
name: 'Deployments',
href: '/deploy',
icon: Cog6ToothIcon,
},
]

return (
<nav className="flex flex-col">
Expand Down
43 changes: 20 additions & 23 deletions src/components/Services/ComponentsNav/ComponentsNav.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,34 @@
import { useRouter } from 'next/router'
import { getFirstElementIfArray } from 'src/utils'
import { useSelectService } from 'src/features/variables'
import { useParamsContext } from '../useParamsContext'
import { ComponentsDropdown } from './ComponentsDropdown'
import { ComponentsTabs } from './ComponentsTabs'
import { useComponentsList } from './hooks'

export function ComponentsNav() {
const {
query: { serviceId: tempServiceId, componentId: tempComponentId },
isReady,
} = useRouter()
const componentId = isReady && getFirstElementIfArray(tempComponentId)
const serviceId = isReady && getFirstElementIfArray(tempServiceId)
const { loading, components } = useComponentsList(serviceId)
const { serviceId: currentServiceId, componentId: currentComponentId } =
useParamsContext()

if (!isReady && loading) return <p>Loading</p>

const [usedComponents, unusedComponents] = components.reduce(
(acc, component) => {
const { id: componentId, isUsed } = component
const [usedComponents, unusedComponents] = useSelectService(
currentServiceId
).value.components.reduce(
([usedComponents, unusedComponents], component) => {
const {
value: { id: componentId, variables },
} = component
const isUsed = Object.values(variables).length > 0
if (isUsed) {
acc[0].push({
usedComponents.push({
id: componentId,
href: `/services/${serviceId}/components/${componentId}`,
href: `/services/${currentServiceId}/components/${componentId}`,
})
} else {
acc[1].push({
unusedComponents.push({
id: componentId,
href: `/services/${serviceId}/components/${componentId}`,
href: `/services/${currentServiceId}/components/${componentId}`,
})
}
return acc
return [usedComponents, unusedComponents]
},
[[{ id: serviceId, href: `/services/${serviceId}` }], []]
[[{ id: currentServiceId, href: `/services/${currentServiceId}` }], []]
)

return (
Expand All @@ -40,14 +37,14 @@ export function ComponentsNav() {
<ComponentsDropdown
usedComponents={usedComponents}
unusedComponents={unusedComponents}
currentTabId={componentId}
currentTabId={currentComponentId}
/>
</div>
<div className="hidden sm:block">
<ComponentsTabs
usedComponents={usedComponents}
unusedComponents={unusedComponents}
currentTabId={componentId}
currentTabId={currentComponentId}
/>
</div>
</div>
Expand Down
1 change: 0 additions & 1 deletion src/components/Services/ComponentsNav/hooks/index.ts

This file was deleted.

39 changes: 0 additions & 39 deletions src/components/Services/ComponentsNav/hooks/useComponentsList.ts

This file was deleted.

25 changes: 25 additions & 0 deletions src/components/Services/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useRouter } from 'next/router'
import { PageTitle } from 'src/components/Layout/primitives/PageTitle'
import { ComponentsNav } from 'src/components/Services/ComponentsNav'
import { getFirstElementIfArray } from 'src/utils'
import { ParamsContextProvider } from './ParamsContext'

export function Layout({ children }) {
const {
query: { serviceId: tempServiceId, componentId: tempComponentId },
isReady,
} = useRouter()
const currentServiceId = isReady && getFirstElementIfArray(tempServiceId)
const currentComponentId = isReady && getFirstElementIfArray(tempComponentId)

return (
<ParamsContextProvider
serviceId={currentServiceId}
componentId={currentComponentId}
>
<PageTitle>Variables configuration</PageTitle>
<ComponentsNav />
{children}
</ParamsContextProvider>
)
}
22 changes: 22 additions & 0 deletions src/components/Services/ParamsContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { createContext, useEffect } from 'react'
import { clearUserInput } from 'src/features/userInput'
import { useAppDispatch } from 'src/store'

export const ParamsContext = createContext<{
serviceId: string
componentId?: string
}>(null)

export function ParamsContextProvider({ children, serviceId, componentId }) {
const dispatch = useAppDispatch()

useEffect(() => {
dispatch(clearUserInput())
}, [serviceId, dispatch])

return (
<ParamsContext.Provider value={{ serviceId, componentId }}>
{children}
</ParamsContext.Provider>
)
}
72 changes: 72 additions & 0 deletions src/components/Services/VariablesDisplay/Fields/ArrayList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { useState } from 'react'
import { setProperty } from 'src/features/userInput'
import { useAppDispatch } from 'src/store'
import { classNames } from 'src/utils'
import { useParamsContext } from '../../useParamsContext'

export function ArrayList({
property,
value,
dict,
}: {
property: string
value: any[]
dict?: string
}) {
console.log('dict', dict)
return (
<ol className="flex flex-grow flex-col gap-2">
{value.map((v) => (
<ValueArrayElement key={v} value={v} dict={dict} property={property} />
))}
</ol>
)
}

function ValueArrayElement({
value,
dict,
property,
}: {
value: any
dict?: string
property: string
}) {
const { serviceId, componentId } = useParamsContext()
const dispatch = useAppDispatch()
const [error, setError] = useState(false)
const fullProperty = [dict, property].filter(Boolean).join('.')

function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
setError(false)
try {
const parsedValue = JSON.parse(event.target.value)
dispatch(
setProperty({
serviceId,
componentId,
property: fullProperty,
value: parsedValue,
})
)
} catch (err) {
setError(true)
}
}

return (
<li key={fullProperty} className="flex grow">
<input
name={fullProperty}
className={classNames(
'grow',
error && 'bg-red-200',
typeof value === 'number' ? 'text-teal-600' : 'text-slate-700',
'hover:opacity-100 hover:bg-slate-200 transition duration-75 ease-in-out'
)}
defaultValue={JSON.stringify(value)}
onChange={handleChange}
/>
</li>
)
}
36 changes: 36 additions & 0 deletions src/components/Services/VariablesDisplay/Fields/BooleanField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Toggle } from 'src/components/commons'
import { useAppDispatch } from 'src/store'
import { useParamsContext } from '../../useParamsContext'
import { setProperty } from 'src/features/userInput'

export function BooleanField({
property,
value,
dict,
}: {
property: string
value: boolean
dict?: string
}) {
const { serviceId, componentId } = useParamsContext()
const dispatch = useAppDispatch()

const fullProperty = [dict, property].filter(Boolean).join('.')

function handleChecked(event: React.ChangeEvent<HTMLInputElement>) {
const newValue = event.target.checked
dispatch(
setProperty({
serviceId,
componentId,
property: fullProperty,
value: newValue,
})
)
}
return (
<div className="flex flex-grow flex-col">
<Toggle handleChecked={handleChecked} defaultValue={value} />
</div>
)
}
Loading