Skip to content

Commit

Permalink
creating an aggregation of interfaces to simplify writing
Browse files Browse the repository at this point in the history
  • Loading branch information
bdebon committed Jan 2, 2023
1 parent dc0fd3b commit 5dd4665
Show file tree
Hide file tree
Showing 29 changed files with 173 additions and 241 deletions.
39 changes: 18 additions & 21 deletions libs/domains/application/src/lib/slices/applications.slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
createSlice,
} from '@reduxjs/toolkit'
import {
Application,
ApplicationAdvancedSettings,
ApplicationConfigurationApi,
ApplicationDeploymentHistoryApi,
Expand All @@ -23,7 +22,6 @@ import {
ContainerMainCallsApi,
ContainerMetricsApi,
ContainerRequest,
ContainerResponse,
ContainersApi,
DeploymentHistoryApplication,
Instance,
Expand All @@ -32,13 +30,13 @@ import {
JobDeploymentHistoryApi,
JobMainCallsApi,
JobRequest,
JobResponse,
JobsApi,
Link,
Status,
} from 'qovery-typescript-axios'
import { ServiceTypeEnum, isApplication, isContainer, isJob } from '@qovery/shared/enums'
import {
AdvancedSettings,
ApplicationEntity,
ApplicationsState,
ContainerApplicationEntity,
Expand Down Expand Up @@ -80,7 +78,7 @@ const jobDeploymentsApi = new JobDeploymentHistoryApi()
const jobConfigurationApi = new JobConfigurationApi()

export const fetchApplications = createAsyncThunk<
Application[] | ContainerResponse[],
ApplicationEntity[],
{ environmentId: string; withoutStatus?: boolean }
>('applications/fetch', async (data, thunkApi) => {
const result = await Promise.all([
Expand Down Expand Up @@ -153,7 +151,7 @@ export const editApplication = createAsyncThunk(
)
}

return response.data as Application
return response.data as ApplicationEntity
}
)

Expand All @@ -173,7 +171,7 @@ export const createApplication = createAsyncThunk(
response = await jobsApi.createJob(payload.environmentId, payload.data as JobRequest)
}

return response.data as Application | ContainerResponse | JobResponse
return response.data as ApplicationEntity
}
)

Expand Down Expand Up @@ -295,7 +293,7 @@ export const editApplicationAdvancedSettings = createAsyncThunk<
})

export const fetchDefaultApplicationAdvancedSettings = createAsyncThunk<
ApplicationAdvancedSettings | JobAdvancedSettings,
AdvancedSettings,
{
serviceType: ServiceTypeEnum
}
Expand Down Expand Up @@ -374,7 +372,7 @@ export const applicationsSlice = createSlice({
state.loadingStatus = 'loading'
})
// fetch applications
.addCase(fetchApplications.fulfilled, (state: ApplicationsState, action: PayloadAction<Application[]>) => {
.addCase(fetchApplications.fulfilled, (state: ApplicationsState, action: PayloadAction<ApplicationEntity[]>) => {
applicationsAdapter.upsertMany(state, action.payload)
action.payload.forEach((app) => {
state.joinEnvApplication = addOneToManyRelation(app.environment?.id, app.id, { ...state.joinEnvApplication })
Expand All @@ -390,7 +388,7 @@ export const applicationsSlice = createSlice({
state.loadingStatus = 'loading'
})
.addCase(editApplication.fulfilled, (state: ApplicationsState, action) => {
const update: Update<Application> = {
const update: Update<ApplicationEntity> = {
id: action.meta.arg.applicationId,
changes: {
...action.payload,
Expand Down Expand Up @@ -449,7 +447,7 @@ export const applicationsSlice = createSlice({
},
})
)
applicationsAdapter.updateMany(state, update as Update<Application>[])
applicationsAdapter.updateMany(state, update as Update<ApplicationEntity>[])
state.statusLoadingStatus = 'loaded'
})
.addCase(fetchApplicationsStatus.rejected, (state: ApplicationsState, action) => {
Expand Down Expand Up @@ -568,8 +566,7 @@ export const applicationsSlice = createSlice({
changes: {
advanced_settings: {
loadingStatus: 'loading',
current_settings: (state.entities[applicationId] as GitApplicationEntity)?.advanced_settings
?.current_settings,
current_settings: state.entities[applicationId]?.advanced_settings?.current_settings,
},
},
}
Expand All @@ -582,7 +579,7 @@ export const applicationsSlice = createSlice({
changes: {
advanced_settings: {
loadingStatus: 'loaded',
current_settings: action.payload as ApplicationAdvancedSettings,
current_settings: action.payload,
},
},
}
Expand All @@ -603,11 +600,11 @@ export const applicationsSlice = createSlice({
changes: {
advanced_settings: {
loadingStatus: 'error',
current_settings: (state.entities[applicationId] as GitApplicationEntity)?.advanced_settings
?.current_settings,
current_settings: state.entities[applicationId]?.advanced_settings?.current_settings,
},
},
}

toast(
ToastEnum.ERROR,
`Your advanced settings have not been updated. Something must be wrong with the values provided`
Expand Down Expand Up @@ -663,7 +660,7 @@ export const applicationsSlice = createSlice({
},
},
}
applicationsAdapter.updateOne(state, update as Update<Application>)
applicationsAdapter.updateOne(state, update as Update<ApplicationEntity>)
})
.addCase(fetchApplicationDeployments.fulfilled, (state: ApplicationsState, action) => {
const update = {
Expand All @@ -675,7 +672,7 @@ export const applicationsSlice = createSlice({
},
},
}
applicationsAdapter.updateOne(state, update as Update<Application>)
applicationsAdapter.updateOne(state, update as Update<ApplicationEntity>)
})
.addCase(fetchApplicationDeployments.rejected, (state: ApplicationsState, action) => {
const update = {
Expand All @@ -686,7 +683,7 @@ export const applicationsSlice = createSlice({
},
},
}
applicationsAdapter.updateOne(state, update as Update<Application>)
applicationsAdapter.updateOne(state, update as Update<ApplicationEntity>)
})
// get application status
.addCase(fetchApplicationStatus.pending, (state: ApplicationsState, action) => {
Expand All @@ -698,7 +695,7 @@ export const applicationsSlice = createSlice({
},
},
}
applicationsAdapter.updateOne(state, update as Update<Application>)
applicationsAdapter.updateOne(state, update as Update<ApplicationEntity>)
})
.addCase(fetchApplicationStatus.fulfilled, (state: ApplicationsState, action) => {
const update = {
Expand All @@ -707,7 +704,7 @@ export const applicationsSlice = createSlice({
status: action.payload,
},
}
applicationsAdapter.updateOne(state, update as Update<Application>)
applicationsAdapter.updateOne(state, update as Update<ApplicationEntity>)
state.statusLoadingStatus = 'loaded'
})
.addCase(fetchApplicationStatus.rejected, (state: ApplicationsState, action) => {
Expand Down Expand Up @@ -741,7 +738,7 @@ export const selectApplicationsEntities = createSelector(getApplicationsState, s

export const selectApplicationsEntitiesByEnvId = (state: RootState, environmentId: string): ApplicationEntity[] => {
const appState = getApplicationsState(state)
return getEntitiesByIds<Application>(appState.entities, appState?.joinEnvApplication[environmentId])
return getEntitiesByIds<ApplicationEntity>(appState.entities, appState?.joinEnvApplication[environmentId])
}

export const selectApplicationById = (state: RootState, applicationId: string): ApplicationEntity | undefined =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,28 @@ import { useSelector } from 'react-redux'
import { useParams } from 'react-router-dom'
import { getApplicationsState, getCountNewCommitsToDeploy } from '@qovery/domains/application'
import { isJob } from '@qovery/shared/enums'
import { GitApplicationEntity, JobApplicationEntity, LoadingStatus } from '@qovery/shared/interfaces'
import { ApplicationEntity, LoadingStatus } from '@qovery/shared/interfaces'
import { RootState } from '@qovery/store'
import LastCommit from '../../ui/last-commit/last-commit'

export function LastCommitFeature() {
const { applicationId = '' } = useParams()
const commitDeltaCount = useSelector(getCountNewCommitsToDeploy(applicationId))
const application = useSelector<RootState, GitApplicationEntity | undefined>(
(state) => getApplicationsState(state).entities[applicationId] as GitApplicationEntity | undefined
const application = useSelector<RootState, ApplicationEntity | undefined>(
(state) => getApplicationsState(state).entities[applicationId]
)

const getCommitById = (commits?: Commit[]) => {
const deployedCommitId = isJob(application)
? (application as JobApplicationEntity).source?.docker?.git_repository?.deployed_commit_id
? application?.source?.docker?.git_repository?.deployed_commit_id
: application?.git_repository?.deployed_commit_id

const deployedCommit = commits?.find((commit) => commit.git_commit_id === deployedCommitId)

if (deployedCommit) {
return deployedCommit
} else {
return isJob(application)
? (application as JobApplicationEntity).source?.docker?.git_repository
: application?.git_repository
return isJob(application) ? application?.source?.docker?.git_repository : application?.git_repository
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ApplicationAdvancedSettings, JobAdvancedSettings } from 'qovery-typescript-axios'
import { ServiceTypeEnum, isApplication, isContainer, isJob } from '@qovery/shared/enums'
import { GitApplicationEntity, JobApplicationEntity } from '@qovery/shared/interfaces'
import { ApplicationEntity, GitApplicationEntity } from '@qovery/shared/interfaces'

export function initFormValues(
keys: string[],
application: GitApplicationEntity | JobApplicationEntity,
application: ApplicationEntity,
serviceType: ServiceTypeEnum
): { [key: string]: string } {
const values: { [key: string]: string } = {}
Expand All @@ -16,7 +16,7 @@ export function initFormValues(
values[key] = currentSettings[key as keyof ApplicationAdvancedSettings]?.toString() || ''
}
} else if (isJob(serviceType)) {
const currentSettings = (application as JobApplicationEntity)?.advanced_settings?.current_settings
const currentSettings = application?.advanced_settings?.current_settings
if (currentSettings) {
values[key] = currentSettings[key as keyof JobAdvancedSettings]?.toString() || ''
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { JobAdvancedSettings } from 'qovery-typescript-axios'
import React from 'react'
import * as storeApplication from '@qovery/domains/application'
import { cronjobFactoryMock } from '@qovery/domains/application'
import { GitApplicationEntity, JobApplicationEntity } from '@qovery/shared/interfaces'
import { JobApplicationEntity } from '@qovery/shared/interfaces'
import * as InitFormValues from './init-form-values/init-form-values'
import PageSettingsAdvancedFeature from './page-settings-advanced-feature'

Expand Down Expand Up @@ -61,7 +61,7 @@ describe('PageSettingsAdvancedFeature', () => {
let promise: Promise

beforeEach(() => {
;(mockApplication as JobApplicationEntity).advanced_settings = {
mockApplication.advanced_settings = {
loadingStatus: 'not loaded',
current_settings: mockAdvancedSettings,
}
Expand Down Expand Up @@ -96,7 +96,7 @@ describe('PageSettingsAdvancedFeature', () => {
})

it('should dispatch fetchApplicationAdvancedSettings if advanced_settings does not exist', async () => {
;(mockApplication as GitApplicationEntity).advanced_settings = undefined
mockApplication.advanced_settings = undefined
const fetchApplicationAdvancedSettingsSpy: SpyInstance = jest.spyOn(
storeApplication,
'fetchApplicationAdvancedSettings'
Expand All @@ -111,26 +111,26 @@ describe('PageSettingsAdvancedFeature', () => {

// I think the useForm hook also use useState, this is why the first 4th call are to ignored. https://gist.github.com/mauricedb/eb2bae5592e3ddc64fa965cde4afe7bc
it('should set the keys if application and advanced_settings are defined', async () => {
;(mockApplication as GitApplicationEntity).advanced_settings!.loadingStatus = 'loaded'
mockApplication.advanced_settings!.loadingStatus = 'loaded'
jest.spyOn(React, 'useState').mockImplementation(useStateMock)
render(<PageSettingsAdvancedFeature />)
expect(setState).toHaveBeenNthCalledWith(
10,
Object.keys((mockApplication as GitApplicationEntity).advanced_settings?.current_settings || {}).sort()
Object.keys(mockApplication.advanced_settings?.current_settings || {}).sort()
)
await act(async () => {
await promise
})
})

it('should dispatch editApplicationAdvancedSettings if form is submitted', async () => {
;(mockApplication as GitApplicationEntity).advanced_settings!.loadingStatus = 'loaded'
mockApplication.advanced_settings!.loadingStatus = 'loaded'
const editApplicationAdvancedSettingsSpy: SpyInstance = jest.spyOn(
storeApplication,
'editApplicationAdvancedSettings'
)

const { getByLabelText, getByTestId, baseElement, debug } = render(<PageSettingsAdvancedFeature />)
const { getByLabelText, getByTestId } = render(<PageSettingsAdvancedFeature />)

await act(() => {
const input = getByLabelText('cronjob.success_jobs_history_limit')
Expand All @@ -149,9 +149,7 @@ describe('PageSettingsAdvancedFeature', () => {
getByTestId('submit-button').click()
})

expect(editApplicationAdvancedSettingsSpy.mock.calls[0][0].applicationId).toBe(
(mockApplication as GitApplicationEntity).id
)
expect(editApplicationAdvancedSettingsSpy.mock.calls[0][0].applicationId).toBe(mockApplication.id)
expect(editApplicationAdvancedSettingsSpy.mock.calls[0][0].settings).toStrictEqual({
'liveness_probe.http_get.path': '/',
'cronjob.success_jobs_history_limit': 63,
Expand All @@ -164,7 +162,7 @@ describe('PageSettingsAdvancedFeature', () => {
})

it('should init the form', async () => {
;(mockApplication as GitApplicationEntity).advanced_settings!.loadingStatus = 'loaded'
mockApplication.advanced_settings!.loadingStatus = 'loaded'
const spy = jest.spyOn(InitFormValues, 'initFormValues')
render(<PageSettingsAdvancedFeature />)
expect(spy).toHaveBeenCalled()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ApplicationAdvancedSettings, JobAdvancedSettings } from 'qovery-typescript-axios'
import { useEffect, useState } from 'react'
import { FormProvider, useForm } from 'react-hook-form'
import { useDispatch, useSelector } from 'react-redux'
Expand All @@ -12,7 +11,7 @@ import {
selectApplicationById,
} from '@qovery/domains/application'
import { ServiceTypeEnum, getServiceType } from '@qovery/shared/enums'
import { GitApplicationEntity, JobApplicationEntity } from '@qovery/shared/interfaces'
import { AdvancedSettings, ApplicationEntity } from '@qovery/shared/interfaces'
import { objectFlattener } from '@qovery/shared/utils'
import { AppDispatch, RootState } from '@qovery/store'
import PageSettingsAdvanced from '../../ui/page-settings-advanced/page-settings-advanced'
Expand All @@ -21,13 +20,13 @@ import { initFormValues } from './init-form-values/init-form-values'
export function PageSettingsAdvancedFeature() {
const { applicationId = '', environmentId = '' } = useParams()

const application = useSelector<RootState, GitApplicationEntity | JobApplicationEntity | undefined>(
const application = useSelector<RootState, ApplicationEntity | undefined>(
(state) => selectApplicationById(state, applicationId),
(a, b) => {
return a?.id === b?.id && a?.advanced_settings?.loadingStatus === b?.advanced_settings?.loadingStatus
}
)
const defaultSettings = useSelector<RootState, ApplicationAdvancedSettings | JobAdvancedSettings | undefined>(
const defaultSettings = useSelector<RootState, AdvancedSettings | undefined>(
(state) => getApplicationsState(state).defaultApplicationAdvancedSettings.settings
)
const [keys, setKeys] = useState<string[]>([])
Expand Down Expand Up @@ -99,9 +98,7 @@ export function PageSettingsAdvancedFeature() {
// so if field is empty string replace by value found in defaultSettings (because default value is well typed)
Object.keys(dataFormatted).forEach((key) => {
if (dataFormatted[key] === '') {
dataFormatted[key] = defaultSettings
? defaultSettings[key as keyof (ApplicationAdvancedSettings | JobAdvancedSettings)]
: ''
dataFormatted[key] = defaultSettings ? defaultSettings[key as keyof AdvancedSettings] : ''
}
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useDispatch, useSelector } from 'react-redux'
import { useParams } from 'react-router-dom'
import { editApplication, postApplicationActionsRestart, selectApplicationById } from '@qovery/domains/application'
import { ServiceTypeEnum, getServiceType, isCronJob, isLifeCycleJob } from '@qovery/shared/enums'
import { ApplicationEntity, JobApplicationEntity, JobConfigureData } from '@qovery/shared/interfaces'
import { ApplicationEntity, JobConfigureData } from '@qovery/shared/interfaces'
import { toastError } from '@qovery/shared/toast'
import { AppDispatch, RootState } from '@qovery/store'
import PageSettingsConfigureJob from '../../ui/page-settings-configure-job/page-settings-configure-job'
Expand All @@ -13,12 +13,12 @@ export function PageSettingsConfigureJobFeature() {
const { applicationId = '', environmentId = '' } = useParams()
const methods = useForm<JobConfigureData>({ mode: 'onChange' })

const application: JobApplicationEntity | undefined = useSelector<RootState, ApplicationEntity | undefined>(
const application: ApplicationEntity | undefined = useSelector<RootState, ApplicationEntity | undefined>(
(state) => selectApplicationById(state, applicationId),
(a, b) => {
return JSON.stringify(a?.id) === JSON.stringify(b?.id)
}
) as JobApplicationEntity | undefined
) as ApplicationEntity | undefined

const [loading, setLoading] = useState(false)

Expand Down

0 comments on commit 5dd4665

Please sign in to comment.