Skip to content

Commit

Permalink
feat: ADDON-67093 add custom warning message for forms (#970)
Browse files Browse the repository at this point in the history
Add possibility to display custom warning on top of form. Warning
appears on render and is "default" warning.

Support only 4 modes (create, edit, config, clone) as they are used for
displaying form.

![Screenshot 2023-12-12 at 10 58
44](https://github.com/splunk/addonfactory-ucc-generator/assets/143183665/8bc94245-1e1f-4353-8ff2-d3bd6c23c695)

![Screenshot 2023-12-12 at 10 59
07](https://github.com/splunk/addonfactory-ucc-generator/assets/143183665/edeb8ef4-6559-47d8-8325-e3c89af0fc00)
  • Loading branch information
soleksy-splunk authored Dec 15, 2023
1 parent c83c17d commit 64daa77
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
| style | string | By specifying this property in the global config file, the forms can either be opened as a new page or in a dialog. <br>Supported values are "page" or "dialog". <br> Default value is **dialog**. |
| options | object | This property allows you to enable the [saveValidator](../advanced/save_validator) feature. |
| hook | object | It is used to add custom behaviour to forms. Visit the [Custom Hook](../custom_ui_extensions/custom_hook) page to learn more. |
| warning | object | It is used to add custom warning message for each of modes ('create', 'edit', 'config', 'clone'), message is displayed on form |
| conf | string | TBD |
| restHandlerName | string | TBD |
| restHandlerModule | string | TBD |
Expand Down
1 change: 1 addition & 0 deletions docs/inputs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Developers are required to add services in the global config file to create a ne
| style | string | By specifying this property in the global config file, the forms can either be opened as a new page or in a dialog. <br>Supported values are "page" or "dialog". <br> Default value is **dialog**. |
| options | object | This property allows you to enable the [saveValidator](../advanced/save_validator) feature. |
| hook | object | It is used to add custom behaviour to forms. Visit the [Custom Hook](../custom_ui_extensions/custom_hook) page to learn more. |
| warning | object | It is used to add custom warning message for each of modes ('create', 'edit', 'config', 'clone'), message is displayed on form |
| conf | string | TBD |
| restHandlerName | string | TBD |
| restHandlerModule | string | TBD |
Expand Down
6 changes: 6 additions & 0 deletions docs/inputs/tabs.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ If `title` and `description` are provided in the global config file then it woul
],
"header": [],
"moreInfo": []
},
"warning": {
"create": "Warning text for create mode",
"edit": "Warning text for edit mode",
"clone": "Warning text for clone mode",
"config": "Warning text for config mode",
}
},
{
Expand Down
35 changes: 34 additions & 1 deletion splunk_add_on_ucc_framework/schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,13 @@
"maxLength": 50
}
},
"required": ["task", "supportsAdhoc", "subject", "category", "technology"]
"required": [
"task",
"supportsAdhoc",
"subject",
"category",
"technology"
]
},
"entity": {
"type": "array",
Expand Down Expand Up @@ -1400,6 +1406,9 @@
"restHandlerClass": {
"type": "string",
"maxLength": 100
},
"warning": {
"$ref": "#/definitions/WarningMessage"
}
},
"not": {
Expand Down Expand Up @@ -1824,6 +1833,9 @@
},
"customTab": {
"type": "object"
},
"warning": {
"$ref": "#/definitions/WarningMessage"
}
},
"anyOf": [
Expand Down Expand Up @@ -1909,6 +1921,27 @@
"required": ["name"],
"additionalProperties": false
},
"WarningMessage": {
"type": "object",
"properties": {
"create": {
"type": "string",
"maxLength": 500
},
"edit": {
"type": "string",
"maxLength": 500
},
"clone": {
"type": "string",
"maxLength": 500
},
"config": {
"type": "string",
"maxLength": 500
}
}
},
"Field": {
"type": "string",
"pattern": "(?!^(?:persistentQueueSize|queueSize|start_by_shell|output_mode|output_field|owner|app|sharing)$)(?:^\\w+$)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
"tabs": [
{
"name": "account",
"warning": {
"create": "Some warning for account text create",
"edit": "Some warning for account text edit",
"clone": "Some warning for account text clone"
},
"table": {
"actions": [
"edit",
Expand Down Expand Up @@ -231,6 +236,9 @@
},
{
"name": "proxy",
"warning": {
"config": "Some warning for proxy text config"
},
"entity": [
{
"type": "checkbox",
Expand Down Expand Up @@ -332,6 +340,9 @@
},
{
"name": "logging",
"warning": {
"config": "Some logging for proxy text config"
},
"entity": [
{
"type": "singleSelect",
Expand Down Expand Up @@ -459,6 +470,11 @@
"services": [
{
"name": "example_input_one",
"warning": {
"create": "Some warning for input text create",
"edit": "Some warning for input text edit",
"clone": "Some warning for input text clone"
},
"entity": [
{
"type": "text",
Expand Down Expand Up @@ -1338,7 +1354,7 @@
"meta": {
"name": "Splunk_TA_UCCExample",
"restRoot": "splunk_ta_uccexample",
"version": "5.34.1Racdcfb2e",
"version": "5.34.1R3fad1a25",
"displayName": "Splunk UCC test Add-on",
"schemaVersion": "0.0.3"
}
Expand Down
7 changes: 5 additions & 2 deletions ui/src/components/BaseFormView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class BaseFormView extends PureComponent {
addCustomValidator: this.addCustomValidator,
utilCustomFunctions: this.util,
};
this.customWarningMessage = '';

if (props.page === PAGE_INPUT) {
globalConfig.pages.inputs.services.forEach((service) => {
Expand All @@ -83,6 +84,7 @@ class BaseFormView extends PureComponent {
this.currentInput =
context?.rowData?.[props.serviceName]?.[props.stanzaName];
}
this.customWarningMessage = service?.warning?.[props.mode] || '';
}
});
} else {
Expand All @@ -93,6 +95,7 @@ class BaseFormView extends PureComponent {
if (flag) {
this.entities = tab.entity;
this.options = tab.options;
this.customWarningMessage = tab?.warning?.[props.mode] || '';
if (tab.hook) {
this.hookDeferred = this.loadHook(
tab.hook.src,
Expand Down Expand Up @@ -372,7 +375,7 @@ class BaseFormView extends PureComponent {
this.state = {
data: temState,
errorMsg: '',
warningMsg: '',
warningMsg: this.customWarningMessage,
};

// Hook on create method call
Expand Down Expand Up @@ -782,7 +785,7 @@ class BaseFormView extends PureComponent {
clearAllErrorMsg = (State) => {
const newFields = State ? { ...State } : { ...this.state };
newFields.errorMsg = '';
newFields.warningMsg = '';
newFields.warningMsg = this.customWarningMessage || '';
const newData = State ? { ...State.data } : { ...this.state.data };
const temData = {};
Object.keys(newData).forEach((key) => {
Expand Down
59 changes: 57 additions & 2 deletions ui/src/components/EntityModal/EntityModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import EntityModal, { EntityModalProps } from './EntityModal';
import { setUnifiedConfig } from '../../util/util';
import {
DEFAULT_VALUE,
getConfigAccerssTokenMock,
WARNING_MESSAGES,
getConfigAccessTokenMock,
getConfigBasicOauthDisableonEdit,
getConfigEnableFalseForOauth,
getConfigFullyEnabledField,
getConfigOauthOauthDisableonEdit,
getConfigWithOauthDefaultValue,
getConfigWarningMessage,
} from './TestConfig';
import { ERROR_AUTH_PROCESS_TERMINATED_TRY_AGAIN } from '../../constants/oAuthErrorMessage';

Expand Down Expand Up @@ -197,7 +199,7 @@ describe('EntityModal - auth_endpoint_token_access_type', () => {
const handleRequestClose = jest.fn();

const setUpConfigWithDisabedOauth = () => {
const newConfig = getConfigAccerssTokenMock();
const newConfig = getConfigAccessTokenMock();
setUnifiedConfig(newConfig);
};

Expand Down Expand Up @@ -256,6 +258,59 @@ describe('EntityModal - auth_endpoint_token_access_type', () => {
});
});

describe('EntityModal - custom warning', () => {
const handleRequestClose = jest.fn();

const setUpConfigWithWarningMessageForConfiguration = () => {
const newConfig = getConfigWarningMessage();
setUnifiedConfig(newConfig);
};

const setUpConfigWithWarningMessageForInputServices = () => {
const newConfig = getConfigWarningMessage();
setUnifiedConfig(newConfig);
};

const renderModal = (inputMode: string, page: string) => {
const props = {
serviceName: 'account',
mode: inputMode,
stanzaName: undefined,
formLabel: 'formLabel',
page,
groupName: '',
open: true,
handleRequestClose: () => {},
} satisfies EntityModalProps;
render(<EntityModal {...props} handleRequestClose={handleRequestClose} />);
};

it.each`
mode | page
${'create'} | ${'configuration'}
${'edit'} | ${'configuration'}
${'clone'} | ${'configuration'}
${'config'} | ${'configuration'}
${'create'} | ${'input'}
${'edit'} | ${'input'}
${'clone'} | ${'input'}
${'config'} | ${'input'}
`(
'display custom warning for $mode mode - $page tab',
({ mode, page }: { mode: keyof typeof WARNING_MESSAGES; page: string }) => {
if (page === 'configuration') {
setUpConfigWithWarningMessageForConfiguration();
} else {
setUpConfigWithWarningMessageForInputServices();
}
renderModal(mode, page);

const warningMessage = screen.getByText(WARNING_MESSAGES[mode]);
expect(warningMessage).toBeInTheDocument();
}
);
});

describe('Default value', () => {
const handleRequestClose = jest.fn();
const setUpConfigWithDefaultValue = () => {
Expand Down
43 changes: 42 additions & 1 deletion ui/src/components/EntityModal/TestConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ const accessTokenMock = [
} satisfies z.infer<typeof OAuthEntity>,
];

export const getConfigAccerssTokenMock = () => {
export const getConfigAccessTokenMock = () => {
const globalConfig = getGlobalConfigMock();
const newConfig = {
...globalConfig,
Expand Down Expand Up @@ -222,6 +222,47 @@ export const getConfigEnableFalseForOauth = () => {
return newConfig satisfies z.infer<typeof GlobalConfigSchema>;
};

export const WARNING_MESSAGES = {
create: 'Some warning text create',
edit: 'Some warning text edit',
clone: 'Some warning text clone',
config: 'Some warning text config',
};

export const getConfigWarningMessage = () => {
const globalConfig = getGlobalConfigMock();
const newConfig = {
...globalConfig,
pages: {
...globalConfig.pages,
configuration: {
...globalConfig.pages.configuration,
tabs: [
{ entity: accessTokenMock, ...defaultTableProps, warning: WARNING_MESSAGES },
],
},
},
};
return newConfig satisfies z.infer<typeof GlobalConfigSchema>;
};

export const getConfigWarningMessageForInputServices = () => {
const globalConfig = getGlobalConfigMock();
const newConfig = {
...globalConfig,
pages: {
...globalConfig.pages,
input: {
...globalConfig.pages.configuration,
services: [
{ entity: accessTokenMock, ...defaultTableProps, warning: WARNING_MESSAGES },
],
},
},
};
return newConfig satisfies z.infer<typeof GlobalConfigSchema>;
};

export const getConfigEnableFalseForOauthBasic = () => {
const globalConfig = getGlobalConfigMock();
const newConfig = {
Expand Down
12 changes: 12 additions & 0 deletions ui/src/types/globalConfig/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ const HooksSchema = z
saveValidator: z.string().optional(),
})
.optional();

const WarningSchema = z
.object({
create: z.string().optional(),
edit: z.string().optional(),
config: z.string().optional(),
clone: z.string().optional(),
})
.optional();

export const TabSchema = z.object({
entity: z.array(AnyOfEntity).optional(),
name: z.string(),
Expand All @@ -44,6 +54,7 @@ export const TabSchema = z.object({
restHandlerModule: z.string().optional(),
restHandlerClass: z.string().optional(),
customTab: z.record(z.any()).optional(),
warning: WarningSchema,
});

const GroupsSchema = z
Expand Down Expand Up @@ -74,6 +85,7 @@ export const TableLessServiceSchema = z.object({
restHandlerName: z.string().optional(),
restHandlerModule: z.string().optional(),
restHandlerClass: z.string().optional(),
warning: WarningSchema,
});
export const TableFullServiceSchema = TableLessServiceSchema.extend({
description: z.string().optional(),
Expand Down

0 comments on commit 64daa77

Please sign in to comment.