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:
parent
a23183e68b
commit
52e70e479f
|
|
@ -4,12 +4,13 @@ import { connect } from "react-redux";
|
||||||
import { Dialog, Classes } from "@blueprintjs/core";
|
import { Dialog, Classes } from "@blueprintjs/core";
|
||||||
import { isPermitted } from "pages/Applications/permissionHelpers";
|
import { isPermitted } from "pages/Applications/permissionHelpers";
|
||||||
|
|
||||||
const StyledDialog = styled(Dialog)`
|
const StyledDialog = styled(Dialog)<{ setMaxWidth?: boolean }>`
|
||||||
&& {
|
&& {
|
||||||
background: white;
|
background: white;
|
||||||
& .bp3-dialog-footer-actions {
|
& .bp3-dialog-footer-actions {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
${props => props.setMaxWidth && `width: 100vh;`}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
@ -23,6 +24,7 @@ type FormDialogComponentProps = {
|
||||||
trigger: ReactNode;
|
trigger: ReactNode;
|
||||||
permissionRequired?: string;
|
permissionRequired?: string;
|
||||||
permissions?: string[];
|
permissions?: string[];
|
||||||
|
setMaxWidth?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FormDialogComponent = (props: FormDialogComponentProps) => {
|
export const FormDialogComponent = (props: FormDialogComponentProps) => {
|
||||||
|
|
@ -53,6 +55,7 @@ export const FormDialogComponent = (props: FormDialogComponentProps) => {
|
||||||
title={props.title}
|
title={props.title}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
|
setMaxWidth={props.setMaxWidth}
|
||||||
>
|
>
|
||||||
<div className={Classes.DIALOG_BODY}>
|
<div className={Classes.DIALOG_BODY}>
|
||||||
<Form
|
<Form
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import styled from "styled-components";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { AppState } from "reducers";
|
import { AppState } from "reducers";
|
||||||
import { Card, Icon } from "@blueprintjs/core";
|
import { Card, Icon } from "@blueprintjs/core";
|
||||||
|
import Button from "components/editorComponents/Button";
|
||||||
import {
|
import {
|
||||||
getApplicationList,
|
getApplicationList,
|
||||||
getIsFetchingApplications,
|
getIsFetchingApplications,
|
||||||
|
|
@ -22,6 +23,7 @@ import PageSectionDivider from "pages/common/PageSectionDivider";
|
||||||
import { getApplicationPayloads } from "mockComponentProps/ApplicationPayloads";
|
import { getApplicationPayloads } from "mockComponentProps/ApplicationPayloads";
|
||||||
import ApplicationCard from "./ApplicationCard";
|
import ApplicationCard from "./ApplicationCard";
|
||||||
import CreateApplicationForm from "./CreateApplicationForm";
|
import CreateApplicationForm from "./CreateApplicationForm";
|
||||||
|
import InviteUsersFormv2 from "pages/organization/InviteUsersFromv2";
|
||||||
import { CREATE_APPLICATION_FORM_NAME } from "constants/forms";
|
import { CREATE_APPLICATION_FORM_NAME } from "constants/forms";
|
||||||
import { PERMISSION_TYPE } from "./permissionHelpers";
|
import { PERMISSION_TYPE } from "./permissionHelpers";
|
||||||
import { DELETING_APPLICATION } from "constants/messages";
|
import { DELETING_APPLICATION } from "constants/messages";
|
||||||
|
|
@ -40,6 +42,7 @@ const OrgDropDown = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0px 30px;
|
padding: 0px 30px;
|
||||||
font-size: ${props => props.theme.fontSizes[1]}px;
|
font-size: ${props => props.theme.fontSizes[1]}px;
|
||||||
|
justify-content: space-between;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ApplicationCardsWrapper = styled.div`
|
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>
|
</OrgDropDown>
|
||||||
<ApplicationCardsWrapper key={organization.id}>
|
<ApplicationCardsWrapper key={organization.id}>
|
||||||
<FormDialogComponent
|
<FormDialogComponent
|
||||||
|
|
|
||||||
111
app/client/src/pages/organization/InviteUsersFromv2.tsx
Normal file
111
app/client/src/pages/organization/InviteUsersFromv2.tsx
Normal 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),
|
||||||
|
);
|
||||||
|
|
@ -52,3 +52,23 @@ export const inviteUsersToOrgSubmitHandler = (
|
||||||
throw new SubmissionError(error);
|
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);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,16 @@ import { ORG_INVITE_USERS_PAGE_URL } from "constants/routes";
|
||||||
import PageSectionDivider from "pages/common/PageSectionDivider";
|
import PageSectionDivider from "pages/common/PageSectionDivider";
|
||||||
import PageSectionHeader from "pages/common/PageSectionHeader";
|
import PageSectionHeader from "pages/common/PageSectionHeader";
|
||||||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||||
|
import InviteUsersFormv2 from "pages/organization/InviteUsersFromv2";
|
||||||
import Button from "components/editorComponents/Button";
|
import Button from "components/editorComponents/Button";
|
||||||
import { Org, OrgUser } from "constants/orgConstants";
|
import { Org, OrgUser } from "constants/orgConstants";
|
||||||
import { Menu, MenuItem, Popover, Position } from "@blueprintjs/core";
|
import { Menu, MenuItem, Popover, Position } from "@blueprintjs/core";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { FormIcons } from "icons/FormIcons";
|
import { FormIcons } from "icons/FormIcons";
|
||||||
import "@syncfusion/ej2-react-grids/styles/material.css";
|
import "@syncfusion/ej2-react-grids/styles/material.css";
|
||||||
import { stringify } from "querystring";
|
|
||||||
import { RouteComponentProps } from "react-router";
|
import { RouteComponentProps } from "react-router";
|
||||||
import Spinner from "components/editorComponents/Spinner";
|
import Spinner from "components/editorComponents/Spinner";
|
||||||
|
import FormDialogComponent from "components/editorComponents/form/FormDialogComponent";
|
||||||
type OrgProps = {
|
type OrgProps = {
|
||||||
org?: Org;
|
org?: Org;
|
||||||
changeOrgName: (value: string) => void;
|
changeOrgName: (value: string) => void;
|
||||||
|
|
@ -138,13 +139,20 @@ export const OrgSettings = (props: PageProps) => {
|
||||||
<PageSectionDivider />
|
<PageSectionDivider />
|
||||||
<PageSectionHeader>
|
<PageSectionHeader>
|
||||||
<h2>Users</h2>
|
<h2>Users</h2>
|
||||||
|
<FormDialogComponent
|
||||||
|
trigger={
|
||||||
<Button
|
<Button
|
||||||
intent="primary"
|
intent="primary"
|
||||||
text="Invite Users"
|
text="Invite Users"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
iconAlignment="left"
|
iconAlignment="left"
|
||||||
filled
|
filled
|
||||||
onClick={() => history.push(ORG_INVITE_USERS_PAGE_URL)}
|
/>
|
||||||
|
}
|
||||||
|
Form={InviteUsersFormv2}
|
||||||
|
orgId={orgId}
|
||||||
|
title={"Invite Users"}
|
||||||
|
setMaxWidth
|
||||||
/>
|
/>
|
||||||
</PageSectionHeader>
|
</PageSectionHeader>
|
||||||
{props.isFetchAllUsers && props.isFetchAllRoles ? (
|
{props.isFetchAllUsers && props.isFetchAllRoles ? (
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,10 @@ type InviteUserPayload = {
|
||||||
groupIds: string[];
|
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 response: ApiResponse = yield callAPI(UserApi.inviteUser, payload);
|
||||||
const isValidResponse = yield validateResponse(response);
|
const isValidResponse = yield validateResponse(response);
|
||||||
if (!isValidResponse) {
|
if (!isValidResponse) {
|
||||||
|
|
@ -183,29 +186,22 @@ export function* inviteUser(payload: InviteUserPayload, reject: any) {
|
||||||
|
|
||||||
export function* inviteUsers(
|
export function* inviteUsers(
|
||||||
action: ReduxActionWithPromise<{
|
action: ReduxActionWithPromise<{
|
||||||
data: Array<{ roleId: string; emails: string[] }>;
|
data: { emails: string[]; orgId: string; roleName: string };
|
||||||
}>,
|
}>,
|
||||||
) {
|
) {
|
||||||
const { data, resolve, reject } = action.payload;
|
const { data, resolve, reject } = action.payload;
|
||||||
try {
|
try {
|
||||||
const sagasToCall = [];
|
const sagasToCall: any[] = [];
|
||||||
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];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const email in emailSet) {
|
data.emails.forEach((email: string) => {
|
||||||
sagasToCall.push(
|
sagasToCall.push(
|
||||||
call(inviteUser, { email, groupIds: emailSet[email] }, reject),
|
call(
|
||||||
|
inviteUser,
|
||||||
|
{ email, orgId: data.orgId, roleName: data.roleName },
|
||||||
|
reject,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
yield all(sagasToCall);
|
yield all(sagasToCall);
|
||||||
yield put({
|
yield put({
|
||||||
type: ReduxActionTypes.INVITE_USERS_TO_ORG_SUCCESS,
|
type: ReduxActionTypes.INVITE_USERS_TO_ORG_SUCCESS,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ import { createSelector } from "reselect";
|
||||||
import { AppState } from "reducers";
|
import { AppState } from "reducers";
|
||||||
import { OrgRole, Org } from "constants/orgConstants";
|
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 getOrgs = (state: AppState) => state.ui.orgs.list;
|
||||||
export const getAllUsers = (state: AppState) => state.ui.orgs.orgUsers;
|
export const getAllUsers = (state: AppState) => state.ui.orgs.orgUsers;
|
||||||
export const getAllRoles = (state: AppState) => state.ui.orgs.orgRoles;
|
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[]) => {
|
export const getDefaultRole = createSelector(getRoles, (roles?: OrgRole[]) => {
|
||||||
return roles?.find(role => role.isDefault);
|
return roles?.find(role => role.isDefault);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user