@upsnap/strapi 1.0.7 → 1.0.8

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.
@@ -131,7 +131,6 @@ const PLAN_LIMITS = {
131
131
  max_status_pages: 1
132
132
  }
133
133
  };
134
- const DASHBOARD_URL = "https://upsnap.ai";
135
134
  const STATS_PAGE_URL = "https://stats.upsnap.ai";
136
135
  const DEFAULT_REGION = {
137
136
  id: "default",
@@ -348,6 +347,22 @@ async function getPrimaryMonitorId() {
348
347
  return null;
349
348
  }
350
349
  }
350
+ async function handleLogout() {
351
+ try {
352
+ await setPrimaryMonitorId("");
353
+ const res = await request("/settings", {
354
+ method: "POST",
355
+ data: { token: null, logOut: true }
356
+ });
357
+ if (res.ok) {
358
+ return true;
359
+ }
360
+ return false;
361
+ } catch (err) {
362
+ console.log("Error while logging out ", err);
363
+ return;
364
+ }
365
+ }
351
366
  const STORAGE_KEY = "selectedMonitor";
352
367
  function getUserData() {
353
368
  if (typeof window === "undefined") return null;
@@ -426,6 +441,7 @@ function MonitorsTable({
426
441
  const [defaultEmail, setDefaultEmail] = React.useState();
427
442
  const isInternalUpdate = React.useRef(false);
428
443
  const [primaryMonitorId, setPrimaryMonitorIdState] = React.useState(null);
444
+ const navigate = reactRouterDom.useNavigate();
429
445
  React.useEffect(() => {
430
446
  async function fetchPrimaryMonitorId() {
431
447
  try {
@@ -473,6 +489,8 @@ function MonitorsTable({
473
489
  if (result) {
474
490
  reactToastify.toast.success("Primary monitor set successfully");
475
491
  setPrimaryMonitorIdState(monitor.id);
492
+ navigate("/plugins/upsnap/dashboard");
493
+ return;
476
494
  } else {
477
495
  reactToastify.toast.error("Failed to set primary monitor");
478
496
  }
@@ -4838,6 +4856,19 @@ const statusPageSchema = object({
4838
4856
  name: string().min(1, "Name is required").max(100, "Name must be less than 100 characters"),
4839
4857
  monitor_ids: array(string()).min(1, "At least one monitor is required")
4840
4858
  });
4859
+ const loginSchema = object({
4860
+ email: string().email("Invalid email address"),
4861
+ password: string().min(1, "Password is required")
4862
+ });
4863
+ const registerSchema = object({
4864
+ fullName: string().min(2, "Full name must be at least 2 characters"),
4865
+ email: string().email("Invalid email address"),
4866
+ password: string().min(8, "Password must be at least 8 characters").regex(/[A-Z]/, "Password must contain at least one uppercase letter").regex(/[a-z]/, "Password must contain at least one lowercase letter").regex(/\d/, "Password must contain at least one number"),
4867
+ confirmPassword: string().min(1, "Confirm password is required")
4868
+ }).refine((data) => data.password === data.confirmPassword, {
4869
+ message: "Passwords do not match",
4870
+ path: ["confirmPassword"]
4871
+ });
4841
4872
  const serviceConfigSchema = object({
4842
4873
  enabled: boolean(),
4843
4874
  monitor_interval: number().optional(),
@@ -6416,6 +6447,13 @@ function Monitors({ onTabChange }) {
6416
6447
  const [bulkDeleteIds, setBulkDeleteIds] = React.useState([]);
6417
6448
  const [bulkDeleteModalOpen, setBulkDeleteModalOpen] = React.useState(false);
6418
6449
  const userDetails = getUserData();
6450
+ const [alertMessage, setAlertMessage] = React.useState("");
6451
+ React.useEffect(() => {
6452
+ (async () => {
6453
+ const fetchedMonitorId = await getPrimaryMonitorId();
6454
+ if (!fetchedMonitorId) setAlertMessage("Please select a primary monitor to continue!");
6455
+ })();
6456
+ }, []);
6419
6457
  const load = async () => {
6420
6458
  try {
6421
6459
  setLoading(true);
@@ -6525,6 +6563,7 @@ function Monitors({ onTabChange }) {
6525
6563
  }
6526
6564
  };
6527
6565
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { width: "100%", children: [
6566
+ alertMessage && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { width: "100%", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { closeLabel: "Close", title: "", children: alertMessage.charAt(0).toUpperCase() + alertMessage.slice(1) }) }),
6528
6567
  !showEdit && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 4, children: [
6529
6568
  /* @__PURE__ */ jsxRuntime.jsxs(
6530
6569
  designSystem.Flex,
@@ -6600,56 +6639,6 @@ function Monitors({ onTabChange }) {
6600
6639
  )
6601
6640
  ] });
6602
6641
  }
6603
- function APIToken() {
6604
- const [token, setToken] = React.useState("");
6605
- const [loading, setLoading] = React.useState(false);
6606
- const navigate = reactRouterDom.useNavigate();
6607
- React.useEffect(() => {
6608
- request("/settings", {
6609
- method: "GET"
6610
- }).then((res) => {
6611
- setToken(res.token || "");
6612
- });
6613
- }, []);
6614
- const save = async () => {
6615
- setLoading(true);
6616
- await request("/settings", {
6617
- method: "POST",
6618
- data: { token }
6619
- }).then((res) => {
6620
- if (!res.ok) {
6621
- reactToastify.toast.error(res.error || "Failed to save token");
6622
- setLoading(false);
6623
- return;
6624
- }
6625
- reactToastify.toast.success("Token saved successfully");
6626
- navigate("/plugins/upsnap/dashboard");
6627
- });
6628
- setLoading(false);
6629
- };
6630
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 3, children: [
6631
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, alignItems: "start", children: [
6632
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", children: "Token Settings" }),
6633
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", children: [
6634
- "Enter the Upsnap API Key and save to enable Healthcheck settings. To access the API key, please visit the",
6635
- " ",
6636
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { href: DASHBOARD_URL, isExternal: true, children: "Upsnap Dashboard" })
6637
- ] })
6638
- ] }),
6639
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginTop: 6, width: "100%", children: [
6640
- /* @__PURE__ */ jsxRuntime.jsx(
6641
- designSystem.TextInput,
6642
- {
6643
- placeholder: "API Token",
6644
- type: "password",
6645
- value: token,
6646
- onChange: (e) => setToken(e.target.value)
6647
- }
6648
- ),
6649
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { loading, onClick: save, children: "Save" }) })
6650
- ] })
6651
- ] });
6652
- }
6653
6642
  const getNestedValue = (obj, path) => {
6654
6643
  return path.split(".").reduce((current, key) => current?.[key], obj);
6655
6644
  };
@@ -7510,7 +7499,7 @@ function SettingsTabs({
7510
7499
  activeTab,
7511
7500
  onTabChange
7512
7501
  }) {
7513
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.Root, { defaultValue: activeTab, value: activeTab, onValueChange: onTabChange, children: [
7502
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 8, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Card, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.CardBody, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.CardContent, { width: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.Root, { defaultValue: activeTab, value: activeTab, onValueChange: onTabChange, children: [
7514
7503
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.List, { "aria-label": "Manage your attribute", children: /* @__PURE__ */ jsxRuntime.jsx(
7515
7504
  designSystem.Flex,
7516
7505
  {
@@ -7523,28 +7512,389 @@ function SettingsTabs({
7523
7512
  ) }),
7524
7513
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.Content, { value: activeTab, children: [
7525
7514
  activeTab === "monitors" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(Monitors, { onTabChange }) }),
7526
- activeTab === "notification_channels" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 2, children: /* @__PURE__ */ jsxRuntime.jsx(IntegrationsPage, {}) }),
7527
- activeTab === "api_key" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 1, children: /* @__PURE__ */ jsxRuntime.jsx(APIToken, {}) })
7515
+ activeTab === "notification_channels" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 2, children: /* @__PURE__ */ jsxRuntime.jsx(IntegrationsPage, {}) })
7528
7516
  ] })
7529
- ] }) });
7517
+ ] }) }) }) }) });
7518
+ }
7519
+ function LogInForm({
7520
+ setShowLoginForm,
7521
+ setShowRegisterForm,
7522
+ setShowExpiredMessage
7523
+ }) {
7524
+ const [email2, setEmail] = React.useState("");
7525
+ const [password, setPassword] = React.useState("");
7526
+ const [errors, setErrors] = React.useState(null);
7527
+ const [loading, setLoading] = React.useState(false);
7528
+ const [forgotPasswordError, setForgotPasswordError] = React.useState("");
7529
+ const navigate = reactRouterDom.useNavigate();
7530
+ const handleSubmit = (e) => {
7531
+ e.preventDefault();
7532
+ setLoading(true);
7533
+ const result = loginSchema.safeParse({ email: email2, password });
7534
+ if (!result.success) {
7535
+ setErrors(result.error);
7536
+ setLoading(false);
7537
+ return;
7538
+ }
7539
+ setErrors(null);
7540
+ request("/login", {
7541
+ method: "POST",
7542
+ data: {
7543
+ email: email2,
7544
+ password
7545
+ }
7546
+ }).then((res) => {
7547
+ if (res?.ok) {
7548
+ reactToastify.toast.success("Login Successful");
7549
+ navigate("/plugins/upsnap/dashboard");
7550
+ return;
7551
+ }
7552
+ reactToastify.toast.error(res?.message || "Not able to login, please try again.");
7553
+ setShowExpiredMessage(res?.message);
7554
+ }).catch((err) => {
7555
+ reactToastify.toast.error("Not able to login, please try again.");
7556
+ }).finally(() => {
7557
+ setLoading(false);
7558
+ });
7559
+ };
7560
+ const handleForgotPassword = () => {
7561
+ if (!email2) {
7562
+ setForgotPasswordError("Please enter the email.");
7563
+ return;
7564
+ }
7565
+ setForgotPasswordError("");
7566
+ request("/forgot-password", {
7567
+ method: "POST",
7568
+ data: {
7569
+ email: email2
7570
+ }
7571
+ }).then((res) => {
7572
+ if (res?.ok) {
7573
+ reactToastify.toast.success(res?.message);
7574
+ return;
7575
+ }
7576
+ reactToastify.toast.error(res?.message || "Not able to login, please try again.");
7577
+ setShowExpiredMessage(res?.message);
7578
+ }).catch((err) => {
7579
+ reactToastify.toast.error("Not able to send email, please try again.");
7580
+ }).finally(() => {
7581
+ setLoading(false);
7582
+ });
7583
+ };
7584
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { margin: "auto", width: { initial: "100%", medium: "55%" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Card, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.CardBody, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.CardContent, { width: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, width: "100%", children: [
7585
+ /* @__PURE__ */ jsxRuntime.jsxs(
7586
+ designSystem.Flex,
7587
+ {
7588
+ marginBottom: 3,
7589
+ direction: "column",
7590
+ gap: 1,
7591
+ justifyContent: "start",
7592
+ alignItems: "start",
7593
+ children: [
7594
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: "Sign In" }),
7595
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral600", marginBottom: 3, children: "Enter your email and password to Sign In." })
7596
+ ]
7597
+ }
7598
+ ),
7599
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, { marginBottom: 3 }),
7600
+ /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 3, width: "100%", children: [
7601
+ /* @__PURE__ */ jsxRuntime.jsxs(
7602
+ designSystem.Field.Root,
7603
+ {
7604
+ width: "100%",
7605
+ error: errors?.issues.find((issue2) => issue2.path[0] === "email")?.message || forgotPasswordError,
7606
+ required: true,
7607
+ children: [
7608
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Email" }),
7609
+ /* @__PURE__ */ jsxRuntime.jsx(
7610
+ designSystem.Field.Input,
7611
+ {
7612
+ type: "email",
7613
+ placeholder: "example@gmail.com",
7614
+ value: email2,
7615
+ onChange: (e) => setEmail(e.target.value)
7616
+ }
7617
+ ),
7618
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
7619
+ ]
7620
+ }
7621
+ ),
7622
+ /* @__PURE__ */ jsxRuntime.jsxs(
7623
+ designSystem.Field.Root,
7624
+ {
7625
+ width: "100%",
7626
+ error: errors?.issues.find((issue2) => issue2.path[0] === "password")?.message,
7627
+ required: true,
7628
+ children: [
7629
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Password" }),
7630
+ /* @__PURE__ */ jsxRuntime.jsx(
7631
+ designSystem.Field.Input,
7632
+ {
7633
+ type: "password",
7634
+ placeholder: "Enter a password",
7635
+ value: password,
7636
+ onChange: (e) => setPassword(e.target.value)
7637
+ }
7638
+ ),
7639
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
7640
+ ]
7641
+ }
7642
+ ),
7643
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "end", marginTop: 4, children: /* @__PURE__ */ jsxRuntime.jsx(
7644
+ designSystem.Link,
7645
+ {
7646
+ onClick: (e) => {
7647
+ e?.preventDefault();
7648
+ handleForgotPassword();
7649
+ },
7650
+ children: "forgot password?"
7651
+ }
7652
+ ) }) }),
7653
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { width: "100%", justifyContent: "end", marginTop: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { size: "L", type: "submit", loading, children: "Sign In" }) })
7654
+ ] }) }),
7655
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", marginTop: 4, children: /* @__PURE__ */ jsxRuntime.jsx(
7656
+ designSystem.Link,
7657
+ {
7658
+ onClick: (e) => {
7659
+ e?.preventDefault();
7660
+ setShowLoginForm(false);
7661
+ setShowRegisterForm(true);
7662
+ },
7663
+ children: "Not registered? Create account"
7664
+ }
7665
+ ) })
7666
+ ] }) }) }) }) });
7667
+ }
7668
+ function RegisterForm({
7669
+ setShowRegisterForm,
7670
+ setShowLoginForm,
7671
+ setShowExpiredMessage
7672
+ }) {
7673
+ const [fullName, setFullName] = React.useState("");
7674
+ const [email2, setEmail] = React.useState("");
7675
+ const [password, setPassword] = React.useState("");
7676
+ const [confirmPassword, setConfirmPassword] = React.useState("");
7677
+ const [confirmPasswordError, setConfirmPasswordError] = React.useState("");
7678
+ const [errors, setErrors] = React.useState(null);
7679
+ const [loading, setLoading] = React.useState(false);
7680
+ const navigate = reactRouterDom.useNavigate();
7681
+ const handleSubmit = (e) => {
7682
+ e.preventDefault();
7683
+ setLoading(true);
7684
+ const result = registerSchema.safeParse({ email: email2, password, fullName, confirmPassword });
7685
+ if (!result.success) {
7686
+ setErrors(result.error);
7687
+ setLoading(false);
7688
+ return;
7689
+ }
7690
+ setErrors(null);
7691
+ const domainUrl = window.strapi?.backendURL || window.location.origin;
7692
+ request("/signup", {
7693
+ method: "POST",
7694
+ data: {
7695
+ email: email2,
7696
+ password,
7697
+ fullName,
7698
+ source: "strapi",
7699
+ site_url: domainUrl
7700
+ }
7701
+ }).then((res) => {
7702
+ if (res?.ok) {
7703
+ reactToastify.toast.success(res?.message || "UpSnap Connected.");
7704
+ reactToastify.toast.success("Your site is now being monitored every 5 minutes.");
7705
+ navigate("/plugins/upsnap/dashboard");
7706
+ return;
7707
+ }
7708
+ reactToastify.toast.error("Not able to register, please try again.");
7709
+ }).catch((err) => {
7710
+ reactToastify.toast.error("Not able to register, please try again.");
7711
+ }).finally(() => {
7712
+ setLoading(false);
7713
+ });
7714
+ };
7715
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { margin: "auto", width: { initial: "100%", medium: "55%" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Card, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.CardBody, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.CardContent, { width: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, width: "100%", children: [
7716
+ /* @__PURE__ */ jsxRuntime.jsxs(
7717
+ designSystem.Flex,
7718
+ {
7719
+ marginBottom: 3,
7720
+ direction: "column",
7721
+ gap: 1,
7722
+ justifyContent: "start",
7723
+ alignItems: "start",
7724
+ children: [
7725
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: "Register" }),
7726
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral600", marginBottom: 3, children: "Create a free UpSnap beta account to start monitoring your site." })
7727
+ ]
7728
+ }
7729
+ ),
7730
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, { marginBottom: 3 }),
7731
+ /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 3, width: "100%", children: [
7732
+ /* @__PURE__ */ jsxRuntime.jsxs(
7733
+ designSystem.Field.Root,
7734
+ {
7735
+ width: "100%",
7736
+ error: errors?.issues.find((issue2) => issue2.path[0] === "fullName")?.message,
7737
+ required: true,
7738
+ children: [
7739
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Full Name" }),
7740
+ /* @__PURE__ */ jsxRuntime.jsx(
7741
+ designSystem.Field.Input,
7742
+ {
7743
+ type: "text",
7744
+ placeholder: "Ted Lasso",
7745
+ value: fullName,
7746
+ onChange: (e) => setFullName(e.target.value)
7747
+ }
7748
+ ),
7749
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
7750
+ ]
7751
+ }
7752
+ ),
7753
+ /* @__PURE__ */ jsxRuntime.jsxs(
7754
+ designSystem.Field.Root,
7755
+ {
7756
+ width: "100%",
7757
+ error: errors?.issues.find((issue2) => issue2.path[0] === "email")?.message,
7758
+ required: true,
7759
+ children: [
7760
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Email" }),
7761
+ /* @__PURE__ */ jsxRuntime.jsx(
7762
+ designSystem.Field.Input,
7763
+ {
7764
+ type: "email",
7765
+ placeholder: "example@gmail.com",
7766
+ value: email2,
7767
+ onChange: (e) => setEmail(e.target.value)
7768
+ }
7769
+ ),
7770
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
7771
+ ]
7772
+ }
7773
+ ),
7774
+ /* @__PURE__ */ jsxRuntime.jsxs(
7775
+ designSystem.Field.Root,
7776
+ {
7777
+ width: "100%",
7778
+ error: errors?.issues.find((issue2) => issue2.path[0] === "password")?.message,
7779
+ required: true,
7780
+ children: [
7781
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Password" }),
7782
+ /* @__PURE__ */ jsxRuntime.jsx(
7783
+ designSystem.Field.Input,
7784
+ {
7785
+ type: "password",
7786
+ placeholder: "Enter a password",
7787
+ value: password,
7788
+ onChange: (e) => {
7789
+ const value = e.target.value;
7790
+ setPassword(value);
7791
+ }
7792
+ }
7793
+ ),
7794
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
7795
+ ]
7796
+ }
7797
+ ),
7798
+ /* @__PURE__ */ jsxRuntime.jsxs(
7799
+ designSystem.Field.Root,
7800
+ {
7801
+ width: "100%",
7802
+ error: errors?.issues.find((issue2) => issue2.path[0] === "confirmPassword")?.message || confirmPasswordError,
7803
+ required: true,
7804
+ children: [
7805
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Confirm Password" }),
7806
+ /* @__PURE__ */ jsxRuntime.jsx(
7807
+ designSystem.Field.Input,
7808
+ {
7809
+ type: "password",
7810
+ placeholder: "Confirm password",
7811
+ value: confirmPassword,
7812
+ onChange: (e) => {
7813
+ const value = e.target.value;
7814
+ setConfirmPassword(value);
7815
+ if (password && value && password !== value) {
7816
+ setConfirmPasswordError("Passwords do not match");
7817
+ } else {
7818
+ setConfirmPasswordError("");
7819
+ }
7820
+ }
7821
+ }
7822
+ ),
7823
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
7824
+ ]
7825
+ }
7826
+ ),
7827
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { width: "100%", justifyContent: "end", marginTop: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { size: "L", type: "submit", loading, children: "Start Free Beta Monitoring" }) })
7828
+ ] }) }),
7829
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", marginTop: 4, children: /* @__PURE__ */ jsxRuntime.jsx(
7830
+ designSystem.Link,
7831
+ {
7832
+ onClick: (e) => {
7833
+ e?.preventDefault();
7834
+ setShowRegisterForm(false);
7835
+ setShowLoginForm(true);
7836
+ },
7837
+ children: "Already have an account?"
7838
+ }
7839
+ ) })
7840
+ ] }) }) }) }) });
7530
7841
  }
7531
7842
  function Settings() {
7532
7843
  const [activeTab, setActiveTab] = React.useState("monitors");
7844
+ const [showLogin, setShowLogin] = React.useState(false);
7845
+ const [showRegister, setShowRegister] = React.useState(false);
7846
+ const [showExpiredMessage, setShowExpiredMessage] = React.useState("");
7847
+ const [loading, setLoading] = React.useState(false);
7848
+ React.useEffect(() => {
7849
+ request("/settings", {
7850
+ method: "GET"
7851
+ }).then((res) => {
7852
+ if (!res?.token) {
7853
+ setShowRegister(true);
7854
+ setShowLogin(false);
7855
+ }
7856
+ });
7857
+ }, []);
7533
7858
  const handleTabChange = (tab) => {
7859
+ if (tab === "api_key") {
7860
+ setShowLogin(true);
7861
+ setShowRegister(false);
7862
+ return;
7863
+ }
7534
7864
  setActiveTab(tab);
7535
7865
  };
7536
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 8, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Card, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.CardBody, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.CardContent, { width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
7537
- SettingsTabs,
7538
- {
7539
- tabs: [
7540
- { name: "Monitors", value: "monitors" },
7541
- { name: "Notification Channels", value: "notification_channels" },
7542
- { name: "API Key", value: "api_key" }
7543
- ],
7544
- activeTab,
7545
- onTabChange: handleTabChange
7866
+ const logOut = async () => {
7867
+ setLoading(true);
7868
+ const result = await handleLogout();
7869
+ if (result) {
7870
+ reactToastify.toast.success("Logged out successfully.");
7871
+ setLoading(false);
7872
+ setShowLogin(true);
7873
+ return;
7546
7874
  }
7547
- ) }) }) }) });
7875
+ setLoading(false);
7876
+ reactToastify.toast.error("Not able to log out, please try again.");
7877
+ return;
7878
+ };
7879
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7880
+ showExpiredMessage && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { margin: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { closeLabel: "Close", title: "", variant: "danger", children: showExpiredMessage.charAt(0).toUpperCase() + showExpiredMessage.slice(1) }) }),
7881
+ showLogin && /* @__PURE__ */ jsxRuntime.jsx(LogInForm, { setShowLoginForm: setShowLogin, setShowRegisterForm: setShowRegister, setShowExpiredMessage }),
7882
+ showRegister && /* @__PURE__ */ jsxRuntime.jsx(RegisterForm, { setShowRegisterForm: setShowRegister, setShowLoginForm: setShowLogin, setShowExpiredMessage }),
7883
+ !showLogin && !showRegister && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7884
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { width: "100%", paddingRight: 8, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "end", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: logOut, loading, children: "Log out" }) }) }),
7885
+ /* @__PURE__ */ jsxRuntime.jsx(
7886
+ SettingsTabs,
7887
+ {
7888
+ tabs: [
7889
+ { name: "Monitors", value: "monitors" },
7890
+ { name: "Notification Channels", value: "notification_channels" }
7891
+ ],
7892
+ activeTab,
7893
+ onTabChange: handleTabChange
7894
+ }
7895
+ )
7896
+ ] })
7897
+ ] });
7548
7898
  }
7549
7899
  const HistogramContainer = styled__default.default(designSystem.Box)`
7550
7900
  display: flex;
@@ -8371,7 +8721,7 @@ function Dashboard() {
8371
8721
  for (let attempt = 0; attempt < retries; attempt++) {
8372
8722
  try {
8373
8723
  const res = await request(`/monitor/${monitorId}`, { method: "GET" });
8374
- if (res?.monitor?.message === "Invalid authentication token") {
8724
+ if (res?.monitor?.message === "Invalid authentication token" || res?.monitor?.status === "error") {
8375
8725
  navigate("/plugins/upsnap/settings");
8376
8726
  return null;
8377
8727
  }
@@ -8857,6 +9207,7 @@ const RegionResponseTimeChart = ({
8857
9207
  function Reachability() {
8858
9208
  const [data, setData] = React.useState(null);
8859
9209
  const [loading, setLoading] = React.useState(true);
9210
+ const [refreshing, setRefreshing] = React.useState(false);
8860
9211
  const [selectedMonitor, setSelectedMonitor] = React.useState(null);
8861
9212
  const [regionId, setRegionId] = React.useState(null);
8862
9213
  const [regionResponseTimeData, setRegionResponseTimeData] = React.useState({});
@@ -8892,27 +9243,37 @@ function Reachability() {
8892
9243
  }
8893
9244
  }
8894
9245
  };
8895
- React.useEffect(() => {
9246
+ const fetchMonitorDetails = async () => {
8896
9247
  if (monitorId) {
8897
9248
  setLoading(true);
8898
- request(`/monitor/${monitorId}`, { method: "GET" }).then((res) => {
9249
+ try {
9250
+ const res = await request(`/monitor/${monitorId}`, { method: "GET" });
8899
9251
  if (res?.monitor?.message === "Invalid authentication token") {
8900
9252
  setSelectedMonitor(null);
8901
9253
  navigate("/plugins/upsnap/settings");
9254
+ } else {
9255
+ const monitorData = res.monitor?.data || null;
9256
+ setSelectedMonitor(monitorData);
9257
+ if (monitorData?.monitor?.regions) {
9258
+ await fetchResponseTimeDataForRegions(
9259
+ monitorData.monitor.regions,
9260
+ responseTimeRange || "last_24_hours"
9261
+ );
9262
+ }
8902
9263
  }
8903
- setSelectedMonitor(res.monitor?.data || null);
8904
- if (res.monitor?.data?.monitor?.regions) {
8905
- fetchResponseTimeDataForRegions(
8906
- res.monitor.data.monitor.regions,
8907
- responseTimeRange || "last_24_hours"
8908
- );
8909
- }
9264
+ } catch (error) {
9265
+ console.error("Error fetching monitor details:", error);
9266
+ } finally {
8910
9267
  setLoading(false);
8911
- });
9268
+ }
8912
9269
  }
9270
+ };
9271
+ React.useEffect(() => {
9272
+ fetchMonitorDetails();
8913
9273
  }, [monitorId]);
8914
- const getReachabilityData = async (url, region) => {
8915
- setLoading(true);
9274
+ const getReachabilityData = async (url) => {
9275
+ const stateSetter = loading ? setLoading : setRefreshing;
9276
+ stateSetter(true);
8916
9277
  try {
8917
9278
  const res = await request("/monitor/health-check/uptime", {
8918
9279
  method: "POST",
@@ -8922,7 +9283,7 @@ function Reachability() {
8922
9283
  } catch (err) {
8923
9284
  setData(null);
8924
9285
  } finally {
8925
- setLoading(false);
9286
+ stateSetter(false);
8926
9287
  }
8927
9288
  };
8928
9289
  const fetchResponseTimeForRegion = async (regionId2, start, end) => {
@@ -8940,7 +9301,7 @@ function Reachability() {
8940
9301
  if (selectedMonitor) {
8941
9302
  const primaryRegion = selectedMonitor?.monitor?.regions?.find((r) => r.is_primary);
8942
9303
  setRegionId(primaryRegion?.id || null);
8943
- getReachabilityData(selectedMonitor?.monitor?.config?.meta?.url, primaryRegion?.id || null);
9304
+ getReachabilityData(selectedMonitor?.monitor?.config?.meta?.url);
8944
9305
  }
8945
9306
  }, [selectedMonitor]);
8946
9307
  React.useEffect(() => {
@@ -8972,6 +9333,11 @@ function Reachability() {
8972
9333
  fetchResponseTimeDataForRegions(selectedMonitor.monitor.regions, String(range) || "last_24_hours");
8973
9334
  }
8974
9335
  };
9336
+ const handleRefresh = async () => {
9337
+ if (selectedMonitor) {
9338
+ await getReachabilityData(selectedMonitor.monitor.config.meta.url);
9339
+ }
9340
+ };
8975
9341
  const regionNames = React.useMemo(() => {
8976
9342
  const names = {};
8977
9343
  if (selectedMonitor?.monitor?.regions && Array.isArray(selectedMonitor?.monitor?.regions)) {
@@ -8988,11 +9354,15 @@ function Reachability() {
8988
9354
  const tls = meta?.tls;
8989
9355
  const regions = selectedMonitor?.monitor?.regions || [];
8990
9356
  return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, children: [
8991
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginBottom: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "beta", children: [
8992
- "Reachability (",
8993
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { href: selectedMonitor?.monitor?.config?.meta?.url, isExternal: true, children: selectedMonitor.monitor?.name || "" }),
8994
- ")"
8995
- ] }) }),
9357
+ /* @__PURE__ */ jsxRuntime.jsx(
9358
+ PageHeader,
9359
+ {
9360
+ title: "Reachability",
9361
+ monitorUrl: selectedMonitor.monitor?.config?.meta?.url,
9362
+ onRefresh: handleRefresh,
9363
+ refreshing
9364
+ }
9365
+ ),
8996
9366
  /* @__PURE__ */ jsxRuntime.jsx(
8997
9367
  StatusCard,
8998
9368
  {