Skip to content

Commit

Permalink
Merge pull request #44275 from rezkiy37/feature/43684-report-fields-c…
Browse files Browse the repository at this point in the history
…reating-flow-4

Implement the policy report fields creation flow
  • Loading branch information
mountiny authored Jul 3, 2024
2 parents 34d27b6 + 256ca29 commit 685d3f7
Show file tree
Hide file tree
Showing 40 changed files with 1,923 additions and 56 deletions.
32 changes: 12 additions & 20 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1852,6 +1852,11 @@ const CONST = {
MAKE_MEMBER: 'makeMember',
MAKE_ADMIN: 'makeAdmin',
},
BULK_ACTION_TYPES: {
DELETE: 'delete',
DISABLE: 'disable',
ENABLE: 'enable',
},
MORE_FEATURES: {
ARE_CATEGORIES_ENABLED: 'areCategoriesEnabled',
ARE_TAGS_ENABLED: 'areTagsEnabled',
Expand All @@ -1862,21 +1867,6 @@ const CONST = {
ARE_EXPENSIFY_CARDS_ENABLED: 'areExpensifyCardsEnabled',
ARE_TAXES_ENABLED: 'tax',
},
CATEGORIES_BULK_ACTION_TYPES: {
DELETE: 'delete',
DISABLE: 'disable',
ENABLE: 'enable',
},
TAGS_BULK_ACTION_TYPES: {
DELETE: 'delete',
DISABLE: 'disable',
ENABLE: 'enable',
},
DISTANCE_RATES_BULK_ACTION_TYPES: {
DELETE: 'delete',
DISABLE: 'disable',
ENABLE: 'enable',
},
DEFAULT_CATEGORIES: [
'Advertising',
'Benefits',
Expand Down Expand Up @@ -1907,11 +1897,6 @@ const CONST = {
DUPLICATE_SUBSCRIPTION: 'duplicateSubscription',
FAILED_TO_CLEAR_BALANCE: 'failedToClearBalance',
},
TAX_RATES_BULK_ACTION_TYPES: {
DELETE: 'delete',
DISABLE: 'disable',
ENABLE: 'enable',
},
COLLECTION_KEYS: {
DESCRIPTION: 'description',
REIMBURSER: 'reimburser',
Expand Down Expand Up @@ -2259,6 +2244,7 @@ const CONST = {
LOGIN_CHARACTER_LIMIT: 254,
CATEGORY_NAME_LIMIT: 256,
TAG_NAME_LIMIT: 256,
WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH: 256,
REPORT_NAME_LIMIT: 100,
TITLE_CHARACTER_LIMIT: 100,
DESCRIPTION_LIMIT: 500,
Expand Down Expand Up @@ -5082,6 +5068,12 @@ const CONST = {
},

EXCLUDE_FROM_LAST_VISITED_PATH: [SCREENS.NOT_FOUND, SCREENS.SAML_SIGN_IN, SCREENS.VALIDATE_LOGIN] as string[],

REPORT_FIELD_TYPES: {
TEXT: 'text',
DATE: 'date',
LIST: 'dropdown',
},
} as const;

type Country = keyof typeof CONST.ALL_COUNTRIES;
Expand Down
3 changes: 3 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@ const ONYXKEYS = {
WORKSPACE_RATE_AND_UNIT_FORM_DRAFT: 'workspaceRateAndUnitFormDraft',
WORKSPACE_TAX_CUSTOM_NAME: 'workspaceTaxCustomName',
WORKSPACE_TAX_CUSTOM_NAME_DRAFT: 'workspaceTaxCustomNameDraft',
WORKSPACE_REPORT_FIELDS_FORM: 'workspaceReportFieldsForm',
WORKSPACE_REPORT_FIELDS_FORM_DRAFT: 'workspaceReportFieldsFormDraft',
POLICY_CREATE_DISTANCE_RATE_FORM: 'policyCreateDistanceRateForm',
POLICY_CREATE_DISTANCE_RATE_FORM_DRAFT: 'policyCreateDistanceRateFormDraft',
POLICY_DISTANCE_RATE_EDIT_FORM: 'policyDistanceRateEditForm',
Expand Down Expand Up @@ -564,6 +566,7 @@ type OnyxFormValuesMapping = {
[ONYXKEYS.FORMS.WORKSPACE_TAG_FORM]: FormTypes.WorkspaceTagForm;
[ONYXKEYS.FORMS.WORKSPACE_RATE_AND_UNIT_FORM]: FormTypes.WorkspaceRateAndUnitForm;
[ONYXKEYS.FORMS.WORKSPACE_TAX_CUSTOM_NAME]: FormTypes.WorkspaceTaxCustomName;
[ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM]: FormTypes.WorkspaceReportFieldsForm;
[ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM]: FormTypes.CloseAccountForm;
[ONYXKEYS.FORMS.PROFILE_SETTINGS_FORM]: FormTypes.ProfileSettingsForm;
[ONYXKEYS.FORMS.DISPLAY_NAME_FORM]: FormTypes.DisplayNameForm;
Expand Down
20 changes: 20 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,26 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/reportFields',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/reportFields` as const,
},
WORKSPACE_CREATE_REPORT_FIELD: {
route: 'settings/workspaces/:policyID/reportFields/new',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/reportFields/new` as const,
},
WORKSPACE_REPORT_FIELD_LIST_VALUES: {
route: 'settings/workspaces/:policyID/reportFields/new/listValues',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/reportFields/new/listValues` as const,
},
WORKSPACE_REPORT_FIELD_ADD_VALUE: {
route: 'settings/workspaces/:policyID/reportFields/new/addValue',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/reportFields/new/addValue` as const,
},
WORKSPACE_REPORT_FIELD_VALUE_SETTINGS: {
route: 'settings/workspaces/:policyID/reportFields/new/:valueIndex',
getRoute: (policyID: string, valueIndex: number) => `settings/workspaces/${policyID}/reportFields/new/${valueIndex}` as const,
},
WORKSPACE_REPORT_FIELD_EDIT_VALUE: {
route: 'settings/workspaces/:policyID/reportFields/new/:valueIndex/edit',
getRoute: (policyID: string, valueIndex: number) => `settings/workspaces/${policyID}/reportFields/new/${valueIndex}/edit` as const,
},
WORKSPACE_EXPENSIFY_CARD: {
route: 'settings/workspaces/:policyID/expensify-card',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/expensify-card` as const,
Expand Down
5 changes: 5 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@ const SCREENS = {
TAG_EDIT: 'Tag_Edit',
TAXES: 'Workspace_Taxes',
REPORT_FIELDS: 'Workspace_ReportFields',
REPORT_FIELDS_CREATE: 'Workspace_ReportFields_Create',
REPORT_FIELDS_LIST_VALUES: 'Workspace_ReportFields_ListValues',
REPORT_FIELDS_ADD_VALUE: 'Workspace_ReportFields_AddValue',
REPORT_FIELDS_VALUE_SETTINGS: 'Workspace_ReportFields_ValueSettings',
REPORT_FIELDS_EDIT_VALUE: 'Workspace_ReportFields_EditValue',
TAX_EDIT: 'Workspace_Tax_Edit',
TAX_NAME: 'Workspace_Tax_Name',
TAX_VALUE: 'Workspace_Tax_Value',
Expand Down
4 changes: 2 additions & 2 deletions src/components/ButtonWithDropdownMenu/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ type PaymentType = DeepValueOf<typeof CONST.IOU.PAYMENT_TYPE | typeof CONST.IOU.

type WorkspaceMemberBulkActionType = DeepValueOf<typeof CONST.POLICY.MEMBERS_BULK_ACTION_TYPES>;

type WorkspaceDistanceRatesBulkActionType = DeepValueOf<typeof CONST.POLICY.DISTANCE_RATES_BULK_ACTION_TYPES>;
type WorkspaceDistanceRatesBulkActionType = DeepValueOf<typeof CONST.POLICY.BULK_ACTION_TYPES>;

type WorkspaceTaxRatesBulkActionType = DeepValueOf<typeof CONST.POLICY.TAX_RATES_BULK_ACTION_TYPES>;
type WorkspaceTaxRatesBulkActionType = DeepValueOf<typeof CONST.POLICY.BULK_ACTION_TYPES>;

type DropdownOption<TValueType> = {
value: TValueType;
Expand Down
4 changes: 3 additions & 1 deletion src/components/Form/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ type ValidInputs =
| typeof AddPlaidBankAccount
| typeof EmojiPickerButtonDropdown;

type ValueTypeKey = 'string' | 'boolean' | 'date' | 'country';
type ValueTypeKey = 'string' | 'boolean' | 'date' | 'country' | 'reportFields' | 'disabledListValues';
type ValueTypeMap = {
string: string;
boolean: boolean;
date: Date;
country: Country | '';
reportFields: string[];
disabledListValues: boolean[];
};
type FormValue = ValueOf<ValueTypeMap>;

Expand Down
17 changes: 13 additions & 4 deletions src/components/TextPicker/TextSelectorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import Modal from '@components/Modal';
import ScreenWrapper from '@components/ScreenWrapper';
import ScrollView from '@components/ScrollView';
import Text from '@components/Text';
import TextInput from '@components/TextInput';
import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types';
import useLocalize from '@hooks/useLocalize';
Expand All @@ -14,7 +15,7 @@ import CONST from '@src/CONST';
import type {TextSelectorModalProps} from './types';
import usePaddingStyle from './usePaddingStyle';

function TextSelectorModal({value, description = '', onValueSelected, isVisible, onClose, ...rest}: TextSelectorModalProps) {
function TextSelectorModal({value, description = '', subtitle, onValueSelected, isVisible, onClose, shouldClearOnClose, ...rest}: TextSelectorModalProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();

Expand All @@ -24,6 +25,13 @@ function TextSelectorModal({value, description = '', onValueSelected, isVisible,
const inputRef = useRef<BaseTextInputRef | null>(null);
const focusTimeoutRef = useRef<NodeJS.Timeout | null>(null);

const hide = useCallback(() => {
onClose();
if (shouldClearOnClose) {
setValue('');
}
}, [onClose, shouldClearOnClose]);

useFocusEffect(
useCallback(() => {
focusTimeoutRef.current = setTimeout(() => {
Expand All @@ -44,8 +52,8 @@ function TextSelectorModal({value, description = '', onValueSelected, isVisible,
<Modal
type={CONST.MODAL.MODAL_TYPE.RIGHT_DOCKED}
isVisible={isVisible}
onClose={onClose}
onModalHide={onClose}
onClose={hide}
onModalHide={hide}
hideModalContentWhileAnimating
useNativeDriver
shouldUseModalPaddingStyle={false}
Expand All @@ -59,12 +67,13 @@ function TextSelectorModal({value, description = '', onValueSelected, isVisible,
>
<HeaderWithBackButton
title={description}
onBackButtonPress={onClose}
onBackButtonPress={hide}
/>
<ScrollView
contentContainerStyle={[styles.flex1, styles.mh5, styles.mb5]}
keyboardShouldPersistTaps="handled"
>
<View style={styles.pb4}>{!!subtitle && <Text style={[styles.sidebarLinkText, styles.optionAlternateText]}>{subtitle}</Text>}</View>
<View style={styles.flex1}>
<TextInput
// eslint-disable-next-line react/jsx-props-no-spreading
Expand Down
7 changes: 5 additions & 2 deletions src/components/TextPicker/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ type TextSelectorModalProps = {

/** Whether to show the tooltip text */
shouldShowTooltips?: boolean;
} & Pick<MenuItemBaseProps, 'description'> &

/** Whether to clear the input value when the modal closes */
shouldClearOnClose?: boolean;
} & Pick<MenuItemBaseProps, 'subtitle' | 'description'> &
TextProps;

type TextPickerProps = {
Expand All @@ -39,7 +42,7 @@ type TextPickerProps = {

/** Whether to show the tooltip text */
shouldShowTooltips?: boolean;
} & Pick<MenuItemBaseProps, 'rightLabel' | 'description'> &
} & Pick<MenuItemBaseProps, 'rightLabel' | 'subtitle' | 'description'> &
TextProps;

export type {TextSelectorModalProps, TextPickerProps};
42 changes: 40 additions & 2 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,9 @@ export default {
companyID: 'Company ID',
userID: 'User ID',
disable: 'Disable',
initialValue: 'Initial value',
currentDate: 'Current date',
value: 'Value',
},
location: {
useCurrent: 'Use current location',
Expand Down Expand Up @@ -1990,7 +1993,7 @@ export default {
reimburse: 'Reimbursements',
categories: 'Categories',
tags: 'Tags',
reportFields: 'Report Fields',
reportFields: 'Report fields',
taxes: 'Taxes',
bills: 'Bills',
invoices: 'Invoices',
Expand Down Expand Up @@ -2433,9 +2436,42 @@ export default {
title: "You haven't created any report fields",
subtitle: 'Add a custom field (text, date, or dropdown) that appears on reports.',
},
subtitle: "Report fields apply to all spend and can be helpful when you'd like to prompt for extra information",
subtitle: "Report fields apply to all spend and can be helpful when you'd like to prompt for extra information.",
disableReportFields: 'Disable report fields',
disableReportFieldsConfirmation: 'Are you sure? Text and date fields will be deleted, and lists will be disabled.',
textType: 'Text',
dateType: 'Date',
dropdownType: 'List',
textAlternateText: 'Add a field for free text input.',
dateAlternateText: 'Add a calendar for date selection.',
dropdownAlternateText: 'Add a list of options to choose from.',
nameInputSubtitle: 'Choose a name for the report field.',
typeInputSubtitle: 'Choose what type of report field to use.',
initialValueInputSubtitle: 'Enter a starting value to show in the report field.',
listValuesInputSubtitle: 'These values will appear in your report field dropdown. Enabled values can be selected by members.',
listInputSubtitle: 'These values will appear in your report field list. Enabled values can be selected by members.',
deleteValue: 'Delete value',
deleteValues: 'Delete values',
disableValue: 'Disable value',
disableValues: 'Disable values',
enableValue: 'Enable value',
enableValues: 'Enable values',
emptyReportFieldsValues: {
title: "You haven't created any list values",
subtitle: 'Add custom values to appear on reports.',
},
deleteValuePrompt: 'Are you sure you want to delete this list value?',
deleteValuesPrompt: 'Are you sure you want to delete these list values?',
listValueRequiredError: 'Please enter a list value name',
existingListValueError: 'A list value with this name already exists',
editValue: 'Edit value',
listValues: 'List values',
addValue: 'Add value',
existingReportFieldNameError: 'A report field with this name already exists',
reportFieldNameRequiredError: 'Please enter a report field name',
reportFieldTypeRequiredError: 'Please choose a report field type',
reportFieldInitialValueRequiredError: 'Please choose a report field initial value',
genericFailureMessage: 'An error occurred while updating the report field. Please try again.',
},
tags: {
tagName: 'Tag name',
Expand Down Expand Up @@ -2847,6 +2883,8 @@ export default {
editor: {
descriptionInputLabel: 'Description',
nameInputLabel: 'Name',
typeInputLabel: 'Type',
initialValueInputLabel: 'Initial value',
nameInputHelpText: "This is the name you'll see on your workspace.",
nameIsRequiredError: "You'll need to give your workspace a name.",
currencyInputLabel: 'Default currency',
Expand Down
40 changes: 39 additions & 1 deletion src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,9 @@ export default {
companyID: 'Empresa ID',
userID: 'Usuario ID',
disable: 'Deshabilitar',
initialValue: 'Valor inicial',
currentDate: 'Fecha actual',
value: 'Valor',
},
connectionComplete: {
title: 'Conexión completa',
Expand Down Expand Up @@ -2467,9 +2470,42 @@ export default {
title: 'No has creado ningún campo de informe',
subtitle: 'Añade un campo personalizado (texto, fecha o desplegable) que aparezca en los informes.',
},
subtitle: 'Los campos de informe se aplican a todos los gastos y pueden ser útiles cuando desees solicitar información adicional',
subtitle: 'Los campos de informe se aplican a todos los gastos y pueden ser útiles cuando quieras solicitar información adicional.',
disableReportFields: 'Desactivar campos de informe',
disableReportFieldsConfirmation: 'Estás seguro? Se eliminarán los campos de texto y fecha y se desactivarán las listas.',
textType: 'Texto',
dateType: 'Fecha',
dropdownType: 'Lista',
textAlternateText: 'Añade un campo para introducir texto libre.',
dateAlternateText: 'Añade un calendario para la selección de fechas.',
dropdownAlternateText: 'Añade una lista de opciones para elegir.',
nameInputSubtitle: 'Elige un nombre para el campo del informe.',
typeInputSubtitle: 'Elige qué tipo de campo de informe utilizar.',
initialValueInputSubtitle: 'Ingresa un valor inicial para mostrar en el campo del informe.',
listValuesInputSubtitle: 'Estos valores aparecerán en el desplegable del campo de tu informe. Los miembros pueden seleccionar los valores habilitados.',
listInputSubtitle: 'Estos valores aparecerán en la lista de campos de tu informe. Los miembros pueden seleccionar los valores habilitados.',
deleteValue: 'Eliminar valor',
deleteValues: 'Eliminar valores',
disableValue: 'Desactivar valor',
disableValues: 'Desactivar valores',
enableValue: 'Habilitar valor',
enableValues: 'Habilitar valores',
emptyReportFieldsValues: {
title: 'No has creado ningún valor en la lista',
subtitle: 'Añade valores personalizados para que aparezcan en los informes.',
},
deleteValuePrompt: '¿Estás seguro de que quieres eliminar este valor de la lista?',
deleteValuesPrompt: '¿Estás seguro de que quieres eliminar estos valores de la lista?',
listValueRequiredError: 'Ingresa un nombre para el valor de la lista',
existingListValueError: 'Ya existe un valor en la lista con este nombre',
editValue: 'Editar valor',
listValues: 'Valores de la lista',
addValue: 'Añade valor',
existingReportFieldNameError: 'Ya existe un campo de informe con este nombre',
reportFieldNameRequiredError: 'Ingresa un nombre de campo de informe',
reportFieldTypeRequiredError: 'Elige un tipo de campo de informe',
reportFieldInitialValueRequiredError: 'Elige un valor inicial de campo de informe',
genericFailureMessage: 'Se ha producido un error al actualizar el campo del informe. Por favor, inténtalo de nuevo.',
},
tags: {
tagName: 'Nombre de etiqueta',
Expand Down Expand Up @@ -2881,6 +2917,8 @@ export default {
editor: {
nameInputLabel: 'Nombre',
descriptionInputLabel: 'Descripción',
typeInputLabel: 'Tipo',
initialValueInputLabel: 'Valor inicial',
nameInputHelpText: 'Este es el nombre que verás en tu espacio de trabajo.',
nameIsRequiredError: 'Debes definir un nombre para tu espacio de trabajo.',
currencyInputLabel: 'Moneda por defecto',
Expand Down
6 changes: 6 additions & 0 deletions src/libs/API/parameters/CreateWorkspaceReportFieldParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type CreateWorkspaceReportFieldParams = {
policyID: string;
reportFields: string;
};

export default CreateWorkspaceReportFieldParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ export type {default as DeleteMoneyRequestOnSearchParams} from './DeleteMoneyReq
export type {default as HoldMoneyRequestOnSearchParams} from './HoldMoneyRequestOnSearchParams';
export type {default as UnholdMoneyRequestOnSearchParams} from './UnholdMoneyRequestOnSearchParams';
export type {default as UpdateNetSuiteSubsidiaryParams} from './UpdateNetSuiteSubsidiaryParams';
export type {default as CreateWorkspaceReportFieldParams} from './CreateWorkspaceReportFieldParams';
export type {default as OpenPolicyExpensifyCardsPageParams} from './OpenPolicyExpensifyCardsPageParams';
export type {default as RequestExpensifyCardLimitIncreaseParams} from './RequestExpensifyCardLimitIncreaseParams';
export type {default as UpdateNetSuiteGenericTypeParams} from './UpdateNetSuiteGenericTypeParams';
5 changes: 5 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ const WRITE_COMMANDS = {
UNHOLD_MONEY_REQUEST_ON_SEARCH: 'UnholdMoneyRequestOnSearch',
REQUEST_REFUND: 'User_RefundPurchase',
UPDATE_NETSUITE_SUBSIDIARY: 'UpdateNetSuiteSubsidiary',
CREATE_WORKSPACE_REPORT_FIELD: 'CreatePolicyReportField',
UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION: 'UpdateNetSuiteSyncTaxConfiguration',
UPDATE_NETSUITE_EXPORTER: 'UpdateNetSuiteExporter',
UPDATE_NETSUITE_EXPORT_DATE: 'UpdateNetSuiteExportDate',
Expand Down Expand Up @@ -492,6 +493,10 @@ type WriteCommandParameters = {

// Netsuite parameters
[WRITE_COMMANDS.UPDATE_NETSUITE_SUBSIDIARY]: Parameters.UpdateNetSuiteSubsidiaryParams;

// Workspace report field parameters
[WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD]: Parameters.CreateWorkspaceReportFieldParams;

[WRITE_COMMANDS.UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>;
[WRITE_COMMANDS.UPDATE_NETSUITE_EXPORTER]: Parameters.UpdateNetSuiteGenericTypeParams<'email', string>;
[WRITE_COMMANDS.UPDATE_NETSUITE_EXPORT_DATE]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf<typeof CONST.NETSUITE_EXPORT_DATE>>;
Expand Down
Loading

0 comments on commit 685d3f7

Please sign in to comment.