-
Notifications
You must be signed in to change notification settings - Fork 27
feat: Add useTopics model hook and query for topics listing #136
base: main
Are you sure you want to change the base?
Conversation
PR ReportBundle SizesView bundle sizes for 'client'
Overall bundle size change: 0.47%View bundle sizes for 'server'
Overall bundle size change: 0.16%Test CoverageView test coverage
Triggered by commit: a4c0f81 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this Andy!
The core code looks good - as per the doc however, the model hook should be private, and defined in the 'Topics' panel component (along with tests to match/align). I also think a few capabilities may be need adding to the hook too.
Other than that, this LGTM
client/Models/README.md
Outdated
@@ -0,0 +1,37 @@ | |||
# Models |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The model for a Panel/Group is a hook, but really should be a private one - ie useTopics
(I would suggest a rename to useTopicModel
to be hyper picky) would be defined in a Model.ts
file in the Topics Panel (and not exported as it is private/internals).
As for testing, Panels are meant to be behaviourally tested. Ie, a table with data appears with the expected info. As there is no UI (yet), thus no table, it makes asserting (indirectly) that the model is behaving abit more obtuse. I think what would be sensible is to add a placeholder View.patternfly.ts
/View.carbon.ts
, which just stringifies the model output. Then, tests can assert the right data is present (just not in a table), which can then be updated when the component work comes along
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to confirm - models live inside the component that needs them, whereas reusable hooks go in the hooks
dir?
Therefore, useTopics
is a particular hook (if we want to encapsulate for reuse) - and the Model
can either call useTopics
or just the default useQuery
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to confirm - models live inside the component that needs them, whereas reusable hooks go in the
hooks
dir?Therefore,
useTopics
is a particular hook (if we want to encapsulate for reuse) - and theModel
can either calluseTopics
or just the defaultuseQuery
?
Yes - absolutley. If the intent was to have a reusable hook representing/abstracting the query, than that should be in Hooks
. Given the context (and other changes), I reviewed/interpreted it as a model hook - and that (as is), model hooks are defined with their components, not in their own section (so I am expecting the code to move, and this readme to be removed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rearranged/refactored the code into a private hook in the Topics panel component.
client/Models/useTopics/Hook.ts
Outdated
import { useTopicsType } from './useTopics.types'; | ||
|
||
export const useTopics = (): useTopicsType => { | ||
const useGetTopics = () => useQuery(GET_TOPICS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would cross reference the behviours described here: #70 (comment)
I think we will need to also have a variable for topic name, which gets debounced etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should also add, the consumer of the model is the view. Within reason, if there are things the model can do to make the view as simple as possible (eg if no data returning an empty array), or obfiscate (loading, error states etc) that would be good too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have added client-side filter handling for the topics listing. The mockapi server doesn't support this yet, so it currently doesn't make any difference when running the webpack-dev-server, but you can see the filter input field changes are debounced correctly by watching the network calls..
client/Models/README.md
Outdated
|
||
## Test approach | ||
|
||
Elements should be tested in a functional manor. See [Test Driven Development](../../docs/Test.md#style-of-test). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Elements should be tested in a functional manor. See [Test Driven Development](../../docs/Test.md#style-of-test). | |
Elements should be tested in a functional manner. See [Test Driven Development](../../docs/Test.md#style-of-test). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed - along with all the others :)
client/Panels/Home/Home.tsx
Outdated
return ( | ||
<div className='home'> | ||
<img src={image} alt='Strimzi logo' /> | ||
<p>Welcome to the Strimzi UI</p> | ||
{showVersion && isComplete && <p>{`Version: ${version}`}</p>} | ||
{loading || !data ? ( | ||
<p>Loading...</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Translation ;)
client/Models/README.md
Outdated
@@ -0,0 +1,37 @@ | |||
# Models |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to confirm - models live inside the component that needs them, whereas reusable hooks go in the hooks
dir?
Therefore, useTopics
is a particular hook (if we want to encapsulate for reuse) - and the Model
can either call useTopics
or just the default useQuery
?
- This commit adds a new `useTopics` model hook, which makes GraphQL requests to the server to administer Kafka topics. - The hook returns a set of sub-hooks, with just the `useGetTopics` sub-hook implemented for now. `useGetTopics` returns the list of topics (including name, number of partitions and number of replicas). Contributes to: strimzi#124 Signed-off-by: Andrew Borley <[email protected]>
- Addresses initial review comments. Contributes to: strimzi#124 Signed-off-by: Andrew Borley <[email protected]>
70105af
to
1da8fda
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple of minor comments
@@ -52,7 +52,7 @@ When('it is rendered with no version', () => { | |||
showVersionSet = false; | |||
}); | |||
|
|||
Then('it should display the expected text', () => { | |||
Then('it should display the expected text', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wont block the PR on it, but was this intended?
fireEvent.change(renderResult.getByPlaceholderText('filter'), { | ||
target: { value: filter }, | ||
}); | ||
await waitFor(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My personal preference would be that rather than using mock timers, we use the apollo helpers, eg
await apolloMockResponse(); // tick for data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
* Copyright Strimzi authors. | ||
* License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). | ||
*/ | ||
import { generateMockDataResponseForGQLRequest } from 'utils/test/withApollo/withApollo.util'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import { generateMockDataResponseForGQLRequest } from 'utils/test'
?
describe('`useTopics` hook', () => { | ||
describe('`useGetTopics` hook', () => { | ||
beforeEach(() => { | ||
jest.useFakeTimers(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment here re use of helper functions, and not to control timers
client/Panels/Topics/Model.ts
Outdated
}; | ||
|
||
return { | ||
useGetTopics, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting (and not what I expected - not to say that is wrong!). I expected that we would also be owning/exporting the state for the filter - ie its value and function to update it, which in fact is a (lodash) debounced version. When that debounce clears, then the value is set, firing the query. Does this mean the view is making use of a useState
call to track the filter value?
Edit: having seen the code below, I see this is the case. My preference would be the Model does all hook work, and that the view imports as few hooks as possible (for easy sharing of the business logic/keeping the view layers thin)
- Based on review comments from @matthew-chirgwin Contributes to: strimzi#124 Signed-off-by: Andrew Borley <[email protected]>
@matthew-chirgwin - I have pushed up a new commit based on your suggestions. It seems to work fine in webpack-dev-server and the e2e server, and tests are passing, but I'm getting an eslint warning that I haven't been able to get past so far. |
|
||
init(); //Bootstrap i18next support | ||
ReactDOM.render( | ||
<ApolloProvider client={apolloClient}> | ||
<ConfigFeatureFlagProvider> | ||
<LoggingProvider> | ||
<FeatureFlag flag={'client.Pages.PlaceholderHome'}> | ||
<Home /> | ||
<Home> | ||
<Topics /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a router, not hard coding like this.
import debounce from 'lodash.debounce'; | ||
|
||
const onChangeEvent = ( | ||
evt: ChangeEvent<HTMLInputElement>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use html events here, it breaks the MVVC abstraction. Use scalar types or add an abstraction.
debounce(setTopicsFilter, 500), | ||
[] | ||
); | ||
const { data, loading, error } = useQuery<topicsType>(GET_TOPICS, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Types start with capital letters.
fireEvent.change(renderResult.getByPlaceholderText('filter'), { | ||
target: { value: filter }, | ||
}); | ||
await waitFor(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
name: string; | ||
partitions: number; | ||
replicas: number; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the types generated by the Rama's PR here.
replicas | ||
} | ||
} | ||
`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not valid graphql schema - update to latest schema from admin server.
useTopics
model hook, which makes GraphQLrequests to the server to administer Kafka topics.
useGetTopics
sub-hook implemented for now.
useGetTopics
returns the list of topics(including name, number of partitions and number of replicas).
Contributes to: #124
Signed-off-by: Andrew Borley [email protected]