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

Wave8/workspace switcher #15

Merged
merged 32 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ce7ad35
Create WorkspaceSelectorPage
mateuuszzzzz Dec 13, 2023
8bff47a
Update design and implement page in RHP temporarily
mateuuszzzzz Dec 14, 2023
01c740c
Adapt OptionRow for Workspace Switcher
mateuuszzzzz Dec 14, 2023
2b0cb18
Comment unused variable
mateuuszzzzz Dec 14, 2023
f5a0d7b
Integrate search bar
mateuuszzzzz Dec 20, 2023
daa8597
Fix typos
mateuuszzzzz Dec 21, 2023
476eeda
Move switcher to LHP
mateuuszzzzz Dec 21, 2023
62b122a
Cherry pick workspace card
MaciejSWM Dec 20, 2023
0db1612
Implement simplified search
mateuuszzzzz Dec 21, 2023
792190c
Add translations
mateuuszzzzz Dec 22, 2023
4a1735e
Add BrickRoadsUtils
WojtekBoman Dec 18, 2023
72f72d3
Refactor getBrickRoadForPolicy return type
WojtekBoman Dec 18, 2023
ad55ac8
Refactor getBrickRoadForPolicy function
WojtekBoman Dec 18, 2023
7a3caa4
Refactor getWorkspacesBrickRoads function
WojtekBoman Dec 18, 2023
7043a9a
Add export type BrickRoad
WojtekBoman Dec 18, 2023
2023eaa
Refactor BrickRoad type, add commments in BrickRoadsUtils
WojtekBoman Dec 19, 2023
6cc0437
Fix lint in BrickRoadsUtils
WojtekBoman Dec 19, 2023
f618fcc
Refactor BrickRoadsUtils
WojtekBoman Dec 21, 2023
bc79188
Add logic for gbr/rbr and unread chats
mateuuszzzzz Dec 22, 2023
a115286
Add navigation to workspace editor
mateuuszzzzz Dec 22, 2023
f4d5b1f
Add navigation to main page
mateuuszzzzz Dec 22, 2023
c3378bd
Update shouldShowPolicy
mateuuszzzzz Dec 22, 2023
2371230
Fix conditional rendering
mateuuszzzzz Dec 22, 2023
63c9c67
Adjust spanish translation
mateuuszzzzz Dec 22, 2023
e1d746d
Resolve conflicts
mateuuszzzzz Jan 4, 2024
b65dfd6
Fix import
mateuuszzzzz Jan 4, 2024
b7b2075
Merge branch 'ideal-nav-merge' into wave8/workspace-switcher
mateuuszzzzz Jan 4, 2024
adbb9a1
Resolve conflicts with ideal-nav-merge
mateuuszzzzz Jan 10, 2024
7c7f8fa
Add context for storing active workspacegp
mateuuszzzzz Jan 11, 2024
4a5eb63
Add filtering of reports based on active workspace
mateuuszzzzz Jan 11, 2024
a092248
Remove redundant export
mateuuszzzzz Jan 11, 2024
e77d1a0
Change icon of switcher button based on active workspace
mateuuszzzzz Jan 11, 2024
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
2 changes: 2 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Onyx from 'react-native-onyx';
import {PickerStateProvider} from 'react-native-picker-select';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import '../wdyr';
import ActiveWorkspaceContextProvider from './components/ActiveWorkspace/ActiveWorkspaceProvider';
import ColorSchemeWrapper from './components/ColorSchemeWrapper';
import ComposeProviders from './components/ComposeProviders';
import CustomStatusBarAndBackground from './components/CustomStatusBarAndBackground';
Expand Down Expand Up @@ -69,6 +70,7 @@ function App() {
PickerStateProvider,
EnvironmentProvider,
CustomStatusBarAndBackgroundContextProvider,
ActiveWorkspaceContextProvider,
]}
>
<CustomStatusBarAndBackground />
Expand Down
4 changes: 4 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3065,7 +3065,11 @@ const CONST = {
DEFAULT: 5,
CAROUSEL: 3,
},
BRICK_ROAD: {
GBR: 'info',
RBR: 'error',

},
VIOLATIONS: {
ALL_TAG_LEVELS_REQUIRED: 'allTagLevelsRequired',
AUTO_REPORTED_REJECTED_EXPENSE: 'autoReportedRejectedExpense',
Expand Down
2 changes: 1 addition & 1 deletion src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const ROUTES = {
route: 'bank-account/:stepToOpen?',
getRoute: (stepToOpen = '', policyID = '', backTo?: string) => getUrlWithBackToParam(`bank-account/${stepToOpen}?policyID=${policyID}`, backTo),
},

WORKSPACE_SWITCHER: 'workspaceSwitcher',
SETTINGS: 'settings',
SETTINGS_PROFILE: 'settings/profile',
SETTINGS_SHARE_CODE: 'settings/shareCode',
Expand Down
4 changes: 4 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ const SCREENS = {
},
LEFT_MODAL: {
SEARCH: 'Search',
WORKSPACE_SWITCHER: 'WorkspaceSwitcher',
},
WORKSPACE_SWITCHER: {
ROOT: 'WorkspaceSwitcher_Root',
},
RIGHT_MODAL: {
SETTINGS: 'Settings',
Expand Down
11 changes: 11 additions & 0 deletions src/components/ActiveWorkspace/ActiveWorkspaceContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {createContext} from 'react';

type ActiveWorkspaceContextType = {
activeWorkspaceID?: string;
setActiveWorkspaceID: (activeWorkspaceID?: string) => void;
}

const ActiveWorkspaceContext = createContext<ActiveWorkspaceContextType>({activeWorkspaceID: undefined, setActiveWorkspaceID: () => undefined});

export default ActiveWorkspaceContext;
export {type ActiveWorkspaceContextType};
17 changes: 17 additions & 0 deletions src/components/ActiveWorkspace/ActiveWorkspaceProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, {useMemo, useState} from 'react';
import ActiveWorkspaceContext from './ActiveWorkspaceContext';

function ActiveWorkspaceContextProvider({children}: React.PropsWithChildren) {
const [activeWorkspaceID, setActiveWorkspaceID] = useState<string | undefined>(undefined);

const value = useMemo(
() => ({
activeWorkspaceID,
setActiveWorkspaceID,
}), [activeWorkspaceID]
)

return <ActiveWorkspaceContext.Provider value={value}>{children}</ActiveWorkspaceContext.Provider>;
}

export default ActiveWorkspaceContextProvider;
1 change: 1 addition & 0 deletions src/components/EnvironmentBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function EnvironmentBadge() {
badgeStyles={[styles.alignSelfStart, styles.headerEnvBadge]}
textStyles={[styles.headerEnvBadgeText]}
environment={environment}
pressable
/>
);
}
Expand Down
1 change: 1 addition & 0 deletions src/components/MultipleAvatars.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ function MultipleAvatars({
<Avatar
source={icons[0].source}
size={size}
fill={icons[0].fill ?? theme.iconSuccessFill}
name={icons[0].name}
type={icons[0].type}
fallbackIcon={icons[0].fallbackIcon}
Expand Down
8 changes: 8 additions & 0 deletions src/components/OptionRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,14 @@ function OptionRow({
/>
</View>
)}
{option.brickRoadIndicator === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO && (
<View style={[styles.alignItemsCenter, styles.justifyContentCenter]}>
<Icon
src={Expensicons.DotIndicator}
fill={theme.iconSuccessFill}
/>
</View>
)}
{showSelectedState && (
<>
{shouldShowSelectedStateAsButton && !isSelected ? (
Expand Down
8 changes: 6 additions & 2 deletions src/components/OptionsList/BaseOptionsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ function BaseOptionsList({
return true;
}

if (option.policyID && option.policyID === item.policyID) {
return true;
}

if (_.isEmpty(option.name)) {
return false;
}
Expand All @@ -201,7 +205,7 @@ function BaseOptionsList({
return (
<OptionRow
keyForList={item.keyForList}
option={item}
option={{...item, brickRoadIndicator: isSelected ? undefined : item.brickRoadIndicator}}
showTitleTooltip={showTitleTooltip}
hoverStyle={optionHoveredStyle}
optionIsFocused={!disableFocusOptions && !isItemDisabled && focusedIndex === index + section.indexOffset}
Expand All @@ -212,7 +216,7 @@ function BaseOptionsList({
selectedStateButtonText={multipleOptionSelectorButtonText}
onSelectedStatePressed={onAddToSelection}
highlightSelected={highlightSelectedOptions}
boldStyle={boldStyle}
boldStyle={_.isUndefined(item.boldStyle) ? boldStyle : item.boldStyle}
isDisabled={isItemDisabled}
shouldHaveOptionSeparator={index > 0 && shouldHaveOptionSeparator}
shouldDisableRowInnerPadding={shouldDisableRowInnerPadding}
Expand Down
4 changes: 3 additions & 1 deletion src/components/OptionsSelector/BaseOptionsSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Button from '@components/Button';
import FixedFooter from '@components/FixedFooter';
import FormHelpMessage from '@components/FormHelpMessage';
import Icon from '@components/Icon';
import {Info} from '@components/Icon/Expensicons';
import {Info, MagnifyingGlass} from '@components/Icon/Expensicons';
import OptionsList from '@components/OptionsList';
import {PressableWithoutFeedback} from '@components/Pressable';
import ShowMoreButton from '@components/ShowMoreButton';
Expand Down Expand Up @@ -492,6 +492,7 @@ class BaseOptionsSelector extends Component {
spellCheck={false}
shouldInterceptSwipe={this.props.shouldTextInputInterceptSwipe}
isLoading={this.props.isLoadingNewOptions}
iconLeft={MagnifyingGlass}
testID="options-selector-input"
/>
);
Expand All @@ -502,6 +503,7 @@ class BaseOptionsSelector extends Component {
onSelectRow={this.props.onSelectRow ? this.selectRow : undefined}
sections={this.state.sections}
focusedIndex={this.state.focusedIndex}
disableFocusOptions={this.props.disableFocusOptions}
selectedOptions={this.props.selectedOptions}
canSelectMultipleOptions={this.props.canSelectMultipleOptions}
shouldShowMultipleOptionSelectorAsButton={this.props.shouldShowMultipleOptionSelectorAsButton}
Expand Down
4 changes: 4 additions & 0 deletions src/components/OptionsSelector/optionsSelectorPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ const propTypes = {
/** Whether to disable interactivity of option rows */
isDisabled: PropTypes.bool,

/** Whether to disable focus options of rows */
disableFocusOptions: PropTypes.bool,

/** Display the text of the option in bold font style */
boldStyle: PropTypes.bool,

Expand Down Expand Up @@ -163,6 +166,7 @@ const defaultProps = {
shouldShowOptions: true,
disableArrowKeysActions: false,
isDisabled: false,
disableFocusOptions: false,
shouldHaveOptionSeparator: false,
initiallyFocusedOptionKey: undefined,
maxLength: CONST.SEARCH_MAX_LENGTH,
Expand Down
11 changes: 11 additions & 0 deletions src/components/TextInput/BaseTextInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ function BaseTextInput(
placeholder = '',
errorText = '',
icon = null,
iconLeft = null,
textInputContainerStyles,
touchableInputWrapperStyle,
containerStyles,
Expand Down Expand Up @@ -317,6 +318,16 @@ function BaseTextInput(
</>
) : null}
<View style={[styles.textInputAndIconContainer, isMultiline && hasLabel && styles.textInputMultilineContainer, styles.pointerEventsBoxNone]}>
{!inputProps.secureTextEntry && iconLeft && (
<View style={[styles.textInputLeftIconContainer, !isReadOnly ? styles.cursorPointer : styles.pointerEventsNone]}>
<Icon
src={iconLeft}
fill={theme.icon}
height={20}
width={20}
/>
</View>
)}
{Boolean(prefixCharacter) && (
<View style={styles.textInputPrefixWrapper}>
<Text
Expand Down
3 changes: 3 additions & 0 deletions src/components/TextInput/BaseTextInput/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ type CustomBaseTextInputProps = {
/** Icon to display in right side of text input */
icon?: IconAsset | null;

/** Icon to display in left side of text input */
iconLeft: IconAsset | null;

/** Customize the TextInput container */
textInputContainerStyles?: StyleProp<ViewStyle>;

Expand Down
30 changes: 27 additions & 3 deletions src/components/WorkspaceSwitcherButton.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
import React from 'react';
import React, { useMemo } from 'react';
import useLocalize from '@hooks/useLocalize';
import CONST from '@src/CONST';
import Navigation from '@libs/Navigation/Navigation';
import ROUTES from '@src/ROUTES';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import {getPolicy, getDefaultWorkspaceAvatar} from "@libs/ReportUtils"
import * as Expensicons from './Icon/Expensicons';
import {PressableWithFeedback} from './Pressable';
import SubscriptAvatar from './SubscriptAvatar';

function WorkspaceSwitcherButton() {
const {translate} = useLocalize();
const {activeWorkspaceID} = useActiveWorkspace();


const {source, name, type} = useMemo(() => {

if(!activeWorkspaceID) {
return {source: Expensicons.ExpensifyAppIcon, name: CONST.WORKSPACE_SWITCHER.NAME, type: CONST.ICON_TYPE_AVATAR}
}

const policy = getPolicy(activeWorkspaceID);
const avatar = policy?.avatar && policy?.avatar?.length > 0 ? policy.avatar : getDefaultWorkspaceAvatar(policy?.name);
return {
source: avatar,
name: policy?.name,
type: CONST.ICON_TYPE_WORKSPACE,
}
}, [activeWorkspaceID]);


return (
<PressableWithFeedback
accessibilityRole={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.workspaces')}
accessible
onPress={() => {}}
onPress={() => {
Navigation.navigate(ROUTES.WORKSPACE_SWITCHER);
}}
>
<SubscriptAvatar
mainAvatar={{source: Expensicons.ExpensifyAppIcon, name: CONST.WORKSPACE_SWITCHER.NAME, type: CONST.ICON_TYPE_AVATAR}}
mainAvatar={{source, name, type}}
subscriptIcon={{source: Expensicons.DownArrow, width: CONST.WORKSPACE_SWITCHER.SUBSCRIPT_ICON_SIZE, height: CONST.WORKSPACE_SWITCHER.SUBSCRIPT_ICON_SIZE}}
showTooltip={false}
noMargin
Expand Down
9 changes: 9 additions & 0 deletions src/hooks/useActiveWorkspace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {useContext} from 'react';
import ActiveWorkspaceContext from '@components/ActiveWorkspace/ActiveWorkspaceContext';
import type { ActiveWorkspaceContextType } from '@components/ActiveWorkspace/ActiveWorkspaceContext';

function useActiveWorkspace(): ActiveWorkspaceContextType {
return useContext(ActiveWorkspaceContext);
}

export default useActiveWorkspace;
4 changes: 4 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1553,6 +1553,10 @@ export default {
notFound: 'No workspace found',
description: 'Rooms are a great place to discuss and work with multiple people. To begin collaborating, create or join a workspace',
},
switcher: {
headerTitle: 'Choose a workspace',
everythingSection: 'Everything',
},
new: {
newWorkspace: 'New workspace',
getTheExpensifyCardAndMore: 'Get the Expensify Card and more',
Expand Down
4 changes: 4 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1576,6 +1576,10 @@ export default {
notFound: 'No se encontró ningún espacio de trabajo',
description: 'Las salas son un gran lugar para discutir y trabajar con varias personas. Para comenzar a colaborar, cree o únase a un espacio de trabajo',
},
switcher: {
headerTitle: 'Elige un espacio de trabajo',
everythingSection: 'Todo',
},
new: {
newWorkspace: 'Nuevo espacio de trabajo',
getTheExpensifyCardAndMore: 'Consigue la Tarjeta Expensify y más',
Expand Down
5 changes: 5 additions & 0 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import type {
TaskDetailsNavigatorParamList,
TeachersUniteNavigatorParamList,
WalletStatementNavigatorParamList,
WorkspaceSwitcherNavigatorParamList,
} from '@navigation/types';
import type {ThemeStyles} from '@styles/index';
import type {Screen} from '@src/SCREENS';
Expand Down Expand Up @@ -195,6 +196,9 @@ const AccountSettingsModalStackNavigator = createModalStackNavigator(
},
(styles) => ({cardStyle: styles.navigationScreenCardStyle, headerShown: false}),
);
const WorkspaceSwitcherModalStackNavigator = createModalStackNavigator<WorkspaceSwitcherNavigatorParamList>({
[SCREENS.WORKSPACE_SWITCHER.ROOT]: () => require('../../../pages/WorkspaceSwitcherPage').default as React.ComponentType,
});

const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorParamList>({
[SCREENS.SETTINGS.SHARE_CODE]: () => require('../../../pages/ShareCodePage').default as React.ComponentType,
Expand Down Expand Up @@ -310,6 +314,7 @@ export {
PrivateNotesModalStackNavigator,
ProfileModalStackNavigator,
ReferralModalStackNavigator,
WorkspaceSwitcherModalStackNavigator,
ReimbursementAccountModalStackNavigator,
ReportDetailsModalStackNavigator,
ReportParticipantsModalStackNavigator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ function LeftModalNavigator({navigation}: LeftModalNavigatorProps) {
name={SCREENS.LEFT_MODAL.SEARCH}
component={ModalStackNavigators.SearchModalStackNavigator}
/>
<Stack.Screen
name={SCREENS.LEFT_MODAL.WORKSPACE_SWITCHER}
component={ModalStackNavigators.WorkspaceSwitcherModalStackNavigator}
/>
</Stack.Navigator>
</View>
</NoDropZone>
Expand Down
7 changes: 7 additions & 0 deletions src/libs/Navigation/linkingConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ const linkingConfig: LinkingOptions<RootStackParamList> = {
[SCREENS.SEARCH_ROOT]: ROUTES.SEARCH,
},
},
[SCREENS.LEFT_MODAL.WORKSPACE_SWITCHER]: {
screens: {
[SCREENS.WORKSPACE_SWITCHER.ROOT]: {
path: ROUTES.WORKSPACE_SWITCHER,
},
},
},
},
},
[NAVIGATORS.RIGHT_MODAL_NAVIGATOR]: {
Expand Down
6 changes: 6 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ type CentralPaneNavigatorParamList = {
};
};

type WorkspaceSwitcherNavigatorParamList = {
[SCREENS.WORKSPACE_SWITCHER.ROOT]: undefined;
};

type SettingsNavigatorParamList = {
[SCREENS.SETTINGS.ROOT]: undefined;
[SCREENS.SETTINGS.SHARE_CODE]: undefined;
Expand Down Expand Up @@ -367,6 +371,7 @@ type PrivateNotesNavigatorParamList = {

type LeftModalNavigatorParamList = {
[SCREENS.LEFT_MODAL.SEARCH]: NavigatorScreenParams<SearchNavigatorParamList>;
[SCREENS.LEFT_MODAL.WORKSPACE_SWITCHER]: NavigatorScreenParams<WorkspaceSwitcherNavigatorParamList>;
};

type RightModalNavigatorParamList = {
Expand Down Expand Up @@ -514,4 +519,5 @@ export type {
ReferralDetailsNavigatorParamList,
ReimbursementAccountNavigatorParamList,
State,
WorkspaceSwitcherNavigatorParamList,
};
5 changes: 1 addition & 4 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,7 @@ function getPolicyBrickRoadIndicatorStatus(policy: OnyxEntry<Policy>, policyMemb
*/
function shouldShowPolicy(policy: OnyxEntry<Policy>, isOffline: boolean): boolean {
return (
!!policy &&
policy?.isPolicyExpenseChatEnabled &&
policy?.role === CONST.POLICY.ROLE.ADMIN &&
(isOffline || policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || Object.keys(policy.errors ?? {}).length > 0)
!!policy && policy?.isPolicyExpenseChatEnabled && (isOffline || policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || Object.keys(policy.errors ?? {}).length > 0)
);
}

Expand Down
Loading
Loading