Skip to content

Commit

Permalink
chore(chat): split models.reducers.ts to types, selectors and reduc…
Browse files Browse the repository at this point in the history
…ers (#2958)
  • Loading branch information
IlyaBondar authored Jan 20, 2025
1 parent 345c989 commit 5048d44
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 163 deletions.
168 changes: 5 additions & 163 deletions apps/chat/src/store/models/models.reducers.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,29 @@
import { PayloadAction, createSelector, createSlice } from '@reduxjs/toolkit';
import { PayloadAction, createSlice } from '@reduxjs/toolkit';

import { combineEntities } from '@/src/utils/app/common';
import { canWriteSharedWithMe } from '@/src/utils/app/share';
import { translate } from '@/src/utils/app/translation';

import { ApplicationInfo, ApplicationStatus } from '@/src/types/applications';
import { EntityType } from '@/src/types/common';
import { ErrorMessage } from '@/src/types/error';
import {
DialAIEntityModel,
InstalledModel,
ModelsMap,
PublishRequestDialAIEntityModel,
} from '@/src/types/models';

import { RECENT_MODELS_COUNT } from '@/src/constants/chat';
import { errorsMessages } from '@/src/constants/errors';
import { DeleteType } from '@/src/constants/marketplace';

import { RootState } from '../index';
import * as ModelsSelectors from './models.selectors';
import { ModelsState } from './models.types';

import { UploadStatus } from '@epam/ai-dial-shared';
import { sortBy } from 'lodash-es';
import cloneDeep from 'lodash-es/cloneDeep';
import groupBy from 'lodash-es/groupBy';
import omit from 'lodash-es/omit';
import orderBy from 'lodash-es/orderBy';
import uniq from 'lodash-es/uniq';

export interface ModelsState {
initialized: boolean;
status: UploadStatus;
error: ErrorMessage | undefined;
models: DialAIEntityModel[];
modelsMap: ModelsMap;
recentModelsIds: string[];
recentModelsStatus: UploadStatus;
isInstalledModelsInitialized: boolean;
installedModels: InstalledModel[];
publishRequestModels: PublishRequestDialAIEntityModel[];
publishedApplicationIds: string[];
}
export { ModelsSelectors };

const initialState: ModelsState = {
initialized: false,
Expand Down Expand Up @@ -132,6 +115,7 @@ export const modelsSlice = createSlice({
: [translate(errorsMessages.generalServer, { ns: 'common' })],
} as ErrorMessage;
},

initRecentModels: (
state,
{
Expand Down Expand Up @@ -319,146 +303,4 @@ export const modelsSlice = createSlice({
},
});

const rootSelector = (state: RootState): ModelsState => state.models;

const selectModelsIsLoading = createSelector([rootSelector], (state) => {
return (
state.status === UploadStatus.LOADING ||
state.status === UploadStatus.UNINITIALIZED
);
});

const selectIsModelsLoaded = createSelector([rootSelector], (state) => {
return state.status === UploadStatus.LOADED;
});

const selectIsInstalledModelsInitialized = createSelector(
[rootSelector],
(state) => {
return state.isInstalledModelsInitialized;
},
);

const selectModelsError = createSelector([rootSelector], (state) => {
return state.error;
});

const selectIsRecentModelsLoaded = createSelector([rootSelector], (state) => {
return state.recentModelsStatus === UploadStatus.LOADED;
});

const selectModels = createSelector([rootSelector], (state) => {
const groups = groupBy(state.models, (model) =>
model.reference === model.id ? 'rest' : 'custom',
);

return sortBy(
[
...(groups.rest ?? []),
...orderBy(groups.custom ?? [], 'version', 'desc'),
],
(model) => model.name.toLowerCase(),
);
});

const selectModelTopics = createSelector([rootSelector], (state) => {
return uniq(
state.models?.flatMap((model) => model.topics ?? []) ?? [],
).sort();
});

const selectModelsMap = createSelector([rootSelector], (state) => {
return state.modelsMap;
});
const selectRecentModelsIds = createSelector([rootSelector], (state) => {
return state.recentModelsIds;
});

const selectRecentModels = createSelector(
[selectRecentModelsIds, selectModelsMap],
(recentModelsIds, modelsMap) => {
return recentModelsIds.map((id) => modelsMap[id]).filter(Boolean);
},
);

const selectModelsOnly = createSelector([selectModels], (models) => {
return models.filter((model) => model.type === EntityType.Model);
});

const selectPublishRequestModels = createSelector([rootSelector], (state) => {
return state.publishRequestModels;
});

const selectPublishedApplicationIds = createSelector(
[rootSelector],
(state) => {
return state.publishedApplicationIds;
},
);

const selectInstalledModels = createSelector([rootSelector], (state) => {
return state.installedModels;
});

const selectInstalledModelIds = createSelector([rootSelector], (state) => {
return new Set(state.installedModels.map(({ id }) => id));
});

const selectRecentWithInstalledModelsIds = createSelector(
[selectRecentModelsIds, selectInstalledModelIds],
(recentModelIds, installedModelIds) => {
// TODO: implement Pin-behavior in future
const installedWithoutRecents = Array.from(installedModelIds).filter(
(id) => !recentModelIds.includes(id),
);
return [...recentModelIds, ...installedWithoutRecents];
},
);

const selectInitialized = createSelector(
[rootSelector],
(state) => state.initialized,
);

const selectCustomModels = createSelector([rootSelector], (state) => {
return state.models.filter((model) => model.reference !== model.id);
});

const selectSharedWithMeModels = createSelector(
[selectCustomModels],
(customModels) => {
return customModels.filter((model) => model.sharedWithMe);
},
);

const selectSharedWriteModels = createSelector(
[selectCustomModels],
(customModels) => {
return customModels.filter((model) => canWriteSharedWithMe(model));
},
);

export const ModelsSelectors = {
selectIsInstalledModelsInitialized,
selectIsModelsLoaded,
selectModelsIsLoading,
selectModelsError,
selectModels,
selectModelsMap,
selectCustomModels,
selectInstalledModels,
selectInstalledModelIds,
selectRecentModelsIds,
selectRecentModels,
selectIsRecentModelsLoaded,
selectModelsOnly,
selectPublishRequestModels,
selectPublishedApplicationIds,
selectModelTopics,
selectRecentWithInstalledModelsIds,
selectInitialized,
selectSharedWithMeModels,
selectSharedWriteModels,
};

export const ModelsActions = modelsSlice.actions;
143 changes: 143 additions & 0 deletions apps/chat/src/store/models/models.selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { createSelector } from '@reduxjs/toolkit';

import { canWriteSharedWithMe } from '@/src/utils/app/share';

import { EntityType } from '@/src/types/common';

import { RootState } from '../index';
import { ModelsState } from './models.types';

import { UploadStatus } from '@epam/ai-dial-shared';
import { sortBy } from 'lodash-es';
import groupBy from 'lodash-es/groupBy';
import orderBy from 'lodash-es/orderBy';
import uniq from 'lodash-es/uniq';

const rootSelector = (state: RootState): ModelsState => state.models;

export const selectModelsIsLoading = createSelector([rootSelector], (state) => {
return (
state.status === UploadStatus.LOADING ||
state.status === UploadStatus.UNINITIALIZED
);
});

export const selectIsModelsLoaded = createSelector([rootSelector], (state) => {
return state.status === UploadStatus.LOADED;
});

export const selectIsInstalledModelsInitialized = createSelector(
[rootSelector],
(state) => {
return state.isInstalledModelsInitialized;
},
);

export const selectModelsError = createSelector([rootSelector], (state) => {
return state.error;
});

export const selectIsRecentModelsLoaded = createSelector(
[rootSelector],
(state) => {
return state.recentModelsStatus === UploadStatus.LOADED;
},
);

export const selectModels = createSelector([rootSelector], (state) => {
const groups = groupBy(state.models, (model) =>
model.reference === model.id ? 'rest' : 'custom',
);

return sortBy(
[
...(groups.rest ?? []),
...orderBy(groups.custom ?? [], 'version', 'desc'),
],
(model) => model.name.toLowerCase(),
);
});

export const selectModelTopics = createSelector([rootSelector], (state) => {
return uniq(
state.models?.flatMap((model) => model.topics ?? []) ?? [],
).sort();
});

export const selectModelsMap = createSelector([rootSelector], (state) => {
return state.modelsMap;
});

export const selectRecentModelsIds = createSelector([rootSelector], (state) => {
return state.recentModelsIds;
});

export const selectRecentModels = createSelector(
[selectRecentModelsIds, selectModelsMap],
(recentModelsIds, modelsMap) => {
return recentModelsIds.map((id) => modelsMap[id]).filter(Boolean);
},
);

export const selectModelsOnly = createSelector([selectModels], (models) => {
return models.filter((model) => model.type === EntityType.Model);
});

export const selectPublishRequestModels = createSelector(
[rootSelector],
(state) => {
return state.publishRequestModels;
},
);

export const selectPublishedApplicationIds = createSelector(
[rootSelector],
(state) => {
return state.publishedApplicationIds;
},
);

export const selectInstalledModels = createSelector([rootSelector], (state) => {
return state.installedModels;
});

export const selectInstalledModelIds = createSelector(
[rootSelector],
(state) => {
return new Set(state.installedModels.map(({ id }) => id));
},
);

export const selectRecentWithInstalledModelsIds = createSelector(
[selectRecentModelsIds, selectInstalledModelIds],
(recentModelIds, installedModelIds) => {
// TODO: implement Pin-behavior in future
const installedWithoutRecents = Array.from(installedModelIds).filter(
(id) => !recentModelIds.includes(id),
);
return [...recentModelIds, ...installedWithoutRecents];
},
);

export const selectInitialized = createSelector(
[rootSelector],
(state) => state.initialized,
);

export const selectCustomModels = createSelector([rootSelector], (state) => {
return state.models.filter((model) => model.reference !== model.id);
});

export const selectSharedWithMeModels = createSelector(
[selectCustomModels],
(customModels) => {
return customModels.filter((model) => model.sharedWithMe);
},
);

export const selectSharedWriteModels = createSelector(
[selectCustomModels],
(customModels) => {
return customModels.filter((model) => canWriteSharedWithMe(model));
},
);
23 changes: 23 additions & 0 deletions apps/chat/src/store/models/models.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ErrorMessage } from '@/src/types/error';
import {
DialAIEntityModel,
InstalledModel,
ModelsMap,
PublishRequestDialAIEntityModel,
} from '@/src/types/models';

import { UploadStatus } from '@epam/ai-dial-shared';

export interface ModelsState {
initialized: boolean;
status: UploadStatus;
error: ErrorMessage | undefined;
models: DialAIEntityModel[];
modelsMap: ModelsMap;
recentModelsIds: string[];
recentModelsStatus: UploadStatus;
isInstalledModelsInitialized: boolean;
installedModels: InstalledModel[];
publishRequestModels: PublishRequestDialAIEntityModel[];
publishedApplicationIds: string[];
}

0 comments on commit 5048d44

Please sign in to comment.