-
Notifications
You must be signed in to change notification settings - Fork 356
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
React header #6197
React header #6197
Conversation
@miq-bot add_reviewer @martinpovolny |
@miq-bot add_reviewer @epwinchell |
@miq-bot add_reviewer @Hyperkid123 |
Touches notifications, pinging @skateman . Also the notifications should be converted to React as a priority. This is a piece of Angular that is loaded on every page. Let's avoid that soon. Toolbars will be gone in a moment, then GTL will be replaced and trees. There should be no angular on most pages in the next release. |
@martinpovolny the pf-react implementation of the drawer is very far from our needs. We did some customizations with @himdel on top of the angular-based implementation and we would have to do that and a little more with the react one before we're able to actually consume it. I was looking into this last year and it seemed like a painful task. But I'm in the area already because of the popup throttling, so I'll re-evaluate this as well. Gonna take a look at this piece of code of course ... gimme some 🕐 |
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.
Great job, a few problems and some stuff open for debate...
app/assets/stylesheets/main.scss
Outdated
@@ -66,5 +66,4 @@ $login-container-details-border-color-rgba: rgba(0, 0, 0, 0.5); | |||
body.login.whitelabel { | |||
background: url($img-bg-login-whitelabel); | |||
background-size: 100% auto; | |||
} | |||
|
|||
} |
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.
Missing newline here...
:items => item.items.to_a.map(&method(:item_to_hash)), | ||
:visible => item.visible?, | ||
:link_params => item.link_params | ||
} |
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.
You could implement this a little prettier:
%i[
id
name
icon
placement
before
type
href
parent_id
feature
rbac_feature
defaults
link_params
].each_with_object(:visible => item.visible?, :items => item.items.to_a.map(&method(:item_to_hash))) do |obj, key|
obj[key] = item.try(key)
end
Except of visible
and items
all the fields map nicely to the keys...
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.
10 points to Griffindor for the &method
btw 🥇 😆
<Help helpMenu={helpMenu} /> | ||
{ currentUser && ( | ||
<React.Fragment> | ||
<Configuration opsExplorerAllowed={opsExplorerAllowed} /> |
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.
TBH I don't see a reason why to have this as a separate component in a separate file, this is way too small for that and you're creating much bigger ones here. I'd just extract it into a function, but don't take this seriously and ask someone who actually knows React 😉
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.
This was actually by my command! ☠️
But it is better to make these component as small and independent as possible. It is much easier to find them, test them and fix them if need be.
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.
Then IMO the other one(s) should be small(er) as well... It's just feels weird that you have one small, and the rest is HUGE.
customLogo, currentUser, helpMenu, opsExplorerAllowed, applianceName, miqGroups, currentGroup, userMenu, | ||
}) => ( | ||
<React.Fragment> | ||
<CustomLogo customLogo={customLogo} /> |
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.
Same as below...
@@ -47,6 +53,7 @@ angular.module('ManageIQ').controller('headerController', ['$scope', 'eventNotif | |||
|
|||
vm.notificationsIndicatorTooltip = miqFormatNotification(__('%{count} unread notifications'), | |||
{count: notificationCount}); | |||
ManageIQ.redux.store.dispatch({ type: '@@notifications/setUnreadCount', payload: notificationCount.text }); |
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.
Could you please write a few words into the PR's description about this idea. I know how it works because I made it up 😆 but others might not...
@@ -91,6 +91,11 @@ angular.module('ManageIQ').service('eventNotifications', ['$timeout', '$window', | |||
}); | |||
|
|||
updateUnreadCount(events); | |||
var x = 0; | |||
_.forEach(state.groups, function(group) { |
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.
@@ -1,5 +1,33 @@ | |||
module ApplicationHelper | |||
module Navbar | |||
def menu_to_json(position) |
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.
For now, it's okay to have this method here, but after this is done, we should extract it into the Menu::Manager
. I have an idea about that, just let's not forget it so we need to talk when this is done and we're both in the office.
@@ -0,0 +1 @@ | |||
= react('RightSection', { :customLogo => ::Settings.server.custom_logo, :currentUser => current_user, :helpMenu => menu_to_json(:help),:opsExplorerAllowed => ApplicationHelper.role_allows?(:feature => 'ops_explorer', :any => true), :applianceName => appliance_name, :miqGroups => current_user.miq_groups, :currentGroup => current_group, :userMenu => menu_to_json(:top_right) }, {:class => "nav navbar-nav navbar-right navbar-iconic"}, 'ul') |
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.
Missing newline
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.
Maybe it's completely wrong and maybe out of the context of this PR, but could we preseed these data into the Redux store upon login? Then we would have them cached and the list of props would be simpler/shorter/nicer...
app/javascript/miq-redux/store.js
Outdated
unreadCount: 0, | ||
}; | ||
|
||
const nPrefix = '@@notifications/'; |
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.
It's just a semantic nitpick and others might disagree with me, but I'd prefer singular here. Just to be a little more future-prooof. Also the setUnreadCount
is a little too specific and there's a 100% chance it will be dropped in the future in favor of something like new
. So I'd just go with @@notification/new
instead, but this is also something where others might and should stop me.
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.
Honestly i don't really care about this :D As long as its same everywhere I am ok with both.
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.
Yeah, in this case let's go with singular please.
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.
Tested. Looks good.
@@ -91,6 +91,8 @@ angular.module('ManageIQ').service('eventNotifications', ['$timeout', '$window', | |||
}); | |||
|
|||
updateUnreadCount(events); | |||
const totalUnreadCount = state.groups.reduce((sum, group) => (sum + group.unreadCount), 0); |
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.
I don't think that we can use Array.prototype.reduce
in old JS. This is not ES6 and its not being compiled by webpack.
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.
es6-shim. We can use any ES6 libary feature just fine, only the syntax ones have to go through babel.
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.
@fhlavac this is the one ^.. reduce
is fine, but arrow functions are new syntax
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.
Oh, and also const
! :)
@@ -0,0 +1,19 @@ | |||
import React from 'react'; | |||
|
|||
const Configuration = ({ |
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.
I don't see any prop types validation here.
import React from 'react'; | ||
import { Dropdown, Icon, MenuItem } from 'patternfly-react'; | ||
|
||
const Help = ({ |
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.
Missing prop types again.
import React from 'react'; | ||
import { Dropdown, Icon, MenuItem } from 'patternfly-react'; | ||
|
||
const UserOptions = ({ |
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.
PropTypes
@@ -70,6 +76,12 @@ ManageIQ.component.addReact('TagGroup', props => <TagGroup {...props} />); | |||
ManageIQ.component.addReact('TagView', TagView); | |||
ManageIQ.component.addReact('TaggingWrapperConnected', TaggingWrapperConnected); | |||
ManageIQ.component.addReact('TextualSummaryWrapper', TextualSummaryWrapper); | |||
ManageIQ.component.addReact('RightSection', RightSection); |
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.
These should be sorted alphabetically by the component name. It helps us to avoid constant PR conflicts when registering new react components.
Looks good! Please, do not forget to move Thx, @fhlavac, @Hyperkid123, @skateman ! |
id={group.description} | ||
key={group.id} | ||
title={__('Change to this Group')} | ||
onClick={(e) => { e.preventDefault(); miqSparkleOn(); miqToggleUserOptions(group.id); }} |
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.
This will need a change once #6325 gets merged.
e.preventDefault(); miqChangeGroup(group.id);
should do it, just make sure the id is a string please ;)
<MenuItem | ||
id="logout-btn" | ||
href="/dashboard/logout" | ||
onClick={event => !miqCheckForChanges() && event.preventDefault()} |
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.
And this also needs updating - this time for #6065 (merged in August)
I suggest
(e) => miqCheckForChanges() ? (ManageIQ.logoutInProgress = true) : e.preventDefault()
(Maybe you should go through the git log of all the files removed here and check for recent changes just to make sure ;).)
During the merge of menu_to_json() some props were renamed
Update after different menu_to_json() implementations merge
currentGroup should always be defined
Also move globals for ES-lint to .eslintrc.json
Prefix top-navbar components with 'nav.' in component-definitions-common
Add create(:user_with_group) to cloud_network, cloud_subnet controller
Checked commits fhlavac/manageiq-ui-classic@40c71fa~...0ca1e44 with ruby 2.5.5, rubocop 0.69.0, haml-lint 0.20.0, and yamllint 1.10.0 |
Restarted travis to recover from unrelated failures. |
LGTM, tested vertical menu still working, group switcher, the usual buttons .. everything looks fine 👍 |
🎉 |
@fhlavac good job. Now to the next bit 😄 |
❤️ 😍 💟 👍 |
@Hyperkid123 @martinpovolny @epwinchell
This PR is dependent on #5854
In notifications part I currently call setUnreadCount (function returning number of unread notifications) by Redux. Previously, it was solved in Angular.
Currently: When number of unread notifications in drawer is updated, Rx message is sent to React header and Redux dispatch updates value stored in Redux store.