Skip to content

Commit

Permalink
Merge pull request #36039 from allroundexperts/feat-35331
Browse files Browse the repository at this point in the history
feat: add delete option to deletable report fields
  • Loading branch information
thienlnam authored Apr 5, 2024
2 parents ebc59d1 + 237cc51 commit d3c60f6
Show file tree
Hide file tree
Showing 14 changed files with 442 additions and 271 deletions.
2 changes: 2 additions & 0 deletions src/components/ReportActionItem/MoneyReportView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
import AnimatedEmptyStateBackground from '@pages/home/report/AnimatedEmptyStateBackground';
import variables from '@styles/variables';
import * as reportActions from '@src/libs/actions/Report';
import ROUTES from '@src/ROUTES';
import type {Policy, PolicyReportField, Report} from '@src/types/onyx';

Expand Down Expand Up @@ -81,6 +82,7 @@ function MoneyReportView({report, policy, shouldShowHorizontalRule}: MoneyReport
errors={report.errorFields?.[fieldKey]}
errorRowStyles={styles.ph5}
key={`menuItem-${fieldKey}`}
onClose={() => reportActions.clearReportFieldErrors(report.reportID, reportField)}
>
<MenuItemWithTopDescription
description={Str.UCFirst(reportField.name)}
Expand Down
4 changes: 2 additions & 2 deletions src/components/SelectionList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type CommonListItemProps<TItem> = {
onDismissError?: (item: TItem) => void;

/** Component to display on the right side */
rightHandSideComponent?: ((item: TItem) => ReactElement<TItem>) | ReactElement | null;
rightHandSideComponent?: ((item: TItem) => ReactElement<TItem> | null) | ReactElement | null;

/** Styles for the pressable component */
pressableStyle?: StyleProp<ViewStyle>;
Expand Down Expand Up @@ -278,7 +278,7 @@ type BaseSelectionListProps<TItem extends ListItem> = Partial<ChildrenProps> & {
isKeyboardShown?: boolean;

/** Component to display on the right side of each child */
rightHandSideComponent?: ((item: ListItem) => ReactElement<ListItem>) | ReactElement | null;
rightHandSideComponent?: ((item: ListItem) => ReactElement<ListItem> | null) | ReactElement | null;

/** Whether to show the loading indicator for new options */
isLoadingNewOptions?: boolean;
Expand Down
4 changes: 4 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1919,6 +1919,10 @@ export default {
subtitle: 'Sync your chart of accounts and more.',
},
},
reportFields: {
delete: 'Delete field',
deleteConfirmation: 'Are you sure that you want to delete this field?',
},
tags: {
tagName: 'Tag name',
requiresTag: 'Members must tag all spend',
Expand Down
4 changes: 4 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1946,6 +1946,10 @@ export default {
subtitle: 'Sincroniza tu plan de cuentas y otras opciones.',
},
},
reportFields: {
delete: 'Eliminar campos',
deleteConfirmation: '¿Estás seguro de que quieres eliminar esta campos?',
},
tags: {
tagName: 'Nombre de etiqueta',
requiresTag: 'Los miembros deben etiquetar todos los gastos',
Expand Down
5 changes: 5 additions & 0 deletions src/libs/API/parameters/DeleteReportFieldParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type DeleteReportFieldParams = {
fieldID: string;
};

export default DeleteReportFieldParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export type {default as CompleteEngagementModalParams} from './CompleteEngagemen
export type {default as SetNameValuePairParams} from './SetNameValuePairParams';
export type {default as SetReportFieldParams} from './SetReportFieldParams';
export type {default as SetReportNameParams} from './SetReportNameParams';
export type {default as DeleteReportFieldParams} from './DeleteReportFieldParams';
export type {default as CompleteSplitBillParams} from './CompleteSplitBillParams';
export type {default as UpdateMoneyRequestParams} from './UpdateMoneyRequestParams';
export type {default as RequestMoneyParams} from './RequestMoneyParams';
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ const WRITE_COMMANDS = {
COMPLETE_ENGAGEMENT_MODAL: 'CompleteEngagementModal',
SET_NAME_VALUE_PAIR: 'SetNameValuePair',
SET_REPORT_FIELD: 'Report_SetFields',
DELETE_REPORT_FIELD: 'RemoveReportField',
SET_REPORT_NAME: 'RenameReport',
COMPLETE_SPLIT_BILL: 'CompleteSplitBill',
UPDATE_MONEY_REQUEST_DATE: 'UpdateMoneyRequestDate',
Expand Down Expand Up @@ -324,6 +325,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.SET_NAME_VALUE_PAIR]: Parameters.SetNameValuePairParams;
[WRITE_COMMANDS.SET_REPORT_FIELD]: Parameters.SetReportFieldParams;
[WRITE_COMMANDS.SET_REPORT_NAME]: Parameters.SetReportNameParams;
[WRITE_COMMANDS.DELETE_REPORT_FIELD]: Parameters.DeleteReportFieldParams;
[WRITE_COMMANDS.COMPLETE_SPLIT_BILL]: Parameters.CompleteSplitBillParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DATE]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_MERCHANT]: Parameters.UpdateMoneyRequestParams;
Expand Down
102 changes: 102 additions & 0 deletions src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ type GetOptionsConfig = {
includeSelectedOptions?: boolean;
includeTaxRates?: boolean;
taxRates?: TaxRatesWithDefault;
includePolicyReportFieldOptions?: boolean;
policyReportFieldOptions?: string[];
recentlyUsedPolicyReportFieldOptions?: string[];
transactionViolations?: OnyxCollection<TransactionViolation[]>;
};

Expand Down Expand Up @@ -184,6 +187,7 @@ type GetOptions = {
categoryOptions: CategoryTreeSection[];
tagOptions: CategorySection[];
taxRatesOptions: CategorySection[];
policyReportFieldOptions?: CategorySection[] | null;
};

type PreviewConfig = {showChatPreviewLine?: boolean; forcePolicyNamePreview?: boolean; showPersonalDetails?: boolean};
Expand Down Expand Up @@ -1229,6 +1233,81 @@ function hasEnabledTags(policyTagList: Array<PolicyTagList[keyof PolicyTagList]>
return hasEnabledOptions(policyTagValueList);
}

/**
* Transforms the provided report field options into option objects.
*
* @param reportFieldOptions - an initial report field options array
*/
function getReportFieldOptions(reportFieldOptions: string[]): Option[] {
return reportFieldOptions.map((name) => ({
text: name,
keyForList: name,
searchText: name,
tooltipText: name,
isDisabled: false,
}));
}

/**
* Build the section list for report field options
*/
function getReportFieldOptionsSection(options: string[], recentlyUsedOptions: string[], selectedOptions: Array<Partial<ReportUtils.OptionData>>, searchInputValue: string) {
const reportFieldOptionsSections = [];
const selectedOptionKeys = selectedOptions.map(({text, keyForList, name}) => text ?? keyForList ?? name ?? '').filter((o) => !!o);
let indexOffset = 0;

if (searchInputValue) {
const searchOptions = options.filter((option) => option.toLowerCase().includes(searchInputValue.toLowerCase()));

reportFieldOptionsSections.push({
// "Search" section
title: '',
shouldShow: true,
indexOffset,
data: getReportFieldOptions(searchOptions),
});

return reportFieldOptionsSections;
}

const filteredRecentlyUsedOptions = recentlyUsedOptions.filter((recentlyUsedOption) => !selectedOptionKeys.includes(recentlyUsedOption));
const filteredOptions = options.filter((option) => !selectedOptionKeys.includes(option));

if (selectedOptionKeys.length) {
reportFieldOptionsSections.push({
// "Selected" section
title: '',
shouldShow: true,
indexOffset,
data: getReportFieldOptions(selectedOptionKeys),
});

indexOffset += selectedOptionKeys.length;
}

if (filteredRecentlyUsedOptions.length > 0) {
reportFieldOptionsSections.push({
// "Recent" section
title: Localize.translateLocal('common.recent'),
shouldShow: true,
indexOffset,
data: getReportFieldOptions(filteredRecentlyUsedOptions),
});

indexOffset += filteredRecentlyUsedOptions.length;
}

reportFieldOptionsSections.push({
// "All" section when items amount more than the threshold
title: Localize.translateLocal('common.all'),
shouldShow: true,
indexOffset,
data: getReportFieldOptions(filteredOptions),
});

return reportFieldOptionsSections;
}

/**
* Transforms tax rates to a new object format - to add codes and new name with concatenated name and value.
*
Expand Down Expand Up @@ -1454,6 +1533,9 @@ function getOptions(
includeTaxRates,
taxRates,
includeSelfDM = false,
includePolicyReportFieldOptions = false,
policyReportFieldOptions = [],
recentlyUsedPolicyReportFieldOptions = [],
}: GetOptionsConfig,
): GetOptions {
if (includeCategories) {
Expand Down Expand Up @@ -1498,6 +1580,20 @@ function getOptions(
};
}

if (includePolicyReportFieldOptions) {
const transformedPolicyReportFieldOptions = getReportFieldOptionsSection(policyReportFieldOptions, recentlyUsedPolicyReportFieldOptions, selectedOptions, searchInputValue);
return {
recentReports: [],
personalDetails: [],
userToInvite: null,
currentUserOption: null,
categoryOptions: [],
tagOptions: [],
taxRatesOptions: [],
policyReportFieldOptions: transformedPolicyReportFieldOptions,
};
}

const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(searchInputValue)));
const searchValue = parsedPhoneNumber.possible ? parsedPhoneNumber.number?.e164 : searchInputValue.toLowerCase();
const topmostReportId = Navigation.getTopmostReportId() ?? '';
Expand Down Expand Up @@ -1881,6 +1977,9 @@ function getFilteredOptions(
includeTaxRates = false,
taxRates: TaxRatesWithDefault = {} as TaxRatesWithDefault,
includeSelfDM = false,
includePolicyReportFieldOptions = false,
policyReportFieldOptions: string[] = [],
recentlyUsedPolicyReportFieldOptions: string[] = [],
) {
return getOptions(
{reports, personalDetails},
Expand All @@ -1905,6 +2004,9 @@ function getFilteredOptions(
includeTaxRates,
taxRates,
includeSelfDM,
includePolicyReportFieldOptions,
policyReportFieldOptions,
recentlyUsedPolicyReportFieldOptions,
},
);
}
Expand Down
73 changes: 73 additions & 0 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,18 @@ function updateReportName(reportID: string, value: string, previousValue: string
API.write(WRITE_COMMANDS.SET_REPORT_NAME, parameters, {optimisticData, failureData, successData});
}

function clearReportFieldErrors(reportID: string, reportField: PolicyReportField) {
const fieldKey = ReportUtils.getReportFieldKey(reportField.fieldID);
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {
pendingFields: {
[fieldKey]: null,
},
errorFields: {
[fieldKey]: null,
},
});
}

function updateReportField(reportID: string, reportField: PolicyReportField, previousReportField: PolicyReportField) {
const fieldKey = ReportUtils.getReportFieldKey(reportField.fieldID);
const recentlyUsedValues = allRecentlyUsedReportFields?.[fieldKey] ?? [];
Expand Down Expand Up @@ -1678,6 +1690,65 @@ function updateReportField(reportID: string, reportField: PolicyReportField, pre
API.write(WRITE_COMMANDS.SET_REPORT_FIELD, parameters, {optimisticData, failureData, successData});
}

function deleteReportField(reportID: string, reportField: PolicyReportField) {
const fieldKey = ReportUtils.getReportFieldKey(reportField.fieldID);

const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
fieldList: {
[fieldKey]: null,
},
pendingFields: {
[fieldKey]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
},
},
];

const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
fieldList: {
[fieldKey]: reportField,
},
pendingFields: {
[fieldKey]: null,
},
errorFields: {
[fieldKey]: ErrorUtils.getMicroSecondOnyxError('report.genericUpdateReportFieldFailureMessage'),
},
},
},
];

const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
pendingFields: {
[fieldKey]: null,
},
errorFields: {
[fieldKey]: null,
},
},
},
];

const parameters = {
reportID,
fieldID: fieldKey,
};

API.write(WRITE_COMMANDS.DELETE_REPORT_FIELD, parameters, {optimisticData, failureData, successData});
}

function updateDescription(reportID: string, previousValue: string, newValue: string) {
// No change needed, navigate back
if (previousValue === newValue) {
Expand Down Expand Up @@ -3010,6 +3081,8 @@ export {
clearNewRoomFormError,
updateReportField,
updateReportName,
deleteReportField,
clearReportFieldErrors,
resolveActionableMentionWhisper,
updateRoomVisibility,
setGroupDraft,
Expand Down
Loading

0 comments on commit d3c60f6

Please sign in to comment.