App icon indicating copy to clipboard operation
App copied to clipboard

[$500] Add a search bar on the workspaces list

Open roryabraham opened this issue 2 years ago β€’ 14 comments

coming from https://expensify.slack.com/archives/C01GTK53T8Q/p1711147247599549...

Problem

If you have many workspaces on your workspaces list, it can be hard to find a particular one.

Solution

Add a search bar to filter the workspaces list.

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~016fc1028e9b86cc67
  • Upwork Job ID: 1771337546180210688
  • Last Price Increase: 2024-03-30

roryabraham avatar Mar 23 '24 00:03 roryabraham

Triggered auto assignment to @sonialiap (NewFeature), see https://stackoverflowteams.com/c/expensify/questions/14418#:~:text=BugZero%20process%20steps%20for%20feature%20requests for more details.

melvin-bot[bot] avatar Mar 23 '24 00:03 melvin-bot[bot]

Job added to Upwork: https://www.upwork.com/jobs/~016fc1028e9b86cc67

melvin-bot[bot] avatar Mar 23 '24 00:03 melvin-bot[bot]

Triggered auto assignment to Contributor-plus team member for initial proposal review - @eVoloshchak (External)

melvin-bot[bot] avatar Mar 23 '24 00:03 melvin-bot[bot]

Hi Rory, can i make a proposal for this one? or is it already taken?

hayes102 avatar Mar 23 '24 00:03 hayes102

πŸ“£ @hayes102! πŸ“£ Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork. Please follow these steps:

  1. Make sure you've read and understood the contributing guidelines.
  2. Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
  3. Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
  4. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details. Screen Shot 2022-11-16 at 4 42 54 PM Format:
Contributor details
Your Expensify account email: <REPLACE EMAIL HERE>
Upwork Profile Link: <REPLACE LINK HERE>

melvin-bot[bot] avatar Mar 23 '24 00:03 melvin-bot[bot]

Proposal

Please re-state the problem that we are trying to solve in this issue.

Add a search bar on the workspaces list

What is the root cause of that problem?

This is a new feature

What changes do you think we should make in order to solve the problem?

We can re-use the filter logic in WorkspaceSwitcherPage to filter the workspace in WorkspaceListPage

  1. Create a state for search term
const [searchTerm, setSearchTerm] = useState('');
  1. Create a textInput component
const textInput = (
        <TextInput 
          defaultValue={searchTerm}
          onChangeText={(value) => {
              setSearchTerm(value);
          }}
          selectTextOnFocus
          spellCheck={false}
          iconLeft={MagnifyingGlass}
          placeholder={translate('workspace.switcher.placeholder')}
      />
  )
  • Note: this is the main idea, other logics like focus, blur, ... of TextInput can be done on the PR
  1. Update listHeaderComponent to include the search bar
const shouldShowTextInput = workspaces.length >= CONST.WORKSPACE_SWITCHER.MINIMUM_WORKSPACES_TO_SHOW_SEARCH;
const listHeaderComponent = useCallback(() => {
  const headerContent = isLessThanMediumScreen ? (
      <View style={styles.mt5} />
  ) : (
      <View style={[styles.flexRow, styles.gap5, styles.p5, styles.pl10, styles.appBG]}>
          {filteredAndSortedUserWorkspaces.length > 0 ? (
              <>
                  <View style={[styles.flexRow, styles.flex1]}>
                      <Text
                          numberOfLines={1}
                          style={[styles.flexGrow1, styles.textLabelSupporting]}
                      >
                          {translate('workspace.common.workspaceName')}
                      </Text>
                  </View>
                  <View style={[styles.flexRow, styles.flex1, styles.workspaceOwnerSectionTitle]}>
                      <Text
                          numberOfLines={1}
                          style={[styles.flexGrow1, styles.textLabelSupporting]}
                      >
                          {translate('workspace.common.workspaceOwner')}
                      </Text>
                  </View>
                  <View style={[styles.flexRow, styles.flex1, styles.workspaceTypeSectionTitle]}>
                      <Text
                          numberOfLines={1}
                          style={[styles.flexGrow1, styles.textLabelSupporting]}
                      >
                          {translate('workspace.common.workspaceType')}
                      </Text>
                  </View>
                  <View style={[styles.ml10, styles.mr2]} />
              </>
          ) : (
              <Text>{translate('common.noResultsFound')}</Text>
          )}
      </View>
  );
  return (
      <>
          <View style={[styles.gap5, styles.p5, styles.pl10, styles.appBG]}>{shouldShowTextInput && textInput}</View>
          {headerContent}
      </>
  );
}, [isLessThanMediumScreen, styles, translate, shouldShowTextInput, filteredAndSortedUserWorkspaces.length]);
  1. Create a filter workspace variable, re-use the logic here
const sortWorkspacesBySelected = (workspace1: WorkspaceItem, workspace2: WorkspaceItem, selectedWorkspaceID: string | undefined): number => {
    if (workspace1.policyID === selectedWorkspaceID) {
        return -1;
    }
    if (workspace2.policyID === selectedWorkspaceID) {
        return 1;
    }
    return workspace1.title?.toLowerCase().localeCompare(workspace2.title?.toLowerCase() ?? '') ?? 0;
};
const filteredAndSortedUserWorkspaces = useMemo(
    () =>
    workspaces
            .filter((policy) => policy.title?.toLowerCase().includes(searchTerm?.toLowerCase() ?? ''))
            .sort((policy1, policy2) => sortWorkspacesBySelected(policy1, policy2, activeWorkspaceID)),
    [searchTerm, workspaces, activeWorkspaceID],
);
  1. Pass filteredAndSortedUserWorkspaces as the data of FlatList
data={filteredAndSortedUserWorkspaces}

https://github.com/Expensify/App/blob/191d9326cd6cdbdc76d24ddf09f8a2f5fe6295ec/src/pages/workspace/WorkspacesListPage.tsx#L410

What alternative solutions did you explore? (Optional)

NA

Result

https://github.com/Expensify/App/assets/161821005/f8dcaaaf-e830-4b63-bfab-d57a5da36d8e

nkdengineer avatar Mar 23 '24 03:03 nkdengineer

Proposal

Please re-state the problem that we are trying to solve in this issue.

Add search is workspace list

What is the root cause of that problem?

This is a new feature

What changes do you think we should make in order to solve the problem?

Added search bar in workspace list. Based on user input it will filter the list of workspace.

Header Component This is draft structure for demo purpose, will look for reusable component if any once this proposal gets accepted. image
Filter workspace logic Instead of directly filtering on workspaces, I'm creating 2nd memoize variable to filter as if workspace is empty, create workspace section will be shown. Using `useDeferredValue` to smoothly update UI. image
Demo video

https://github.com/Expensify/App/assets/91016903/533cad91-da43-4ca0-a215-bc77fab22ecc

What alternative solutions did you explore? (Optional)

N.A.

nayabatir1 avatar Mar 23 '24 08:03 nayabatir1

Proposal

Please re-state the problem that we are trying to solve in this issue.

Add a search bar on the workspaces list

What is the root cause of that problem?

Feature Request

What changes do you think we should make in order to solve the problem?

Firstly, We don't need to create everything from scratch, we have major logic to filter workspaces in the Workspace Switcher LHN itself: For the Logic part, We can directly use the logic to filter workspaces from here: https://github.com/Expensify/App/blob/191d9326cd6cdbdc76d24ddf09f8a2f5fe6295ec/src/pages/WorkspaceSwitcherPage.tsx#L147-L153

Then we should define a TextInput which will be used to enter user data, this can be taken fromBaseOptionsSelector :

https://github.com/Expensify/App/blob/2003844351cd57b5197852459bc36ec07b6a7d26/src/components/OptionsSelector/BaseOptionsSelector.js#L506-L532

Over here we also need to define a new Place Holder text for workspace list: workspaceSearch: 'Search Workspace'

Then we need to add this TextInput in listHeaderComponent in WorkspacesListPage: https://github.com/Expensify/App/blob/191d9326cd6cdbdc76d24ddf09f8a2f5fe6295ec/src/pages/workspace/WorkspacesListPage.tsx#L220

And finally, Update the data parameter in FlatList to show the workspaces according to the filtered values https://github.com/Expensify/App/blob/191d9326cd6cdbdc76d24ddf09f8a2f5fe6295ec/src/pages/workspace/WorkspacesListPage.tsx#L410

Note: We should also add a No results found for inputs which do not match workspace names

Test Branch: https://github.com/GandalfGwaihir/App/tree/issue38854

allgandalf avatar Mar 23 '24 12:03 allgandalf

This is a feature request rather than a bug, so the first proposal to correctly explain the general idea of how to implement the feature - is a winning proposal. Extensive code diffs aren't needed (Source), the exact details of the implementation can be worked out during the PR review

Based on that, I think we should proceed with @nkdengineer's proposal πŸŽ€πŸ‘€πŸŽ€ C+ reviewed!

eVoloshchak avatar Mar 25 '24 15:03 eVoloshchak

Current assignee @roryabraham is eligible for the choreEngineerContributorManagement assigner, not assigning anyone new.

melvin-bot[bot] avatar Mar 25 '24 15:03 melvin-bot[bot]

hello @eVoloshchak , i actually had the first dibs here, context:

allgandalf avatar Mar 25 '24 15:03 allgandalf

To prevent such situations, I suggest removing the 'Help Wanted' tag if the issue is specific to a particular individual. If the proposed assignment is unsatisfactory, then we can consider adding the tag to seek alternative solutions. I've experienced the same situation here πŸ˜†

wildan-m avatar Mar 26 '24 02:03 wildan-m

i actually had the first dibs here, context:

@GandalfGwaihir, thanks for linking that! In that case, @roryabraham, could you assign @GandalfGwaihir to this please?

eVoloshchak avatar Mar 28 '24 19:03 eVoloshchak

πŸ“£ It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? πŸ’Έ

melvin-bot[bot] avatar Mar 30 '24 16:03 melvin-bot[bot]

πŸ“£ @GandalfGwaihir πŸŽ‰ An offer has been automatically sent to your Upwork account for the Contributor role πŸŽ‰ Thanks for contributing to the Expensify app!

Offer link Upwork job Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review πŸ§‘β€πŸ’» Keep in mind: Code of Conduct | Contributing πŸ“–

melvin-bot[bot] avatar Apr 03 '24 13:04 melvin-bot[bot]

@GandalfGwaihir all yours, looking forward to having a workspace search! πŸ™

sonialiap avatar Apr 03 '24 13:04 sonialiap

I think we should park the breaks on this and wait for search v2 and introducing it consistently. We purposefully left it out of the v1 of the Workspaces page knowing we'd be working into a more holistic search design. CC: @Expensify/design

trjExpensify avatar Apr 03 '24 19:04 trjExpensify

I agree with that.

shawnborton avatar Apr 03 '24 19:04 shawnborton

damn , the updated code was ready for one 😒

allgandalf avatar Apr 03 '24 19:04 allgandalf

Agree with pausing this. It hasn't gone through our internal design process yet, though it will within the next 1-2 weeks, and at that point once we have alignment, we can pick this back up.

JmillsExpensify avatar Apr 03 '24 19:04 JmillsExpensify

Going to track it as part of [Search v1] for now to keep it in view, though I'll likely update this to wherever we go with Search v2.

trjExpensify avatar Apr 03 '24 19:04 trjExpensify

@eVoloshchak, @sonialiap, @roryabraham, @GandalfGwaihir Eep! 4 days overdue now. Issues have feelings too...

melvin-bot[bot] avatar Apr 09 '24 18:04 melvin-bot[bot]

Not overdue, this is on HOLD

eVoloshchak avatar Apr 15 '24 17:04 eVoloshchak