-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Create WorkspaceTagsSettingsPage #37755
Changes from 4 commits
5fe99d5
5d218e1
489b4df
9de8694
b7d6673
cd25554
5ab9f8e
1164897
aa61446
941d1de
0879031
75b82c9
6333956
82b72ff
7510fa0
220439f
28efa41
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
type RenamePolicyTaglist = { | ||
policyID: string; | ||
oldName: string; | ||
newName: string; | ||
}; | ||
|
||
export default RenamePolicyTaglist; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
type SetPolicyRequiresTag = { | ||
policyID: string; | ||
requiresTag: boolean; | ||
}; | ||
|
||
export default SetPolicyRequiresTag; |
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2489,6 +2489,99 @@ | |||||||||||
API.write('SetWorkspaceRequiresCategory', parameters, onyxData); | ||||||||||||
} | ||||||||||||
|
||||||||||||
function setPolicyRequiresTag(policyID: string, requiresTag: boolean) { | ||||||||||||
const onyxData: OnyxData = { | ||||||||||||
optimisticData: [ | ||||||||||||
{ | ||||||||||||
onyxMethod: Onyx.METHOD.MERGE, | ||||||||||||
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, | ||||||||||||
value: { | ||||||||||||
requiresTag, | ||||||||||||
errors: { | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. errors are working, it shows an error, we have the same in categories There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm seeing the following issues when simulating an error from the API:
Screen.Recording.2024-03-08.at.3.14.18.PM.mov
Screen.Recording.2024-03-08.at.3.15.17.PM.mov![]() There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this thread resolved? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm retesting this now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, this is still happening. I think we can continue with this and I'll address it in a fast following PR. |
||||||||||||
requiresTag: null, | ||||||||||||
}, | ||||||||||||
pendingFields: { | ||||||||||||
requiresTag: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, | ||||||||||||
}, | ||||||||||||
}, | ||||||||||||
}, | ||||||||||||
], | ||||||||||||
successData: [ | ||||||||||||
{ | ||||||||||||
onyxMethod: Onyx.METHOD.MERGE, | ||||||||||||
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, | ||||||||||||
value: { | ||||||||||||
errors: { | ||||||||||||
requiresTag: null, | ||||||||||||
}, | ||||||||||||
pendingFields: { | ||||||||||||
requiresTag: null, | ||||||||||||
}, | ||||||||||||
}, | ||||||||||||
}, | ||||||||||||
], | ||||||||||||
failureData: [ | ||||||||||||
{ | ||||||||||||
onyxMethod: Onyx.METHOD.MERGE, | ||||||||||||
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, | ||||||||||||
value: { | ||||||||||||
requiresTag: !requiresTag, | ||||||||||||
errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), | ||||||||||||
pendingFields: { | ||||||||||||
requiresTag: null, | ||||||||||||
}, | ||||||||||||
}, | ||||||||||||
}, | ||||||||||||
], | ||||||||||||
}; | ||||||||||||
|
||||||||||||
const parameters = { | ||||||||||||
policyID, | ||||||||||||
requiresTag, | ||||||||||||
}; | ||||||||||||
|
||||||||||||
API.write(WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG, parameters, onyxData); | ||||||||||||
} | ||||||||||||
|
||||||||||||
function renamePolicyTaglist(policyID: string, policyTagListName: {oldName: string; newName: string}, policyTags: OnyxEntry<PolicyTagList>) { | ||||||||||||
const newName = policyTagListName.newName; | ||||||||||||
const oldName = policyTagListName.oldName; | ||||||||||||
const oldPolicyTags = policyTags?.[oldName] ?? {}; | ||||||||||||
const onyxData: OnyxData = { | ||||||||||||
optimisticData: [ | ||||||||||||
{ | ||||||||||||
onyxMethod: Onyx.METHOD.MERGE, | ||||||||||||
key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, | ||||||||||||
value: { | ||||||||||||
[newName]: {...oldPolicyTags, name: newName}, | ||||||||||||
[oldName]: null, | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm I think the correct pattern here is to have the old tagList pending as delete and the new one pending as add
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In addition, we'd have successData to remove the pendingActions and delete the old taglist |
||||||||||||
}, | ||||||||||||
}, | ||||||||||||
], | ||||||||||||
failureData: [ | ||||||||||||
{ | ||||||||||||
onyxMethod: Onyx.METHOD.MERGE, | ||||||||||||
key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, | ||||||||||||
value: { | ||||||||||||
errors: { | ||||||||||||
[oldName]: oldName, | ||||||||||||
[newName]: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), | ||||||||||||
}, | ||||||||||||
[newName]: null, | ||||||||||||
[oldName]: oldPolicyTags, | ||||||||||||
}, | ||||||||||||
}, | ||||||||||||
], | ||||||||||||
}; | ||||||||||||
const parameters = { | ||||||||||||
policyID: policyID, | ||||||||||||
oldName: oldName, | ||||||||||||
newName: newName, | ||||||||||||
}; | ||||||||||||
|
||||||||||||
API.write(WRITE_COMMANDS.RENAME_POLICY_TAG_LIST, parameters, onyxData); | ||||||||||||
} | ||||||||||||
|
||||||||||||
function clearCategoryErrors(policyID: string, categoryName: string) { | ||||||||||||
const category = allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`]?.[categoryName]; | ||||||||||||
|
||||||||||||
|
@@ -2553,4 +2646,6 @@ | |||||||||||
setWorkspaceCategoryEnabled, | ||||||||||||
setWorkspaceRequiresCategory, | ||||||||||||
clearCategoryErrors, | ||||||||||||
setPolicyRequiresTag, | ||||||||||||
renamePolicyTaglist, | ||||||||||||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import {StackScreenProps} from '@react-navigation/stack'; | ||
import React, {useCallback, useMemo, useRef} from 'react'; | ||
import {View} from 'react-native'; | ||
import {withOnyx} from 'react-native-onyx'; | ||
import type {OnyxEntry} from 'react-native-onyx'; | ||
import FormProvider from '@components/Form/FormProvider'; | ||
import InputWrapper from '@components/Form/InputWrapper'; | ||
import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; | ||
import HeaderWithBackButton from '@components/HeaderWithBackButton'; | ||
import type {AnimatedTextInputRef} from '@components/RNTextInput'; | ||
import ScreenWrapper from '@components/ScreenWrapper'; | ||
import TextInput from '@components/TextInput'; | ||
import useLocalize from '@hooks/useLocalize'; | ||
import useThemeStyles from '@hooks/useThemeStyles'; | ||
import * as Policy from '@libs/actions/Policy'; | ||
import Navigation from '@libs/Navigation/Navigation'; | ||
import * as PolicyUtils from '@libs/PolicyUtils'; | ||
import type {SettingsNavigatorParamList} from '@navigation/types'; | ||
import CONST from '@src/CONST'; | ||
import ONYXKEYS from '@src/ONYXKEYS'; | ||
import SCREENS from '@src/SCREENS'; | ||
import INPUT_IDS from '@src/types/form/PolicyTagNameForm'; | ||
import type * as OnyxTypes from '@src/types/onyx'; | ||
|
||
type WorkspaceEditTagsPageOnyxProps = { | ||
/** Collection of tags attached to a policy */ | ||
policyTags: OnyxEntry<OnyxTypes.PolicyTagList>; | ||
}; | ||
|
||
type WorkspaceEditTagsPageProps = WorkspaceEditTagsPageOnyxProps & StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.TAGS_EDIT>; | ||
|
||
function WorkspaceEditTagsPage({route, policyTags}: WorkspaceEditTagsPageProps) { | ||
const styles = useThemeStyles(); | ||
const {translate} = useLocalize(); | ||
const taglistName = useMemo(() => PolicyUtils.getTagLists(policyTags)[0].name, [policyTags]); | ||
const inputRef = useRef<AnimatedTextInputRef>(null); | ||
|
||
const validateTagName = useCallback((values: FormOnyxValues<typeof ONYXKEYS.FORMS.POLICY_TAG_NAME_FORM>) => { | ||
waterim marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const errors: FormInputErrors<typeof ONYXKEYS.FORMS.POLICY_TAG_NAME_FORM> = {}; | ||
if (!values[INPUT_IDS.POLICY_TAGS_NAME] && values[INPUT_IDS.POLICY_TAGS_NAME].trim() === '') { | ||
errors[INPUT_IDS.POLICY_TAGS_NAME] = 'common.error.fieldRequired'; | ||
} | ||
return errors; | ||
}, []); | ||
|
||
const updateTaglistName = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.POLICY_TAG_NAME_FORM>) => { | ||
waterim marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Policy.renamePolicyTaglist(route.params.policyID, {oldName: taglistName, newName: values[INPUT_IDS.POLICY_TAGS_NAME]}, policyTags); | ||
Navigation.goBack(); | ||
}; | ||
|
||
return ( | ||
<ScreenWrapper | ||
includeSafeAreaPaddingBottom={false} | ||
shouldEnableMaxHeight | ||
onEntryTransitionEnd={() => { | ||
inputRef.current?.focus(); | ||
}} | ||
waterim marked this conversation as resolved.
Show resolved
Hide resolved
|
||
testID={WorkspaceEditTagsPage.displayName} | ||
> | ||
<HeaderWithBackButton title={translate(`workspace.tags.customTagName`)} /> | ||
<FormProvider | ||
style={[styles.flexGrow1, styles.ph5]} | ||
formID={ONYXKEYS.FORMS.POLICY_TAG_NAME_FORM} | ||
onSubmit={updateTaglistName} | ||
validate={validateTagName} | ||
submitButtonText={translate('common.save')} | ||
enabledWhenOffline | ||
> | ||
<View style={styles.mb4}> | ||
<InputWrapper | ||
InputComponent={TextInput} | ||
inputID={INPUT_IDS.POLICY_TAGS_NAME} | ||
label={translate(`workspace.tags.customTagName`)} | ||
accessibilityLabel={translate(`workspace.tags.customTagName`)} | ||
defaultValue={taglistName} | ||
role={CONST.ROLE.PRESENTATION} | ||
ref={inputRef} | ||
/> | ||
</View> | ||
</FormProvider> | ||
</ScreenWrapper> | ||
); | ||
} | ||
|
||
WorkspaceEditTagsPage.displayName = 'WorkspaceEditTagsPage'; | ||
|
||
export default withOnyx<WorkspaceEditTagsPageProps, WorkspaceEditTagsPageOnyxProps>({ | ||
policyTags: { | ||
key: ({route}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${route.params.policyID}`, | ||
}, | ||
})(WorkspaceEditTagsPage); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We were only supporting single level tags here (#43754) so we updated this to suport multi-level tags in #44937