@dexteel/mesf-core 7.12.0 → 7.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "7.12.0"
2
+ ".": "7.13.0"
3
3
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [7.13.0](https://github.com/dexteel/mesf-core-frontend/compare/@dexteel/mesf-core-v7.12.1...@dexteel/mesf-core-v7.13.0) (2026-01-28)
4
+
5
+
6
+ ### Features
7
+
8
+ * **Profiles:** add clone profile functionality ([0279f13](https://github.com/dexteel/mesf-core-frontend/commit/0279f1395cfa8c4bef24c366358cab45c9de21c7))
9
+
10
+ ## [7.12.1](https://github.com/dexteel/mesf-core-frontend/compare/@dexteel/mesf-core-v7.12.0...@dexteel/mesf-core-v7.12.1) (2026-01-27)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **sp-executor:** exclude backend-managed parameters user from UI and execution payload ([4cd1b89](https://github.com/dexteel/mesf-core-frontend/commit/4cd1b89298cf8830ba21bab40e504d62bfc67d5a))
16
+
3
17
  ## [7.12.0](https://github.com/dexteel/mesf-core-frontend/compare/@dexteel/mesf-core-v7.11.2...@dexteel/mesf-core-v7.12.0) (2026-01-22)
4
18
 
5
19
 
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import { Profile } from "../../models/Profile";
3
+ type Props = {
4
+ profile: Profile | null;
5
+ show: boolean;
6
+ onHide: (shouldUpdate: boolean) => void;
7
+ suffixTitle?: string;
8
+ };
9
+ export declare const CloneProfile: ({ profile, show, onHide, suffixTitle }: Props) => React.JSX.Element;
10
+ export {};
@@ -4,9 +4,10 @@ type Props = {
4
4
  setProfileId: Function;
5
5
  setShowDeleteModal: Function;
6
6
  setShowCreateModal: Function;
7
+ setShowCloneModal: Function;
7
8
  setModalProceduresProfile: Function;
8
9
  };
9
- export declare const useProfilesOptionsFunctions: ({ setProfileId, setShowDeleteModal, setShowCreateModal, setModalProceduresProfile, }: Props) => {
10
+ export declare const useProfilesOptionsFunctions: ({ setProfileId, setShowDeleteModal, setShowCreateModal, setShowCloneModal, setModalProceduresProfile, }: Props) => {
10
11
  getMenuOptions: (data: Profile) => MenuOptionType[];
11
12
  };
12
13
  export {};
@@ -12,3 +12,7 @@ export declare const upsertProfileActions: ({ profileId, actions, }: {
12
12
  actions: Action[];
13
13
  }) => Promise<void>;
14
14
  export declare const deleteProfile: (profileId: number) => Promise<void>;
15
+ export declare const cloneProfile: ({ SourceProfileId, NewProfileName, }: {
16
+ SourceProfileId: number;
17
+ NewProfileName: string;
18
+ }) => Promise<void>;
package/dist/index.esm.js CHANGED
@@ -26,6 +26,7 @@ import EditIcon from '@mui/icons-material/Edit';
26
26
  import FindInPageIcon from '@mui/icons-material/FindInPage';
27
27
  import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd';
28
28
  import { ArrowRight, ArrowBackRounded, ArrowForwardRounded, SkipNext, ChevronLeft, ChevronRight, Cloud, Square as Square$1, Timeline, Send, Menu as Menu$1, People, Storage, Group, Assignment, Chat, ViewList, Build, Settings as Settings$2, Code as Code$1, FastRewind, FastForward, ZoomIn, Restore, Lock, Create, Delete, Folder, InsertChart, Search, PlaylistAdd, DragIndicator, Save, AttachFile, CloudUpload, GetApp } from '@mui/icons-material';
29
+ import ContentCopyIcon from '@mui/icons-material/ContentCopy';
29
30
  import FormatListBulletedSharpIcon from '@mui/icons-material/FormatListBulletedSharp';
30
31
  import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
31
32
  import CloseIcon from '@mui/icons-material/Close';
@@ -3372,6 +3373,89 @@ const deleteProfile = (profileId) => __awaiter(void 0, void 0, void 0, function*
3372
3373
  throw new Error(resp.message || "Error when delete profile");
3373
3374
  }
3374
3375
  });
3376
+ // fx clonar profile
3377
+ const cloneProfile = (_a) => __awaiter(void 0, [_a], void 0, function* ({ SourceProfileId, NewProfileName, }) {
3378
+ const apiService = new MESApiService();
3379
+ const parameters = [
3380
+ { name: "SourceProfileId", value: SourceProfileId },
3381
+ { name: "NewProfileName", value: NewProfileName },
3382
+ ];
3383
+ const resp = yield apiService.callV2("[SEC].[CloneProfile]", parameters);
3384
+ if (!resp.ok) {
3385
+ throw new Error(resp.message || "Error when cloning profile");
3386
+ }
3387
+ });
3388
+
3389
+ const CloneProfile = ({ profile, show, onHide, suffixTitle }) => {
3390
+ var _a, _b;
3391
+ const [openSnackbar, setOpenSnackbar] = useState(false);
3392
+ const [isSubmitLoading, setIsSubmitLoading] = useState(false);
3393
+ const [error, setError] = useState("");
3394
+ const queryClient = useQueryClient();
3395
+ const { register, handleSubmit, reset, formState: { errors }, } = useForm();
3396
+ const cloneProfileMutation = useMutation({
3397
+ mutationFn: cloneProfile,
3398
+ onSuccess: () => {
3399
+ queryClient.invalidateQueries({ queryKey: ["profiles"] });
3400
+ setOpenSnackbar(true);
3401
+ onHide(false);
3402
+ },
3403
+ onError: (error) => {
3404
+ setError(error.message);
3405
+ },
3406
+ onSettled: () => {
3407
+ setIsSubmitLoading(false);
3408
+ },
3409
+ });
3410
+ const onSubmit = (data) => __awaiter(void 0, void 0, void 0, function* () {
3411
+ if (!(profile === null || profile === void 0 ? void 0 : profile.ProfileId))
3412
+ return;
3413
+ setIsSubmitLoading(true);
3414
+ yield cloneProfileMutation.mutate({
3415
+ SourceProfileId: profile.ProfileId,
3416
+ NewProfileName: data.NewProfileName,
3417
+ });
3418
+ });
3419
+ const handleClose = (event, reason) => {
3420
+ if (reason === "clickaway") {
3421
+ return;
3422
+ }
3423
+ setOpenSnackbar(false);
3424
+ };
3425
+ useEffect(() => {
3426
+ if (show && profile) {
3427
+ reset({ NewProfileName: `${profile.ProfileName} Copy` });
3428
+ }
3429
+ }, [show, profile]);
3430
+ return (React.createElement(React.Fragment, null,
3431
+ show && (React.createElement(HelmetDexteel, { title: `Clone Profile${suffixTitle ? ` - ${suffixTitle}` : ""}` })),
3432
+ React.createElement(Grid2, { container: true },
3433
+ React.createElement(Grid2, null,
3434
+ React.createElement(MesfModal, { title: "CLONE PROFILE", open: show, handleClose: () => onHide(false), id: "clone-profile-modal", maxWidth: "md" },
3435
+ React.createElement("form", { onSubmit: handleSubmit(onSubmit) },
3436
+ React.createElement(MesfModal.Content, { style: { padding: "15px 30px" } },
3437
+ React.createElement(Grid2, { container: true, spacing: 1 },
3438
+ React.createElement(Grid2, { size: { md: 12, xs: 12 } },
3439
+ React.createElement(TextField, Object.assign({}, register("NewProfileName", {
3440
+ required: true,
3441
+ validate: {
3442
+ notWhitespace: (value) => value.trim() !== "" ||
3443
+ "Profile name cannot be only whitespace",
3444
+ },
3445
+ }), { label: "New profile name", variant: "outlined", error: !!errors.NewProfileName, fullWidth: true, margin: "dense", autoComplete: "off" })),
3446
+ " ",
3447
+ ((_a = errors.NewProfileName) === null || _a === void 0 ? void 0 : _a.type) === "required" && (React.createElement("span", { style: { fontSize: 12, color: "#F44336" } }, "Profile name is required")),
3448
+ ((_b = errors.NewProfileName) === null || _b === void 0 ? void 0 : _b.type) === "notWhitespace" && (React.createElement("span", { style: { fontSize: 12, color: "#F44336" } }, errors.NewProfileName.message))))),
3449
+ React.createElement(MesfModal.Actions, { style: { padding: "20px 30px 30px" } },
3450
+ React.createElement(Grid2, { container: true, spacing: 2, justifyContent: "flex-end" },
3451
+ React.createElement(Grid2, { size: { md: 3, xs: 12 }, style: { margin: 0 } },
3452
+ React.createElement(Button, { fullWidth: true, variant: "contained", color: "inherit", onClick: () => onHide(false) }, "Cancel")),
3453
+ React.createElement(Grid2, { size: { md: 3, xs: 12 }, style: { margin: 0 } },
3454
+ React.createElement(Button, { fullWidth: true, startIcon: isSubmitLoading && React.createElement(CircularProgress, { size: "1rem" }), disabled: isSubmitLoading, variant: "contained", color: "primary", type: "submit" }, "Clone")))))))),
3455
+ React.createElement(Snackbar, { open: openSnackbar, autoHideDuration: 2500, onClose: handleClose, anchorOrigin: { vertical: "bottom", horizontal: "center" } },
3456
+ React.createElement(Alert$1, { severity: "success", onClose: handleClose }, "The profile was cloned successfully")),
3457
+ React.createElement(ErrorModal, { error: error, onHide: () => setError(""), title: "Error Cloning Profile" })));
3458
+ };
3375
3459
 
3376
3460
  const INITIAL_VALUES$2 = {
3377
3461
  ProfileId: null,
@@ -3745,7 +3829,7 @@ const ActionsOfProfile = ({ profileForEdit, show, onHide, suffixTitle, }) => {
3745
3829
  React.createElement(ErrorModal, { error: nameError, onHide: () => setNameError(""), title: "Error Editing Profile" })));
3746
3830
  };
3747
3831
 
3748
- const useProfilesOptionsFunctions = ({ setProfileId, setShowDeleteModal, setShowCreateModal, setModalProceduresProfile, }) => {
3832
+ const useProfilesOptionsFunctions = ({ setProfileId, setShowDeleteModal, setShowCreateModal, setShowCloneModal, setModalProceduresProfile, }) => {
3749
3833
  const getMenuOptions = (data) => {
3750
3834
  let options = [];
3751
3835
  if (!data) {
@@ -3788,6 +3872,15 @@ const useProfilesOptionsFunctions = ({ setProfileId, setShowDeleteModal, setShow
3788
3872
  },
3789
3873
  icon: React__default.createElement(DeleteIcon, null),
3790
3874
  },
3875
+ {
3876
+ name: "Clone Profile",
3877
+ key: "clone_profile",
3878
+ onClick: () => {
3879
+ setProfileId(data);
3880
+ setShowCloneModal(true);
3881
+ },
3882
+ icon: React__default.createElement(ContentCopyIcon, null),
3883
+ },
3791
3884
  ]);
3792
3885
  }
3793
3886
  return options;
@@ -3874,6 +3967,7 @@ const TableProfiles = () => {
3874
3967
  const [modalCreateActive, setModalCreateActive] = useState(false);
3875
3968
  const [modalProceduresProfile, setModalProceduresProfile] = useState(false);
3876
3969
  const [modalDeleteProfile, setModalDeleteProfile] = useState(false);
3970
+ const [modalCloneProfile, setModalCloneProfile] = useState(false);
3877
3971
  const [profile, setProfile] = useState(null);
3878
3972
  const [gridApi, setGridApi] = useState(null);
3879
3973
  const [error, setError] = useState("");
@@ -3901,6 +3995,7 @@ const TableProfiles = () => {
3901
3995
  setProfileId: setProfile,
3902
3996
  setShowCreateModal: setModalCreateActive,
3903
3997
  setShowDeleteModal: setModalDeleteProfile,
3998
+ setShowCloneModal: setModalCloneProfile,
3904
3999
  setModalProceduresProfile,
3905
4000
  });
3906
4001
  const { showContextMenu, registerConfig } = useContextMenuMESF();
@@ -3960,6 +4055,10 @@ const TableProfiles = () => {
3960
4055
  setProfile(null);
3961
4056
  if (shouldUpdate)
3962
4057
  refetch();
4058
+ }, suffixTitle: "Profile Management" }),
4059
+ React.createElement(CloneProfile, { show: modalCloneProfile, profile: profile, onHide: () => {
4060
+ setModalCloneProfile(false);
4061
+ setProfile(null);
3963
4062
  }, suffixTitle: "Profile Management" })));
3964
4063
  };
3965
4064
 
@@ -10195,6 +10294,7 @@ const executeStoredProcedure = (procedureName, parameters) => __awaiter(void 0,
10195
10294
  return yield apiService.callV2(procedureName, parameters);
10196
10295
  });
10197
10296
 
10297
+ const BACKEND_MANAGED_PARAMS = ["@user"];
10198
10298
  const SPExecutorPage = () => {
10199
10299
  const [procedures, setProcedures] = useState([]);
10200
10300
  const [allParameters, setAllParameters] = useState([]);
@@ -10222,10 +10322,12 @@ const SPExecutorPage = () => {
10222
10322
  useEffect(() => {
10223
10323
  loadData();
10224
10324
  }, []);
10325
+ // Parameters that should be excluded from the UI (handled by the backend)
10225
10326
  const currentParameters = useMemo(() => {
10226
10327
  if (!selectedProcedure)
10227
10328
  return [];
10228
- return allParameters.filter((p) => p.FullName === selectedProcedure.FullName);
10329
+ return allParameters.filter((p) => p.FullName === selectedProcedure.FullName &&
10330
+ !BACKEND_MANAGED_PARAMS.includes(p.ParameterName.toLowerCase()));
10229
10331
  }, [selectedProcedure, allParameters]);
10230
10332
  const handleProcedureChange = (proc) => {
10231
10333
  setSelectedProcedure(proc);
@@ -10237,8 +10339,10 @@ const SPExecutorPage = () => {
10237
10339
  setError("");
10238
10340
  const startTime = Date.now();
10239
10341
  // Build parameters array - only include checked parameters
10342
+ // Also filter out backend-managed params (@User) as a safety net
10240
10343
  const parameters = formState
10241
- .filter((p) => p.include)
10344
+ .filter((p) => p.include &&
10345
+ !BACKEND_MANAGED_PARAMS.includes(p.parameterName.toLowerCase()))
10242
10346
  .map((p) => ({
10243
10347
  name: p.parameterName,
10244
10348
  value: p.sendAsNull ? null : p.value,