2021-02-11 12:54:00 +00:00
|
|
|
import React, {
|
|
|
|
|
Component,
|
|
|
|
|
useContext,
|
|
|
|
|
useEffect,
|
|
|
|
|
useRef,
|
|
|
|
|
useState,
|
|
|
|
|
} from "react";
|
|
|
|
|
import styled, { ThemeContext } from "styled-components";
|
|
|
|
|
import { connect, useDispatch, useSelector } from "react-redux";
|
2021-01-21 06:19:06 +00:00
|
|
|
import { useLocation } from "react-router-dom";
|
2019-11-25 05:07:27 +00:00
|
|
|
import { AppState } from "reducers";
|
2021-02-11 12:54:00 +00:00
|
|
|
import { Card, Classes as BlueprintClasses, Dialog } from "@blueprintjs/core";
|
2021-03-16 18:48:36 +00:00
|
|
|
import { truncateTextUsingEllipsis } from "constants/DefaultTheme";
|
2019-11-07 04:59:40 +00:00
|
|
|
import {
|
|
|
|
|
getApplicationList,
|
2021-02-11 12:54:00 +00:00
|
|
|
getApplicationSearchKeyword,
|
2019-11-21 10:52:49 +00:00
|
|
|
getCreateApplicationError,
|
2021-02-11 12:54:00 +00:00
|
|
|
getIsCreatingApplication,
|
2020-02-03 12:19:10 +00:00
|
|
|
getIsDeletingApplication,
|
2020-09-01 07:16:54 +00:00
|
|
|
getIsDuplicatingApplication,
|
2021-02-11 12:54:00 +00:00
|
|
|
getIsFetchingApplications,
|
2020-11-25 12:24:14 +00:00
|
|
|
getIsSavingOrgInfo,
|
2021-02-11 12:54:00 +00:00
|
|
|
getUserApplicationsOrgs,
|
|
|
|
|
getUserApplicationsOrgsList,
|
2019-11-25 05:07:27 +00:00
|
|
|
} from "selectors/applicationSelectors";
|
2019-11-07 04:59:40 +00:00
|
|
|
import {
|
|
|
|
|
ApplicationPayload,
|
2021-02-11 12:54:00 +00:00
|
|
|
ReduxActionTypes,
|
2019-11-25 05:07:27 +00:00
|
|
|
} from "constants/ReduxActionConstants";
|
2019-12-23 12:16:33 +00:00
|
|
|
import PageWrapper from "pages/common/PageWrapper";
|
2019-11-21 10:52:49 +00:00
|
|
|
import SubHeader from "pages/common/SubHeader";
|
2019-12-23 12:16:33 +00:00
|
|
|
import PageSectionDivider from "pages/common/PageSectionDivider";
|
2019-11-21 10:52:49 +00:00
|
|
|
import ApplicationCard from "./ApplicationCard";
|
2020-08-12 11:41:56 +00:00
|
|
|
import OrgInviteUsersForm from "pages/organization/OrgInviteUsersForm";
|
2021-02-11 12:54:00 +00:00
|
|
|
import { isPermitted, PERMISSION_TYPE } from "./permissionHelpers";
|
2020-05-14 10:47:13 +00:00
|
|
|
import FormDialogComponent from "components/editorComponents/form/FormDialogComponent";
|
2021-02-11 06:36:07 +00:00
|
|
|
// import OnboardingHelper from "components/editorComponents/Onboarding/Helper";
|
2020-05-27 13:36:06 +00:00
|
|
|
import { User } from "constants/userConstants";
|
|
|
|
|
import { getCurrentUser } from "selectors/usersSelectors";
|
2020-11-11 13:12:05 +00:00
|
|
|
import { CREATE_ORGANIZATION_FORM_NAME } from "constants/forms";
|
2020-06-11 11:31:32 +00:00
|
|
|
import {
|
|
|
|
|
DropdownOnSelectActions,
|
2021-02-11 12:54:00 +00:00
|
|
|
getOnSelectAction,
|
2020-06-11 11:31:32 +00:00
|
|
|
} from "pages/common/CustomizedDropdown/dropdownHelpers";
|
2020-09-16 11:50:47 +00:00
|
|
|
import Button, { Size } from "components/ads/Button";
|
|
|
|
|
import Text, { TextType } from "components/ads/Text";
|
|
|
|
|
import Icon, { IconName, IconSize } from "components/ads/Icon";
|
|
|
|
|
import MenuItem from "components/ads/MenuItem";
|
|
|
|
|
import {
|
|
|
|
|
duplicateApplication,
|
|
|
|
|
updateApplication,
|
|
|
|
|
} from "actions/applicationActions";
|
|
|
|
|
import { Classes } from "components/ads/common";
|
|
|
|
|
import Menu from "components/ads/Menu";
|
|
|
|
|
import { Position } from "@blueprintjs/core/lib/esm/common/position";
|
2020-09-09 05:18:36 +00:00
|
|
|
import HelpModal from "components/designSystems/appsmith/help/HelpModal";
|
2020-11-11 13:12:05 +00:00
|
|
|
import { UpdateApplicationPayload, UserRoles } from "api/ApplicationApi";
|
2020-09-28 06:29:41 +00:00
|
|
|
import PerformanceTracker, {
|
|
|
|
|
PerformanceTransactionName,
|
|
|
|
|
} from "utils/PerformanceTracker";
|
2020-10-20 07:14:39 +00:00
|
|
|
import { loadingUserOrgs } from "./ApplicationLoaders";
|
2020-10-14 10:35:19 +00:00
|
|
|
import { creatingApplicationMap } from "reducers/uiReducers/applicationsReducer";
|
2020-11-25 12:24:14 +00:00
|
|
|
import EditableText, {
|
|
|
|
|
EditInteractionKind,
|
|
|
|
|
SavingState,
|
|
|
|
|
} from "components/ads/EditableText";
|
|
|
|
|
import { notEmptyValidator } from "components/ads/TextInput";
|
|
|
|
|
import { saveOrg } from "actions/orgActions";
|
2021-06-02 09:56:22 +00:00
|
|
|
import { leaveOrganization } from "actions/userActions";
|
2020-10-19 12:11:14 +00:00
|
|
|
import CenteredWrapper from "../../components/designSystems/appsmith/CenteredWrapper";
|
|
|
|
|
import NoSearchImage from "../../assets/images/NoSearchResult.svg";
|
2020-12-09 07:06:02 +00:00
|
|
|
import { getNextEntityName, getRandomPaletteColor } from "utils/AppsmithUtils";
|
2020-10-31 06:40:51 +00:00
|
|
|
import Spinner from "components/ads/Spinner";
|
2020-11-11 13:12:05 +00:00
|
|
|
import ProfileImage from "pages/common/ProfileImage";
|
2020-12-09 07:06:02 +00:00
|
|
|
import { AppIconCollection } from "components/ads/AppIcon";
|
2021-01-19 06:17:15 +00:00
|
|
|
import ProductUpdatesModal from "pages/Applications/ProductUpdatesModal";
|
2021-02-11 06:36:07 +00:00
|
|
|
import WelcomeHelper from "components/editorComponents/Onboarding/WelcomeHelper";
|
|
|
|
|
import { useIntiateOnboarding } from "components/editorComponents/Onboarding/utils";
|
|
|
|
|
import AnalyticsUtil from "utils/AnalyticsUtil";
|
2021-05-05 07:10:35 +00:00
|
|
|
import { createOrganizationSubmitHandler } from "../organization/helpers";
|
2021-06-16 18:36:34 +00:00
|
|
|
import UserApi from "api/UserApi";
|
2021-06-03 06:18:08 +00:00
|
|
|
import ImportApplicationModal from "./ImportApplicationModal";
|
2021-06-16 15:51:18 +00:00
|
|
|
import { SIGNUP_SUCCESS_URL } from "constants/routes";
|
2020-05-27 13:36:06 +00:00
|
|
|
|
2021-07-29 08:49:46 +00:00
|
|
|
import { getIsSafeRedirectURL } from "utils/helpers";
|
|
|
|
|
|
2020-05-27 13:36:06 +00:00
|
|
|
const OrgDropDown = styled.div`
|
|
|
|
|
display: flex;
|
2020-12-24 04:32:25 +00:00
|
|
|
padding: ${(props) => props.theme.spaces[4]}px
|
|
|
|
|
${(props) => props.theme.spaces[4]}px;
|
|
|
|
|
font-size: ${(props) => props.theme.fontSizes[1]}px;
|
2020-06-03 13:54:42 +00:00
|
|
|
justify-content: space-between;
|
2020-09-28 05:06:06 +00:00
|
|
|
align-items: center;
|
2020-05-27 13:36:06 +00:00
|
|
|
`;
|
2019-11-07 04:59:40 +00:00
|
|
|
|
|
|
|
|
const ApplicationCardsWrapper = styled.div`
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-flow: row wrap;
|
2019-11-21 10:52:49 +00:00
|
|
|
justify-content: flex-start;
|
|
|
|
|
align-items: space-evenly;
|
2020-12-24 04:32:25 +00:00
|
|
|
font-size: ${(props) => props.theme.fontSizes[4]}px;
|
2019-11-07 04:59:40 +00:00
|
|
|
`;
|
|
|
|
|
|
2020-07-16 10:39:07 +00:00
|
|
|
const OrgSection = styled.div``;
|
|
|
|
|
|
2020-09-16 11:50:47 +00:00
|
|
|
const PaddingWrapper = styled.div`
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) => props.theme.card.minWidth + props.theme.spaces[5] * 2}px;
|
|
|
|
|
margin: ${(props) => props.theme.spaces[6] + 1}px 0px
|
|
|
|
|
${(props) => props.theme.spaces[6] + 1}px 0px;
|
2020-10-21 09:23:40 +00:00
|
|
|
|
|
|
|
|
@media screen and (min-width: 1500px) {
|
2020-12-24 04:32:25 +00:00
|
|
|
margin-right: ${(props) => props.theme.spaces[12] - 1}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
.bp3-card {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) => props.theme.card.minWidth}px;
|
|
|
|
|
height: ${(props) => props.theme.card.minHeight}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media screen and (min-width: 1500px) and (max-width: 1512px) {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) =>
|
|
|
|
|
props.theme.card.minWidth + props.theme.spaces[4] * 2}px;
|
|
|
|
|
margin-right: ${(props) => props.theme.spaces[12] - 1}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
.bp3-card {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) => props.theme.card.minWidth - 5}px;
|
|
|
|
|
height: ${(props) => props.theme.card.minHeight - 5}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@media screen and (min-width: 1478px) and (max-width: 1500px) {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) =>
|
|
|
|
|
props.theme.card.minWidth + props.theme.spaces[4] * 2}px;
|
|
|
|
|
margin-right: ${(props) => props.theme.spaces[11] + 1}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
.bp3-card {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) => props.theme.card.minWidth - 8}px;
|
|
|
|
|
height: ${(props) => props.theme.card.minHeight - 8}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media screen and (min-width: 1447px) and (max-width: 1477px) {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) =>
|
|
|
|
|
props.theme.card.minWidth + props.theme.spaces[3] * 2}px;
|
|
|
|
|
margin-right: ${(props) => props.theme.spaces[11] - 4}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
.bp3-card {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) => props.theme.card.minWidth - 8}px;
|
|
|
|
|
height: ${(props) => props.theme.card.minHeight - 8}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media screen and (min-width: 1417px) and (max-width: 1446px) {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) =>
|
|
|
|
|
props.theme.card.minWidth + props.theme.spaces[3] * 2}px;
|
|
|
|
|
margin-right: ${(props) => props.theme.spaces[11] - 8}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
.bp3-card {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) => props.theme.card.minWidth - 11}px;
|
|
|
|
|
height: ${(props) => props.theme.card.minHeight - 11}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media screen and (min-width: 1400px) and (max-width: 1417px) {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) =>
|
|
|
|
|
props.theme.card.minWidth + props.theme.spaces[2] * 2}px;
|
|
|
|
|
margin-right: ${(props) => props.theme.spaces[11] - 12}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
.bp3-card {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) => props.theme.card.minWidth - 15}px;
|
|
|
|
|
height: ${(props) => props.theme.card.minHeight - 15}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media screen and (max-width: 1400px) {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) =>
|
|
|
|
|
props.theme.card.minWidth + props.theme.spaces[2] * 2}px;
|
|
|
|
|
margin-right: ${(props) => props.theme.spaces[11] - 16}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
.bp3-card {
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) => props.theme.card.minWidth - 15}px;
|
|
|
|
|
height: ${(props) => props.theme.card.minHeight - 15}px;
|
2020-10-21 09:23:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-09-16 11:50:47 +00:00
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const StyledDialog = styled(Dialog)<{ setMaxWidth?: boolean }>`
|
|
|
|
|
&& {
|
2020-12-24 04:32:25 +00:00
|
|
|
background: ${(props) => props.theme.colors.modal.bg};
|
2020-11-25 12:24:14 +00:00
|
|
|
& .${BlueprintClasses.DIALOG_HEADER} {
|
2020-12-24 04:32:25 +00:00
|
|
|
background: ${(props) => props.theme.colors.modal.bg};
|
|
|
|
|
padding: ${(props) => props.theme.spaces[4]}px
|
|
|
|
|
${(props) => props.theme.spaces[4]}px;
|
2020-09-16 11:50:47 +00:00
|
|
|
}
|
2020-11-25 12:24:14 +00:00
|
|
|
& .${BlueprintClasses.DIALOG_FOOTER_ACTIONS} {
|
2020-09-16 11:50:47 +00:00
|
|
|
display: block;
|
|
|
|
|
}
|
2020-12-24 04:32:25 +00:00
|
|
|
${(props) => props.setMaxWidth && `width: 100vh;`}
|
2020-11-25 12:24:14 +00:00
|
|
|
|
|
|
|
|
.${BlueprintClasses.HEADING} {
|
2020-12-24 04:32:25 +00:00
|
|
|
color: ${(props) => props.theme.colors.modal.headerText};
|
2020-11-25 12:24:14 +00:00
|
|
|
}
|
2020-06-17 04:17:25 +00:00
|
|
|
}
|
2020-05-20 14:09:51 +00:00
|
|
|
`;
|
|
|
|
|
|
2020-09-16 11:50:47 +00:00
|
|
|
const LeftPaneWrapper = styled.div`
|
|
|
|
|
// height: 50vh;
|
2020-09-17 07:57:19 +00:00
|
|
|
overflow: auto;
|
2020-09-16 11:50:47 +00:00
|
|
|
width: 256px;
|
|
|
|
|
display: flex;
|
|
|
|
|
padding-left: 16px;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
position: fixed;
|
|
|
|
|
top: 77px;
|
|
|
|
|
`;
|
|
|
|
|
const ApplicationContainer = styled.div`
|
2020-12-24 04:32:25 +00:00
|
|
|
height: calc(100vh - ${(props) => props.theme.homePage.search.height - 40}px);
|
2020-09-17 07:57:19 +00:00
|
|
|
overflow: auto;
|
2020-12-24 04:32:25 +00:00
|
|
|
padding-right: ${(props) => props.theme.homePage.leftPane.rightMargin}px;
|
|
|
|
|
margin-top: ${(props) => props.theme.homePage.search.height}px;
|
|
|
|
|
margin-left: ${(props) =>
|
2020-09-16 11:50:47 +00:00
|
|
|
props.theme.homePage.leftPane.width +
|
|
|
|
|
props.theme.homePage.leftPane.rightMargin +
|
|
|
|
|
props.theme.homePage.leftPane.leftPadding}px;
|
|
|
|
|
width: calc(
|
|
|
|
|
100% -
|
2020-12-24 04:32:25 +00:00
|
|
|
${(props) =>
|
2020-09-16 11:50:47 +00:00
|
|
|
props.theme.homePage.leftPane.width +
|
|
|
|
|
props.theme.homePage.leftPane.rightMargin +
|
|
|
|
|
props.theme.homePage.leftPane.leftPadding}px
|
|
|
|
|
);
|
2021-01-21 06:19:06 +00:00
|
|
|
scroll-behavior: smooth;
|
2020-08-03 11:44:18 +00:00
|
|
|
`;
|
|
|
|
|
|
2020-09-16 11:50:47 +00:00
|
|
|
const ItemWrapper = styled.div`
|
|
|
|
|
padding: 9px 15px;
|
|
|
|
|
`;
|
|
|
|
|
const StyledIcon = styled(Icon)`
|
|
|
|
|
margin-right: 11px;
|
|
|
|
|
`;
|
2020-11-11 13:12:05 +00:00
|
|
|
const UserImageContainer = styled.div`
|
|
|
|
|
display: flex;
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
|
|
|
|
div {
|
|
|
|
|
cursor: default;
|
|
|
|
|
margin-right: -6px;
|
|
|
|
|
width: 24px;
|
|
|
|
|
height: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
div:last-child {
|
|
|
|
|
margin-right: 0px;
|
|
|
|
|
}
|
|
|
|
|
`;
|
|
|
|
|
const OrgShareUsers = styled.div`
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
`;
|
2020-09-16 11:50:47 +00:00
|
|
|
|
2020-10-14 10:35:19 +00:00
|
|
|
function Item(props: {
|
|
|
|
|
label: string;
|
|
|
|
|
textType: TextType;
|
|
|
|
|
icon?: IconName;
|
|
|
|
|
isFetchingApplications: boolean;
|
|
|
|
|
}) {
|
2020-09-16 11:50:47 +00:00
|
|
|
return (
|
|
|
|
|
<ItemWrapper>
|
|
|
|
|
{props.icon && <StyledIcon />}
|
2020-10-14 10:35:19 +00:00
|
|
|
<Text
|
|
|
|
|
className={
|
|
|
|
|
props.isFetchingApplications ? BlueprintClasses.SKELETON : ""
|
|
|
|
|
}
|
2021-04-28 10:28:39 +00:00
|
|
|
type={props.textType}
|
2020-10-14 10:35:19 +00:00
|
|
|
>
|
|
|
|
|
{" "}
|
|
|
|
|
{props.label}
|
|
|
|
|
</Text>
|
2020-09-16 11:50:47 +00:00
|
|
|
</ItemWrapper>
|
|
|
|
|
);
|
|
|
|
|
}
|
2020-10-14 10:35:19 +00:00
|
|
|
function LeftPaneSection(props: {
|
|
|
|
|
heading: string;
|
|
|
|
|
children?: any;
|
|
|
|
|
isFetchingApplications: boolean;
|
|
|
|
|
}) {
|
2020-09-16 11:50:47 +00:00
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{/* <MenuItem text={props.heading}/> */}
|
2020-10-14 10:35:19 +00:00
|
|
|
<Item
|
2021-04-28 10:28:39 +00:00
|
|
|
isFetchingApplications={props.isFetchingApplications}
|
2020-10-14 10:35:19 +00:00
|
|
|
label={props.heading}
|
|
|
|
|
textType={TextType.H6}
|
2021-02-11 12:54:00 +00:00
|
|
|
/>
|
2020-09-16 11:50:47 +00:00
|
|
|
{props.children}
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const StyledAnchor = styled.a`
|
|
|
|
|
position: relative;
|
|
|
|
|
top: -24px;
|
|
|
|
|
// width: 0;
|
|
|
|
|
// height: 0;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const WorkpsacesNavigator = styled.div`
|
2020-09-17 07:57:19 +00:00
|
|
|
overflow: auto;
|
2020-12-24 04:32:25 +00:00
|
|
|
height: calc(100vh - ${(props) => props.theme.homePage.header + 36 + 25}px);
|
2021-02-11 06:36:07 +00:00
|
|
|
padding-bottom: 88px;
|
2020-09-16 11:50:47 +00:00
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const textIconStyles = (props: { color: string; hover: string }) => {
|
|
|
|
|
return `
|
|
|
|
|
&&&&&& {
|
|
|
|
|
.${Classes.TEXT},.${Classes.ICON} svg path {
|
|
|
|
|
color: ${props.color};
|
|
|
|
|
stroke: ${props.color};
|
|
|
|
|
fill: ${props.color};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
.${Classes.TEXT},.${Classes.ICON} svg path {
|
|
|
|
|
color: ${props.hover};
|
|
|
|
|
stroke: ${props.hover};
|
|
|
|
|
fill: ${props.hover};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
`;
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-20 14:09:51 +00:00
|
|
|
const ApplicationAddCardWrapper = styled(Card)`
|
2020-05-14 10:47:13 +00:00
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
2020-09-28 05:06:06 +00:00
|
|
|
justify-content: center;
|
2020-12-24 04:32:25 +00:00
|
|
|
background: ${(props) => props.theme.colors.applications.bg};
|
2020-05-14 10:47:13 +00:00
|
|
|
align-items: center;
|
2020-12-24 04:32:25 +00:00
|
|
|
width: ${(props) => props.theme.card.minWidth}px;
|
|
|
|
|
height: ${(props) => props.theme.card.minHeight}px;
|
2020-05-14 10:47:13 +00:00
|
|
|
position: relative;
|
2020-08-18 06:40:11 +00:00
|
|
|
box-shadow: none;
|
2020-09-16 11:50:47 +00:00
|
|
|
border-radius: 0;
|
|
|
|
|
padding: 0;
|
2020-12-24 04:32:25 +00:00
|
|
|
margin: ${(props) => props.theme.spaces[5]}px;
|
2020-05-14 10:47:13 +00:00
|
|
|
a {
|
|
|
|
|
display: block;
|
|
|
|
|
position: absolute;
|
|
|
|
|
left: 0;
|
|
|
|
|
top: 0;
|
2020-12-24 04:32:25 +00:00
|
|
|
height: calc(100% - ${(props) => props.theme.card.titleHeight}px);
|
2020-05-14 10:47:13 +00:00
|
|
|
width: 100%;
|
|
|
|
|
}
|
2020-06-18 12:31:56 +00:00
|
|
|
cursor: pointer;
|
2020-09-16 11:50:47 +00:00
|
|
|
&:hover {
|
2020-12-24 04:32:25 +00:00
|
|
|
background: ${(props) => props.theme.colors.applications.hover.bg};
|
2020-09-16 11:50:47 +00:00
|
|
|
}
|
2020-12-24 04:32:25 +00:00
|
|
|
${(props) => {
|
2020-09-16 11:50:47 +00:00
|
|
|
return `${textIconStyles({
|
2020-09-23 14:06:50 +00:00
|
|
|
color: props.theme.colors.applications.textColor,
|
|
|
|
|
hover: props.theme.colors.applications.hover.textColor,
|
2020-09-16 11:50:47 +00:00
|
|
|
})}`;
|
|
|
|
|
}}
|
2020-05-14 10:47:13 +00:00
|
|
|
`;
|
|
|
|
|
|
2021-05-13 08:35:39 +00:00
|
|
|
function OrgMenuItem({ isFetchingApplications, org, selected }: any) {
|
2020-12-21 09:05:58 +00:00
|
|
|
const menuRef = useRef<HTMLAnchorElement>(null);
|
2021-01-21 06:19:06 +00:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (selected) {
|
|
|
|
|
menuRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
|
|
|
menuRef.current?.click();
|
|
|
|
|
}
|
|
|
|
|
}, [selected]);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<MenuItem
|
2021-09-07 09:15:11 +00:00
|
|
|
containerClassName={
|
|
|
|
|
isFetchingApplications ? BlueprintClasses.SKELETON : ""
|
|
|
|
|
}
|
2021-04-28 10:28:39 +00:00
|
|
|
ellipsize={20}
|
|
|
|
|
href={`${window.location.pathname}#${org.organization.slug}`}
|
2021-01-21 06:19:06 +00:00
|
|
|
icon="workspace"
|
|
|
|
|
key={org.organization.slug}
|
2021-04-28 10:28:39 +00:00
|
|
|
ref={menuRef}
|
2021-01-21 06:19:06 +00:00
|
|
|
selected={selected}
|
2021-04-28 10:28:39 +00:00
|
|
|
text={org.organization.name}
|
2021-01-21 06:19:06 +00:00
|
|
|
/>
|
|
|
|
|
);
|
2021-04-28 10:28:39 +00:00
|
|
|
}
|
2021-01-21 06:19:06 +00:00
|
|
|
|
2021-05-05 07:10:35 +00:00
|
|
|
const submitCreateOrganizationForm = async (data: any, dispatch: any) => {
|
|
|
|
|
const result = await createOrganizationSubmitHandler(data, dispatch);
|
|
|
|
|
return result;
|
|
|
|
|
};
|
2021-06-02 09:56:22 +00:00
|
|
|
|
2021-01-21 06:19:06 +00:00
|
|
|
function LeftPane() {
|
2021-05-05 07:10:35 +00:00
|
|
|
const dispatch = useDispatch();
|
2020-10-14 10:35:19 +00:00
|
|
|
const fetchedUserOrgs = useSelector(getUserApplicationsOrgs);
|
|
|
|
|
const isFetchingApplications = useSelector(getIsFetchingApplications);
|
|
|
|
|
let userOrgs;
|
|
|
|
|
if (!isFetchingApplications) {
|
|
|
|
|
userOrgs = fetchedUserOrgs;
|
|
|
|
|
} else {
|
|
|
|
|
userOrgs = loadingUserOrgs as any;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-21 06:19:06 +00:00
|
|
|
const location = useLocation();
|
|
|
|
|
const urlHash = location.hash.slice(1);
|
2020-12-21 09:05:58 +00:00
|
|
|
|
2021-02-11 06:36:07 +00:00
|
|
|
const initiateOnboarding = useIntiateOnboarding();
|
|
|
|
|
|
2020-09-16 11:50:47 +00:00
|
|
|
return (
|
|
|
|
|
<LeftPaneWrapper>
|
2020-10-14 10:35:19 +00:00
|
|
|
<LeftPaneSection
|
|
|
|
|
heading="ORGANIZATIONS"
|
|
|
|
|
isFetchingApplications={isFetchingApplications}
|
|
|
|
|
>
|
2020-10-28 05:39:28 +00:00
|
|
|
<WorkpsacesNavigator data-cy="t--left-panel">
|
2021-05-05 07:10:35 +00:00
|
|
|
{!isFetchingApplications && fetchedUserOrgs && (
|
|
|
|
|
<MenuItem
|
|
|
|
|
cypressSelector="t--org-new-organization-auto-create"
|
|
|
|
|
icon="plus"
|
|
|
|
|
onSelect={() =>
|
|
|
|
|
submitCreateOrganizationForm(
|
|
|
|
|
{
|
|
|
|
|
name: getNextEntityName(
|
|
|
|
|
"Untitled organization ",
|
|
|
|
|
fetchedUserOrgs.map((el: any) => el.organization.name),
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
dispatch,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
text={CREATE_ORGANIZATION_FORM_NAME}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2020-09-16 11:50:47 +00:00
|
|
|
{userOrgs &&
|
|
|
|
|
userOrgs.map((org: any) => (
|
2021-01-21 06:19:06 +00:00
|
|
|
<OrgMenuItem
|
2021-04-28 10:28:39 +00:00
|
|
|
isFetchingApplications={isFetchingApplications}
|
2021-01-21 06:19:06 +00:00
|
|
|
key={org.organization.slug}
|
|
|
|
|
org={org}
|
|
|
|
|
selected={urlHash === org.organization.slug}
|
2020-09-16 11:50:47 +00:00
|
|
|
/>
|
|
|
|
|
))}
|
2021-02-11 06:36:07 +00:00
|
|
|
<div style={{ marginTop: 12 }}>
|
|
|
|
|
<Item
|
2021-04-28 10:28:39 +00:00
|
|
|
isFetchingApplications={isFetchingApplications}
|
2021-02-11 06:36:07 +00:00
|
|
|
label={"GETTING STARTED"}
|
|
|
|
|
textType={TextType.H6}
|
2021-04-28 10:28:39 +00:00
|
|
|
/>
|
2021-02-11 06:36:07 +00:00
|
|
|
</div>
|
|
|
|
|
<MenuItem
|
2021-09-07 09:15:11 +00:00
|
|
|
containerClassName={
|
|
|
|
|
isFetchingApplications ? BlueprintClasses.SKELETON : ""
|
|
|
|
|
}
|
2021-02-11 06:36:07 +00:00
|
|
|
icon="book"
|
|
|
|
|
onSelect={() => {
|
|
|
|
|
window.open("https://docs.appsmith.com/", "_blank");
|
|
|
|
|
}}
|
2021-04-28 10:28:39 +00:00
|
|
|
text={"Documentation"}
|
2021-02-11 06:36:07 +00:00
|
|
|
/>
|
|
|
|
|
<MenuItem
|
2021-09-07 09:15:11 +00:00
|
|
|
containerClassName={
|
2021-02-11 06:36:07 +00:00
|
|
|
isFetchingApplications
|
|
|
|
|
? BlueprintClasses.SKELETON
|
|
|
|
|
: "t--welcome-tour"
|
|
|
|
|
}
|
|
|
|
|
icon="shine"
|
|
|
|
|
onSelect={() => {
|
|
|
|
|
AnalyticsUtil.logEvent("WELCOME_TOUR_CLICK");
|
|
|
|
|
|
|
|
|
|
initiateOnboarding();
|
|
|
|
|
}}
|
2021-04-28 10:28:39 +00:00
|
|
|
text={"Welcome Tour"}
|
2021-02-11 06:36:07 +00:00
|
|
|
/>
|
2020-09-16 11:50:47 +00:00
|
|
|
</WorkpsacesNavigator>
|
|
|
|
|
</LeftPaneSection>
|
|
|
|
|
</LeftPaneWrapper>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const CreateNewLabel = styled(Text)`
|
|
|
|
|
margin-top: 18px;
|
|
|
|
|
`;
|
|
|
|
|
|
2020-10-08 09:49:15 +00:00
|
|
|
const OrgNameElement = styled(Text)`
|
|
|
|
|
max-width: 500px;
|
2021-03-16 18:48:36 +00:00
|
|
|
${truncateTextUsingEllipsis}
|
2020-10-08 09:49:15 +00:00
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const OrgNameHolder = styled(Text)`
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
`;
|
|
|
|
|
|
2020-09-16 11:50:47 +00:00
|
|
|
const OrgNameWrapper = styled.div<{ disabled?: boolean }>`
|
2020-12-24 04:32:25 +00:00
|
|
|
cursor: ${(props) => (!props.disabled ? "pointer" : "inherit")};
|
|
|
|
|
${(props) => {
|
2020-09-16 11:50:47 +00:00
|
|
|
const color = props.disabled
|
2020-09-23 14:06:50 +00:00
|
|
|
? props.theme.colors.applications.orgColor
|
|
|
|
|
: props.theme.colors.applications.hover.orgColor[9];
|
2020-09-16 11:50:47 +00:00
|
|
|
return `${textIconStyles({
|
|
|
|
|
color: color,
|
|
|
|
|
hover: color,
|
|
|
|
|
})}`;
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
.${Classes.ICON} {
|
2020-12-24 04:32:25 +00:00
|
|
|
display: ${(props) => (!props.disabled ? "inline" : "none")};;
|
2020-09-16 11:50:47 +00:00
|
|
|
margin-left: 8px;
|
2020-12-24 04:32:25 +00:00
|
|
|
color: ${(props) => props.theme.colors.applications.iconColor};
|
2020-09-16 11:50:47 +00:00
|
|
|
}
|
2020-06-11 11:31:32 +00:00
|
|
|
`;
|
2020-11-25 12:24:14 +00:00
|
|
|
const OrgRename = styled(EditableText)`
|
|
|
|
|
padding: 0 2px;
|
|
|
|
|
`;
|
2020-06-11 11:31:32 +00:00
|
|
|
|
2020-10-19 12:11:14 +00:00
|
|
|
const NoSearchResultImg = styled.img`
|
|
|
|
|
margin: 1em;
|
|
|
|
|
`;
|
|
|
|
|
|
2021-04-28 10:28:39 +00:00
|
|
|
function ApplicationsSection(props: any) {
|
2021-06-03 06:18:08 +00:00
|
|
|
const enableImportExport = true;
|
2020-09-16 11:50:47 +00:00
|
|
|
const dispatch = useDispatch();
|
2021-02-11 12:54:00 +00:00
|
|
|
const theme = useContext(ThemeContext);
|
2020-11-25 12:24:14 +00:00
|
|
|
const isSavingOrgInfo = useSelector(getIsSavingOrgInfo);
|
2020-10-14 10:35:19 +00:00
|
|
|
const isFetchingApplications = useSelector(getIsFetchingApplications);
|
2020-09-16 11:50:47 +00:00
|
|
|
const userOrgs = useSelector(getUserApplicationsOrgsList);
|
2020-10-14 10:35:19 +00:00
|
|
|
const creatingApplicationMap = useSelector(getIsCreatingApplication);
|
2020-09-16 11:50:47 +00:00
|
|
|
const currentUser = useSelector(getCurrentUser);
|
2020-11-25 12:24:14 +00:00
|
|
|
const deleteApplication = (applicationId: string) => {
|
2020-09-16 11:50:47 +00:00
|
|
|
if (applicationId && applicationId.length > 0) {
|
|
|
|
|
dispatch({
|
|
|
|
|
type: ReduxActionTypes.DELETE_APPLICATION_INIT,
|
|
|
|
|
payload: {
|
|
|
|
|
applicationId,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
2021-06-04 10:56:58 +00:00
|
|
|
const [warnLeavingOrganization, setWarnLeavingOrganization] = useState(false);
|
|
|
|
|
const [orgToOpenMenu, setOrgToOpenMenu] = useState<string | null>(null);
|
2020-09-16 11:50:47 +00:00
|
|
|
const updateApplicationDispatch = (
|
|
|
|
|
id: string,
|
|
|
|
|
data: UpdateApplicationPayload,
|
|
|
|
|
) => {
|
|
|
|
|
dispatch(updateApplication(id, data));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const duplicateApplicationDispatch = (applicationId: string) => {
|
|
|
|
|
dispatch(duplicateApplication(applicationId));
|
|
|
|
|
};
|
|
|
|
|
|
2020-10-12 13:06:05 +00:00
|
|
|
const [selectedOrgId, setSelectedOrgId] = useState<string | undefined>();
|
2021-06-03 06:18:08 +00:00
|
|
|
const [
|
|
|
|
|
selectedOrgIdForImportApplication,
|
|
|
|
|
setSelectedOrgIdForImportApplication,
|
|
|
|
|
] = useState<string | undefined>();
|
2020-09-16 11:50:47 +00:00
|
|
|
const Form: any = OrgInviteUsersForm;
|
2020-11-25 12:24:14 +00:00
|
|
|
|
2021-06-02 09:56:22 +00:00
|
|
|
const leaveOrg = (orgId: string) => {
|
2021-06-04 10:56:58 +00:00
|
|
|
setWarnLeavingOrganization(false);
|
|
|
|
|
setOrgToOpenMenu(null);
|
2021-06-02 09:56:22 +00:00
|
|
|
dispatch(leaveOrganization(orgId));
|
|
|
|
|
};
|
|
|
|
|
|
2020-11-25 12:24:14 +00:00
|
|
|
const OrgNameChange = (newName: string, orgId: string) => {
|
|
|
|
|
dispatch(
|
|
|
|
|
saveOrg({
|
|
|
|
|
id: orgId as string,
|
|
|
|
|
name: newName,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2021-04-28 10:28:39 +00:00
|
|
|
function OrgMenuTarget(props: {
|
2021-01-21 06:19:06 +00:00
|
|
|
orgName: string;
|
|
|
|
|
disabled?: boolean;
|
|
|
|
|
orgSlug: string;
|
2021-04-28 10:28:39 +00:00
|
|
|
}) {
|
2021-05-13 08:35:39 +00:00
|
|
|
const { disabled, orgName, orgSlug } = props;
|
2020-09-16 11:50:47 +00:00
|
|
|
|
2021-02-11 12:54:00 +00:00
|
|
|
return (
|
2021-06-04 10:56:58 +00:00
|
|
|
<OrgNameWrapper
|
|
|
|
|
className="t--org-name"
|
|
|
|
|
disabled={disabled}
|
|
|
|
|
onClick={() => setOrgToOpenMenu(orgSlug)}
|
|
|
|
|
>
|
2021-02-11 12:54:00 +00:00
|
|
|
<StyledAnchor id={orgSlug} />
|
2020-10-14 10:35:19 +00:00
|
|
|
<OrgNameHolder
|
|
|
|
|
className={isFetchingApplications ? BlueprintClasses.SKELETON : ""}
|
2021-04-28 10:28:39 +00:00
|
|
|
type={TextType.H1}
|
2020-10-14 10:35:19 +00:00
|
|
|
>
|
|
|
|
|
<OrgNameElement
|
|
|
|
|
className={isFetchingApplications ? BlueprintClasses.SKELETON : ""}
|
2021-04-28 10:28:39 +00:00
|
|
|
type={TextType.H1}
|
2020-10-14 10:35:19 +00:00
|
|
|
>
|
|
|
|
|
{orgName}
|
|
|
|
|
</OrgNameElement>
|
2021-02-11 12:54:00 +00:00
|
|
|
<Icon name="downArrow" size={IconSize.XXS} />
|
2020-10-08 09:49:15 +00:00
|
|
|
</OrgNameHolder>
|
2020-09-16 11:50:47 +00:00
|
|
|
</OrgNameWrapper>
|
|
|
|
|
);
|
2021-04-28 10:28:39 +00:00
|
|
|
}
|
2020-09-16 11:50:47 +00:00
|
|
|
|
2020-10-14 10:35:19 +00:00
|
|
|
const createNewApplication = (applicationName: string, orgId: string) => {
|
2021-02-11 12:54:00 +00:00
|
|
|
const color = getRandomPaletteColor(theme.colors.appCardColors);
|
2020-12-09 07:06:02 +00:00
|
|
|
const icon =
|
|
|
|
|
AppIconCollection[Math.floor(Math.random() * AppIconCollection.length)];
|
|
|
|
|
|
2020-10-14 10:35:19 +00:00
|
|
|
return dispatch({
|
|
|
|
|
type: ReduxActionTypes.CREATE_APPLICATION_INIT,
|
|
|
|
|
payload: {
|
|
|
|
|
applicationName,
|
|
|
|
|
orgId,
|
2020-12-09 07:06:02 +00:00
|
|
|
icon,
|
|
|
|
|
color,
|
2020-10-14 10:35:19 +00:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let updatedOrgs;
|
|
|
|
|
if (!isFetchingApplications) {
|
|
|
|
|
updatedOrgs = userOrgs;
|
|
|
|
|
} else {
|
|
|
|
|
updatedOrgs = loadingUserOrgs as any;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-19 12:11:14 +00:00
|
|
|
let organizationsListComponent;
|
|
|
|
|
if (
|
|
|
|
|
!isFetchingApplications &&
|
|
|
|
|
props.searchKeyword &&
|
|
|
|
|
props.searchKeyword.trim().length > 0 &&
|
|
|
|
|
updatedOrgs.length === 0
|
|
|
|
|
) {
|
|
|
|
|
organizationsListComponent = (
|
|
|
|
|
<CenteredWrapper style={{ flexDirection: "column", marginTop: "-150px" }}>
|
|
|
|
|
<CreateNewLabel type={TextType.H4}>
|
|
|
|
|
Whale! Whale! this name doesn't ring a bell!
|
|
|
|
|
</CreateNewLabel>
|
2021-04-28 10:28:39 +00:00
|
|
|
<NoSearchResultImg alt="No result found" src={NoSearchImage} />
|
2020-10-19 12:11:14 +00:00
|
|
|
</CenteredWrapper>
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
organizationsListComponent = updatedOrgs.map(
|
|
|
|
|
(organizationObject: any, index: number) => {
|
2021-05-13 08:35:39 +00:00
|
|
|
const { applications, organization, userRoles } = organizationObject;
|
2020-10-19 12:11:14 +00:00
|
|
|
const hasManageOrgPermissions = isPermitted(
|
|
|
|
|
organization.userPermissions,
|
|
|
|
|
PERMISSION_TYPE.MANAGE_ORGANIZATION,
|
|
|
|
|
);
|
|
|
|
|
return (
|
|
|
|
|
<OrgSection className="t--org-section" key={index}>
|
|
|
|
|
<OrgDropDown>
|
|
|
|
|
{(currentUser || isFetchingApplications) && (
|
2020-11-25 12:24:14 +00:00
|
|
|
<Menu
|
2021-04-28 10:28:39 +00:00
|
|
|
className="t--org-name"
|
2021-05-05 07:10:35 +00:00
|
|
|
cypressSelector="t--org-name"
|
2021-06-02 09:56:22 +00:00
|
|
|
disabled={isFetchingApplications}
|
2021-06-04 10:56:58 +00:00
|
|
|
isOpen={organization.slug === orgToOpenMenu}
|
|
|
|
|
onClose={() => {
|
|
|
|
|
setOrgToOpenMenu(null);
|
|
|
|
|
}}
|
|
|
|
|
onClosing={() => {
|
|
|
|
|
setWarnLeavingOrganization(false);
|
|
|
|
|
}}
|
2021-04-28 10:28:39 +00:00
|
|
|
position={Position.BOTTOM_RIGHT}
|
2020-11-25 12:24:14 +00:00
|
|
|
target={OrgMenuTarget({
|
|
|
|
|
orgName: organization.name,
|
2021-01-21 06:19:06 +00:00
|
|
|
orgSlug: organization.slug,
|
2020-11-25 12:24:14 +00:00
|
|
|
})}
|
|
|
|
|
>
|
2021-06-02 09:56:22 +00:00
|
|
|
{hasManageOrgPermissions && (
|
|
|
|
|
<>
|
|
|
|
|
<OrgRename
|
|
|
|
|
cypressSelector="t--org-rename-input"
|
|
|
|
|
defaultValue={organization.name}
|
|
|
|
|
editInteractionKind={EditInteractionKind.SINGLE}
|
|
|
|
|
fill
|
|
|
|
|
hideEditIcon={false}
|
|
|
|
|
isEditingDefault={false}
|
|
|
|
|
isInvalid={(value: string) => {
|
|
|
|
|
return notEmptyValidator(value).message;
|
|
|
|
|
}}
|
|
|
|
|
onBlur={(value: string) => {
|
|
|
|
|
OrgNameChange(value, organization.id);
|
|
|
|
|
}}
|
|
|
|
|
placeholder="Workspace name"
|
|
|
|
|
savingState={
|
|
|
|
|
isSavingOrgInfo
|
|
|
|
|
? SavingState.STARTED
|
|
|
|
|
: SavingState.NOT_STARTED
|
|
|
|
|
}
|
|
|
|
|
underline
|
|
|
|
|
/>
|
|
|
|
|
<MenuItem
|
|
|
|
|
cypressSelector="t--org-setting"
|
|
|
|
|
icon="general"
|
|
|
|
|
onSelect={() =>
|
|
|
|
|
getOnSelectAction(DropdownOnSelectActions.REDIRECT, {
|
|
|
|
|
path: `/org/${organization.id}/settings/general`,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
text="Organization Settings"
|
|
|
|
|
/>
|
2021-06-03 06:18:08 +00:00
|
|
|
{enableImportExport && (
|
|
|
|
|
<MenuItem
|
|
|
|
|
cypressSelector="t--org-import-app"
|
|
|
|
|
icon="upload"
|
|
|
|
|
onSelect={() =>
|
|
|
|
|
setSelectedOrgIdForImportApplication(
|
|
|
|
|
organization.id,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
text="Import Application"
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2021-06-02 09:56:22 +00:00
|
|
|
<MenuItem
|
|
|
|
|
icon="share"
|
|
|
|
|
onSelect={() => setSelectedOrgId(organization.id)}
|
|
|
|
|
text="Share"
|
|
|
|
|
/>
|
|
|
|
|
<MenuItem
|
|
|
|
|
icon="user"
|
|
|
|
|
onSelect={() =>
|
|
|
|
|
getOnSelectAction(DropdownOnSelectActions.REDIRECT, {
|
|
|
|
|
path: `/org/${organization.id}/settings/members`,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
text="Members"
|
|
|
|
|
/>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
2020-11-25 12:24:14 +00:00
|
|
|
<MenuItem
|
2021-06-02 09:56:22 +00:00
|
|
|
icon="logout"
|
2021-06-04 10:56:58 +00:00
|
|
|
onSelect={() =>
|
|
|
|
|
!warnLeavingOrganization
|
|
|
|
|
? setWarnLeavingOrganization(true)
|
|
|
|
|
: leaveOrg(organization.id)
|
|
|
|
|
}
|
|
|
|
|
text={
|
|
|
|
|
!warnLeavingOrganization
|
|
|
|
|
? "Leave Organization"
|
|
|
|
|
: "Are you sure?"
|
|
|
|
|
}
|
|
|
|
|
type={!warnLeavingOrganization ? undefined : "warning"}
|
2020-11-25 12:24:14 +00:00
|
|
|
/>
|
|
|
|
|
</Menu>
|
2020-10-19 12:11:14 +00:00
|
|
|
)}
|
2021-06-03 06:18:08 +00:00
|
|
|
{selectedOrgIdForImportApplication && (
|
|
|
|
|
<ImportApplicationModal
|
|
|
|
|
isModalOpen={
|
|
|
|
|
selectedOrgIdForImportApplication === organization.id
|
|
|
|
|
}
|
|
|
|
|
onClose={() => setSelectedOrgIdForImportApplication("")}
|
|
|
|
|
organizationId={selectedOrgIdForImportApplication}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2020-10-19 12:11:14 +00:00
|
|
|
{hasManageOrgPermissions && (
|
|
|
|
|
<StyledDialog
|
|
|
|
|
canEscapeKeyClose={false}
|
2021-04-28 10:28:39 +00:00
|
|
|
canOutsideClickClose={false}
|
2020-10-19 12:11:14 +00:00
|
|
|
isOpen={selectedOrgId === organization.id}
|
2021-04-28 10:28:39 +00:00
|
|
|
onClose={() => setSelectedOrgId("")}
|
2020-10-19 12:11:14 +00:00
|
|
|
setMaxWidth
|
2021-04-28 10:28:39 +00:00
|
|
|
title={`Invite Users to ${organization.name}`}
|
2020-10-19 12:11:14 +00:00
|
|
|
>
|
|
|
|
|
<div className={BlueprintClasses.DIALOG_BODY}>
|
|
|
|
|
<Form orgId={organization.id} />
|
|
|
|
|
</div>
|
|
|
|
|
</StyledDialog>
|
|
|
|
|
)}
|
|
|
|
|
{isPermitted(
|
|
|
|
|
organization.userPermissions,
|
|
|
|
|
PERMISSION_TYPE.INVITE_USER_TO_ORGANIZATION,
|
|
|
|
|
) &&
|
|
|
|
|
!isFetchingApplications && (
|
2020-11-11 13:12:05 +00:00
|
|
|
<OrgShareUsers>
|
|
|
|
|
<UserImageContainer>
|
2021-01-12 01:22:31 +00:00
|
|
|
{userRoles.slice(0, 5).map((el: UserRoles) => (
|
|
|
|
|
<ProfileImage
|
|
|
|
|
className="org-share-user-icons"
|
|
|
|
|
key={el.username}
|
2021-06-16 18:36:34 +00:00
|
|
|
source={`/api/${UserApi.photoURL}/${el.username}`}
|
2021-04-28 10:28:39 +00:00
|
|
|
userName={el.name ? el.name : el.username}
|
2021-01-12 01:22:31 +00:00
|
|
|
/>
|
|
|
|
|
))}
|
2020-12-10 08:07:48 +00:00
|
|
|
{userRoles.length > 5 ? (
|
2020-11-11 13:12:05 +00:00
|
|
|
<ProfileImage
|
|
|
|
|
className="org-share-user-icons"
|
2020-12-10 08:07:48 +00:00
|
|
|
commonName={`+${userRoles.length - 5}`}
|
2020-11-12 09:31:51 +00:00
|
|
|
/>
|
|
|
|
|
) : null}
|
2020-11-11 13:12:05 +00:00
|
|
|
</UserImageContainer>
|
|
|
|
|
<FormDialogComponent
|
2021-04-28 10:28:39 +00:00
|
|
|
Form={OrgInviteUsersForm}
|
|
|
|
|
canOutsideClickClose
|
|
|
|
|
orgId={organization.id}
|
|
|
|
|
title={`Invite Users to ${organization.name}`}
|
2020-11-11 13:12:05 +00:00
|
|
|
trigger={
|
|
|
|
|
<Button
|
|
|
|
|
icon={"share"}
|
|
|
|
|
size={Size.small}
|
2021-04-28 10:28:39 +00:00
|
|
|
text={"Share"}
|
2020-11-11 13:12:05 +00:00
|
|
|
/>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</OrgShareUsers>
|
2020-09-16 11:50:47 +00:00
|
|
|
)}
|
2020-10-19 12:11:14 +00:00
|
|
|
</OrgDropDown>
|
|
|
|
|
<ApplicationCardsWrapper key={organization.id}>
|
|
|
|
|
{isPermitted(
|
|
|
|
|
organization.userPermissions,
|
|
|
|
|
PERMISSION_TYPE.CREATE_APPLICATION,
|
|
|
|
|
) &&
|
|
|
|
|
!isFetchingApplications && (
|
|
|
|
|
<PaddingWrapper>
|
2020-10-31 06:40:51 +00:00
|
|
|
<ApplicationAddCardWrapper
|
|
|
|
|
onClick={() => {
|
|
|
|
|
if (
|
2020-11-12 13:28:12 +00:00
|
|
|
Object.entries(creatingApplicationMap).length === 0 ||
|
|
|
|
|
(creatingApplicationMap &&
|
|
|
|
|
!creatingApplicationMap[organization.id])
|
2020-10-31 06:40:51 +00:00
|
|
|
) {
|
|
|
|
|
createNewApplication(
|
|
|
|
|
getNextEntityName(
|
|
|
|
|
"Untitled application ",
|
|
|
|
|
applications.map((el: any) => el.name),
|
|
|
|
|
),
|
|
|
|
|
organization.id,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{creatingApplicationMap &&
|
|
|
|
|
creatingApplicationMap[organization.id] ? (
|
|
|
|
|
<Spinner size={IconSize.XXXL} />
|
|
|
|
|
) : (
|
2021-04-28 10:28:39 +00:00
|
|
|
<>
|
2020-10-31 06:40:51 +00:00
|
|
|
<Icon
|
|
|
|
|
className="t--create-app-popup"
|
|
|
|
|
name={"plus"}
|
|
|
|
|
size={IconSize.LARGE}
|
2021-02-11 12:54:00 +00:00
|
|
|
/>
|
2020-10-31 06:40:51 +00:00
|
|
|
<CreateNewLabel
|
|
|
|
|
className="createnew"
|
2021-04-28 10:28:39 +00:00
|
|
|
type={TextType.H4}
|
2020-10-31 06:40:51 +00:00
|
|
|
>
|
|
|
|
|
Create New
|
|
|
|
|
</CreateNewLabel>
|
2021-04-28 10:28:39 +00:00
|
|
|
</>
|
2020-10-31 06:40:51 +00:00
|
|
|
)}
|
|
|
|
|
</ApplicationAddCardWrapper>
|
2020-10-19 12:11:14 +00:00
|
|
|
</PaddingWrapper>
|
|
|
|
|
)}
|
|
|
|
|
{applications.map((application: any) => {
|
|
|
|
|
return (
|
2021-03-02 05:55:45 +00:00
|
|
|
<PaddingWrapper key={application.id}>
|
|
|
|
|
<ApplicationCard
|
|
|
|
|
application={application}
|
|
|
|
|
delete={deleteApplication}
|
|
|
|
|
duplicate={duplicateApplicationDispatch}
|
2021-06-03 06:18:08 +00:00
|
|
|
enableImportExport={enableImportExport}
|
2021-04-28 10:28:39 +00:00
|
|
|
key={application.id}
|
|
|
|
|
update={updateApplicationDispatch}
|
2021-03-02 05:55:45 +00:00
|
|
|
/>
|
|
|
|
|
</PaddingWrapper>
|
2020-10-19 12:11:14 +00:00
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
<PageSectionDivider />
|
|
|
|
|
</ApplicationCardsWrapper>
|
|
|
|
|
</OrgSection>
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<ApplicationContainer className="t--applications-container">
|
|
|
|
|
{organizationsListComponent}
|
2020-09-16 11:50:47 +00:00
|
|
|
<HelpModal page={"Applications"} />
|
2021-02-11 06:36:07 +00:00
|
|
|
<WelcomeHelper />
|
2020-09-16 11:50:47 +00:00
|
|
|
</ApplicationContainer>
|
|
|
|
|
);
|
2021-04-28 10:28:39 +00:00
|
|
|
}
|
2019-11-07 04:59:40 +00:00
|
|
|
type ApplicationProps = {
|
|
|
|
|
applicationList: ApplicationPayload[];
|
|
|
|
|
createApplication: (appName: string) => void;
|
2020-09-16 11:50:47 +00:00
|
|
|
searchApplications: (keyword: string) => void;
|
2020-10-14 10:35:19 +00:00
|
|
|
isCreatingApplication: creatingApplicationMap;
|
2019-11-21 10:52:49 +00:00
|
|
|
isFetchingApplications: boolean;
|
|
|
|
|
createApplicationError?: string;
|
2020-01-27 08:24:58 +00:00
|
|
|
deleteApplication: (id: string) => void;
|
2020-02-03 12:19:10 +00:00
|
|
|
deletingApplication: boolean;
|
2020-09-01 07:16:54 +00:00
|
|
|
duplicatingApplication: boolean;
|
2020-05-27 13:36:06 +00:00
|
|
|
getAllApplication: () => void;
|
2020-06-10 08:29:21 +00:00
|
|
|
userOrgs: any;
|
2020-05-27 13:36:06 +00:00
|
|
|
currentUser?: User;
|
2020-10-19 12:11:14 +00:00
|
|
|
searchKeyword: string | undefined;
|
2019-11-07 04:59:40 +00:00
|
|
|
};
|
2021-06-04 07:48:17 +00:00
|
|
|
|
|
|
|
|
const getIsFromSignup = () => {
|
2021-06-16 15:51:18 +00:00
|
|
|
return window.location?.pathname === SIGNUP_SUCCESS_URL;
|
2021-06-04 07:48:17 +00:00
|
|
|
};
|
2021-06-16 15:51:18 +00:00
|
|
|
|
2020-06-11 11:31:32 +00:00
|
|
|
class Applications extends Component<
|
|
|
|
|
ApplicationProps,
|
2021-06-04 07:48:17 +00:00
|
|
|
{ selectedOrgId: string; showOnboardingForm: boolean }
|
2020-06-11 11:31:32 +00:00
|
|
|
> {
|
|
|
|
|
constructor(props: ApplicationProps) {
|
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
|
selectedOrgId: "",
|
2021-06-04 07:48:17 +00:00
|
|
|
showOnboardingForm: false,
|
2020-06-11 11:31:32 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-07 04:59:40 +00:00
|
|
|
componentDidMount() {
|
2020-09-28 06:29:41 +00:00
|
|
|
PerformanceTracker.stopTracking(PerformanceTransactionName.LOGIN_CLICK);
|
|
|
|
|
PerformanceTracker.stopTracking(PerformanceTransactionName.SIGN_UP);
|
2021-06-16 15:51:18 +00:00
|
|
|
const isFromSignUp = getIsFromSignup();
|
2021-08-20 07:30:36 +00:00
|
|
|
if (isFromSignUp) {
|
2021-06-28 07:38:44 +00:00
|
|
|
this.redirectUsingQueryParam();
|
|
|
|
|
}
|
2021-08-20 07:30:36 +00:00
|
|
|
this.props.getAllApplication();
|
|
|
|
|
}
|
2021-06-28 07:38:44 +00:00
|
|
|
|
|
|
|
|
redirectUsingQueryParam = () => {
|
|
|
|
|
const urlObject = new URL(window.location.href);
|
|
|
|
|
const redirectUrl = urlObject?.searchParams.get("redirectUrl");
|
|
|
|
|
if (redirectUrl) {
|
|
|
|
|
try {
|
2021-07-29 08:49:46 +00:00
|
|
|
if (getIsSafeRedirectURL(redirectUrl)) {
|
|
|
|
|
window.location.replace(redirectUrl);
|
|
|
|
|
}
|
2021-06-28 07:38:44 +00:00
|
|
|
} catch (e) {
|
|
|
|
|
console.error("Error handling the redirect url");
|
2021-06-16 15:51:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
2021-06-28 07:38:44 +00:00
|
|
|
};
|
|
|
|
|
|
2019-11-07 04:59:40 +00:00
|
|
|
public render() {
|
|
|
|
|
return (
|
2019-12-23 12:16:33 +00:00
|
|
|
<PageWrapper displayName="Applications">
|
2021-08-20 07:30:36 +00:00
|
|
|
<ProductUpdatesModal />
|
|
|
|
|
<LeftPane />
|
|
|
|
|
<SubHeader
|
|
|
|
|
search={{
|
|
|
|
|
placeholder: "Search for apps...",
|
|
|
|
|
queryFn: this.props.searchApplications,
|
|
|
|
|
defaultValue: this.props.searchKeyword,
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
<ApplicationsSection searchKeyword={this.props.searchKeyword} />
|
2019-12-23 12:16:33 +00:00
|
|
|
</PageWrapper>
|
2019-11-07 04:59:40 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-01 07:16:54 +00:00
|
|
|
|
2019-11-07 04:59:40 +00:00
|
|
|
const mapStateToProps = (state: AppState) => ({
|
|
|
|
|
applicationList: getApplicationList(state),
|
|
|
|
|
isFetchingApplications: getIsFetchingApplications(state),
|
|
|
|
|
isCreatingApplication: getIsCreatingApplication(state),
|
2019-11-21 10:52:49 +00:00
|
|
|
createApplicationError: getCreateApplicationError(state),
|
2020-02-03 12:19:10 +00:00
|
|
|
deletingApplication: getIsDeletingApplication(state),
|
2020-09-01 07:16:54 +00:00
|
|
|
duplicatingApplication: getIsDuplicatingApplication(state),
|
2020-06-10 08:29:21 +00:00
|
|
|
userOrgs: getUserApplicationsOrgsList(state),
|
2020-05-27 13:36:06 +00:00
|
|
|
currentUser: getCurrentUser(state),
|
2020-10-19 12:11:14 +00:00
|
|
|
searchKeyword: getApplicationSearchKeyword(state),
|
2019-11-07 04:59:40 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const mapDispatchToProps = (dispatch: any) => ({
|
2020-05-27 13:36:06 +00:00
|
|
|
getAllApplication: () =>
|
|
|
|
|
dispatch({ type: ReduxActionTypes.GET_ALL_APPLICATION_INIT }),
|
2019-11-07 04:59:40 +00:00
|
|
|
createApplication: (appName: string) => {
|
|
|
|
|
dispatch({
|
|
|
|
|
type: ReduxActionTypes.CREATE_APPLICATION_INIT,
|
|
|
|
|
payload: {
|
|
|
|
|
name: appName,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
},
|
2020-01-20 08:07:00 +00:00
|
|
|
searchApplications: (keyword: string) => {
|
|
|
|
|
dispatch({
|
|
|
|
|
type: ReduxActionTypes.SEARCH_APPLICATIONS,
|
|
|
|
|
payload: {
|
|
|
|
|
keyword,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
},
|
2019-11-07 04:59:40 +00:00
|
|
|
});
|
|
|
|
|
|
2019-11-22 14:02:55 +00:00
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(Applications);
|