-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(slo): slo edit form improvements #148419
Conversation
Pinging @elastic/actionable-observability (Team: Actionable Observability) |
a8a1e81
to
920eff0
Compare
@@ -41,7 +42,7 @@ export class UpdateSLO { | |||
|
|||
private updateSLO(originalSlo: SLO, params: UpdateSLOParams) { | |||
let hasBreakingChange = false; | |||
const updatedSlo: SLO = Object.assign({}, originalSlo, params, { updated_at: new Date() }); | |||
const updatedSlo: SLO = merge({}, originalSlo, params, { updatedAt: new Date() }); |
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.
💬 lodash's merge is better than a simple Object.assign as it merge recursively the objects
@@ -27,10 +27,10 @@ export interface SloListSearchFilterSortBarProps { | |||
onChangeIndicatorTypeFilter: (filter: FilterType[]) => void; | |||
} | |||
|
|||
export type SortType = 'name' | 'indicator_type'; | |||
export type SortType = 'name' | 'indicatorType'; |
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.
💬 Missed part of a previous refactoring from snake_case to camelCase. The values have been updated to camelCase as well.
@@ -163,19 +165,58 @@ describe('SLO Edit Page', () => { | |||
); | |||
}); | |||
|
|||
it('renders the SLO Edit page with prefilled form values if sloId route param is passed', async () => { | |||
it('calls the createSlo hook if all required values are filled in', 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.
💬 Only new test is here. Others have been slightly modified to fit the new use case (edit)
}; | ||
} | ||
|
||
export function transformValuesToUpdateSLOInput(values: CreateSLOInput): UpdateSLOInput { |
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.
💬 Duplication on purpose. They are not the same type even if UpdateSLOInput is included in (i.e. ⊂) CreateSLOInput
if (!values) return undefined; | ||
|
||
return { | ||
...values, | ||
...omit(values, ['id', 'revision', 'createdAt', 'updatedAt', 'summary']), |
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.
💬 These fields are not used by the form and must not be present in the payload for the create or update API.
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.
Does it mean whatever data we pass to the form, will be sent to the API?
If sending this information can create an issue on the API side, I am wondering if it make sense to omit these fields there as well 🤔
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 am wondering if it make sense to omit these fields there as well 🤔
omit these fields where?
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.
On the BE side.
Maybe I am missing something but I thought for fields like 'createdAt', 'updatedAt'
we always want to set them on the BE side, so I thought maybe we can ignore these fields even if FE sends them to make sure it will not create an issue.
@@ -35,7 +53,8 @@ export const SLO_EDIT_FORM_DEFAULT_VALUES: CreateSLOParams = { | |||
}, | |||
}, | |||
timeWindow: { | |||
duration: TIMEWINDOW_OPTIONS[0].value as any, // Get this to be a proper Duration | |||
duration: |
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.
💬 Now that we use CreateSLOInput
, the types are only primitives, so no more casting as any necessary
@@ -163,19 +165,61 @@ describe('SLO Edit Page', () => { | |||
); | |||
}); | |||
|
|||
it('renders the SLO Edit page with prefilled form values if sloId route param is passed', async () => { | |||
it.skip('calls the createSlo hook if all required values are filled in', 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.
💬 Disabled for now as it takes 4s to wait for the submit button to be enabled... And I can't figure out why.
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.
Nice Job! 👏🏻
Tested locally, I've added some comments in the code and had some questions in general that probably are not in the scope of this ticket just noticed them while reviewing:
- I didn't see a loader for the SLO list page
- Create/Edit SLO
- Index input is invalid at the start, even before user started filling the form
- Create SLO is disabled but it is not clear why
- It would be better to have it enabled but when clicked, we show invalid inputs
- I saw in creating a rule in security, there is a possibility to only show one step at a time, maybe it can be useful here as well
- Since we only have
KQL
input, can we disable clicking on theKQL
part of the input? - I think it will be helpful to have an example in the placeholder of the input (for
Query filter
,Good Query
,Total Query
)
@@ -42,6 +43,7 @@ export interface Props { | |||
const maxWidth = 775; | |||
|
|||
export function SloEditForm({ slo }: Props) { |
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.
In this context, SloEdit
is also covering create, right? Does it make sense to reflect it somehow in the name? It was a bit hard to understand what is covered on this page in the code.
Maybe we can remove the slo_edit
prefix from the components and have SloEditCreate
for the page level.
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 think that's a good idea, I'll rename it.
cc @CoenWarmer Except if you strongly disagree
x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx
Outdated
Show resolved
Hide resolved
x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx
Show resolved
Hide resolved
@@ -65,7 +67,7 @@ export function SloEditFormObjectivesTimeslices({ control }: Props) { | |||
min={1} | |||
max={120} | |||
step={1} | |||
onChange={(event) => field.onChange(String(event.target.value))} | |||
onChange={(event) => field.onChange(String(Number(event.target.value)))} |
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.
Why do you need to use Number
here?
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.
Interesting thing here. Since we are using the API response type, timeslices duration
is actually a string (because it is formatted as "1m" or "1h"). When we read the response, we trim the unit part and keep only the duration, but it is still a string from the type standpoint.
Therefore, here I'm parsing the string value to a Number (so the input works well), and finally to a String because that's the expected type. If I don't Number()
it, the input does not behave like this (going from value to 0 to new value) 👇🏻
Screen.Recording.2023-01-12.at.10.23.05.AM.mov
if (!values) return undefined; | ||
|
||
return { | ||
...values, | ||
...omit(values, ['id', 'revision', 'createdAt', 'updatedAt', 'summary']), |
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.
Does it mean whatever data we pass to the form, will be sent to the API?
If sending this information can create an issue on the API side, I am wondering if it make sense to omit these fields there as well 🤔
5c62cfa
to
c314f9a
Compare
I created a ticket to track these comments: #148820 The index selector and KQL filter needs to be improved for sure, we should ideally have autocompletion of the fields from the index: #148306 |
💚 Build Succeeded
Metrics [docs]Public APIs missing comments
Async chunks
History
To update your PR or re-run it, just comment with: cc @kdelemme |
📝 Summary
Resolves #148311
Resolves #148308
Resolves #148254
Part of #148306
This PR changes the index selector logic to allow partial index selection with
*
suffix. The suggestion is still broken when using the*
prefix though. We need to iterate on this or use another component.This PR also adds a new
CreateSLOInput
type that is theOutput
of theCreateSLOParams
schema. Meaning it's an object with only primitive values that is expected to be received by the API route handler. Which then is validated and parsed into aCreateSLOParams
type by io-ts and used in the application service.Finally, this PR fixes the form when using a timeslices budgeting method, and correctly handles the edit flow of an existing SLO.
🥼 Manual testing
Run the branch locally and go into the SLOs page. You can play with the create form and then edit any existing SLO from there.
🎥 Recording
create.slo.mov
edit.slo.mov