From 4e8f00b1fe8bc148cf16d37c38fac0e3b42bedde Mon Sep 17 00:00:00 2001
From: June Zhao <60997220+junjun107@users.noreply.github.com>
Date: Sat, 17 Aug 2024 16:44:18 -0700
Subject: [PATCH 1/5] implement global enable feature functionality (#2181)
* implement global enable feature functionality
* refactor for easy read
* check feature data before rendering
---
client/package-lock.json | 4 +-
client/src/components/Admin/Features.js | 424 ++++++++++--------
client/src/hooks/useFeatureFlag.js | 16 +-
client/src/services/feature-service.js | 6 +
server/app/controllers/feature-controller.ts | 21 +-
server/app/routes/feature-router.ts | 5 +
server/app/services/feature-service.ts | 28 +-
.../app/validation-schema/feature-schema.ts | 3 +
...174_add-isEnabled-to-feature-flag-table.js | 17 +
server/types/feature-types.ts | 1 +
10 files changed, 322 insertions(+), 203 deletions(-)
create mode 100644 server/migrations/1718762357174_add-isEnabled-to-feature-flag-table.js
diff --git a/client/package-lock.json b/client/package-lock.json
index de2816ad5..bbb59dadd 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "foodoasis-client",
- "version": "1.0.82",
+ "version": "1.0.83",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "foodoasis-client",
- "version": "1.0.82",
+ "version": "1.0.83",
"license": "GPL-2.0",
"dependencies": {
"@craco/craco": "^7.0.0",
diff --git a/client/src/components/Admin/Features.js b/client/src/components/Admin/Features.js
index b94de9079..677a92778 100644
--- a/client/src/components/Admin/Features.js
+++ b/client/src/components/Admin/Features.js
@@ -17,6 +17,8 @@ import {
TableRow,
TextField,
Typography,
+ FormControlLabel,
+ Switch,
} from "@mui/material";
import {
Delete as DeleteIcon,
@@ -28,6 +30,7 @@ import { useFormik } from "formik";
import React, { useEffect, useState } from "react";
import * as Yup from "yup";
import { useFeatureToLogin } from "../../hooks/useFeatureToLogin";
+import { useFeatures } from "../../hooks/useFeatures";
import * as accountService from "../../services/account-service";
import * as featureService from "../../services/feature-service";
import * as featureToLoginService from "../../services/feature-to-login-service";
@@ -48,21 +51,33 @@ const Features = () => {
refetch: featureToLoginRefetch,
} = useFeatureToLogin();
+ const { data: featuresData, loading: featuresLoading } = useFeatures();
+
useEffect(() => {
- const newRows = featureToLoginData.map((feature) => ({
- featureId: feature.feature_id,
- name: feature.feature_name,
- featureToLoginId: feature.ftl_id,
- history: feature.users.map((user) => ({
- loginId: user.login_id,
- firstName: user.first_name,
- lastName: user.last_name,
- email: user.email,
- featureToLoginId: user.featureToLoginId || feature.ftl_id,
- })),
- }));
- setRows(newRows);
- }, [featureToLoginData]);
+ if (featuresData && featureToLoginData) {
+ const newRows = featuresData.map((feature) => {
+ const featureToLogin = featureToLoginData.find(
+ (ftl) => ftl.feature_id === feature.id
+ );
+ return {
+ featureId: feature.id,
+ name: feature.name,
+ is_enabled: feature.is_enabled,
+ history: featureToLogin
+ ? featureToLogin.users.map((user) => ({
+ loginId: user.login_id,
+ firstName: user.first_name,
+ lastName: user.last_name,
+ email: user.email,
+ featureToLoginId:
+ user.featureToLoginId || featureToLogin.ftl_id,
+ }))
+ : [],
+ };
+ });
+ setRows(newRows);
+ }
+ }, [featureToLoginData, featuresData]);
const handleModalClose = () => {
setFeatureModalOpen(false);
@@ -84,6 +99,18 @@ const Features = () => {
setSelectedRowId(rowName);
}
};
+ const handleIsEnabled = async (featureId, isEnabled) => {
+ try {
+ await featureService.update(featureId, { is_enabled: isEnabled });
+ setRows((prevRows) =>
+ prevRows.map((row) =>
+ row.featureId === featureId ? { ...row, is_enabled: isEnabled } : row
+ )
+ );
+ } catch (error) {
+ console.error("Error updating feature:", error);
+ }
+ };
const featureFormik = useFormik({
initialValues: {
name: "",
@@ -143,6 +170,23 @@ const Features = () => {
setRowsPerPage(+event.target.value);
setPage(0);
};
+
+ if (featuresLoading || featureToLoginLoading || !featuresData) {
+ return (
+
+
+
+ );
+ }
return (
{
Add New Feature
- {featureToLoginLoading ? (
-
-
-
- ) : (
-
-
-
-
-
- Feature ID
- Feature Name
-
-
-
-
- {rows.map((row, index) => (
-
- handleRowClick(row.name)}
- sx={{
- "& > *": {
- borderBottom: "unset",
- cursor: "pointer",
- backgroundColor: "#efefef",
- },
- }}
- hover
- >
-
- handleRowClick(row.name)}
- >
- {selectedRowId === row.name ? (
-
- ) : (
-
- )}
-
-
-
- {row.featureId}
-
-
+
+
+
+
+ Feature ID
+ Feature Name
+
+
+
+
+ {rows.map((row, index) => (
+
+ handleRowClick(row.name)}
+ sx={{
+ "& > *": {
+ borderBottom: "unset",
+ cursor: "pointer",
+ backgroundColor: "#efefef",
+ },
+ }}
+ hover
+ >
+
+ handleRowClick(row.name)}
>
- {row.name}
-
-
- {
- try {
- await featureService.remove(row.featureId);
- featureToLoginRefetch();
- } catch (error) {
- console.error(
- "Failed to remove user from feature:",
- error
- );
+ {selectedRowId === row.name ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ {row.featureId}
+
+
+ {row.name}
+
+
+
+ handleIsEnabled(row.featureId, e.target.checked)
}
- }}
- >
-
-
-
-
-
-
+ }
+ label={
+
+ Globally Enable
+
+ }
+ />
+
+
+ {
+ try {
+ await featureService.remove(row.featureId);
+ featureToLoginRefetch();
+ } catch (error) {
+ console.error(
+ "Failed to remove user from feature:",
+ error
+ );
+ }
+ }}
+ >
+
+
+
+
+
+
+
-
-
-
-
- Users
-
+
+
+
+ Users
+
-
- handleUserModalOpen(row.name, row.featureId)
- }
- >
-
-
-
+
+ handleUserModalOpen(row.name, row.featureId)
+ }
+ >
+
+
+
-
-
-
- Login ID
- First Name
- Last Name
- Email
+
+
+
+ Login ID
+ First Name
+ Last Name
+ Email
+
+
+
+ {row.history.map((historyRow) => (
+
+
+ {historyRow.loginId}
+
+
+ {historyRow.firstName}
+
+
+ {historyRow.lastName}
+
+
+ {historyRow.email}
+
+
+ {row.history.length > 0 && (
+ {
+ try {
+ await featureToLoginService.removeUserFromFeature(
+ historyRow.featureToLoginId
+ );
+ featureToLoginRefetch();
+ } catch (error) {
+ console.error(
+ "Failed to remove user from feature:",
+ error
+ );
+ }
+ }}
+ >
+
+
+ )}
+
-
-
- {row.history.map((historyRow) => (
-
-
- {historyRow.loginId}
-
-
- {historyRow.firstName}
-
-
- {historyRow.lastName}
-
-
- {historyRow.email}
-
-
- {row.history.length > 0 && (
- {
- try {
- await featureToLoginService.removeUserFromFeature(
- historyRow.featureToLoginId
- );
- featureToLoginRefetch();
- } catch (error) {
- console.error(
- "Failed to remove user from feature:",
- error
- );
- }
- }}
- >
-
-
- )}
-
-
- ))}
-
-
-
-
-
-
-
- ))}
-
-
-
- )}
+ ))}
+
+
+
+
+
+
+
+ ))}
+
+
+