Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Go to Console link from root organization actions and show a URL instead #7490

Merged
merged 7 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/fast-nails-nail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@wso2is/admin.tenants.v1": patch
"@wso2is/react-components": patch
"@wso2is/i18n": patch
---

Remove `Go to Console` link from root organization actions and show a URL instead

**Reason**: There are issues in having a `Go to Console` link and we can't properly workaround this without first resolving https://github.com/wso2/product-is/issues/22615
15 changes: 1 addition & 14 deletions features/admin.tenants.v1/components/tenant-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import Stack from "@oxygen-ui/react/Stack";
import Tooltip from "@oxygen-ui/react/Tooltip";
import Typography from "@oxygen-ui/react/Typography/Typography";
import {
ArrowUpRightFromSquareIcon,
BanIcon,
CircleCheckFilledIcon,
EllipsisVerticalIcon,
Expand Down Expand Up @@ -77,7 +76,7 @@ const TenantCard: FunctionComponent<TenantCardProps> = ({ isLoading, tenant }: T
);
});

const { deleteTenant, disableTenant, enableTenant, navigateToTenantConsole } = useTenants();
const { deleteTenant, disableTenant, enableTenant } = useTenants();

const [ anchorEl, setAnchorEl ] = useState<null | HTMLElement>(null);

Expand Down Expand Up @@ -202,18 +201,6 @@ const TenantCard: FunctionComponent<TenantCardProps> = ({ isLoading, tenant }: T
onClose={ handleClose }
className="tenant-card-footer-dropdown"
>
<MenuItem
className="tenant-card-footer-dropdown-item"
onClick={ () => {
navigateToTenantConsole(tenant);
handleClose();
} }
>
<ListItemIcon>
<ArrowUpRightFromSquareIcon />
</ListItemIcon>
<ListItemText>{ t("tenants:listing.item.actions.goToConsole.label") }</ListItemText>
</MenuItem>
<MenuItem
className={ classNames("tenant-card-footer-dropdown-item", {
error: tenant?.lifecycleStatus?.activated,
Expand Down
6 changes: 0 additions & 6 deletions features/admin.tenants.v1/context/tenant-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ export interface TenantContextProps {
* Function to mutate the tenant list.
*/
mutateTenantList: () => void;
/**
* Navigate to the tenant console.
* @param tenant - Tenant to navigate to.
*/
navigateToTenantConsole: (tenant: Tenant) => void;
/**
* The search query.
*/
Expand Down Expand Up @@ -96,7 +91,6 @@ const TenantContext: Context<TenantContextProps> = createContext<null | TenantCo
isInitialRenderingComplete: false,
isTenantListLoading: false,
mutateTenantList: () => null,
navigateToTenantConsole: () => null,
searchQuery: "",
searchQueryClearTrigger: false,
setSearchQuery: () => null,
Expand Down
52 changes: 52 additions & 0 deletions features/admin.tenants.v1/hooks/use-tenant-console-url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { AppState } from "@wso2is/admin.core.v1/store";
import { useSelector } from "react-redux";
import { Tenant } from "../models/tenants";

/**
* Hook to generate the console URL for a given tenant.
*
* This hook generates the console URL for a specified tenant by replacing the
* tenant domain in the client host URL. It uses the `clientHost` value from
* the Redux store and replaces the existing tenant domain with the provided
* tenant's domain.
*
* @param tenant - The tenant object containing the domain to be used in the URL.
* @returns The console URL for the specified tenant, or `undefined` if the tenant domain is not provided.
*
* @example
* ```tsx
* const tenant: Tenant = { domain: "example.com" };
* const consoleURL = useTenantConsoleURL(tenant);
* console.log(consoleURL); // Outputs the console URL for the specified tenant
* ```
*/
const useTenantConsoleURL = (tenant: Tenant): string | undefined => {
const clientHost: string = useSelector((state: AppState) => state.config?.deployment?.clientHost);
const tenantPrefix: string = useSelector((state: AppState) => state.config?.deployment?.tenantPrefix);

if (!tenant?.domain) {
return undefined;
}

return clientHost.replace(new RegExp(`/${tenantPrefix}/[^/]+/`), `/${tenantPrefix}/${tenant.domain}/`);
};

export default useTenantConsoleURL;
35 changes: 35 additions & 0 deletions features/admin.tenants.v1/pages/edit-tenant-page.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,39 @@
}
}
}

.console-url-copy-field {
.MuiInputBase-root {
min-width: 400px;

&.Mui-readOnly {
cursor: default;
background-color: #e9ecef!important;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we use a SCSS variable for the color?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a temporarily thing that needs to be fixed with Oxygen UI.
We should not encourage to re-use a variable. So, lets link and issue here instead.

}
}
}
}

@media (min-width: 675px) {
.tenant-edit-page {
.console-url-copy-field {
display: flex;
flex-direction: row;
align-content: center;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
gap: 15px;
}
}
}

@media (max-width: 675px) {
.tenant-edit-page {
.console-url-copy-field {
.MuiInputBase-root {
min-width: auto;
}
}
}
}
51 changes: 48 additions & 3 deletions features/admin.tenants.v1/pages/edit-tenant-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,25 @@
*/

import Avatar from "@oxygen-ui/react/Avatar";
import Box from "@oxygen-ui/react/Box";
import IconButton from "@oxygen-ui/react/IconButton";
import TextField from "@oxygen-ui/react/TextField";
import Tooltip from "@oxygen-ui/react/Tooltip";
import Typography from "@oxygen-ui/react/Typography";
import { CopyIcon } from "@oxygen-ui/react-icons";
import { AppConstants } from "@wso2is/admin.core.v1/constants/app-constants";
import { history } from "@wso2is/admin.core.v1/helpers/history";
import { IdentifiableComponentInterface } from "@wso2is/core/models";
import { PageLayout } from "@wso2is/react-components";
import { CommonUtils } from "@wso2is/core/utils";
import { Hint, PageLayout } from "@wso2is/react-components";
import classNames from "classnames";
import moment from "moment";
import React, { FunctionComponent, ReactElement, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { Trans, useTranslation } from "react-i18next";
import useGetTenant from "../api/use-get-tenant";
import useGetTenantOwner from "../api/use-get-tenant-owner";
import EditTenant from "../components/edit-tenant/edit-tenant";
import useTenantConsoleURL from "../hooks/use-tenant-console-url";
import { Tenant, TenantOwner } from "../models/tenants";
import TenantProvider from "../providers/tenant-provider";
import "./edit-tenant-page.scss";
Expand Down Expand Up @@ -64,6 +70,7 @@ const EditTenantPage: FunctionComponent<EditTenantPageProps> = ({
tenant?.owners[0]?.id,
!!tenant
);
const consoleURL: string | undefined = useTenantConsoleURL(tenant);

/**
* Merges the tenant and tenant owner data.
Expand Down Expand Up @@ -100,6 +107,7 @@ const EditTenantPage: FunctionComponent<EditTenantPageProps> = ({
} }
>
<PageLayout
legacyGrid={ false }
pageTitle="Edit Root Organizations"
title={
(<div className="tenant-status">
Expand Down Expand Up @@ -144,6 +152,44 @@ const EditTenantPage: FunctionComponent<EditTenantPageProps> = ({
} }
className="tenant-edit-page"
bottomMargin={ false }
action={
(<TextField
label={
(<Box>
<span>{ t("tenants:edit.consoleURL.label") }</span>
<Hint popup>
<Trans i18nKey="tenants:edit.consoleURL.hint" values={ { domain: tenant?.domain } }>
If you try to login to <strong>{ tenant?.domain }</strong> organization&apos;s
Console using the same browser, you will have to log out from this active
session first.
</Trans>
</Hint>
</Box>)
}
id="filled-start-adornment"
InputProps={ {
endAdornment: (
<Tooltip title="Copy">
<div>
<IconButton
aria-label="Reset field to default"
className="reset-field-to-default-adornment"
onClick={ async () => {
await CommonUtils.copyTextToClipboard(consoleURL);
} }
edge="end"
>
<CopyIcon size={ 12 } />
</IconButton>
</div>
</Tooltip>
),
readOnly: true
} }
value={ consoleURL }
className="console-url-copy-field"
/>)
}
>
<EditTenant tenant={ mergedTenant } />
</PageLayout>
Expand All @@ -152,4 +198,3 @@ const EditTenantPage: FunctionComponent<EditTenantPageProps> = ({
};

export default EditTenantPage;
history;
70 changes: 2 additions & 68 deletions features/admin.tenants.v1/providers/tenant-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,13 @@
* under the License.
*/

import { useAuthContext } from "@asgardeo/auth-react";
import { AppConstants } from "@wso2is/admin.core.v1/constants/app-constants";
import { UIConstants } from "@wso2is/admin.core.v1/constants/ui-constants";
import { history } from "@wso2is/admin.core.v1/helpers/history";
import { AppState } from "@wso2is/admin.core.v1/store";
import { AlertLevels } from "@wso2is/core/models";
import { addAlert } from "@wso2is/core/store";
import { ConfirmationModal } from "@wso2is/react-components";
import React, { PropsWithChildren, ReactElement, useEffect, useState } from "react";
import { Trans, useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { useTranslation } from "react-i18next";
import { useDispatch } from "react-redux";
import { Dispatch } from "redux";
import deleteTenantMetadata from "../api/delete-tenant-metadata";
import updateTenantActivationStatus from "../api/update-tenant-activation-status";
Expand Down Expand Up @@ -81,20 +77,13 @@ const TenantProvider = ({
}: PropsWithChildren<TenantProviderProps>): ReactElement => {
const { t } = useTranslation();
const dispatch: Dispatch = useDispatch();
const { updateConfig } = useAuthContext();

const clientHost: string = useSelector((state: AppState) => state.config?.deployment?.clientHost);

const [ isInitialRenderingComplete, setIsInitialRenderingComplete ] = useState<boolean>(false);
const [ tenantListLimit, setTenantListLimit ] = useState<number>(UIConstants.DEFAULT_RESOURCE_GRID_ITEM_LIMIT);
const [ showDeleteConfirmationModal, setShowDeleteConfirmationModal ] = useState<boolean>(false);
const [ showDisableConfirmationModal, setShowDisableConfirmationModal ] = useState<boolean>(false);
const [ showTenantConsoleNavigationConfirmationModal, setShowTenantConsoleNavigationConfirmationModal ] = useState<
boolean
>(false);
const [ deletingTenant, setDeletingTenant ] = useState<Tenant>(null);
const [ disablingTenant, setDisablingTenant ] = useState<Tenant>(null);
const [ consoleNavigatingTenant, setConsoleNavigatingTenant ] = useState<Tenant>(null);
const [ isTenantDeleteRequestLoading, setIsTenantDeleteRequestLoading ] = useState<boolean>(false);
const [ isTenantStatusUpdateRequestLoading, setIsTenantStatusUpdateRequestLoading ] = useState<boolean>(false);
const [ searchQuery, setSearchQuery ] = useState<string>("");
Expand Down Expand Up @@ -215,22 +204,6 @@ const TenantProvider = ({
});
};

/**
* Handles the tenant console navigation after the user confirms the action.
* @param tenant - Tenant to navigate to.
*/
const handleTenantConsoleNavigation = async (tenant: Tenant): Promise<void> => {
const consoleURL: string = clientHost.replace(/\/t\/[^/]+\//, `/t/${tenant.domain}/`);

setShowTenantConsoleNavigationConfirmationModal(false);

await updateConfig({
signOutRedirectURL: consoleURL
});

history.push(AppConstants.getAppLogoutPath());
};

return (
<TenantContext.Provider
value={ {
Expand All @@ -248,10 +221,6 @@ const TenantProvider = ({
isInitialRenderingComplete,
isTenantListLoading,
mutateTenantList,
navigateToTenantConsole: (tenant: Tenant): void => {
setShowTenantConsoleNavigationConfirmationModal(true);
setConsoleNavigatingTenant(tenant);
},
searchQuery,
searchQueryClearTrigger,
setSearchQuery,
Expand Down Expand Up @@ -322,41 +291,6 @@ const TenantProvider = ({
</ConfirmationModal.Content>
</ConfirmationModal>
) }
{ showTenantConsoleNavigationConfirmationModal && (
<ConfirmationModal
data-componentid="tenant-console-navigation-confirmation-modal"
onClose={ (): void => setShowTenantConsoleNavigationConfirmationModal(false) }
type="warning"
open={ showTenantConsoleNavigationConfirmationModal }
assertionHint={ t("tenants:confirmationModals.navigatingToTenantConsole.assertionHint") }
assertionType="checkbox"
primaryAction={ t("tenants:confirmationModals.navigatingToTenantConsole.primaryAction") }
secondaryAction={ t("tenants:confirmationModals.navigatingToTenantConsole.secondaryAction") }
onSecondaryActionClick={ (): void => setShowTenantConsoleNavigationConfirmationModal(false) }
onPrimaryActionClick={ async () => await handleTenantConsoleNavigation(consoleNavigatingTenant) }
closeOnDimmerClick={ false }
>
<ConfirmationModal.Header data-componentid="tenant-disable-confirmation-modal-header">
{ t("tenants:confirmationModals.navigatingToTenantConsole.header") }
</ConfirmationModal.Header>
<ConfirmationModal.Message
attached
warning
data-componentid="tenant-disable-confirmation-modal-message"
>
{ t("tenants:confirmationModals.navigatingToTenantConsole.message") }
</ConfirmationModal.Message>
<ConfirmationModal.Content data-componentid="tenant-disable-confirmation-modal-content">
<Trans
i18nKey="tenants:confirmationModals.navigatingToTenantConsole.content"
values={ { domain: consoleNavigatingTenant?.domain } }
>
If you continue navigating to the <strong>{ consoleNavigatingTenant?.domain }
</strong>Console, you will be logged out from the current session.
</Trans>
</ConfirmationModal.Content>
</ConfirmationModal>
) }
</TenantContext.Provider>
);
};
Expand Down
Loading
Loading