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

Add Empty state components and use them #285

Merged
merged 28 commits into from
Feb 19, 2021

Conversation

ZitaNemeckova
Copy link
Member

@ZitaNemeckova ZitaNemeckova commented Jan 4, 2021

How it looks so far:
Screenshot 2021-01-26 at 13 53 44
Screenshot 2021-01-26 at 13 52 30
Screenshot 2021-01-26 at 14 49 05
Screenshot 2021-01-26 at 14 51 27

Screenshot 2021-01-26 at 16 09 37

Screenshot 2021-01-26 at 16 20 05

Screenshot 2021-01-25 at 15 56 28

TODO:

  • add EmptyState component for "filter", "unauthorised" and "no data yet"
  • make them fully functional
    • Clear all filters - removed based on UX feedback
    • Add button
  • replace code with components
    • filter
    • unauthorised
    • no data yet
  • add check for filter/no data
  • src/containers/collection-detail/collection-docs.tsx -> Use EmptyState with red ! icon - followup PR
  • EmptyStateNoData -> if possible to add data use "add" icon + primary button else use "search" icon
  • "No stuff yet" -> no headers, no footer, no pagination, just title
  • fix redirect as it's not always not-found
  • Exe. Env. needs to use the new nes too.

List of all pages:

Empty state - No data yet:

  • Collections
  • Namespaces
  • My namespaces
  • Users (it's there but it shouldn't happen)
  • Groups
  • Groups - select a group - click on Users tab
  • Repo management - Remote tab (it's there but it shouldn't happen)
  • Approval

Empty state - No data for filter:

  • Collections
  • Namespaces
  • My namespaces
  • Users
  • Groups
  • Groups - select a group - click on User tab
  • Approval

Empty state - Unauthorised:

  • Groups (view and add/edit)
  • Users (view and add/edit)
  • Approval

Custom "errror" state:

  • Collections - select a collection - click documentation tab (it's there but it shouldn't happen)

@ZitaNemeckova ZitaNemeckova force-pushed the empty_states branch 2 times, most recently from edb06b4 to 33d53d5 Compare January 11, 2021 09:12
@ZitaNemeckova ZitaNemeckova reopened this Jan 22, 2021
@ZitaNemeckova ZitaNemeckova force-pushed the empty_states branch 2 times, most recently from a89b11b to 08bc0c2 Compare January 26, 2021 08:46
@ZitaNemeckova
Copy link
Member Author

@sbuenafe-rh @fionayhlin does it look to be heading the right way?

@sbuenafe-rh
Copy link

@ZitaNemeckova for the No groups empty state, can you swap out the plus icon outline with the solid plus icon? The PF icon name is: fa-plus-circle or if using React name: PlusCircleIcon

For the Not found message. If the Readme file or any other file that isn't available then it should have the PF icon: fa-exclamation-circle with the message: "The file is not available in this version of ___". If the user is searching/filtering for a particular file and it cannot be found, then I would use the magnifying glass icon. Lemme know if you have any questions or need examples/mocks. :)

@sbuenafe-rh
Copy link

@ZitaNemeckova for the No users added to this group, you can shorten that title to No users

@fionayhlin
Copy link

@ZitaNemeckova @sbuenafe-rh Should that be No users yet to match the other titles?

@sbuenafe-rh
Copy link

@fionayhlin @ZitaNemeckova yes! good catch.

@ZitaNemeckova ZitaNemeckova force-pushed the empty_states branch 2 times, most recently from 0e52bee to eefef55 Compare February 3, 2021 11:43
@ZitaNemeckova
Copy link
Member Author

Container Registry:
Screenshot 2021-02-03 at 12 39 09
Screenshot 2021-02-03 at 12 39 52

Groups:
Screenshot 2021-02-03 at 12 48 18

Collection documentation:
Screenshot 2021-02-03 at 12 50 46

Group detail - users:
Screenshot 2021-02-03 at 12 54 21

@sbuenafe-rh @fionayhlin here's new Container Registry empty pages and fixed ones. WDYT?

@ZitaNemeckova ZitaNemeckova changed the title [WIP] Add Empty state components and use them Add Empty state components and use them Feb 3, 2021
@ZitaNemeckova
Copy link
Member Author

@himdel please have a look code-wise, thanks :)

@himdel
Copy link
Collaborator

himdel commented Feb 4, 2021

Sure, thanks for the help getting it working :), some testing...

Repo Management > Remote tab - always shows empty state, on master there are 2 items
My namespaces - Create button doesn't work, nothing happens (the empty state one; the filter one works, but shouldn't be there)
Namespace & My namespaces - filter still there on empty state

(I have yet to go through the code, next comment :))

(I also noticed the UI doesn't stop me from removing the current user, which is probably a bug too, though unrelated :))

And do we have a list of all the screens with an EmptyState?

@@ -48,3 +48,7 @@ export { RemoteRepositoryTable } from './repositories/remote-repository-table';
export { LocalRepositoryTable } from './repositories/local-repository-table';
export { StatusIndicator } from './status/status-indicator';
export { HelperText } from './helper-text/helper-text';
export { EmptyStateFilter } from './empty-state/empty-state-filter';
export { EmptyStateUnauthorised } from './empty-state/empty-state-unauthorised';
Copy link
Collaborator

@himdel himdel Feb 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably be spelled Unauthorized (s -> z)? (ngrams)

@chouseknecht
Copy link

@himdel Thanks for reviewing our code! Appreciate the comments. I think @alikins is working on the issue regarding users deleting their own account. View the issue here.

@ZitaNemeckova
Copy link
Member Author

Screenshot 2021-02-08 at 12 52 07

Screenshot 2021-02-08 at 13 18 14

Screenshot 2021-02-08 at 13 18 24

Screenshot 2021-02-08 at 13 28 08

Screenshot 2021-02-08 at 13 28 18

Screenshot 2021-02-08 at 13 56 32

@sbuenafe-rh @fionayhlin some more Empty State pages. WDYT?

@fionayhlin
Copy link

@ZitaNemeckova @sbuenafe-rh I believe the no results found from search keyword ones should have a "Clear all filters" link button in the empty state under the text, but otherwise looks good!

@ZitaNemeckova
Copy link
Member Author

@fionayhlin We agreed with @sbuenafe-rh that filter handling should stay in filter component only for this case
Screenshot 2021-02-03 at 12 39 09 I assume it included all searches. WDYT?

@ZitaNemeckova
Copy link
Member Author

@himdel It's ready for another round of review. Thanks :)

@@ -69,30 +55,6 @@ export class RemoteRepositoryTable extends React.Component<IProps> {

render() {
const { remotes } = this.props;
if (remotes.length == 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 handled by repository-list now, the only user of RemoteRepositoryTable

@himdel
Copy link
Collaborator

himdel commented Feb 17, 2021

I think EmptyStateUnauthorised is currently missing a screenshot, and unless it's supposed to be different..

diff --git a/src/components/empty-state/empty-state-unauthorised.tsx b/src/components/empty-state/empty-state-unauthorised.tsx
index a205ca6..bef7e2e 100644
--- a/src/components/empty-state/empty-state-unauthorised.tsx
+++ b/src/components/empty-state/empty-state-unauthorised.tsx
@@ -15,9 +15,9 @@ interface IProps {}
 export class EmptyStateUnauthorised extends React.Component<IProps> {
   render() {
     return (
-      <EmptyState variant={EmptyStateVariant.xs}>
+      <EmptyState variant={EmptyStateVariant.small}>
         <EmptyStateIcon icon={LockIcon} />
-        <Title headingLevel='h4'>
+        <Title headingLevel='h4' size='lg'>
           You do not have have access to Automation Hub
         </Title>
         <EmptyStateBody>

(And I still think Unauthorized is the proper spelling, unless Ansible is using non-US spellings?)


Would it make sense to DRY it up by implementing the other empty states on top of EmptyStateCustom?

If we move the {this.props.button && (... logic there, all the other empty states could just be built on top of it, like..

export const EmptyStateFilter = ({}) => (<EmptyStateCustom
  title="No resuls found"
  description="No results match the filter criteria. Remove all filters or clear all filters to show results."
  icon={SearchIcon}
/>);

export const EmptyStateNoData = ({ title, description, button }) => (<EmptyStateCustom
  title={title}
  description={description}
  icon={button ? PlusCircleIcon : SearchIcon}
  button={button}
/>);

export const EmptyStateUnauthorized = ({}) => (<EmptyStateCustom
  title="You do not have have access to Automation Hub"
  description="Contact you organization administrator for more information."
  icon={LockIcon}
/>);

(+- typescript and the component syntax anyway)


I'm seeing some icon changes, InfoIcon -> SearchIcon, WarningTriangleIcon -> SearchIcon, but those are all intentional, right? :)

And I'll continue tomorrow :)

@@ -0,0 +1,12 @@
// Checks that at least one filter is set
export function filterIsSet(params, filters) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be _.some(filters, (filter) => filter in params));, if lodash is preferred.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed :)

@ZitaNemeckova
Copy link
Member Author

@himdel Icon changes are intentional based on UX requirements. s/z is fixed. I'll do the DRY you suggested as it's really cool!

Unathorised:
Screenshot 2021-02-17 at 11 46 01

@ZitaNemeckova
Copy link
Member Author

@himdel last review addressed. Ready for another round. Thanks :)

/>
<div>
<Pagination
{filterIsSet(this.state.params, ['keywords']) ||
Copy link
Collaborator

@himdel himdel Feb 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider using a noData var as well? (also on line 166, and possibly 209)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added noData var. Leaving 209 as is.

<RemoteRepositoryTable
remotes={content}
updateParams={this.updateParams}
editRemote={(remote: RemoteType) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.selectRemoteToEdit becomes unused (and does the same thing except on a copy of remote?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot remember why I did that. Fixing back at this.selectRemoteToEdit

return <Redirect to={Paths.notFound}></Redirect>;
}
return (
const notAutthorised =
Copy link
Collaborator

@himdel himdel Feb 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo, double T (and s/z for consistency (sorry :)))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed :)

@himdel
Copy link
Collaborator

himdel commented Feb 18, 2021

Thanks, looks great :)


Is redirect ever set from outside the component, or can I assume setState({ redirect: ... only happens in the component itself?

If it's local only, would it make sense to split redirect from 404 and use a separate state param? It looks like some components (edit-namespace) still need to Redirect after update, so you're catching Paths.notFound as a special case and dealing with it differently, while others (certification-dashboard) only used Paths.notFound so the Redirect is removed and redirect is used to just mean "not there".

I'm not seeing any logic errors in the conversion 👍 , but if it's safe to split, I'd keep redirect just for Redirect and use something like setState({ notFound: true }) instead for the unauthorized empty state.

EDIT: or unauthorized like in user-edit


I do notice that filterIsSet needs to know the list of params that could be filters while AppliedFilters seems to need a list of params to ignore.. sounds like the 2 lists could get out of sync fairly quickly, new params would get ignored by filterIsSet but not by AppliedFilters, we may want to fix that by having a per screen list of filters, used by both.

And perhaps the meta params could be app global, enforcing page_size, id etc. can never be treated as a filter, regardles of whether the screen is using it or not (and we could drop the ignoredParams list).

But that's probably a separate refactoring as that's not really related to this change?


I can't seem to be able to rebuild now (pkg_resources.VersionConflict: (pulp-container 2.1.0 (/venv/lib/python3.6/site-packages), Requirement.parse('pulp-container==2.3.1')), possibly related to ansible/galaxy_ng#650 ?), so I have not tested the new changes yet.

But except for comments above, LGTM 👍 :)

@ZitaNemeckova
Copy link
Member Author

@himdel

redirect shouldn't be set from outside. I'll fix it as suggested.

Params refactoring sounds like good idea but it's out of scope for this PR.

How to rebuild: galaxy_ng must be on latest master, LOCK_REQUIREMENTS=1 added in .compose.env then build and run migration (to be safe).

@@ -109,6 +104,8 @@ export class NamespaceList extends React.Component<IProps, IState> {
const { namespaces, params, itemCount } = this.state;
const { title, filterOwner } = this.props;
const { user } = this.context;
const noData =
!filterIsSet(this.state.params, ['keywords']) && namespaces.length === 0;
Copy link
Collaborator

@himdel himdel Feb 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

namespaces can be undefined, we can't check length if it is (maybe just move this after the if (!namespaces)?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed 👍

@himdel
Copy link
Collaborator

himdel commented Feb 19, 2021

Ah, managed to rebuild, docker system prune -a --volumes helped, seems like the build doesn't notice changes to requirements :).


Trying to load /ui/namespaces or /ui/my-namespaces (with a fresh db):

 Cannot read property 'length' of undefined
    at NamespaceList../src/containers/namespace-list/namespace-list.tsx.NamespaceList.render (App.js:12364)

(#285 (comment))
(in other places, groups is always an array, so is collections and items; itemCount doesn't do .length; so this is the only place)


src/containers/certification-dashboard/certification-dashboard.tsx is still using the redirect: Paths.notFound pattern to display EmptyStateUnauthorized

src/containers/namespace-detail/namespace-detail.tsx is still redirecting (actual redirect) to Paths.notFound, should it be doing that?

@ZitaNemeckova
Copy link
Member Author

@himdel

src/containers/namespace-detail/namespace-detail.tsx is still redirecting (actual redirect) to Paths.notFound, should it be doing that?

Yes, it gets all http://localhost:8002/ui/<ramdom stuff> calls. This my be worth refactoring later.

Copy link
Collaborator

@himdel himdel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, not seeing any issues in code or when testing 👍

@ZitaNemeckova ZitaNemeckova merged commit a0bd5fd into ansible:master Feb 19, 2021
@ZitaNemeckova ZitaNemeckova deleted the empty_states branch February 19, 2021 14:02
@ZitaNemeckova ZitaNemeckova added the backport-4.2 This PR should be backported to stable-4.2 (1.2) label Feb 19, 2021
@ZitaNemeckova ZitaNemeckova removed the backport-4.2 This PR should be backported to stable-4.2 (1.2) label Apr 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants