Browse Source

SONAR-14498 Support JSON field type in Settings

tags/8.8.0.42792
Jay 3 years ago
parent
commit
8a34c0093e
19 changed files with 259 additions and 106 deletions
  1. 4
    3
      server/sonar-web/src/main/js/api/settings.ts
  2. 25
    19
      server/sonar-web/src/main/js/apps/settings/__tests__/utils-test.ts
  3. 15
    4
      server/sonar-web/src/main/js/apps/settings/components/Definition.tsx
  4. 2
    1
      server/sonar-web/src/main/js/apps/settings/components/DefinitionActions.tsx
  5. 2
    1
      server/sonar-web/src/main/js/apps/settings/components/DefinitionsList.tsx
  6. 2
    1
      server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.tsx
  7. 27
    2
      server/sonar-web/src/main/js/apps/settings/components/__tests__/Definition-test.tsx
  8. 2
    1
      server/sonar-web/src/main/js/apps/settings/components/__tests__/DefinitionActions-test.tsx
  9. 2
    1
      server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSingleSelectList.tsx
  10. 3
    1
      server/sonar-web/src/main/js/apps/settings/components/inputs/PrimitiveInput.tsx
  11. 3
    2
      server/sonar-web/src/main/js/apps/settings/components/inputs/__tests__/Input-test.tsx
  12. 2
    1
      server/sonar-web/src/main/js/apps/settings/components/inputs/__tests__/MultiValueInput-test.tsx
  13. 95
    1
      server/sonar-web/src/main/js/apps/settings/store/__tests__/actions-test.ts
  14. 9
    0
      server/sonar-web/src/main/js/apps/settings/store/actions.ts
  15. 3
    2
      server/sonar-web/src/main/js/apps/settings/store/definitions.ts
  16. 3
    6
      server/sonar-web/src/main/js/apps/settings/store/values.ts
  17. 11
    12
      server/sonar-web/src/main/js/apps/settings/utils.ts
  18. 49
    0
      server/sonar-web/src/main/js/types/settings.ts
  19. 0
    48
      server/sonar-web/src/main/js/types/types.d.ts

+ 4
- 3
server/sonar-web/src/main/js/api/settings.ts View File

@@ -22,8 +22,9 @@ import { getJSON, post, postJSON, RequestData } from 'sonar-ui-common/helpers/re
import throwGlobalError from '../app/utils/throwGlobalError';
import { isCategoryDefinition } from '../apps/settings/utils';
import { BranchParameters } from '../types/branch-like';
import { SettingCategoryDefinition, SettingDefinition, SettingValue } from '../types/settings';

export function getDefinitions(component?: string): Promise<T.SettingCategoryDefinition[]> {
export function getDefinitions(component?: string): Promise<SettingCategoryDefinition[]> {
return getJSON('/api/settings/list_definitions', { component }).then(
r => r.definitions,
throwGlobalError
@@ -32,12 +33,12 @@ export function getDefinitions(component?: string): Promise<T.SettingCategoryDef

export function getValues(
data: { keys: string; component?: string } & BranchParameters
): Promise<T.SettingValue[]> {
): Promise<SettingValue[]> {
return getJSON('/api/settings/values', data).then(r => r.settings);
}

export function setSettingValue(
definition: T.SettingDefinition,
definition: SettingDefinition,
value: any,
component?: string
): Promise<void> {

+ 25
- 19
server/sonar-web/src/main/js/apps/settings/__tests__/utils-test.ts View File

@@ -17,14 +17,19 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import {
Setting,
SettingCategoryDefinition,
SettingFieldDefinition
} from '../../../types/settings';
import { getDefaultValue, getEmptyValue, sanitizeTranslation } from '../utils';

const fields = [
{ key: 'foo', type: 'STRING' } as T.SettingFieldDefinition,
{ key: 'bar', type: 'SINGLE_SELECT_LIST' } as T.SettingFieldDefinition
{ key: 'foo', type: 'STRING' } as SettingFieldDefinition,
{ key: 'bar', type: 'SINGLE_SELECT_LIST' } as SettingFieldDefinition
];

const settingDefinition: T.SettingCategoryDefinition = {
const settingDefinition: SettingCategoryDefinition = {
category: 'test',
fields: [],
key: 'test',
@@ -34,7 +39,7 @@ const settingDefinition: T.SettingCategoryDefinition = {

describe('#getEmptyValue()', () => {
it('should work for property sets', () => {
const setting: T.SettingCategoryDefinition = {
const setting: SettingCategoryDefinition = {
...settingDefinition,
type: 'PROPERTY_SET',
fields
@@ -43,7 +48,7 @@ describe('#getEmptyValue()', () => {
});

it('should work for multi values string', () => {
const setting: T.SettingCategoryDefinition = {
const setting: SettingCategoryDefinition = {
...settingDefinition,
type: 'STRING',
multiValues: true
@@ -52,7 +57,7 @@ describe('#getEmptyValue()', () => {
});

it('should work for multi values boolean', () => {
const setting: T.SettingCategoryDefinition = {
const setting: SettingCategoryDefinition = {
...settingDefinition,
type: 'BOOLEAN',
multiValues: true
@@ -62,19 +67,20 @@ describe('#getEmptyValue()', () => {
});

describe('#getDefaultValue()', () => {
const check = (parentValue?: string, expected?: string) => {
const setting: T.Setting = {
definition: { key: 'test', options: [], type: 'BOOLEAN' },
parentValue,
key: 'test'
};
expect(getDefaultValue(setting)).toEqual(expected);
};

it('should work for boolean field when passing "true"', () =>
check('true', 'settings.boolean.true'));
it('should work for boolean field when passing "false"', () =>
check('false', 'settings.boolean.false'));
it.each([
['true', 'settings.boolean.true'],
['false', 'settings.boolean.false']
])(
'should work for boolean field when passing "%s"',
(parentValue?: string, expected?: string) => {
const setting: Setting = {
definition: { key: 'test', options: [], type: 'BOOLEAN' },
parentValue,
key: 'test'
};
expect(getDefaultValue(setting)).toEqual(expected);
}
);
});

describe('sanitizeTranslation', () => {

+ 15
- 4
server/sonar-web/src/main/js/apps/settings/components/Definition.tsx View File

@@ -29,6 +29,7 @@ import {
isSettingsAppLoading,
Store
} from '../../../store/rootReducer';
import { Setting } from '../../../types/settings';
import { checkValue, resetValue, saveValue } from '../store/actions';
import { cancelChange, changeValue, passValidation } from '../store/settingsPage';
import {
@@ -51,7 +52,7 @@ interface Props {
passValidation: (key: string) => void;
resetValue: (key: string, component?: string) => Promise<void>;
saveValue: (key: string, component?: string) => Promise<void>;
setting: T.Setting;
setting: Setting;
validationMessage?: string;
}

@@ -59,6 +60,8 @@ interface State {
success: boolean;
}

const SAFE_SET_STATE_DELAY = 3000;

export class Definition extends React.PureComponent<Props, State> {
timeout?: number;
mounted = false;
@@ -91,7 +94,10 @@ export class Definition extends React.PureComponent<Props, State> {
return this.props.resetValue(definition.key, componentKey).then(() => {
this.props.cancelChange(definition.key);
this.safeSetState({ success: true });
this.timeout = window.setTimeout(() => this.safeSetState({ success: false }), 3000);
this.timeout = window.setTimeout(
() => this.safeSetState({ success: false }),
SAFE_SET_STATE_DELAY
);
});
};

@@ -113,9 +119,14 @@ export class Definition extends React.PureComponent<Props, State> {
this.props.saveValue(setting.definition.key, component && component.key).then(
() => {
this.safeSetState({ success: true });
this.timeout = window.setTimeout(() => this.safeSetState({ success: false }), 3000);
this.timeout = window.setTimeout(
() => this.safeSetState({ success: false }),
SAFE_SET_STATE_DELAY
);
},
() => {}
() => {
/* Do nothing */
}
);
}
};

+ 2
- 1
server/sonar-web/src/main/js/apps/settings/components/DefinitionActions.tsx View File

@@ -21,6 +21,7 @@ import * as React from 'react';
import { Button, ResetButtonLink, SubmitButton } from 'sonar-ui-common/components/controls/buttons';
import Modal from 'sonar-ui-common/components/controls/Modal';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { Setting } from '../../../types/settings';
import { getDefaultValue, getSettingValue, isEmptyValue } from '../utils';

type Props = {
@@ -31,7 +32,7 @@ type Props = {
onCancel: () => void;
onReset: () => void;
onSave: () => void;
setting: T.Setting;
setting: Setting;
};

type State = { reseting: boolean };

+ 2
- 1
server/sonar-web/src/main/js/apps/settings/components/DefinitionsList.tsx View File

@@ -18,11 +18,12 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { Setting } from '../../../types/settings';
import Definition from './Definition';

interface Props {
component?: T.Component;
settings: T.Setting[];
settings: Setting[];
}

export default function DefinitionsList({ component, settings }: Props) {

+ 2
- 1
server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.tsx View File

@@ -19,6 +19,7 @@
*/
import { groupBy, isEqual, sortBy } from 'lodash';
import * as React from 'react';
import { Setting, SettingCategoryDefinition } from '../../../types/settings';
import { getSubCategoryDescription, getSubCategoryName, sanitizeTranslation } from '../utils';
import DefinitionsList from './DefinitionsList';
import EmailForm from './EmailForm';
@@ -27,7 +28,7 @@ interface Props {
category: string;
component?: T.Component;
fetchValues: Function;
settings: Array<T.Setting & { definition: T.SettingCategoryDefinition }>;
settings: Array<Setting & { definition: SettingCategoryDefinition }>;
subCategory?: string;
}


+ 27
- 2
server/sonar-web/src/main/js/apps/settings/components/__tests__/Definition-test.tsx View File

@@ -20,9 +20,10 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { Setting } from '../../../../types/settings';
import { Definition } from '../Definition';

const setting: T.Setting = {
const setting: Setting = {
key: 'foo',
value: '42',
inherited: true,
@@ -35,6 +36,14 @@ const setting: T.Setting = {
}
};

beforeAll(() => {
jest.useFakeTimers();
});

afterAll(() => {
jest.useRealTimers();
});

it('should render correctly', () => {
const wrapper = shallowRender();
expect(wrapper).toMatchSnapshot();
@@ -65,10 +74,26 @@ it('should correctly save value change', async () => {
await waitAndUpdate(wrapper);
expect(saveValue).toHaveBeenCalledWith(setting.definition.key, undefined);
expect(wrapper.find('AlertSuccessIcon').exists()).toBe(true);
expect(wrapper.state().success).toBe(true);
jest.runAllTimers();
expect(wrapper.state().success).toBe(false);
});

it('should correctly reset', async () => {
const cancelChange = jest.fn();
const resetValue = jest.fn().mockResolvedValue({});
const wrapper = shallowRender({ cancelChange, changedValue: 10, resetValue });
wrapper.find('DefinitionActions').prop<Function>('onReset')();
await waitAndUpdate(wrapper);
expect(resetValue).toHaveBeenCalledWith(setting.definition.key, undefined);
expect(cancelChange).toHaveBeenCalledWith(setting.definition.key);
expect(wrapper.state().success).toBe(true);
jest.runAllTimers();
expect(wrapper.state().success).toBe(false);
});

function shallowRender(props: Partial<Definition['props']> = {}) {
return shallow(
return shallow<Definition>(
<Definition
cancelChange={jest.fn()}
changeValue={jest.fn()}

+ 2
- 1
server/sonar-web/src/main/js/apps/settings/components/__tests__/DefinitionActions-test.tsx View File

@@ -19,9 +19,10 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { SettingCategoryDefinition } from '../../../../types/settings';
import DefinitionActions from '../DefinitionActions';

const definition: T.SettingCategoryDefinition = {
const definition: SettingCategoryDefinition = {
category: 'baz',
description: 'lorem',
fields: [],

+ 2
- 1
server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSingleSelectList.tsx View File

@@ -19,9 +19,10 @@
*/
import * as React from 'react';
import Select from 'sonar-ui-common/components/controls/Select';
import { SettingCategoryDefinition } from '../../../../types/settings';
import { DefaultSpecializedInputProps } from '../../utils';

type Props = DefaultSpecializedInputProps & Pick<T.SettingCategoryDefinition, 'options'>;
type Props = DefaultSpecializedInputProps & Pick<SettingCategoryDefinition, 'options'>;

export default class InputForSingleSelectList extends React.PureComponent<Props> {
handleInputChange = ({ value }: { value: string }) => {

+ 3
- 1
server/sonar-web/src/main/js/apps/settings/components/inputs/PrimitiveInput.tsx View File

@@ -18,6 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { SettingType } from '../../../../types/settings';
import {
DefaultInputProps,
DefaultSpecializedInputProps,
@@ -32,10 +33,11 @@ import InputForString from './InputForString';
import InputForText from './InputForText';

const typeMapping: {
[type in T.SettingType]?: React.ComponentType<DefaultSpecializedInputProps>;
[type in SettingType]?: React.ComponentType<DefaultSpecializedInputProps>;
} = {
STRING: InputForString,
TEXT: InputForText,
JSON: InputForText,
PASSWORD: InputForPassword,
BOOLEAN: InputForBoolean,
INTEGER: InputForNumber,

+ 3
- 2
server/sonar-web/src/main/js/apps/settings/components/inputs/__tests__/Input-test.tsx View File

@@ -19,6 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { Setting, SettingCategoryDefinition } from '../../../../../types/settings';
import { DefaultInputProps } from '../../../utils';
import Input from '../Input';

@@ -26,7 +27,7 @@ const settingValue = {
key: 'example'
};

const settingDefinition: T.SettingCategoryDefinition = {
const settingDefinition: SettingCategoryDefinition = {
category: 'general',
fields: [],
key: 'example',
@@ -57,7 +58,7 @@ it('should render MultiValueInput', () => {
});

it('should render PropertySetInput', () => {
const setting: T.Setting = {
const setting: Setting = {
...settingValue,
definition: { ...settingDefinition, type: 'PROPERTY_SET' }
};

+ 2
- 1
server/sonar-web/src/main/js/apps/settings/components/inputs/__tests__/MultiValueInput-test.tsx View File

@@ -20,6 +20,7 @@
import { shallow, ShallowWrapper } from 'enzyme';
import * as React from 'react';
import { click } from 'sonar-ui-common/helpers/testUtils';
import { SettingCategoryDefinition } from '../../../../../types/settings';
import { DefaultInputProps } from '../../../utils';
import MultiValueInput from '../MultiValueInput';
import PrimitiveInput from '../PrimitiveInput';
@@ -28,7 +29,7 @@ const settingValue = {
key: 'example'
};

const settingDefinition: T.SettingCategoryDefinition = {
const settingDefinition: SettingCategoryDefinition = {
category: 'general',
fields: [],
key: 'example',

+ 95
- 1
server/sonar-web/src/main/js/apps/settings/store/__tests__/actions-test.ts View File

@@ -17,7 +17,11 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { fetchSettings } from '../actions';
import {
getSettingsAppChangedValue,
getSettingsAppDefinition
} from '../../../../store/rootReducer';
import { checkValue, fetchSettings } from '../actions';
import { receiveDefinitions } from '../definitions';

jest.mock('../../../../api/settings', () => ({
@@ -37,6 +41,11 @@ jest.mock('../definitions', () => ({
receiveDefinitions: jest.fn()
}));

jest.mock('../../../../store/rootReducer', () => ({
getSettingsAppDefinition: jest.fn(),
getSettingsAppChangedValue: jest.fn()
}));

it('#fetchSettings should filter LICENSE type settings', async () => {
const dispatch = jest.fn();

@@ -49,3 +58,88 @@ it('#fetchSettings should filter LICENSE type settings', async () => {
}
]);
});

describe('checkValue', () => {
const dispatch = jest.fn();

beforeEach(() => {
jest.clearAllMocks();
});

it('should correctly identify empty strings', () => {
(getSettingsAppDefinition as jest.Mock).mockReturnValue({
defaultValue: 'hello',
type: 'TEXT'
});

(getSettingsAppChangedValue as jest.Mock).mockReturnValue(undefined);
const key = 'key';
expect(checkValue(key)(dispatch, jest.fn())).toBe(false);
expect(dispatch).toBeCalledWith({
type: 'settingsPage/FAIL_VALIDATION',
key,
message: 'settings.state.value_cant_be_empty'
});
});

it('should correctly identify empty with no default', () => {
(getSettingsAppDefinition as jest.Mock).mockReturnValue({
type: 'TEXT'
});

(getSettingsAppChangedValue as jest.Mock).mockReturnValue(undefined);

const key = 'key';
expect(checkValue(key)(dispatch, jest.fn())).toBe(false);
expect(dispatch).toBeCalledWith({
type: 'settingsPage/FAIL_VALIDATION',
key,
message: 'settings.state.value_cant_be_empty_no_default'
});
});

it('should correctly identify non-empty strings', () => {
(getSettingsAppDefinition as jest.Mock).mockReturnValue({
type: 'TEXT'
});

(getSettingsAppChangedValue as jest.Mock).mockReturnValue('not empty');
const key = 'key';
expect(checkValue(key)(dispatch, jest.fn())).toBe(true);
expect(dispatch).toBeCalledWith({
type: 'settingsPage/PASS_VALIDATION',
key
});
});

it('should correctly identify misformed JSON', () => {
(getSettingsAppDefinition as jest.Mock).mockReturnValue({
type: 'JSON'
});

(getSettingsAppChangedValue as jest.Mock).mockReturnValue('{JSON: "asd;{');
const key = 'key';
expect(checkValue(key)(dispatch, jest.fn())).toBe(false);
expect(dispatch).toBeCalledWith({
type: 'settingsPage/FAIL_VALIDATION',
key,
message: 'Unexpected token J in JSON at position 1'
});
});

it('should correctly identify correct JSON', () => {
(getSettingsAppDefinition as jest.Mock).mockReturnValue({
type: 'JSON'
});

(getSettingsAppChangedValue as jest.Mock).mockReturnValue(
'{"number": 42, "question": "answer"}'
);
const key = 'key';
expect(checkValue(key)(dispatch, jest.fn())).toBe(true);
expect(dispatch).toBeCalledWith({
type: 'settingsPage/PASS_VALIDATION',
key
});
});
});

+ 9
- 0
server/sonar-web/src/main/js/apps/settings/store/actions.ts View File

@@ -75,6 +75,15 @@ export function checkValue(key: string) {
return false;
}

if (definition.type === 'JSON') {
try {
JSON.parse(value);
} catch (e) {
dispatch(failValidation(key, e.message));
return false;
}
}

dispatch(passValidation(key));
return true;
};

+ 3
- 2
server/sonar-web/src/main/js/apps/settings/store/definitions.ts View File

@@ -19,6 +19,7 @@
*/
import { keyBy, sortBy, uniqBy } from 'lodash';
import { ActionType } from '../../../store/utils/actions';
import { SettingCategoryDefinition } from '../../../types/settings';
import { DEFAULT_CATEGORY, getCategoryName } from '../utils';

const enum Actions {
@@ -27,9 +28,9 @@ const enum Actions {

type Action = ActionType<typeof receiveDefinitions, Actions.ReceiveDefinitions>;

export type State = T.Dict<T.SettingCategoryDefinition>;
export type State = T.Dict<SettingCategoryDefinition>;

export function receiveDefinitions(definitions: T.SettingCategoryDefinition[]) {
export function receiveDefinitions(definitions: SettingCategoryDefinition[]) {
return { type: Actions.ReceiveDefinitions, definitions };
}


+ 3
- 6
server/sonar-web/src/main/js/apps/settings/store/values.ts View File

@@ -21,6 +21,7 @@ import { keyBy } from 'lodash';
import { combineReducers } from 'redux';
import { Action as AppStateAction, Actions as AppStateActions } from '../../../store/appState';
import { ActionType } from '../../../store/utils/actions';
import { SettingValue } from '../../../types/settings';

enum Actions {
receiveValues = 'RECEIVE_VALUES'
@@ -28,7 +29,7 @@ enum Actions {

type Action = ActionType<typeof receiveValues, Actions.receiveValues>;

type SettingsState = T.Dict<T.SettingValue>;
type SettingsState = T.Dict<SettingValue>;

export interface State {
components: T.Dict<SettingsState>;
@@ -74,11 +75,7 @@ function global(state: State['components'] = {}, action: Action | AppStateAction

export default combineReducers({ components, global });

export function getValue(
state: State,
key: string,
component?: string
): T.SettingValue | undefined {
export function getValue(state: State, key: string, component?: string): SettingValue | undefined {
if (component) {
return state.components[component] && state.components[component][key];
}

+ 11
- 12
server/sonar-web/src/main/js/apps/settings/utils.ts View File

@@ -19,6 +19,7 @@
*/
import { sanitize } from 'dompurify';
import { hasMessage, translate } from 'sonar-ui-common/helpers/l10n';
import { Setting, SettingCategoryDefinition, SettingDefinition } from '../../types/settings';

export const DEFAULT_CATEGORY = 'general';

@@ -32,7 +33,7 @@ export interface DefaultInputProps {
onCancel?: () => void;
onChange: (value: any) => void;
onSave?: () => void;
setting: T.Setting;
setting: Setting;
value: any;
}

@@ -42,12 +43,12 @@ export function sanitizeTranslation(html: string) {
});
}

export function getPropertyName(definition: T.SettingDefinition) {
export function getPropertyName(definition: SettingDefinition) {
const key = `property.${definition.key}.name`;
return hasMessage(key) ? translate(key) : definition.name;
}

export function getPropertyDescription(definition: T.SettingDefinition) {
export function getPropertyDescription(definition: SettingDefinition) {
const key = `property.${definition.key}.description`;
return hasMessage(key) ? translate(key) : definition.description;
}
@@ -67,12 +68,12 @@ export function getSubCategoryDescription(category: string, subCategory: string)
return hasMessage(key) ? translate(key) : null;
}

export function getUniqueName(definition: T.SettingDefinition, index?: string) {
export function getUniqueName(definition: SettingDefinition, index?: string) {
const indexSuffix = index ? `[${index}]` : '';
return `settings[${definition.key}]${indexSuffix}`;
}

export function getSettingValue({ definition, fieldValues, value, values }: T.Setting) {
export function getSettingValue({ definition, fieldValues, value, values }: Setting) {
if (isCategoryDefinition(definition) && definition.multiValues) {
return values;
} else if (definition.type === 'PROPERTY_SET') {
@@ -82,7 +83,7 @@ export function getSettingValue({ definition, fieldValues, value, values }: T.Se
}
}

export function isEmptyValue(definition: T.SettingDefinition, value: any) {
export function isEmptyValue(definition: SettingDefinition, value: any) {
if (value == null) {
return true;
} else if (definition.type === 'BOOLEAN') {
@@ -92,13 +93,11 @@ export function isEmptyValue(definition: T.SettingDefinition, value: any) {
}
}

export function isCategoryDefinition(
item: T.SettingDefinition
): item is T.SettingCategoryDefinition {
export function isCategoryDefinition(item: SettingDefinition): item is SettingCategoryDefinition {
return Boolean((item as any).fields);
}

export function getEmptyValue(item: T.SettingDefinition | T.SettingCategoryDefinition): any {
export function getEmptyValue(item: SettingDefinition | SettingCategoryDefinition): any {
if (isCategoryDefinition(item)) {
if (item.multiValues) {
return [getEmptyValue({ ...item, multiValues: false })];
@@ -117,11 +116,11 @@ export function getEmptyValue(item: T.SettingDefinition | T.SettingCategoryDefin
return '';
}

export function isDefaultOrInherited(setting: T.Setting) {
export function isDefaultOrInherited(setting: Setting) {
return Boolean(setting.inherited);
}

export function getDefaultValue(setting: T.Setting) {
export function getDefaultValue(setting: Setting) {
const { definition, parentFieldValues, parentValue, parentValues } = setting;

if (definition.type === 'PASSWORD') {

+ 49
- 0
server/sonar-web/src/main/js/types/settings.ts View File

@@ -22,3 +22,52 @@ export const enum SettingsKey {
DefaultProjectVisibility = 'projects.default.visibility',
ServerBaseUrl = 'sonar.core.serverBaseURL'
}

export type Setting = SettingValue & { definition: SettingDefinition };

export type SettingType =
| 'STRING'
| 'TEXT'
| 'JSON'
| 'PASSWORD'
| 'BOOLEAN'
| 'FLOAT'
| 'INTEGER'
| 'LICENSE'
| 'LONG'
| 'SINGLE_SELECT_LIST'
| 'PROPERTY_SET';

export interface SettingDefinition {
description?: string;
key: string;
multiValues?: boolean;
name?: string;
options: string[];
type?: SettingType;
}

export interface SettingFieldDefinition extends SettingDefinition {
description: string;
name: string;
}

export interface SettingCategoryDefinition extends SettingDefinition {
category: string;
defaultValue?: string;
deprecatedKey?: string;
fields: SettingFieldDefinition[];
multiValues?: boolean;
subCategory: string;
}

export interface SettingValue {
fieldValues?: Array<T.Dict<string>>;
inherited?: boolean;
key: string;
parentFieldValues?: Array<T.Dict<string>>;
parentValue?: string;
parentValues?: string[];
value?: string;
values?: string[];
}

+ 0
- 48
server/sonar-web/src/main/js/types/types.d.ts View File

@@ -672,54 +672,6 @@ declare namespace T {

export type RuleType = 'BUG' | 'VULNERABILITY' | 'CODE_SMELL' | 'SECURITY_HOTSPOT' | 'UNKNOWN';

export type Setting = SettingValue & { definition: SettingDefinition };

export type SettingType =
| 'STRING'
| 'TEXT'
| 'PASSWORD'
| 'BOOLEAN'
| 'FLOAT'
| 'INTEGER'
| 'LICENSE'
| 'LONG'
| 'SINGLE_SELECT_LIST'
| 'PROPERTY_SET';

export interface SettingDefinition {
description?: string;
key: string;
multiValues?: boolean;
name?: string;
options: string[];
type?: SettingType;
}

export interface SettingFieldDefinition extends SettingDefinition {
description: string;
name: string;
}

export interface SettingCategoryDefinition extends SettingDefinition {
category: string;
defaultValue?: string;
deprecatedKey?: string;
fields: SettingFieldDefinition[];
multiValues?: boolean;
subCategory: string;
}

export interface SettingValue {
fieldValues?: Array<T.Dict<string>>;
inherited?: boolean;
key: string;
parentFieldValues?: Array<T.Dict<string>>;
parentValue?: string;
parentValues?: string[];
value?: string;
values?: string[];
}

export interface Snippet {
start: number;
end: number;

Loading…
Cancel
Save