Skip to content

Commit

Permalink
Merge pull request #223 from stellar/release/3.3.0
Browse files Browse the repository at this point in the history
Release `3.3.0` to `main`
  • Loading branch information
marwen-abid authored Jan 31, 2025
2 parents d06b241 + e2d760f commit 769b698
Show file tree
Hide file tree
Showing 13 changed files with 125 additions and 64 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

> Place unreleased changes here.
## [3.3.0](https://github.com/stellar/stellar-disbursement-platform-frontend/releases/tag/3.3.0) ([diff](https://github.com/stellar/stellar-disbursement-platform-frontend/compare/3.2.0...3.3.0))

> [!WARNING] This version is only compatible with the
> [stellar/stellar-disbursement-platform-backend] version `3.3.0`.
### Added

- Feature that scrolls the screen to top when a notification is displayed.
[#187](https://github.com/stellar/stellar-disbursement-platform-frontend/pull/187)
- Feature where the tenant name is fetched from the local storage first and then
it's only inferred from the domain if `DISABLE_TENANT_PREFIL_FROM_DOMAIN` is
NOT set to true.
[#221](https://github.com/stellar/stellar-disbursement-platform-frontend/pull/221)

## [3.2.0](https://github.com/stellar/stellar-disbursement-platform-frontend/releases/tag/3.2.0) ([diff](https://github.com/stellar/stellar-disbursement-platform-frontend/compare/3.1.0...3.2.0))

> [!WARNING] This version is only compatible with the
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,15 @@ Set the value to true to avoid fetching the file if the Window ENV is not used.
> Set `REACT_APP_DISABLE_WINDOW_ENV=true` to avoid fetching the
> `public/settings/env-config.js` file if the `window._env_` is not used.
<!-- prettier-ignore -->
> [!NOTE]
> Set `REACT_APP_DISABLE_TENANT_PREFIL_FROM_DOMAIN=true` to skip prefilling the hostname from the domain.
For example:

```
REACT_APP_DISABLE_WINDOW_ENV=true
REACT_APP_DISABLE_TENANT_PREFIL_FROM_DOMAIN=false
REACT_APP_API_URL=https://localhost:8000
REACT_APP_STELLAR_EXPERT_URL=https://stellar.expert/explorer/testnet
REACT_APP_HORIZON_URL=https://horizon-testnet.stellar.org
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "stellar-disbursement-platform-frontend",
"version": "3.2.0",
"version": "3.3.0",
"license": "Apache-2.0",
"engines": {
"node": ">=20.x"
Expand Down
42 changes: 22 additions & 20 deletions src/components/NotificationWithButtons/index.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
import React from "react";
import { Link, Notification } from "@stellar/design-system";
import "./styles.scss";

interface NotificationWithButtonsProps {
variant: "primary" | "secondary" | "success" | "error" | "warning";
title: string;
icon?: React.ReactNode;
buttons: {
buttons?: {
label: string;
onClick: () => void;
}[];
children: string | React.ReactNode;
}

export const NotificationWithButtons: React.FC<
export const NotificationWithButtons = React.forwardRef<
HTMLDivElement,
NotificationWithButtonsProps
> = ({
variant,
title,
icon,
buttons,
children,
}: NotificationWithButtonsProps) => {
>(({ variant, title, icon, buttons, children }, ref) => {
return (
<Notification variant={variant} title={title} icon={icon}>
<div>{children}</div>
<div ref={ref} className="NotificationWithButtons__wrapper">
<Notification variant={variant} title={title} icon={icon}>
<div>{children}</div>

<div className="Notification__buttons">
{buttons.map((b) => (
<Link role="button" onClick={b.onClick} key={`btn-${b.label}`}>
{b.label}
</Link>
))}
</div>
</Notification>
{buttons && (
<div className="Notification__buttons">
{buttons.map((b) => (
<Link role="button" onClick={b.onClick} key={`btn-${b.label}`}>
{b.label}
</Link>
))}
</div>
)}
</Notification>
</div>
);
};
});

NotificationWithButtons.displayName = "NotificationWithButtons";
5 changes: 5 additions & 0 deletions src/constants/envVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ declare global {
// `new DefinePlugin({"process.env": ...})` in the webpack config ad well.
interface Window {
_env_: {
DISABLE_TENANT_PREFIL_FROM_DOMAIN: string;
API_URL: string;
STELLAR_EXPERT_URL: string;
HORIZON_URL: string;
Expand Down Expand Up @@ -39,6 +40,9 @@ const generateEnvConfig = async () => {

return {
API_URL: process?.env?.REACT_APP_API_URL || window._env_.API_URL,
DISABLE_TENANT_PREFIL_FROM_DOMAIN:
process?.env?.REACT_APP_DISABLE_TENANT_PREFIL_FROM_DOMAIN ||
window._env_.DISABLE_TENANT_PREFIL_FROM_DOMAIN,
STELLAR_EXPERT_URL:
process?.env?.REACT_APP_STELLAR_EXPERT_URL ||
window._env_.STELLAR_EXPERT_URL,
Expand Down Expand Up @@ -67,6 +71,7 @@ const generateEnvConfig = async () => {
};

export const {
DISABLE_TENANT_PREFIL_FROM_DOMAIN,
API_URL,
STELLAR_EXPERT_URL,
HORIZON_URL,
Expand Down
1 change: 1 addition & 0 deletions src/constants/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const SESSION_EXPIRED = "SESSION EXPIRED";
export const SESSION_EXPIRED_EVENT = "sdp_session_expired_event";
export const LOCAL_STORAGE_SESSION_TOKEN = "sdp_session";
export const LOCAL_STORAGE_DEVICE_ID = "sdp_deviceID";
export const LOCAL_STORAGE_TENANT_NAME = "sdp_tenant_name";
export const UI_STATUS_DISBURSEMENT = "STARTED,PAUSED,COMPLETED";
export const UI_STATUS_DISBURSEMENT_DRAFT = "DRAFT,READY";
export const ORG_NAME_INFO_TEXT =
Expand Down
14 changes: 12 additions & 2 deletions src/helpers/getSdpTenantName.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
export const getSdpTenantName = (organizationName?: string): string =>
organizationName ?? window.location.hostname.split(".")[0];
import { DISABLE_TENANT_PREFIL_FROM_DOMAIN } from "constants/envVariables";
import { localStorageTenantName } from "helpers/localStorageTenantName";

export const getSdpTenantName = (organizationName?: string): string => {
const orgName = organizationName || localStorageTenantName.get();

if (DISABLE_TENANT_PREFIL_FROM_DOMAIN === "true") {
return orgName || "";
}

return orgName || window.location.hostname.split(".")[0];
};
13 changes: 13 additions & 0 deletions src/helpers/localStorageTenantName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { LOCAL_STORAGE_TENANT_NAME } from "constants/settings";

export const localStorageTenantName = {
get: () => {
return localStorage.getItem(LOCAL_STORAGE_TENANT_NAME);
},
set: (token: string) => {
return localStorage.setItem(LOCAL_STORAGE_TENANT_NAME, token);
},
remove: () => {
return localStorage.removeItem(LOCAL_STORAGE_TENANT_NAME);
},
};
11 changes: 0 additions & 11 deletions src/hooks/useScrollToTop.ts

This file was deleted.

47 changes: 28 additions & 19 deletions src/pages/DisbursementDraftDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useCallback, useEffect, useState } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import {
Badge,
Heading,
Link,
Notification,
Button,
Icon,
Modal,
Expand Down Expand Up @@ -32,16 +31,17 @@ import {

import { Breadcrumbs } from "components/Breadcrumbs";
import { Routes } from "constants/settings";
import { SectionHeader } from "components/SectionHeader";
import { Toast } from "components/Toast";
import { DisbursementButtons } from "components/DisbursementButtons";
import { DisbursementDetails } from "components/DisbursementDetails";
import { DisbursementInviteMessage } from "components/DisbursementInviteMessage";
import { DisbursementInstructions } from "components/DisbursementInstructions";
import { DisbursementButtons } from "components/DisbursementButtons";
import { DisbursementInviteMessage } from "components/DisbursementInviteMessage";
import { ErrorWithExtras } from "components/ErrorWithExtras";
import { NotificationWithButtons } from "components/NotificationWithButtons";
import { SectionHeader } from "components/SectionHeader";
import { Toast } from "components/Toast";
import { csvTotalAmount } from "helpers/csvTotalAmount";

import { DisbursementDraft, DisbursementStep, hasWallet } from "types";
import { csvTotalAmount } from "helpers/csvTotalAmount";

export const DisbursementDraftDetails = () => {
const { id: draftId } = useParams();
Expand Down Expand Up @@ -80,9 +80,16 @@ export const DisbursementDraftDetails = () => {
);
const { allBalances } = useAllBalances();

const notificationRef = useRef<HTMLDivElement | null>(null);
const apiError = disbursementDrafts.errorString;
const isLoading = disbursementDetails.status === "PENDING";

useEffect(() => {
if (!apiError && !isCsvUpdatedSuccess && !isResponseSuccess) return;

notificationRef.current?.scrollIntoView({ behavior: "smooth" });
}, [apiError, isCsvUpdatedSuccess, isResponseSuccess]);

const fetchedDisbursementDraft = disbursementDrafts.items.find(
(p) => p.details.id === draftId,
);
Expand Down Expand Up @@ -208,6 +215,7 @@ export const DisbursementDraftDetails = () => {
};

const handleCsvFileChange = (file?: File) => {
setIsCsvUpdatedSuccess(false);
if (apiError) {
dispatch(clearDisbursementDraftsErrorAction());
}
Expand Down Expand Up @@ -353,7 +361,8 @@ export const DisbursementDraftDetails = () => {
return (
<>
{isResponseSuccess ? (
<Notification
<NotificationWithButtons
ref={notificationRef}
variant="success"
title="New disbursement was successfully created"
>
Expand All @@ -372,7 +381,7 @@ export const DisbursementDraftDetails = () => {
Dismiss
</Link>
</div>
</Notification>
</NotificationWithButtons>
) : null}

<form className="DisbursementForm">
Expand All @@ -398,23 +407,22 @@ export const DisbursementDraftDetails = () => {
return (
<>
{isCsvUpdatedSuccess ? (
<Notification variant="success" title="CSV updated">
<NotificationWithButtons
ref={notificationRef}
variant="success"
title="CSV updated"
>
<div>
Your file was updated successfully. Make sure to confirm your
disbursement to start it.
</div>

<div className="Notification__buttons">
<Link
role="button"
onClick={() => {
setIsCsvUpdatedSuccess(false);
}}
>
<Link role="button" onClick={() => setIsCsvUpdatedSuccess(false)}>
Dismiss
</Link>
</div>
</Notification>
</NotificationWithButtons>
) : null}
<form onSubmit={handleSubmitDisbursement} className="DisbursementForm">
<DisbursementDetails
Expand Down Expand Up @@ -487,7 +495,8 @@ export const DisbursementDraftDetails = () => {
</SectionHeader>

{apiError ? (
<Notification
<NotificationWithButtons
ref={notificationRef}
variant="error"
title={
disbursementDrafts.actionType === "submit"
Expand All @@ -501,7 +510,7 @@ export const DisbursementDraftDetails = () => {
extras: disbursementDrafts.errorExtras,
}}
/>
</Notification>
</NotificationWithButtons>
) : null}

{renderContent()}
Expand Down
24 changes: 14 additions & 10 deletions src/pages/DisbursementsNew.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import { useEffect, useState } from "react";
import {
Badge,
Card,
Heading,
Notification,
Title,
} from "@stellar/design-system";
import { useEffect, useRef, useState } from "react";
import { Badge, Card, Heading, Title } from "@stellar/design-system";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import { BigNumber } from "bignumber.js";
Expand Down Expand Up @@ -53,6 +47,7 @@ export const DisbursementsNew = () => {
const [isSavedDraftMessageVisible, setIsSavedDraftMessageVisible] =
useState(false);
const [isResponseSuccess, setIsResponseSuccess] = useState<boolean>(false);
const notificationRef = useRef<HTMLDivElement | null>(null);

const isDraftEnabled = isDetailsValid;
const isReviewEnabled = isDraftEnabled && Boolean(csvFile);
Expand All @@ -63,6 +58,12 @@ export const DisbursementsNew = () => {
const apiError =
disbursementDrafts.status === "ERROR" && disbursementDrafts.errorString;

useEffect(() => {
if (!apiError && !isSavedDraftMessageVisible && !isResponseSuccess) return;

notificationRef.current?.scrollIntoView({ behavior: "smooth" });
}, [isSavedDraftMessageVisible, apiError, isResponseSuccess]);

useEffect(() => {
if (
disbursementDrafts.newDraftId &&
Expand Down Expand Up @@ -262,6 +263,7 @@ export const DisbursementsNew = () => {
<>
{isResponseSuccess ? (
<NotificationWithButtons
ref={notificationRef}
variant="success"
title="New disbursement was successfully created"
buttons={[
Expand Down Expand Up @@ -389,6 +391,7 @@ export const DisbursementsNew = () => {

{isSavedDraftMessageVisible ? (
<NotificationWithButtons
ref={notificationRef}
variant="success"
title="Draft saved"
buttons={[
Expand All @@ -409,7 +412,8 @@ export const DisbursementsNew = () => {
) : null}

{apiError ? (
<Notification
<NotificationWithButtons
ref={notificationRef}
variant="error"
title={
disbursementDrafts.actionType === "submit"
Expand All @@ -423,7 +427,7 @@ export const DisbursementsNew = () => {
extras: disbursementDrafts.errorExtras,
}}
/>
</Notification>
</NotificationWithButtons>
) : null}

{renderCurrentStep()}
Expand Down
Loading

0 comments on commit 769b698

Please sign in to comment.