Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add Environments in the Redux State#1716

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes fromall 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
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -172,6 +172,11 @@ export const ReduxActionTypes = {
/* Enterprise Edition */
FETCH_ENTERPRISE_LICENSE : "FETCH_ENTERPRISE_LICENSE",
SET_ENTERPRISE_LICENSE : "SET_ENTERPRISE_LICENSE",

/* Environments */
FETCH_ENVIRONMENTS : "FETCH_ENVIRONMENTS",
FETCH_ENVIRONMENTS_SUCCESS: "FETCH_ENVIRONMENTS_SUCCESS",
FETCH_ENVIRONMENTS_FAILURE: "FETCH_ENVIRONMENTS_FAILURE",

/* Branding Setting */
FETCH_BRANDING_SETTING : "FETCH_BRANDING_SETTING",
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,28 @@
// client/packages/lowcoder/src/pages/setting/environments/Environments.tsx
import React from "react";
import { Switch, Route, useRouteMatch } from "react-router-dom";
import { EnvironmentProvider } from "./context/EnvironmentContext";
import EnvironmentRoutes from "./routes/EnvironmentRoutes";
import EnvironmentsList from "./EnvironmentsList";

/**
* Top-level Environments component
*Providesthe EnvironmentProviderat the top level
*No longer needsthe EnvironmentProvidersince we use Redux
*/
const Environments: React.FC = () => {
const { path } = useRouteMatch();

return (
<EnvironmentProvider>
<Switch>
{/* Environment list route */}
<Route exact path={path}>
<EnvironmentsList />
</Route>

{/* All routes that need a specific environment */}
<Route path={`${path}/:envId`}>
<EnvironmentRoutes />
</Route>
</Switch>
</EnvironmentProvider>
<Switch>
{/* Environment list route */}
<Route exact path={path}>
<EnvironmentsList />
</Route>

{/* All routes that need a specific environment */}
<Route path={`${path}/:envId`}>
<EnvironmentRoutes />
</Route>
</Switch>
);
};

Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
import React, { useState } from "react";
import React, { useState, useEffect, useRef } from "react";
import { Typography, Alert, Input, Button, Space, Empty, Card, Spin, Row, Col, Tooltip, Badge } from "antd";
import { SearchOutlined, CloudServerOutlined, SyncOutlined, PlusOutlined} from "@ant-design/icons";
import { useHistory } from "react-router-dom";
import { useEnvironmentContext } from "./context/EnvironmentContext";
import { useSelector, useDispatch } from "react-redux";
import { selectEnvironments, selectEnvironmentsLoading, selectEnvironmentsError } from "redux/selectors/enterpriseSelectors";
import { fetchEnvironments } from "redux/reduxActions/enterpriseActions";
import { Environment } from "./types/environment.types";
import EnvironmentsTable from "./components/EnvironmentsTable";
import CreateEnvironmentModal from "./components/CreateEnvironmentModal";
Expand All@@ -17,23 +19,23 @@ const { Title, Text } = Typography;
* Displays a table of environments
*/
const EnvironmentsList: React.FC = () => {
// Use the shared context instead of a local hook
const {
environments,
isLoading,
error,
refreshEnvironments
} = useEnvironmentContext();
// Use Redux state instead of context
const dispatch = useDispatch();
const environments = useSelector(selectEnvironments);
const isLoading = useSelector(selectEnvironmentsLoading);
const error = useSelector(selectEnvironmentsError);

// State for search input
const [searchText, setSearchText] = useState("");
const [isRefreshing, setIsRefreshing] = useState(false);
const [isCreateModalVisible, setIsCreateModalVisible] = useState(false);
const [isCreating, setIsCreating] = useState(false);



// Hook for navigation
const history = useHistory();


// Filter environments based on search text
const filteredEnvironments = environments.filter((env) => {
const searchLower = searchText.toLowerCase();
Expand DownExpand Up@@ -62,18 +64,16 @@ const EnvironmentsList: React.FC = () => {
};

// Handle refresh
const handleRefresh = async () => {
setIsRefreshing(true);
await refreshEnvironments();
setIsRefreshing(false);
const handleRefresh = () => {
dispatch(fetchEnvironments());
};

// Handle create environment
const handleCreateEnvironment = async (environmentData: Partial<Environment>) => {
setIsCreating(true);
try {
await createEnvironment(environmentData);
await refreshEnvironments(); // Refresh the list after creation
dispatch(fetchEnvironments()); // Refresh the list after creation
} catch (error) {
console.error("Failed to create environment:", error);
throw error; // Re-throw to let the modal handle the error display
Expand DownExpand Up@@ -153,7 +153,7 @@ const EnvironmentsList: React.FC = () => {
Create Environment
</Button>
<Button
icon={<SyncOutlined spin={isRefreshing} />}
icon={<SyncOutlined spin={isLoading} />}
onClick={handleRefresh}
loading={isLoading}
type="default"
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,9 +2,10 @@
import React, { useState, useEffect } from 'react';
import { Modal, Form, Select, Checkbox, Button, Spin, Input, Tag, Space, Alert } from 'antd';
import { messageInstance } from 'lowcoder-design/src/components/GlobalInstances';
import { useSelector } from 'react-redux';
import { selectLicensedEnvironments, selectEnvironmentsLoading } from 'redux/selectors/enterpriseSelectors';
import { Environment } from '../types/environment.types';
import { DeployableItemConfig } from '../types/deployable-item.types';
import { useEnvironmentContext } from '../context/EnvironmentContext';
import { getEnvironmentTagColor, formatEnvironmentType } from '../utils/environmentUtils';
import { ExclamationCircleOutlined } from '@ant-design/icons';
import { showFirstCredentialOverwriteConfirm, showSecondCredentialOverwriteConfirm } from './credentialConfirmations';
Expand All@@ -27,7 +28,8 @@ function DeployItemModal({
onSuccess
}: DeployItemModalProps) {
const [form] = Form.useForm();
const { environments, isLoading } = useEnvironmentContext();
const licensedEnvironments = useSelector(selectLicensedEnvironments);
const isLoading = useSelector(selectEnvironmentsLoading);
const [deploying, setDeploying] = useState(false);
const [credentialConfirmationStep, setCredentialConfirmationStep] = useState(0); // 0: not started, 1: first confirmation, 2: confirmed

Expand All@@ -39,8 +41,8 @@ function DeployItemModal({
}, [visible, form]);

// Filter out source environment from target list
const targetEnvironments =environments.filter(
(env: Environment) => env.environmentId !== sourceEnvironment.environmentId && env.isLicensed !== false
const targetEnvironments =licensedEnvironments.filter(
(env: Environment) => env.environmentId !== sourceEnvironment.environmentId
);

// Handle credential checkbox change with double confirmation
Expand DownExpand Up@@ -82,7 +84,7 @@ function DeployItemModal({

try {
const values = await form.validateFields();
const targetEnv =environments.find(env => env.environmentId === values.targetEnvId);
const targetEnv =licensedEnvironments.find(env => env.environmentId === values.targetEnvId);

if (!targetEnv) {
messageInstance.error('Target environment not found');
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,10 +9,11 @@ import React, {
} from "react";
import { messageInstance } from "lowcoder-design/src/components/GlobalInstances";
import { useParams } from "react-router-dom";
import { useDispatch } from "react-redux";
import { fetchEnvironments } from "redux/reduxActions/enterpriseActions";
import { getEnvironmentById, updateEnvironment } from "../services/environments.service";
import { Environment } from "../types/environment.types";
import { useEnvironmentContext } from './EnvironmentContext';


interface SingleEnvironmentContextState {
// Environment data
environment: Environment | null;
Expand DownExpand Up@@ -53,8 +54,8 @@ import React, {
const { envId } = useParams<{ envId: string }>();
const environmentId = propEnvironmentId || envId;

//Access the environments contextto refreshthe list
const{ refreshEnvironments } = useEnvironmentContext();
//Use Redux dispatchto refreshenvironments instead of context
constdispatch = useDispatch();

// State for environment data
const [environment, setEnvironment] = useState<Environment | null>(null);
Expand DownExpand Up@@ -103,18 +104,16 @@ import React, {
messageInstance.success("Environment updated successfully");

// Refresh both the single environment and environments list
await Promise.all([
fetchEnvironment(), // Refresh the current environment
refreshEnvironments() // Refresh the environments list
]);
await fetchEnvironment(); // Refresh the current environment
dispatch(fetchEnvironments()); // Refresh the environments list using Redux

return updatedEnv;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : "Failed to update environment";
messageInstance.error(errorMessage);
throw err;
}
}, [environment, environmentId, fetchEnvironment,refreshEnvironments]);
}, [environment, environmentId, fetchEnvironment,dispatch]);

// Load environment data when the component mounts or environmentId changes
useEffect(() => {
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
import { BrandingConfig, BrandingSettingResponse, EnterpriseLicenseResponse } from "@lowcoder-ee/api/enterpriseApi";
import { createReducer } from "@lowcoder-ee/util/reducerUtils";
import { ReduxAction, ReduxActionTypes } from "constants/reduxActionConstants";

import { Environment } from "pages/setting/environments/types/environment.types";
export interface EnterpriseReduxState {
enterprise: EnterpriseLicenseResponse,
globalBranding?: BrandingConfig,
workspaceBranding?: BrandingConfig,
environments: Environment[],
environmentsLoading: boolean,
environmentsError: string | null,
}

const initialState: EnterpriseReduxState = {
enterprise: {
eeActive: false,
remainingAPICalls: 0,
eeLicenses: [],
}
},
environments: [],
environmentsLoading: false,
environmentsError: null,
};

const enterpriseReducer = createReducer(initialState, {
Expand All@@ -38,6 +44,29 @@ const enterpriseReducer = createReducer(initialState, {
...state,
workspaceBranding: action.payload,
}),

[ReduxActionTypes.FETCH_ENVIRONMENTS]: (
state: EnterpriseReduxState
) => ({
...state,
environmentsLoading: true,
}),
[ReduxActionTypes.FETCH_ENVIRONMENTS_SUCCESS]: (
state: EnterpriseReduxState,
action: ReduxAction<Environment[]>
) => ({
...state,
environments: action.payload,
environmentsLoading: false,
}),
[ReduxActionTypes.FETCH_ENVIRONMENTS_FAILURE]: (
state: EnterpriseReduxState,
action: ReduxAction<string>
) => ({
...state,
environmentsLoading: false,
environmentsError: action.payload,
}),
});

export default enterpriseReducer;
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
import { EnterpriseLicenseResponse, FetchBrandingSettingPayload } from "@lowcoder-ee/api/enterpriseApi";
import { ReduxActionTypes } from "constants/reduxActionConstants";
import { Environment } from "pages/setting/environments/types/environment.types";

export const fetchEnterpriseLicense = () => ({
type: ReduxActionTypes.FETCH_ENTERPRISE_LICENSE,
Expand All@@ -16,3 +17,18 @@ export const fetchBrandingSetting = (payload: FetchBrandingSettingPayload) => {
payload,
};
};

export const fetchEnvironments = () => ({
type: ReduxActionTypes.FETCH_ENVIRONMENTS,
});

export const fetchEnvironmentsSuccess = (environments: Environment[]) => ({
type: ReduxActionTypes.FETCH_ENVIRONMENTS_SUCCESS,
payload: environments,
});

export const fetchEnvironmentsFailure = (error: string) => ({
type: ReduxActionTypes.FETCH_ENVIRONMENTS_FAILURE,
payload: error,
});

16 changes: 15 additions & 1 deletionclient/packages/lowcoder/src/redux/sagas/enterpriseSagas.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
import { call, put, takeLatest } from 'redux-saga/effects';
import { ReduxAction, ReduxActionTypes } from "constants/reduxActionConstants";
import { setEnterpriseLicense } from "redux/reduxActions/enterpriseActions";
import { setEnterpriseLicense, fetchEnvironmentsSuccess, fetchEnvironmentsFailure } from "redux/reduxActions/enterpriseActions";
import { BrandingSettingResponse, EnterpriseLicenseResponse, FetchBrandingSettingPayload, getBranding, getEnterpriseLicense } from "api/enterpriseApi";
import { getEnvironmentsWithLicenseStatus } from "pages/setting/environments/services/environments.service";
import { Environment } from "pages/setting/environments/types/environment.types";

import { AxiosResponse } from 'axios';

function* fetchEnterpriseLicenseSaga(): Generator<any, void, EnterpriseLicenseResponse> {
Expand All@@ -14,6 +17,16 @@ function* fetchEnterpriseLicenseSaga(): Generator<any, void, EnterpriseLicenseRe
}
}

function* fetchEnvironmentsSaga(): Generator<any, void, Environment[]> {
try {
const environments: Environment[] = yield call(getEnvironmentsWithLicenseStatus);
yield put(fetchEnvironmentsSuccess(environments));
} catch (error) {
console.error('Failed to fetch environments:', error);
yield put(fetchEnvironmentsFailure(error as string));
}
}

function* fetchBrandingSettingSaga(action: ReduxAction<FetchBrandingSettingPayload>) {
try {
const response: BrandingSettingResponse = yield getBranding(action.payload.orgId);
Expand DownExpand Up@@ -45,4 +58,5 @@ function* fetchBrandingSettingSaga(action: ReduxAction<FetchBrandingSettingPaylo
export default function* enterpriseSagas() {
yield takeLatest(ReduxActionTypes.FETCH_ENTERPRISE_LICENSE, fetchEnterpriseLicenseSaga);
yield takeLatest(ReduxActionTypes.FETCH_BRANDING_SETTING, fetchBrandingSettingSaga);
yield takeLatest(ReduxActionTypes.FETCH_ENVIRONMENTS, fetchEnvironmentsSaga);
}
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
import { AppState } from "../reducers";


export const selectEnterpriseEditionStatus = (state: AppState) =>
state.ui.enterprise?.enterprise?.eeActive ?? false;

Expand All@@ -25,3 +26,23 @@ export const getGlobalBrandingSetting = (state: AppState) => {
export const getWorkspaceBrandingSetting = (state: AppState) => {
return state.ui.enterprise?.workspaceBranding;
}
// Environment selectors
export const selectEnvironments = (state: AppState) =>
state.ui.enterprise?.environments ?? [];

export const selectEnvironmentsLoading = (state: AppState) =>
state.ui.enterprise?.environmentsLoading ?? false;

export const selectEnvironmentsError = (state: AppState) =>
state.ui.enterprise?.environmentsError ?? null;

export const selectUnlicensedEnvironments = (state: AppState) => {
const environments = state.ui.enterprise?.environments ?? [];
return environments.filter(env => env.isLicensed === false);
};

export const selectLicensedEnvironments = (state: AppState) => {
const environments = state.ui.enterprise?.environments ?? [];
return environments.filter(env => env.isLicensed !== false);
};

View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
import React, { createContext, useContext, useState, useEffect } from 'react';
import { fetchEnterpriseLicense } from 'redux/reduxActions/enterpriseActions';
import { fetchEnterpriseLicense, fetchEnvironments } from 'redux/reduxActions/enterpriseActions';
import { selectEnterpriseEditionStatus } from '@lowcoder-ee/redux/selectors/enterpriseSelectors';
import { useDispatch, useSelector } from 'react-redux';
import { isEEEnvironment } from "util/envUtils";
Expand All@@ -23,6 +23,7 @@ export const EnterpriseProvider: React.FC<ProviderProps> = ({ children }) => {
if (isEEEnvironment()) {
// Fetch the enterprise license only if we're in an EE environment
dispatch(fetchEnterpriseLicense());
dispatch(fetchEnvironments());
} else {
// Set the state to false for non-EE environments
// setEEActiveState(false);
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp