Skip to content
Snippets Groups Projects
device.reducer.ts 4.77 KiB
Newer Older
  • Learn to ignore specific revisions
  • import {
        NetworkelementFlattenedManagedNetworkElement,
        NetworkelementManagedNetworkElement,
    
        PndPrincipalNetworkDomain
    
    } from '@api/api'
    import { DeviceViewTabValues } from '@component/devices/view/device.view.tabs'
    
    import { createSlice, PayloadAction } from '@reduxjs/toolkit'
    
    import { REHYDRATE } from 'redux-persist'
    
    import { RootState } from 'src/stores'
    import '../routines/index'
    import { startListening } from '/src/stores/middleware/listener.middleware'
    
    export type Device = NetworkelementFlattenedManagedNetworkElement
    
    interface SelectedObject {
    
        mne: NetworkelementManagedNetworkElement | null
    
        json: JSON | null
    
    export interface DeviceSliceState {
    
        devices: Device[]
        pnds: PndPrincipalNetworkDomain[]
    
        activeTab: DeviceViewTabValues
    
        selected: SelectedObject | null
    
    }
    
    const initialState: DeviceSliceState = {
        devices: [],
    
        pnds: [],
    
        activeTab: DeviceViewTabValues.METADATA,
    
    interface SetSelectedDeviceType {
        device: Device | null,
        options?: {
            bypassCheck: boolean
        }
    }
    
    
    const deviceSlice = createSlice({
        name: 'device',
        initialState,
        reducers: {
    
            setDevices: (state, action: PayloadAction<Device[] | undefined>) => {
                state.devices = action.payload || []
    
            setPnds: (state, action: PayloadAction<PndPrincipalNetworkDomain[] | undefined>) => {
                state.pnds = action.payload || []
    
            },
            setActiveTab: (state, action: PayloadAction<DeviceViewTabValues>) => {
                state.activeTab = action.payload
            },
    
            setSelectedDevice: {
    
                reducer: (state, { payload, meta }: PayloadAction<SetSelectedDeviceType, string, { skipListener?: boolean }>) => {
                    /**
                     * Do nothing if desired device is already selected
                     * Bypass the check if the flag is set to true. We
                     * use this bypass to trigger the listener functions
                     * accordingly
                     */
                    if (!payload?.options?.bypassCheck && state.selected?.device.id === payload.device?.id) {
                        meta.skipListener = true
    
                    if (!payload.device) {
                        throw Error('Passed null device as parameter while bypassing the safety check')
                    }
    
                    let selectedObject: SelectedObject | null = null;
                    if (payload) {
                        selectedObject = { device: payload.device, mne: null, json: null }
    
                    state.selected = selectedObject
                },
    
                prepare: (payload) => {
    
                        payload,
                        meta: { skipListener: false }
    
            },
            setSelectedMne: (state, action: PayloadAction<NetworkelementManagedNetworkElement>) => {
    
                if (!state.selected) {
                    throw new Error('Can not find corresponding device')
                }
    
                // safety check to prevent possible race conditions
                if (state.selected.device.id !== action.payload.id) {
                    // TODO proper error handling by retry fetching the device object
                    throw new Error('Device and mne id does not match')
    
                state.selected.mne = action.payload
    
            },
    
            setSelectedJson: (state, action: PayloadAction<JSON>) => {
    
                if (!state.selected) {
    
                    throw new Error('Selected Device is null where it shouldn´t be null')
                }
    
    
                state.selected.json = action.payload || null
    
    export const { setDevices, setActiveTab, setSelectedDevice, setSelectedMne, setSelectedJson, setPnds } =
    
        deviceSlice.actions
    
    export const deviceReducerPath = deviceSlice.reducerPath
    
    // add default selected device if no selected device is set
    startListening({
        predicate: (action) => setDevices.match(action),
        effect: async (action, listenerApi) => {
    
            const { device: state } = listenerApi.getOriginalState() as RootState
    
            if (state.selected) {
    
    
            // if there are no devices available do set null
    
            const device = action.payload?.[0] || null
            listenerApi.dispatch(setSelectedDevice({ device } as SetSelectedDeviceType))
    
    
    
    /**
     * On startup reset the selected device 
     */
    startListening({
        predicate: ({ type }: any) => type === REHYDRATE,
        effect: async (_, listenerApi) => {
            const { device: state } = listenerApi.getState() as RootState
            const device = state.selected?.device
            if (!device) {
                return
            }
    
            listenerApi.dispatch(setSelectedDevice({ device, options: { bypassCheck: true } } as SetSelectedDeviceType))
        },
    })