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 { 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
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);
|
||||
});
|
||||
};
|
||||
|
||||
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 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 ? (
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user