From ff6b28487a587aae104fabe6a382cf9dd85efc1e Mon Sep 17 00:00:00 2001 From: Oleg Shuralev Date: Wed, 8 Jan 2020 15:19:52 +0300 Subject: [PATCH] [UI] Normalize Topic State --- .../common/Breadcrumb/Breadcrumb.tsx | 2 +- frontend/src/redux/reducers/topics/reducer.ts | 20 ++++++++--- .../src/redux/reducers/topics/selectors.ts | 33 +++++++++---------- frontend/src/theme/bulma_overrides.scss | 26 +++++++++++++++ frontend/src/theme/index.scss | 16 --------- frontend/src/types/index.ts | 4 +-- frontend/src/types/topic.ts | 5 +++ 7 files changed, 65 insertions(+), 41 deletions(-) diff --git a/frontend/src/components/common/Breadcrumb/Breadcrumb.tsx b/frontend/src/components/common/Breadcrumb/Breadcrumb.tsx index 215917c30c..addce4d4bd 100644 --- a/frontend/src/components/common/Breadcrumb/Breadcrumb.tsx +++ b/frontend/src/components/common/Breadcrumb/Breadcrumb.tsx @@ -24,7 +24,7 @@ const Breadcrumb: React.FC = ({ ))}
  • - {children} + {children}
  • diff --git a/frontend/src/redux/reducers/topics/reducer.ts b/frontend/src/redux/reducers/topics/reducer.ts index 804e612eee..12c86f07e6 100644 --- a/frontend/src/redux/reducers/topics/reducer.ts +++ b/frontend/src/redux/reducers/topics/reducer.ts @@ -1,12 +1,24 @@ -import { Topic, Action } from 'types'; +import { Action, TopicsState } from 'types'; import actionType from 'redux/reducers/actionType'; -export const initialState: Topic[] = []; +export const initialState: TopicsState = { + byName: {}, + allNames: [], +}; -const reducer = (state = initialState, action: Action): Topic[] => { +const reducer = (state = initialState, action: Action): TopicsState => { switch (action.type) { case actionType.GET_TOPICS__SUCCESS: - return action.payload; + return action.payload.reduce( + (memo, topic) => { + const { name } = topic; + memo.byName[name] = topic; + memo.allNames.push(name); + + return memo; + }, + initialState, + ); default: return state; } diff --git a/frontend/src/redux/reducers/topics/selectors.ts b/frontend/src/redux/reducers/topics/selectors.ts index de7b4143e5..69c8061f8a 100644 --- a/frontend/src/redux/reducers/topics/selectors.ts +++ b/frontend/src/redux/reducers/topics/selectors.ts @@ -1,8 +1,11 @@ import { createSelector } from 'reselect'; -import { RootState, Topic, TopicName, FetchStatus } from 'types'; +import { RootState, TopicName, FetchStatus, TopicsState } from 'types'; import { createFetchingSelector } from 'redux/reducers/loader/selectors'; -const topicsState = ({ topics }: RootState): Topic[] => topics; +const topicsState = ({ topics }: RootState): TopicsState => topics; + +const getAllNames = (state: RootState) => topicsState(state).allNames; +const getTopicMap = (state: RootState) => topicsState(state).byName; const getTopicListFetchingStatus = createFetchingSelector('GET_TOPICS'); @@ -13,8 +16,15 @@ export const getIsTopicListFetched = createSelector( export const getTopicList = createSelector( getIsTopicListFetched, - topicsState, - (isFetched, topics) => isFetched ? topics : [], + getAllNames, + getTopicMap, + (isFetched, allNames, byName) => { + if (isFetched) { + return allNames.map((name) => byName[name]) + } + + return []; + }, ); export const getExternalTopicList = createSelector( @@ -22,23 +32,10 @@ export const getExternalTopicList = createSelector( (topics) => topics.filter(({ internal }) => !internal), ); -interface TopicMap {[key: string]: Topic}; - -export const getTopicMap = createSelector( - getTopicList, - (topics) => topics.reduce( - (memo: TopicMap, topic: Topic): TopicMap => ({ - ...memo, - [topic.name]: { ...topic }, - }), - {}, - ) -); - const getTopicName = (_: RootState, topicName: TopicName) => topicName; export const getTopicByName = createSelector( getTopicMap, getTopicName, - (topics: TopicMap, topicName: TopicName) => topics[topicName], + (topics, topicName) => topics[topicName], ); diff --git a/frontend/src/theme/bulma_overrides.scss b/frontend/src/theme/bulma_overrides.scss index 484343687b..5bd74bb8d4 100644 --- a/frontend/src/theme/bulma_overrides.scss +++ b/frontend/src/theme/bulma_overrides.scss @@ -6,3 +6,29 @@ @import "../../node_modules/bulma/sass/grid/_all.sass"; @import "../../node_modules/bulma/sass/layout/_all.sass"; @import "../../node_modules/bulma-switch/src/sass/index.sass"; + +.has-text-overflow-ellipsis { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.breadcrumb li { + &.is-active > span { + padding: 0 0.75em; + } + + &:first-child > span { + padding-left: 0; + } +} + +.section { + animation: fadein .5s; +} + +@keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} diff --git a/frontend/src/theme/index.scss b/frontend/src/theme/index.scss index 9333946176..857c61f7ca 100644 --- a/frontend/src/theme/index.scss +++ b/frontend/src/theme/index.scss @@ -31,19 +31,3 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } - -.has-text-overflow-ellipsis { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.section { - animation: fadein .5s; -} - -@keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 6a85a9b0a6..62a6f81d24 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -6,7 +6,7 @@ import * as topicsActions from 'redux/reducers/topics/actions'; import * as clustersActions from 'redux/reducers/clusters/actions'; import * as brokersActions from 'redux/reducers/brokers/actions'; -import { Topic } from './topic'; +import { TopicsState } from './topic'; import { Cluster } from './cluster'; import { BrokersState } from './broker'; import { LoaderState } from './loader'; @@ -24,7 +24,7 @@ export enum FetchStatus { } export interface RootState { - topics: Topic[]; + topics: TopicsState; clusters: Cluster[]; brokers: BrokersState; loader: LoaderState; diff --git a/frontend/src/types/topic.ts b/frontend/src/types/topic.ts index 070cca8bae..ea08bed523 100644 --- a/frontend/src/types/topic.ts +++ b/frontend/src/types/topic.ts @@ -20,3 +20,8 @@ export interface Topic { internal: boolean; partitions: TopicPartition[]; } + +export interface TopicsState { + byName: { [topicName: string]: Topic }, + allNames: TopicName[], +}