fix:Minor UI changes

- add ellipsis for the application title
- align org name, list of applications
- increase font size of org name
- increase size of create application icon
- add name for create application card
- remove create application button
This commit is contained in:
Tejaaswini Narendra 2020-06-03 13:54:42 +00:00 committed by Trisha Anand
parent a23183e68b
commit 52e70e479f
7 changed files with 186 additions and 27 deletions

View File

@ -4,12 +4,13 @@ import { connect } from "react-redux";
import { Dialog, Classes } from "@blueprintjs/core";
import { isPermitted } from "pages/Applications/permissionHelpers";
const StyledDialog = styled(Dialog)`
const StyledDialog = styled(Dialog)<{ setMaxWidth?: boolean }>`
&& {
background: white;
& .bp3-dialog-footer-actions {
display: block;
}
${props => props.setMaxWidth && `width: 100vh;`}
}
`;
@ -23,6 +24,7 @@ type FormDialogComponentProps = {
trigger: ReactNode;
permissionRequired?: string;
permissions?: string[];
setMaxWidth?: boolean;
};
export const FormDialogComponent = (props: FormDialogComponentProps) => {
@ -53,6 +55,7 @@ export const FormDialogComponent = (props: FormDialogComponentProps) => {
title={props.title}
onClose={onClose}
isOpen={isOpen}
setMaxWidth={props.setMaxWidth}
>
<div className={Classes.DIALOG_BODY}>
<Form

View File

@ -3,6 +3,7 @@ import styled from "styled-components";
import { connect } from "react-redux";
import { AppState } from "reducers";
import { Card, Icon } from "@blueprintjs/core";
import Button from "components/editorComponents/Button";
import {
getApplicationList,
getIsFetchingApplications,
@ -22,6 +23,7 @@ import PageSectionDivider from "pages/common/PageSectionDivider";
import { getApplicationPayloads } from "mockComponentProps/ApplicationPayloads";
import ApplicationCard from "./ApplicationCard";
import CreateApplicationForm from "./CreateApplicationForm";
import InviteUsersFormv2 from "pages/organization/InviteUsersFromv2";
import { CREATE_APPLICATION_FORM_NAME } from "constants/forms";
import { PERMISSION_TYPE } from "./permissionHelpers";
import { DELETING_APPLICATION } from "constants/messages";
@ -40,6 +42,7 @@ const OrgDropDown = styled.div`
display: flex;
padding: 0px 30px;
font-size: ${props => props.theme.fontSizes[1]}px;
justify-content: space-between;
`;
const ApplicationCardsWrapper = styled.div`
@ -142,6 +145,13 @@ class Applications extends Component<ApplicationProps> {
)}
/>
)}
<FormDialogComponent
trigger={<Button text="Share" intent={"primary"} filled />}
Form={InviteUsersFormv2}
orgId={organization.id}
title={"Invite Users"}
setMaxWidth
/>
</OrgDropDown>
<ApplicationCardsWrapper key={organization.id}>
<FormDialogComponent

View File

@ -0,0 +1,111 @@
import React, { useEffect } from "react";
import styled from "styled-components";
import TagListField from "components/editorComponents/form/fields/TagListField";
import FormGroup from "components/editorComponents/form/FormGroup";
import { reduxForm } from "redux-form";
import SelectField from "components/editorComponents/form/fields/SelectField";
import Button from "components/editorComponents/Button";
import { connect } from "react-redux";
import { AppState } from "reducers";
import {
getRoles,
getDefaultRole,
getRolesForField,
} from "selectors/organizationSelectors";
import { ReduxActionTypes } from "constants/ReduxActionConstants";
import { InviteUsersToOrgFormValues, inviteUsersToOrg } from "./helpers";
import { OrgRole } from "constants/orgConstants";
import { INVITE_USERS_TO_ORG_FORM } from "constants/forms";
const StyledForm = styled.div`
width: 100%;
background: white;
padding: ${props => props.theme.spaces[11]}px;
&&& {
.bp3-input {
box-shadow: none;
}
}
`;
const StyledInviteFieldGroup = styled.div`
&& {
display: flex;
flex-direction: row;
flex-wrap: none;
justify-content: space-between;
align-items: flex-start;
& > div {
min-width: 150px;
margin: 0em 1em 1em 0em;
}
& > div:last-of-type {
min-width: 0;
display: flex;
align-self: center;
}
}
`;
const InviteUsersForm = (props: any) => {
const { handleSubmit } = props;
useEffect(() => {
props.fetchAllRoles(props.orgId);
}, [props.orgId]);
return (
<StyledForm>
<StyledInviteFieldGroup>
<FormGroup fill>
<TagListField
name="users"
placeholder="Enter email address"
type="email"
label="Emails"
intent="success"
/>
</FormGroup>
<SelectField
name={`role`}
placeholder="Select a role"
options={props.roles}
size="large"
/>
<Button
text="Invite"
filled
intent="primary"
onClick={handleSubmit((values: any, dispatch: any) => {
inviteUsersToOrg({ ...values, orgId: props.orgId }, dispatch);
})}
/>
</StyledInviteFieldGroup>
</StyledForm>
);
};
export default connect(
(state: AppState) => {
return {
roles: getRolesForField(state),
defaultRole: getDefaultRole(state),
};
},
(dispatch: any) => ({
fetchAllRoles: (orgId: string) =>
dispatch({
type: ReduxActionTypes.FETCH_ALL_ROLES_INIT,
payload: {
orgId,
},
}),
}),
)(
reduxForm<
InviteUsersToOrgFormValues,
{ fetchAllRoles: (orgId: string) => void; roles?: any }
>({
form: INVITE_USERS_TO_ORG_FORM,
})(InviteUsersForm),
);

View File

@ -52,3 +52,23 @@ export const inviteUsersToOrgSubmitHandler = (
throw new SubmissionError(error);
});
};
export const inviteUsersToOrg = (values: any, dispatch: any): Promise<any> => {
const data = {
roleName: values.role,
emails: values.users ? values.users.split(",") : [],
orgId: values.orgId,
};
return new Promise((resolve, reject) => {
dispatch({
type: ReduxActionTypes.INVITE_USERS_TO_ORG_INIT,
payload: {
resolve,
reject,
data,
},
});
}).catch(error => {
throw new SubmissionError(error);
});
};

View File

@ -18,15 +18,16 @@ import { ORG_INVITE_USERS_PAGE_URL } from "constants/routes";
import PageSectionDivider from "pages/common/PageSectionDivider";
import PageSectionHeader from "pages/common/PageSectionHeader";
import { ReduxActionTypes } from "constants/ReduxActionConstants";
import InviteUsersFormv2 from "pages/organization/InviteUsersFromv2";
import Button from "components/editorComponents/Button";
import { Org, OrgUser } from "constants/orgConstants";
import { Menu, MenuItem, Popover, Position } from "@blueprintjs/core";
import styled from "styled-components";
import { FormIcons } from "icons/FormIcons";
import "@syncfusion/ej2-react-grids/styles/material.css";
import { stringify } from "querystring";
import { RouteComponentProps } from "react-router";
import Spinner from "components/editorComponents/Spinner";
import FormDialogComponent from "components/editorComponents/form/FormDialogComponent";
type OrgProps = {
org?: Org;
changeOrgName: (value: string) => void;
@ -138,13 +139,20 @@ export const OrgSettings = (props: PageProps) => {
<PageSectionDivider />
<PageSectionHeader>
<h2>Users</h2>
<Button
intent="primary"
text="Invite Users"
icon="plus"
iconAlignment="left"
filled
onClick={() => history.push(ORG_INVITE_USERS_PAGE_URL)}
<FormDialogComponent
trigger={
<Button
intent="primary"
text="Invite Users"
icon="plus"
iconAlignment="left"
filled
/>
}
Form={InviteUsersFormv2}
orgId={orgId}
title={"Invite Users"}
setMaxWidth
/>
</PageSectionHeader>
{props.isFetchAllUsers && props.isFetchAllRoles ? (

View File

@ -170,7 +170,10 @@ type InviteUserPayload = {
groupIds: string[];
};
export function* inviteUser(payload: InviteUserPayload, reject: any) {
export function* inviteUser(
payload: { email: string; orgId: string; roleName: string },
reject: any,
) {
const response: ApiResponse = yield callAPI(UserApi.inviteUser, payload);
const isValidResponse = yield validateResponse(response);
if (!isValidResponse) {
@ -183,29 +186,22 @@ export function* inviteUser(payload: InviteUserPayload, reject: any) {
export function* inviteUsers(
action: ReduxActionWithPromise<{
data: Array<{ roleId: string; emails: string[] }>;
data: { emails: string[]; orgId: string; roleName: string };
}>,
) {
const { data, resolve, reject } = action.payload;
try {
const sagasToCall = [];
const emailSet: Record<string, string[]> = {};
data.forEach((groupSet: { roleId: string; emails: string[] }) => {
const { emails, roleId } = groupSet;
emails.forEach((email: string) => {
if (emailSet.hasOwnProperty(email)) {
emailSet[email].push(roleId);
} else {
emailSet[email] = [roleId];
}
});
});
const sagasToCall: any[] = [];
for (const email in emailSet) {
data.emails.forEach((email: string) => {
sagasToCall.push(
call(inviteUser, { email, groupIds: emailSet[email] }, reject),
call(
inviteUser,
{ email, orgId: data.orgId, roleName: data.roleName },
reject,
),
);
}
});
yield all(sagasToCall);
yield put({
type: ReduxActionTypes.INVITE_USERS_TO_ORG_SUCCESS,

View File

@ -2,7 +2,9 @@ import { createSelector } from "reselect";
import { AppState } from "reducers";
import { OrgRole, Org } from "constants/orgConstants";
export const getRolesFromState = (state: AppState) => state.ui.orgs.roles;
export const getRolesFromState = (state: AppState) => {
return state.ui.orgs.roles;
};
export const getOrgs = (state: AppState) => state.ui.orgs.list;
export const getAllUsers = (state: AppState) => state.ui.orgs.orgUsers;
export const getAllRoles = (state: AppState) => state.ui.orgs.orgRoles;
@ -30,6 +32,15 @@ export const getRoles = createSelector(getRolesFromState, (roles?: OrgRole[]):
}));
});
export const getRolesForField = createSelector(getAllRoles, (roles?: any) => {
return Object.entries(roles).map(role => {
return {
id: role[0],
name: role[0],
};
});
});
export const getDefaultRole = createSelector(getRoles, (roles?: OrgRole[]) => {
return roles?.find(role => role.isDefault);
});