Skip to content
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

Xstream 112 edit new format attribut color #298

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/admin/public/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@
"date": "Date",
"date_range": "Period",
"encrypted": "Encrypted",
"numeric": "Numeric"
"numeric": "Numeric",
"color": "Color"
},
"values_list_enable": "Enable",
"allow_free_entry": "Allow free entry",
Expand Down
3 changes: 2 additions & 1 deletion apps/admin/public/locales/fr/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@
"date": "Date",
"date_range": "Période",
"encrypted": "Crypté",
"numeric": "Numérique"
"numeric": "Numérique",
"color": "Couleur"
},
"values_list_enable": "Activer",
"allow_free_entry": "Autoriser la saisie libre",
Expand Down
1 change: 1 addition & 0 deletions apps/admin/src/_gqlTypes/globalTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export enum ApplicationType {

export enum AttributeFormat {
boolean = 'boolean',
color = 'color',
date = 'date',
date_range = 'date_range',
encrypted = 'encrypted',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ function ReserveAttribute({attribute}: IReserveAttributeProps): JSX.Element {
const _getElement = () => {
const elemByFormat: {[format in AttributeFormat]: IUIElement} = {
[AttributeFormat.boolean]: formElements[FieldTypes.CHECKBOX],
[AttributeFormat.color]: formElements[FieldTypes.TEXT_INPUT],
[AttributeFormat.date]: formElements[FieldTypes.DATE],
[AttributeFormat.encrypted]: formElements[FieldTypes.ENCRYPTED],
[AttributeFormat.extended]: formElements[FieldTypes.TEXT_INPUT],
Expand Down
6 changes: 3 additions & 3 deletions apps/core/src/domain/actions/validateFormatAction.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,17 @@ describe('validateFormatAction', () => {
});

test('validateFormat COLOR', async () => {
const colorValue = "FFFFFF";
const colorValue = 'FFFFFF';
expect(action(colorValue, {}, {attribute: attrColor})).toBe(colorValue);
});

test('Throw if invalid format COLOR', async () => {
const badColorValue = "AZERTY"
const badColorValue = 'AZERTY';
expect(() => action(badColorValue, {}, {attribute: attrColor})).toThrow(ValidationError);
});

test('Throw if invalid format COLOR, to be less or equal to 6 characters ', async () => {
const badColorValue = "FFFFFFFFFFFFFFFFFFF"
const badColorValue = 'FFFFFFFFFFFFFFFFFFF';
expect(() => action(badColorValue, {}, {attribute: attrColor})).toThrow(ValidationError);
});
});
2 changes: 1 addition & 1 deletion apps/data-studio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@leav/ui": "workspace:libs/ui",
"@leav/utils": "workspace:libs/utils",
"@reduxjs/toolkit": "1.9.2",
"antd": "5.7.0",
"antd": "5.8.3",
"apollo-cache-inmemory": "1.6.6",
"apollo-upload-client": "14.1.3",
"dayjs": "1.11.7",
Expand Down
1 change: 1 addition & 0 deletions apps/data-studio/src/_gqlTypes/globalTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export enum ApplicationType {

export enum AttributeFormat {
boolean = 'boolean',
color = 'color',
date = 'date',
date_range = 'date_range',
encrypted = 'encrypted',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ const allowedConditionByFormat: {[format in AttributeFormat]: AttributeCondition
AttributeConditionFilter.END_BEFORE,
AttributeConditionFilter.IS_EMPTY,
AttributeConditionFilter.IS_NOT_EMPTY
],
[AttributeFormat.color]: [
AttributeConditionFilter.CONTAINS,
AttributeConditionFilter.NOT_CONTAINS,
AttributeConditionFilter.EQUAL,
AttributeConditionFilter.NOT_EQUAL,
AttributeConditionFilter.IS_EMPTY,
AttributeConditionFilter.IS_NOT_EMPTY
]
};

Expand Down
Kekelgrs marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
// License text available at https://www.gnu.org/licenses/lgpl-3.0.txt
import {CheckOutlined, CloseOutlined, FileTextOutlined} from '@ant-design/icons';
import {AnyPrimitive} from '@leav/utils';
import {Switch, Tooltip, Typography} from 'antd';
import {Switch, Tag, Tooltip, Typography} from 'antd';
import {useTranslation} from 'react-i18next';
import styled from 'styled-components';
import {stringifyDateRangeValue} from 'utils';
import {getInvertColor, stringifyDateRangeValue} from 'utils';
import {AttributeFormat} from '_gqlTypes/globalTypes';
import {IDateRangeValue, ITableCell} from '_types/types';
import {cp} from 'fs';
import {isEmpty} from 'lodash';

interface ISimpleCellProps {
cellData: ITableCell;
Expand All @@ -22,7 +24,8 @@ const alignmentByFormat: Record<AttributeFormat, 'left' | 'right' | 'center'> =
[AttributeFormat.date]: 'left',
[AttributeFormat.date_range]: 'left',
[AttributeFormat.extended]: 'left',
[AttributeFormat.encrypted]: 'left'
[AttributeFormat.encrypted]: 'left',
[AttributeFormat.color]: 'left'
};

const Wrapper = styled.div<{format: AttributeFormat}>`
Expand All @@ -46,6 +49,40 @@ function StandardCell({cellData, values}: ISimpleCellProps): JSX.Element {

const displayedValues = values.map(val => _getValueByFormat(val)).join(', ');

const _getTagStyle = (value: string) => {
return {color: getInvertColor('#' + value)};
};

const _getElementToDisplay = () => {
switch (cellData.format) {
case AttributeFormat.boolean:
return (
<Switch
disabled
checked={!!values[0]}
checkedChildren={<CheckOutlined />}
unCheckedChildren={<CloseOutlined />}
/>
);
case AttributeFormat.color:
if (!isEmpty(values)) {
return (
<>
{values.map(valueHex => (
<Tag bordered={true} color={'#' + valueHex} style={_getTagStyle('#' + valueHex)}>
{'#' + valueHex}
</Tag>
))}
</>
);
} else {
return displayedValues;
}
default:
return displayedValues;
}
};

return (
<Wrapper format={cellData.format}>
{cellData.format === AttributeFormat.extended ? (
Expand All @@ -60,16 +97,7 @@ function StandardCell({cellData, values}: ISimpleCellProps): JSX.Element {
}}
style={{margin: 0}}
>
{cellData.format === AttributeFormat.boolean ? (
<Switch
disabled
checked={!!values[0]}
checkedChildren={<CheckOutlined />}
unCheckedChildren={<CloseOutlined />}
/>
) : (
displayedValues
)}
{_getElementToDisplay()}
</Typography.Paragraph>
)}
</Wrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {mockModifier} from '__mocks__/common/value';
import {RECORD_FORM_recordForm_elements_attribute_StandardAttribute} from '_gqlTypes/RECORD_FORM';
import {SAVE_VALUE_BATCH_saveValueBatch_values_Value_attribute} from '_gqlTypes/SAVE_VALUE_BATCH';
import {AttributeFormat, AttributeType} from '_gqlTypes/globalTypes';
import {act, render, screen} from '_tests/testUtils';
import {act, render, screen, waitFor} from '_tests/testUtils';
import {
EditRecordReducerActionsTypes,
initialState
Expand Down Expand Up @@ -213,7 +213,6 @@ describe('StandardField', () => {

const inputElem = screen.getByRole('textbox');
userEvent.click(inputElem);

const calendarElem = screen.getByTestId('datepicker');
expect(calendarElem).toBeInTheDocument();

Expand All @@ -223,6 +222,46 @@ describe('StandardField', () => {
expect(mockHandleSubmit).toHaveBeenCalled();
});

test('Render color field', async () => {
const colorValue = 'FFFFFF';
const newColorValue = '000000';
const recordValuesDate = [
{
...mockRecordValuesCommon,
value: colorValue,
raw_value: colorValue
}
];
render(
<StandardField
element={{
...mockFormElementInput,
attribute: {...mockFormAttribute, format: AttributeFormat.color},
values: recordValuesDate
}}
{...baseProps}
/>
);
// Open ColorPicker Element
const colorElem = screen.getByRole('textbox');
await act(async () => {
userEvent.click(colorElem);
});

const colorPickerElem = screen.getByRole('textbox');
expect(colorPickerElem).toBeInTheDocument();

// Update color value
userEvent.clear(colorPickerElem);
userEvent.type(colorPickerElem, newColorValue);
await act(async () => {
userEvent.click(screen.getByRole('button', {name: 'global.submit'}));
});

expect(colorPickerElem).not.toBeInTheDocument();
expect(mockHandleSubmit).toHaveBeenCalled();
});

test('Render checkbox', async () => {
const recordValuesBoolean = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright LEAV Solutions 2017
// This file is released under LGPL V3
// License text available at https://www.gnu.org/licenses/lgpl-3.0.txt
import {ColorPicker} from 'antd';
import {Color} from 'antd/es/color-picker';
import {IStandardInputProps} from 'components/RecordEdition/EditRecord/_types';

function ColorInput({state, fieldValue, onChange, onFocus}: IStandardInputProps): JSX.Element {
const {editingValue} = fieldValue;
const colorValue = '#' + editingValue.toString();

const _handleColorChange = (value: Color) => {
onChange(value.toHex().toUpperCase());
};
const colorPickerStyle: React.CSSProperties = {
height: fieldValue.index ? '44px' : '54px',
width: '100%',
justifyContent: 'left',
paddingTop: fieldValue.index ? '4px' : '14px',
paddingLeft: '15px'
};

return (
<ColorPicker
showText
disabledAlpha
disabled={state.isReadOnly}
value={colorValue}
style={colorPickerStyle}
open={fieldValue.isEditing}
size="small"
onChangeComplete={_handleColorChange}
onOpenChange={onFocus}
/>
);
}

export default ColorInput;
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import NumberInput from './Inputs/NumberInput';
import TextInput from './Inputs/TextInput';
import ValuesList from './ValuesList';
import {IValueOfValuesList} from './ValuesList/ValuesList';
import ColorInput from './Inputs/ColorInput';

const ErrorMessage = styled.div`
color: ${themeVars.errorColor};
Expand Down Expand Up @@ -183,7 +184,8 @@ const inputComponentByFormat: {[format in AttributeFormat]: (props: IStandardInp
[AttributeFormat.boolean]: CheckboxInput,
[AttributeFormat.numeric]: NumberInput,
[AttributeFormat.encrypted]: EncryptedInput,
[AttributeFormat.extended]: TextInput
[AttributeFormat.extended]: TextInput,
[AttributeFormat.color]: ColorInput
};

type IStringValuesListConf = RECORD_FORM_recordForm_elements_attribute_StandardAttribute_values_list_StandardStringValuesListConf;
Expand Down Expand Up @@ -334,8 +336,16 @@ function StandardFieldValue({
};

const _getInput = (): JSX.Element => {
let inputStyle: React.CSSProperties = {};
if (!fieldValue.isEditing && attribute.format !== AttributeFormat.boolean) {
let displayedValue = String(fieldValue.displayValue);
let prefixValue;
if (
attribute.format === AttributeFormat.color &&
(fieldValue.value === null || fieldValue.value.value === null)
) {
fieldValue.value = null;
}
const hasValue = fieldValue.value !== null;

if (hasValue) {
Expand All @@ -357,17 +367,26 @@ function StandardFieldValue({
);
}
break;
case AttributeFormat.color:
prefixValue = _getColorDisplay();
displayedValue = '#' + displayedValue;
inputStyle = {
paddingLeft: '39px'
};
}
}

return (
<Input
key="display"
className={hasValue ? 'has-value' : ''}
value={displayedValue}
onFocus={_handleFocus}
disabled={state.isReadOnly}
/>
<>
{prefixValue}
<Input
key="display"
style={inputStyle}
className={hasValue ? 'has-value' : ''}
value={displayedValue}
onFocus={_handleFocus}
disabled={state.isReadOnly}
/>
</>
);
}

Expand All @@ -392,6 +411,20 @@ function StandardFieldValue({
);
};

const _getColorDisplay = (): JSX.Element => {
const colorValue = '#' + String(fieldValue.displayValue);
const colorPickerStyle: React.CSSProperties = {
width: '16px',
height: '16px',
borderRadius: '2px',
backgroundColor: colorValue,
marginTop: fieldValue.index ? '15px' : '25px',
marginLeft: '5px'
};

return <label style={colorPickerStyle} />;
};

const _getFilteredValuesList = (): IValueOfValuesList[] => {
let values: Array<Pick<IValueOfValuesList, 'value' | 'rawValue'>> = [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ const _inputTypeByFormat: {[format in AttributeFormat]: FormFieldTypes} = {
[AttributeFormat.boolean]: FormFieldTypes.CHECKBOX,
[AttributeFormat.date_range]: FormFieldTypes.DATE,
[AttributeFormat.encrypted]: FormFieldTypes.TEXT_INPUT,
[AttributeFormat.extended]: FormFieldTypes.TEXT_INPUT
[AttributeFormat.extended]: FormFieldTypes.TEXT_INPUT,
[AttributeFormat.color]: FormFieldTypes.TEXT_INPUT
};

function ValueMetadata({value, attribute, onMetadataSubmit}: IValueMetadataProps): JSX.Element {
Expand Down
3 changes: 2 additions & 1 deletion apps/data-studio/src/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,8 @@
"format_encrypted": "Encrypted",
"format_extended": "Extended",
"format_numeric": "Numeric",
"format_text": "Text"
"format_text": "Text",
"format_color": "Color"
},
"date_range_value": "From {{from}} to {{to}}"
},
Expand Down
3 changes: 2 additions & 1 deletion apps/data-studio/src/locales/fr/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,8 @@
"format_encrypted": "Encrypté",
"format_extended": "Étendu",
"format_numeric": "Numérique",
"format_text": "Texte"
"format_text": "Texte",
"format_color": "Couleur"
},
"date_range_value": "Du {{from}} au {{to}}"
},
Expand Down
Loading
Loading