`portfolios.create_member` now just sends an invitation, so it should be
with the invitation routes. This also de-duplicates the function for
sending a portfolio invitation email.
Use ApplicationRole.id instead of User.id in forms. This eliminates the
need for the function that checks whether a user is in a given
application, because looking up the application role will raise an error
if the user is not.
Our forms should rely on role IDs for displaying user information on the
portfolio page. This way they are decoupled from user table data and can
eventually rely on invitation user data where an invitation has been
sent but a user does not exist yet.
Previously, we were encoding the portfolio_role.user_id as part of the
form data for the portfolio admin page. This was convenient because it
allowed us to easily determine certain display attributes in the
template. Instead, we should rely on the PortfolioRole as the source of
truth for member information. This commit adds:
- Portfolio.owner_role to return the PortfolioRole of the owner
- explicitly passes the PortfolioRole IDs for the PPoC and current user
to the template
- PortfolioRole.full_name for deriving the member name
"Add to existing environment" table, "delete member", and environment
roles and env role edit buttons added for every user in the team
settings list. Accompanying CSS changes.
- uses two route functions - one for update app, another for add
environment
- uses a second form for the app settings page
- uses the /environments/new url naming convention
In order to place modal forms in other places on the page (so that forms
are not nested) it's necessary to move MultiStepModalForm links out of
the component. They just need to refer to the correct modal.
This PR also makes changes to ensure that the active modal is being
unset everywhere correctly when a modal is closed.
The link button to add a new application member to an app that did not
have any ("empty state") was not wired up. This:
- Moves the two steps of the new member modal into macros so that they
can be reused with different button/link types
- Wires the "invite a new team member" button on the application team
page
- Makes a minor CSS tweak so that icons nested under `.empty-state` in
the modal aren't enormous