@plutonhq/core-frontend 0.1.26 → 0.1.27

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.
Files changed (70) hide show
  1. package/dist-lib/@types/backups.d.ts +3 -0
  2. package/dist-lib/@types/backups.d.ts.map +1 -1
  3. package/dist-lib/@types/plans.d.ts +2 -0
  4. package/dist-lib/@types/plans.d.ts.map +1 -1
  5. package/dist-lib/@types/restores.d.ts +2 -0
  6. package/dist-lib/@types/restores.d.ts.map +1 -1
  7. package/dist-lib/components/Device/DeviceInfo/DeviceInfo.module.scss.js +26 -26
  8. package/dist-lib/components/Plan/PlanBackups/PlanBackups.d.ts.map +1 -1
  9. package/dist-lib/components/Plan/PlanBackups/PlanBackups.js +26 -26
  10. package/dist-lib/components/Plan/PlanBackups/PlanBackups.js.map +1 -1
  11. package/dist-lib/components/Plan/PlanForm/PlanForm.d.ts.map +1 -1
  12. package/dist-lib/components/Plan/PlanForm/PlanForm.js +64 -80
  13. package/dist-lib/components/Plan/PlanForm/PlanForm.js.map +1 -1
  14. package/dist-lib/components/Plan/PlanHistory/PlanHistory.js +1 -1
  15. package/dist-lib/components/Plan/PlanHistory/PlanHistory.js.map +1 -1
  16. package/dist-lib/components/Plan/PlanSettings/PlanSourceSettings.d.ts.map +1 -1
  17. package/dist-lib/components/Plan/PlanSettings/PlanSourceSettings.js +39 -30
  18. package/dist-lib/components/Plan/PlanSettings/PlanSourceSettings.js.map +1 -1
  19. package/dist-lib/components/Plan/PlanStats/PlanStats.d.ts.map +1 -1
  20. package/dist-lib/components/Plan/PlanStats/PlanStats.js +25 -25
  21. package/dist-lib/components/Plan/PlanStats/PlanStats.js.map +1 -1
  22. package/dist-lib/components/Plan/PlanStats/PlanStats.module.scss.js +1 -1
  23. package/dist-lib/components/common/Icon/Icon.d.ts.map +1 -1
  24. package/dist-lib/components/common/Icon/Icon.js +12 -1
  25. package/dist-lib/components/common/Icon/Icon.js.map +1 -1
  26. package/dist-lib/components/common/form/IntervalField/IntervalField.d.ts.map +1 -1
  27. package/dist-lib/components/common/form/IntervalField/IntervalField.js +66 -46
  28. package/dist-lib/components/common/form/IntervalField/IntervalField.js.map +1 -1
  29. package/dist-lib/components/common/form/StoragePicker/StoragePicker.d.ts.map +1 -1
  30. package/dist-lib/components/common/form/StoragePicker/StoragePicker.js +49 -47
  31. package/dist-lib/components/common/form/StoragePicker/StoragePicker.js.map +1 -1
  32. package/dist-lib/components/common/form/TagsInput/TagsInput.d.ts +2 -1
  33. package/dist-lib/components/common/form/TagsInput/TagsInput.d.ts.map +1 -1
  34. package/dist-lib/components/common/form/TagsInput/TagsInput.js +15 -15
  35. package/dist-lib/components/common/form/TagsInput/TagsInput.js.map +1 -1
  36. package/dist-lib/components/common/form/TimePicker/TimePicker.module.scss.js +13 -13
  37. package/dist-lib/hooks/usePlanSingleActions.js +7 -7
  38. package/dist-lib/hooks/usePlanSingleActions.js.map +1 -1
  39. package/dist-lib/styles/core-frontend.css +1 -1
  40. package/dist-lib/styles/global.scss +6 -0
  41. package/dist-lib/utils/constants.js +1 -1
  42. package/dist-lib/utils/constants.js.map +1 -1
  43. package/dist-lib/utils/helpers.d.ts +2 -0
  44. package/dist-lib/utils/helpers.d.ts.map +1 -1
  45. package/dist-lib/utils/helpers.js +55 -33
  46. package/dist-lib/utils/helpers.js.map +1 -1
  47. package/dist-lib/utils/plans.js +6 -6
  48. package/dist-lib/utils/plans.js.map +1 -1
  49. package/dist-lib/utils.js +34 -33
  50. package/package.json +1 -1
  51. package/src/@types/backups.ts +3 -0
  52. package/src/@types/plans.ts +2 -0
  53. package/src/@types/restores.ts +2 -0
  54. package/src/components/Device/DeviceInfo/DeviceInfo.module.scss +1 -0
  55. package/src/components/Plan/PlanBackups/PlanBackups.tsx +5 -2
  56. package/src/components/Plan/PlanForm/PlanForm.tsx +1 -19
  57. package/src/components/Plan/PlanHistory/PlanHistory.tsx +1 -1
  58. package/src/components/Plan/PlanSettings/PlanSourceSettings.tsx +15 -1
  59. package/src/components/Plan/PlanStats/PlanStats.module.scss +3 -0
  60. package/src/components/Plan/PlanStats/PlanStats.tsx +2 -8
  61. package/src/components/common/Icon/Icon.tsx +12 -0
  62. package/src/components/common/form/IntervalField/IntervalField.tsx +21 -1
  63. package/src/components/common/form/StoragePicker/StoragePicker.tsx +8 -1
  64. package/src/components/common/form/TagsInput/TagsInput.tsx +3 -2
  65. package/src/components/common/form/TimePicker/TimePicker.module.scss +1 -0
  66. package/src/hooks/usePlanSingleActions.tsx +2 -2
  67. package/src/styles/global.scss +6 -0
  68. package/src/utils/constants.ts +1 -1
  69. package/src/utils/helpers.ts +25 -0
  70. package/src/utils/plans.ts +3 -3
@@ -359,3 +359,9 @@ i.pipe {
359
359
  transform: translateX(100%);
360
360
  }
361
361
  }
362
+
363
+ @media (max-width: 768px) {
364
+ :root {
365
+ --container-width: 100%;
366
+ }
367
+ }
@@ -53,7 +53,7 @@ const e = !1, a = `${window.location.origin}/api`, s = "Pluton", n = {
53
53
  snapCount: 5,
54
54
  policy: "forgetByAge",
55
55
  forgetAge: "1m",
56
- revisions: !0
56
+ revisions: !1
57
57
  },
58
58
  performance: {
59
59
  scan: !0
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sources":["../../src/utils/constants.ts"],"sourcesContent":["import { NewPlanSettings } from '../@types/plans';\r\n\r\nexport const DEV_MODE = import.meta.env.MODE !== 'production';\r\nexport const API_URL = DEV_MODE ? `${import.meta.env.VITE_BACKEND_URL}/api` : `${window.location.origin}/api`;\r\nexport const APP_NAME = import.meta.env.VITE_APP_NAME || 'Pluton';\r\nexport const DEFAULT_PLAN_SETTINGS: NewPlanSettings = {\r\n title: 'New Backup',\r\n method: 'backup',\r\n sourceId: 'main',\r\n sourceType: 'device',\r\n sourceConfig: {\r\n includes: [],\r\n excludes: [],\r\n },\r\n storage: { id: 's89hibdias67', name: '' },\r\n storagePath: '',\r\n settings: {\r\n interval: { type: 'daily', time: '10:00AM', days: '', hours: '', minutes: 5 },\r\n compression: true,\r\n encryption: true,\r\n retries: 5,\r\n retryDelay: 300, // in seconds\r\n notification: {\r\n email: {\r\n enabled: false,\r\n case: 'failure',\r\n type: 'smtp',\r\n emails: '',\r\n },\r\n webhook: {\r\n enabled: false,\r\n case: 'failure',\r\n method: 'POST',\r\n contentType: 'application/json',\r\n url: '',\r\n },\r\n push: {\r\n enabled: false,\r\n url: '',\r\n case: 'failure',\r\n authType: 'none',\r\n authToken: '',\r\n tags: '',\r\n },\r\n slack: {\r\n enabled: false,\r\n case: 'failure',\r\n url: '',\r\n },\r\n discord: {\r\n enabled: false,\r\n case: 'failure',\r\n url: '',\r\n },\r\n },\r\n prune: {\r\n snapCount: 5,\r\n policy: 'forgetByAge',\r\n forgetAge: '1m',\r\n revisions: true,\r\n },\r\n performance: {\r\n scan: true,\r\n },\r\n integrity: {\r\n enabled: false,\r\n interval: { type: 'weekly', time: '10:00AM', days: 'sun', hours: '', minutes: 5 },\r\n method: 'no-read',\r\n notification: {\r\n email: {\r\n enabled: false,\r\n type: 'smtp',\r\n emails: '',\r\n case: 'failure',\r\n },\r\n webhook: {\r\n enabled: false,\r\n method: 'POST',\r\n contentType: 'application/json',\r\n url: '',\r\n case: 'failure',\r\n },\r\n push: {\r\n enabled: false,\r\n url: '',\r\n authType: 'none',\r\n authToken: '',\r\n tags: '',\r\n case: 'failure',\r\n },\r\n slack: {\r\n enabled: false,\r\n case: 'failure',\r\n url: '',\r\n },\r\n discord: {\r\n enabled: false,\r\n case: 'failure',\r\n url: '',\r\n },\r\n },\r\n },\r\n scripts: {\r\n onBackupStart: [],\r\n onBackupEnd: [],\r\n onBackupError: [],\r\n onBackupFailure: [],\r\n onBackupComplete: [],\r\n },\r\n },\r\n tags: [],\r\n};\r\n"],"names":["DEV_MODE","API_URL","APP_NAME","DEFAULT_PLAN_SETTINGS"],"mappings":"AAEO,MAAMA,IAAW,IACXC,IAAiE,GAAG,OAAO,SAAS,MAAM,QAC1FC,IAAW,UACXC,IAAyC;AAAA,EACnD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,cAAc;AAAA,IACX,UAAU,CAAA;AAAA,IACV,UAAU,CAAA;AAAA,EAAC;AAAA,EAEd,SAAS,EAAE,IAAI,gBAAgB,MAAM,GAAA;AAAA,EACrC,aAAa;AAAA,EACb,UAAU;AAAA,IACP,UAAU,EAAE,MAAM,SAAS,MAAM,WAAW,MAAM,IAAI,OAAO,IAAI,SAAS,EAAA;AAAA,IAC1E,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY;AAAA;AAAA,IACZ,cAAc;AAAA,MACX,OAAO;AAAA,QACJ,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,MAAA;AAAA,MAEX,SAAS;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,KAAK;AAAA,MAAA;AAAA,MAER,MAAM;AAAA,QACH,SAAS;AAAA,QACT,KAAK;AAAA,QACL,MAAM;AAAA,QACN,UAAU;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,MAAA;AAAA,MAET,OAAO;AAAA,QACJ,SAAS;AAAA,QACT,MAAM;AAAA,QACN,KAAK;AAAA,MAAA;AAAA,MAER,SAAS;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,QACN,KAAK;AAAA,MAAA;AAAA,IACR;AAAA,IAEH,OAAO;AAAA,MACJ,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,WAAW;AAAA,IAAA;AAAA,IAEd,aAAa;AAAA,MACV,MAAM;AAAA,IAAA;AAAA,IAET,WAAW;AAAA,MACR,SAAS;AAAA,MACT,UAAU,EAAE,MAAM,UAAU,MAAM,WAAW,MAAM,OAAO,OAAO,IAAI,SAAS,EAAA;AAAA,MAC9E,QAAQ;AAAA,MACR,cAAc;AAAA,QACX,OAAO;AAAA,UACJ,SAAS;AAAA,UACT,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,MAAM;AAAA,QAAA;AAAA,QAET,SAAS;AAAA,UACN,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,KAAK;AAAA,UACL,MAAM;AAAA,QAAA;AAAA,QAET,MAAM;AAAA,UACH,SAAS;AAAA,UACT,KAAK;AAAA,UACL,UAAU;AAAA,UACV,WAAW;AAAA,UACX,MAAM;AAAA,UACN,MAAM;AAAA,QAAA;AAAA,QAET,OAAO;AAAA,UACJ,SAAS;AAAA,UACT,MAAM;AAAA,UACN,KAAK;AAAA,QAAA;AAAA,QAER,SAAS;AAAA,UACN,SAAS;AAAA,UACT,MAAM;AAAA,UACN,KAAK;AAAA,QAAA;AAAA,MACR;AAAA,IACH;AAAA,IAEH,SAAS;AAAA,MACN,eAAe,CAAA;AAAA,MACf,aAAa,CAAA;AAAA,MACb,eAAe,CAAA;AAAA,MACf,iBAAiB,CAAA;AAAA,MACjB,kBAAkB,CAAA;AAAA,IAAC;AAAA,EACtB;AAAA,EAEH,MAAM,CAAA;AACT;"}
1
+ {"version":3,"file":"constants.js","sources":["../../src/utils/constants.ts"],"sourcesContent":["import { NewPlanSettings } from '../@types/plans';\r\n\r\nexport const DEV_MODE = import.meta.env.MODE !== 'production';\r\nexport const API_URL = DEV_MODE ? `${import.meta.env.VITE_BACKEND_URL}/api` : `${window.location.origin}/api`;\r\nexport const APP_NAME = import.meta.env.VITE_APP_NAME || 'Pluton';\r\nexport const DEFAULT_PLAN_SETTINGS: NewPlanSettings = {\r\n title: 'New Backup',\r\n method: 'backup',\r\n sourceId: 'main',\r\n sourceType: 'device',\r\n sourceConfig: {\r\n includes: [],\r\n excludes: [],\r\n },\r\n storage: { id: 's89hibdias67', name: '' },\r\n storagePath: '',\r\n settings: {\r\n interval: { type: 'daily', time: '10:00AM', days: '', hours: '', minutes: 5 },\r\n compression: true,\r\n encryption: true,\r\n retries: 5,\r\n retryDelay: 300, // in seconds\r\n notification: {\r\n email: {\r\n enabled: false,\r\n case: 'failure',\r\n type: 'smtp',\r\n emails: '',\r\n },\r\n webhook: {\r\n enabled: false,\r\n case: 'failure',\r\n method: 'POST',\r\n contentType: 'application/json',\r\n url: '',\r\n },\r\n push: {\r\n enabled: false,\r\n url: '',\r\n case: 'failure',\r\n authType: 'none',\r\n authToken: '',\r\n tags: '',\r\n },\r\n slack: {\r\n enabled: false,\r\n case: 'failure',\r\n url: '',\r\n },\r\n discord: {\r\n enabled: false,\r\n case: 'failure',\r\n url: '',\r\n },\r\n },\r\n prune: {\r\n snapCount: 5,\r\n policy: 'forgetByAge',\r\n forgetAge: '1m',\r\n revisions: false,\r\n },\r\n performance: {\r\n scan: true,\r\n },\r\n integrity: {\r\n enabled: false,\r\n interval: { type: 'weekly', time: '10:00AM', days: 'sun', hours: '', minutes: 5 },\r\n method: 'no-read',\r\n notification: {\r\n email: {\r\n enabled: false,\r\n type: 'smtp',\r\n emails: '',\r\n case: 'failure',\r\n },\r\n webhook: {\r\n enabled: false,\r\n method: 'POST',\r\n contentType: 'application/json',\r\n url: '',\r\n case: 'failure',\r\n },\r\n push: {\r\n enabled: false,\r\n url: '',\r\n authType: 'none',\r\n authToken: '',\r\n tags: '',\r\n case: 'failure',\r\n },\r\n slack: {\r\n enabled: false,\r\n case: 'failure',\r\n url: '',\r\n },\r\n discord: {\r\n enabled: false,\r\n case: 'failure',\r\n url: '',\r\n },\r\n },\r\n },\r\n scripts: {\r\n onBackupStart: [],\r\n onBackupEnd: [],\r\n onBackupError: [],\r\n onBackupFailure: [],\r\n onBackupComplete: [],\r\n },\r\n },\r\n tags: [],\r\n};\r\n"],"names":["DEV_MODE","API_URL","APP_NAME","DEFAULT_PLAN_SETTINGS"],"mappings":"AAEO,MAAMA,IAAW,IACXC,IAAiE,GAAG,OAAO,SAAS,MAAM,QAC1FC,IAAW,UACXC,IAAyC;AAAA,EACnD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,cAAc;AAAA,IACX,UAAU,CAAA;AAAA,IACV,UAAU,CAAA;AAAA,EAAC;AAAA,EAEd,SAAS,EAAE,IAAI,gBAAgB,MAAM,GAAA;AAAA,EACrC,aAAa;AAAA,EACb,UAAU;AAAA,IACP,UAAU,EAAE,MAAM,SAAS,MAAM,WAAW,MAAM,IAAI,OAAO,IAAI,SAAS,EAAA;AAAA,IAC1E,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY;AAAA;AAAA,IACZ,cAAc;AAAA,MACX,OAAO;AAAA,QACJ,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,MAAA;AAAA,MAEX,SAAS;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,KAAK;AAAA,MAAA;AAAA,MAER,MAAM;AAAA,QACH,SAAS;AAAA,QACT,KAAK;AAAA,QACL,MAAM;AAAA,QACN,UAAU;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,MAAA;AAAA,MAET,OAAO;AAAA,QACJ,SAAS;AAAA,QACT,MAAM;AAAA,QACN,KAAK;AAAA,MAAA;AAAA,MAER,SAAS;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,QACN,KAAK;AAAA,MAAA;AAAA,IACR;AAAA,IAEH,OAAO;AAAA,MACJ,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,WAAW;AAAA,IAAA;AAAA,IAEd,aAAa;AAAA,MACV,MAAM;AAAA,IAAA;AAAA,IAET,WAAW;AAAA,MACR,SAAS;AAAA,MACT,UAAU,EAAE,MAAM,UAAU,MAAM,WAAW,MAAM,OAAO,OAAO,IAAI,SAAS,EAAA;AAAA,MAC9E,QAAQ;AAAA,MACR,cAAc;AAAA,QACX,OAAO;AAAA,UACJ,SAAS;AAAA,UACT,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,MAAM;AAAA,QAAA;AAAA,QAET,SAAS;AAAA,UACN,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,KAAK;AAAA,UACL,MAAM;AAAA,QAAA;AAAA,QAET,MAAM;AAAA,UACH,SAAS;AAAA,UACT,KAAK;AAAA,UACL,UAAU;AAAA,UACV,WAAW;AAAA,UACX,MAAM;AAAA,UACN,MAAM;AAAA,QAAA;AAAA,QAET,OAAO;AAAA,UACJ,SAAS;AAAA,UACT,MAAM;AAAA,UACN,KAAK;AAAA,QAAA;AAAA,QAER,SAAS;AAAA,UACN,SAAS;AAAA,UACT,MAAM;AAAA,UACN,KAAK;AAAA,QAAA;AAAA,MACR;AAAA,IACH;AAAA,IAEH,SAAS;AAAA,MACN,eAAe,CAAA;AAAA,MACf,aAAa,CAAA;AAAA,MACb,eAAe,CAAA;AAAA,MACf,iBAAiB,CAAA;AAAA,MACjB,kBAAkB,CAAA;AAAA,IAAC;AAAA,EACtB;AAAA,EAEH,MAAM,CAAA;AACT;"}
@@ -1,5 +1,6 @@
1
1
  import { storageOptionField } from '../@types/storages';
2
2
  import { FileItem } from '../@types/system';
3
+ import { PlanInterval } from '../@types/plans';
3
4
  export declare const isMobile: () => boolean;
4
5
  export declare const timeAgo: (input: Date) => string | undefined;
5
6
  /** * Formats a duration in seconds to a human-readable string
@@ -34,5 +35,6 @@ export declare const getAvailableCliApps: (platform?: string) => {
34
35
  label: string;
35
36
  value: string;
36
37
  }[];
38
+ export declare const formatIntervalDisplay: (interval: PlanInterval) => string;
37
39
  export declare const secondsToMinutes: (seconds: number) => string;
38
40
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,eAAO,MAAM,QAAQ,QAAO,OA0B3B,CAAC;AAGF,eAAO,MAAM,OAAO,GAAI,OAAO,IAAI,uBAkBlC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,MAoBhD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,GAAG,MAAM,KAAG,MAYzD,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,MAW3C,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,KAAG,MAI7C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,MAEhD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,MAe3C,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,EAAE,oBAAgB,WAOtD,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,IAAI,MAAM,yIAuCnC,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,kCAU7C,CAAC;AAIF,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,EAAE,QAAQ,MAAM,YAa9D,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,OAAO,2jBAsB/C,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,EAAE,UAAU,MAAM,KAAG,OAyBlE,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBrD;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,OA0D5C,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,KAAG,OAOxC,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,OAAO,kBAAkB,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,kBAAkB,EAAE,KAAG,OAqBrI,CAAC;AAGF,eAAO,MAAM,uBAAuB,GAAI,OAAO,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC,EAAE;;CA4B/F,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,QAAQ,EAAE,EAAE,WAAW,MAAM,QAAQ,EAAE,eAAe,KAAK,GAAG,MAAM,eAqBxG,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,WAAW,MAAM;WACH,MAAM;WAAS,MAAM;GAwCtE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,WAK/C,CAAC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,eAAO,MAAM,QAAQ,QAAO,OA0B3B,CAAC;AAGF,eAAO,MAAM,OAAO,GAAI,OAAO,IAAI,uBAkBlC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,MAoBhD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,GAAG,MAAM,KAAG,MAYzD,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,MAW3C,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,KAAG,MAI7C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,MAEhD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,MAe3C,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,EAAE,oBAAgB,WAOtD,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,IAAI,MAAM,yIAuCnC,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,kCAU7C,CAAC;AAIF,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,EAAE,QAAQ,MAAM,YAa9D,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,OAAO,2jBAsB/C,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,EAAE,UAAU,MAAM,KAAG,OAyBlE,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBrD;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,OA0D5C,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,KAAG,OAOxC,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,OAAO,kBAAkB,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,kBAAkB,EAAE,KAAG,OAqBrI,CAAC;AAGF,eAAO,MAAM,uBAAuB,GAAI,OAAO,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC,EAAE;;CA4B/F,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,QAAQ,EAAE,EAAE,WAAW,MAAM,QAAQ,EAAE,eAAe,KAAK,GAAG,MAAM,eAqBxG,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,WAAW,MAAM;WACH,MAAM;WAAS,MAAM;GAwCtE,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,UAAU,YAAY,KAAG,MAsB9D,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,WAK/C,CAAC"}
@@ -39,23 +39,23 @@ const d = () => {
39
39
  for (; n >= 1024 && s < t.length - 1; )
40
40
  n /= 1024, s++;
41
41
  return `${n.toFixed(2)} ${t[s]}`;
42
- }, g = (e) => e < 1e3 ? e.toString() : `${(e / 1e3).toFixed(1)}k`, w = (e) => (e & 511).toString(8).padStart(3, "0"), v = (e) => e >= 86400 ? `${Math.floor(e / 86400)}d` : e >= 3600 ? `${Math.floor(e / 3600)}h` : e >= 60 ? `${Math.floor(e / 60)}m` : `${Math.floor(e)}s`, b = (e, t = 10) => {
42
+ }, g = (e) => e < 1e3 ? e.toString() : `${(e / 1e3).toFixed(1)}k`, w = (e) => (e & 511).toString(8).padStart(3, "0"), y = (e) => e >= 86400 ? `${Math.floor(e / 86400)}d` : e >= 3600 ? `${Math.floor(e / 3600)}h` : e >= 60 ? `${Math.floor(e / 60)}m` : `${Math.floor(e)}s`, v = (e, t = 10) => {
43
43
  if (e.length <= t * 2) return e;
44
44
  const n = e.slice(0, t), s = e.slice(-t);
45
45
  return `${n}...${s}`;
46
- }, $ = (e) => {
46
+ }, b = (e) => {
47
47
  const t = e.toLowerCase();
48
48
  return t.includes("windows") ? "windows" : t.includes("mac") ? "macos" : t.includes("centos") ? "centos" : t.includes("fedora") ? "fedora" : t.includes("debian") ? "debian" : t.includes("mint") ? "mint" : t.includes("pop") ? "popos" : t.includes("ubuntu") ? "ubuntu" : t.includes("kali") ? "kali" : t.includes("arch") ? "arch" : t.includes("zorin") ? "zorin" : t.includes("manjaro") ? "manjaro" : "linux";
49
- }, y = (e) => {
49
+ }, $ = (e) => {
50
50
  const t = e.toLowerCase();
51
51
  return t.includes("amd") ? "amd" : t.includes("intel") ? "intel" : "processor";
52
52
  }, z = (e, t) => {
53
53
  if (!e || !t) return !1;
54
54
  const n = e.split(".").map(Number), s = t.split(".").map(Number);
55
55
  for (let r = 0; r < 3; r++) {
56
- const o = n[r] || 0, a = s[r] || 0;
57
- if (o < a) return !0;
58
- if (o > a) return !1;
56
+ const o = n[r] || 0, i = s[r] || 0;
57
+ if (o < i) return !0;
58
+ if (o > i) return !1;
59
59
  }
60
60
  return !1;
61
61
  }, A = (e) => {
@@ -80,7 +80,7 @@ function S(e) {
80
80
  return "unknown";
81
81
  }
82
82
  }
83
- const x = (e) => {
83
+ const k = (e) => {
84
84
  if (!e || typeof e != "string")
85
85
  return !1;
86
86
  const t = e.trim();
@@ -89,18 +89,18 @@ const x = (e) => {
89
89
  const [s, r] = t.split("@");
90
90
  if (!s || s.length > 64 || !r || r.length > 253 || !r.includes("."))
91
91
  return !1;
92
- const o = r.split("."), a = o[o.length - 1];
93
- return !(!a || a.length < 2 || s.startsWith(".") || s.endsWith(".") || s.includes("..") || r.startsWith(".") || r.endsWith(".") || r.includes(".."));
94
- }, B = (e) => {
92
+ const o = r.split("."), i = o[o.length - 1];
93
+ return !(!i || i.length < 2 || s.startsWith(".") || s.endsWith(".") || s.includes("..") || r.startsWith(".") || r.endsWith(".") || r.includes(".."));
94
+ }, x = (e) => {
95
95
  try {
96
96
  return new URL(e), !0;
97
97
  } catch {
98
98
  return !1;
99
99
  }
100
- }, k = (e, t, n) => !e.condition || e.condition.length === 0 ? !0 : e.condition.some((s) => Object.entries(s).every(([r, o]) => {
101
- const a = n.find((i) => i.value === r);
102
- return a ? (t[r] !== void 0 ? t[r] : a.default) === o : !1;
103
- })), P = (e) => {
100
+ }, B = (e, t, n) => !e.condition || e.condition.length === 0 ? !0 : e.condition.some((s) => Object.entries(s).every(([r, o]) => {
101
+ const i = n.find((a) => a.value === r);
102
+ return i ? (t[r] !== void 0 ? t[r] : i.default) === o : !1;
103
+ })), L = (e) => {
104
104
  const t = {};
105
105
  return e.forEach((n) => {
106
106
  n.isDirectory && (t[n.path] = 0);
@@ -111,20 +111,20 @@ const x = (e) => {
111
111
  r = r ? `${r}/${s[o]}` : `/${s[o]}`, t[r] !== void 0 && (t[r] += n.size);
112
112
  }
113
113
  }), t;
114
- }, L = (e, t, n) => [...e].sort((s, r) => {
115
- var o, a;
114
+ }, P = (e, t, n) => [...e].sort((s, r) => {
115
+ var o, i;
116
116
  if (t === "name") {
117
- const u = s.name.toLowerCase(), i = r.name.toLowerCase();
118
- return n === "asc" ? u.localeCompare(i) : i.localeCompare(u);
117
+ const u = s.name.toLowerCase(), a = r.name.toLowerCase();
118
+ return n === "asc" ? u.localeCompare(a) : a.localeCompare(u);
119
119
  } else if (t === "modifiedAt") {
120
- const u = new Date(s.modifiedAt).getTime(), i = new Date(r.modifiedAt).getTime();
121
- return n === "asc" ? u - i : i - u;
120
+ const u = new Date(s.modifiedAt).getTime(), a = new Date(r.modifiedAt).getTime();
121
+ return n === "asc" ? u - a : a - u;
122
122
  } else if (t === "size") {
123
- const u = s.size || 0, i = r.size || 0;
124
- return n === "asc" ? u - i : i - u;
123
+ const u = s.size || 0, a = r.size || 0;
124
+ return n === "asc" ? u - a : a - u;
125
125
  } else {
126
- const u = n === "asc" ? 1 : -1, i = ((o = s[t]) == null ? void 0 : o.toString()) || "", l = ((a = r[t]) == null ? void 0 : a.toString()) || "";
127
- return i.localeCompare(l) * u;
126
+ const u = n === "asc" ? 1 : -1, a = ((o = s[t]) == null ? void 0 : o.toString()) || "", l = ((i = r[t]) == null ? void 0 : i.toString()) || "";
127
+ return a.localeCompare(l) * u;
128
128
  }
129
129
  }), T = (e) => {
130
130
  const t = {
@@ -162,29 +162,51 @@ const x = (e) => {
162
162
  });
163
163
  }), n;
164
164
  }
165
+ }, D = (e) => {
166
+ var n, s;
167
+ const t = e.time ? ` at ${e.time}` : "";
168
+ switch (e.type) {
169
+ case "hourly":
170
+ return "every hour";
171
+ case "hours":
172
+ return `every ${(n = e.hours) == null ? void 0 : n.replace("hrs", "")} hours`;
173
+ case "minutes":
174
+ return `every ${e.minutes} minutes`;
175
+ case "daily":
176
+ return `daily${t}`;
177
+ case "weekly":
178
+ return `weekly on ${e.days}${t}`;
179
+ case "days":
180
+ return `every ${(s = e.days) == null ? void 0 : s.replace(/-$/, "").replace(/-/g, ", ")}${t}`;
181
+ case "monthly":
182
+ return `monthly (${e.days})${t}`;
183
+ default:
184
+ return e.type;
185
+ }
165
186
  }, C = (e) => e === 0 ? "" : e > 60 ? `${Math.round(e / 60)} min` : `${e} sec`;
166
187
  export {
167
- P as calculateDirectorySizes,
168
- b as clipPath,
188
+ L as calculateDirectorySizes,
189
+ v as clipPath,
169
190
  z as compareVersions,
170
191
  m as formatBytes,
171
192
  p as formatDateTime,
172
193
  h as formatDuration,
194
+ D as formatIntervalDisplay,
173
195
  g as formatNumberToK,
174
196
  w as formatPermissions,
175
- v as formatSeconds,
197
+ y as formatSeconds,
176
198
  T as getAvailableCliApps,
177
199
  S as getLogLevelName,
178
- $ as getOSIcon,
179
- y as getProcessorIcon,
200
+ b as getOSIcon,
201
+ $ as getProcessorIcon,
180
202
  A as getUpdateDocLink,
181
203
  d as isMobile,
182
204
  M as isServerEdition,
183
- x as isValidEmail,
184
- B as isValidURL,
205
+ k as isValidEmail,
206
+ x as isValidURL,
185
207
  C as secondsToMinutes,
186
- k as shouldDisplayStorageField,
187
- L as sortFileItems,
208
+ B as shouldDisplayStorageField,
209
+ P as sortFileItems,
188
210
  f as timeAgo
189
211
  };
190
212
  //# sourceMappingURL=helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sources":["../../src/utils/helpers.ts"],"sourcesContent":["import { storageOptionField } from '../@types/storages';\r\nimport { FileItem } from '../@types/system';\r\n\r\nexport const isMobile = (): boolean => {\r\n // Server-side rendering check\r\n if (typeof navigator === 'undefined' || typeof window === 'undefined') {\r\n return false;\r\n }\r\n\r\n const userAgent = navigator.userAgent || navigator.vendor || (window as any).opera || '';\r\n\r\n // Check for mobile user agents\r\n const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i;\r\n\r\n // Check for touch capability and screen size\r\n const hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\r\n const smallScreen = window.innerWidth <= 768;\r\n\r\n // Primary check: user agent\r\n if (mobileRegex.test(userAgent)) {\r\n return true;\r\n }\r\n\r\n // Secondary check: touch + small screen (for edge cases)\r\n if (hasTouch && smallScreen) {\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\nconst formatter = new Intl.RelativeTimeFormat('en');\r\nexport const timeAgo = (input: Date) => {\r\n const date = input instanceof Date ? input : new Date(input);\r\n const ranges: { [k: string]: number } = {\r\n years: 3600 * 24 * 365,\r\n months: 3600 * 24 * 30,\r\n weeks: 3600 * 24 * 7,\r\n days: 3600 * 24,\r\n hours: 3600,\r\n minutes: 60,\r\n seconds: 1,\r\n };\r\n const secondsElapsed = (date.getTime() - Date.now()) / 1000;\r\n for (const key in ranges) {\r\n if (ranges[key] < Math.abs(secondsElapsed)) {\r\n const delta = secondsElapsed / ranges[key];\r\n return formatter.format(Math.round(delta), key as Intl.RelativeTimeFormatUnit);\r\n }\r\n }\r\n};\r\n\r\n/** * Formats a duration in seconds to a human-readable string\r\n * @param seconds - Duration in seconds\r\n */\r\nexport const formatDuration = (seconds: number): string => {\r\n if (!seconds) return '0s';\r\n\r\n if (seconds < 1) {\r\n return `${Math.round(seconds * 1000)}ms`;\r\n }\r\n\r\n const hours = Math.floor(seconds / 3600);\r\n const minutes = Math.floor((seconds % 3600) / 60);\r\n const remainingSeconds = Math.floor(seconds % 60);\r\n\r\n if (hours >= 1) {\r\n return `${hours} h ${minutes} min`;\r\n }\r\n\r\n if (minutes >= 1) {\r\n return `${minutes} min`;\r\n }\r\n\r\n return `${remainingSeconds}s`;\r\n};\r\n\r\nexport const formatDateTime = (isoDate: string | number): string => {\r\n const date = new Date(isoDate);\r\n\r\n const options: Intl.DateTimeFormatOptions = {\r\n year: 'numeric',\r\n month: 'short',\r\n day: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n };\r\n\r\n return date.toLocaleString('en-US', options);\r\n};\r\n\r\nexport const formatBytes = (bytes: number): string => {\r\n const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];\r\n let value = bytes || 0;\r\n let unitIndex = 0;\r\n\r\n while (value >= 1024 && unitIndex < units.length - 1) {\r\n value /= 1024;\r\n unitIndex++;\r\n }\r\n\r\n return `${value.toFixed(2)} ${units[unitIndex]}`;\r\n};\r\n\r\nexport const formatNumberToK = (num: number): string => {\r\n if (num < 1000) return num.toString();\r\n const value = num / 1000;\r\n return `${value.toFixed(1)}k`;\r\n};\r\n\r\nexport const formatPermissions = (mode: number): string => {\r\n return (mode & 0o777).toString(8).padStart(3, '0');\r\n};\r\n\r\nexport const formatSeconds = (num: number): string => {\r\n // should convert seconds to minutes, hours or days if applicable\r\n if (num >= 86400) {\r\n return `${Math.floor(num / 86400)}d`;\r\n }\r\n\r\n if (num >= 3600) {\r\n return `${Math.floor(num / 3600)}h`;\r\n }\r\n\r\n if (num >= 60) {\r\n return `${Math.floor(num / 60)}m`;\r\n }\r\n\r\n return `${Math.floor(num)}s`;\r\n};\r\n\r\nexport const clipPath = (path: string, charsOnSide = 10) => {\r\n if (path.length <= charsOnSide * 2) return path;\r\n\r\n const start = path.slice(0, charsOnSide);\r\n const end = path.slice(-charsOnSide);\r\n\r\n return `${start}...${end}`;\r\n};\r\n\r\nexport const getOSIcon = (os: string) => {\r\n const osString = os.toLowerCase();\r\n if (osString.includes('windows')) {\r\n return 'windows';\r\n }\r\n if (osString.includes('mac')) {\r\n return 'macos';\r\n }\r\n if (osString.includes('centos')) {\r\n return 'centos';\r\n }\r\n if (osString.includes('fedora')) {\r\n return 'fedora';\r\n }\r\n if (osString.includes('debian')) {\r\n return 'debian';\r\n }\r\n if (osString.includes('mint')) {\r\n return 'mint';\r\n }\r\n if (osString.includes('pop')) {\r\n return 'popos';\r\n }\r\n if (osString.includes('ubuntu')) {\r\n return 'ubuntu';\r\n }\r\n if (osString.includes('kali')) {\r\n return 'kali';\r\n }\r\n if (osString.includes('arch')) {\r\n return 'arch';\r\n }\r\n if (osString.includes('zorin')) {\r\n return 'zorin';\r\n }\r\n if (osString.includes('manjaro')) {\r\n return 'manjaro';\r\n }\r\n return 'linux';\r\n};\r\n\r\nexport const getProcessorIcon = (brand: string) => {\r\n const osString = brand.toLowerCase();\r\n if (osString.includes('amd')) {\r\n return 'amd';\r\n }\r\n if (osString.includes('intel')) {\r\n return 'intel';\r\n }\r\n\r\n return 'processor';\r\n};\r\n\r\n// Compares two version strings (e.g., \"1.2.3\" and \"1.3.0\")\r\n// returns true if the latest version is newer than the current version\r\nexport const compareVersions = (current: string, latest: string) => {\r\n if (!current || !latest) return false;\r\n const currentParts = current.split('.').map(Number);\r\n const latestParts = latest.split('.').map(Number);\r\n\r\n for (let i = 0; i < 3; i++) {\r\n const curr = currentParts[i] || 0;\r\n const late = latestParts[i] || 0;\r\n\r\n if (curr < late) return true;\r\n if (curr > late) return false;\r\n }\r\n return false;\r\n};\r\n\r\nexport const getUpdateDocLink = (isPRO?: boolean) => {\r\n const installType = (window as any).plutonInstallType || 'unknown';\r\n console.log('installType :', installType);\r\n if (installType === 'binary') {\r\n if (isPRO) {\r\n return 'https://docs.usepluton.com/docs/pluton-pro/install-pluton-pro-desktop#updating';\r\n }\r\n return 'https://docs.usepluton.com/docs/getting-started/install-pluton-desktop#updating';\r\n }\r\n if (installType === 'server') {\r\n if (isPRO) {\r\n return 'https://docs.usepluton.com/docs/pluton-pro/install-pluton-pro-linux-server#updating';\r\n }\r\n return 'https://docs.usepluton.com/docs/getting-started/install-pluton-linux-server#updating-pluton';\r\n }\r\n if (installType === 'docker') {\r\n if (isPRO) {\r\n return 'https://docs.usepluton.com/docs/pluton-pro/deploy-pluton-pro-docker#updating';\r\n }\r\n return 'https://docs.usepluton.com/docs/getting-started/deploy-docker#quick-reference';\r\n }\r\n return 'https://github.com/plutonhq/pluton/releases/latest';\r\n};\r\n\r\nexport const isServerEdition = (distro: string, platform: string): boolean => {\r\n // Check Windows Server editions\r\n if (platform === 'win32') {\r\n return distro.includes('server') || distro.includes('windows server');\r\n }\r\n\r\n // Check Linux server distributions\r\n if (platform === 'linux') {\r\n return (\r\n distro.includes('server') ||\r\n distro.includes('enterprise') ||\r\n distro.includes('centos') ||\r\n distro.includes('redhat') ||\r\n distro.includes('ubuntu server') ||\r\n distro.includes('debian') ||\r\n distro.includes('fedora server')\r\n );\r\n }\r\n\r\n // Check macOS Server (though it's discontinued, some may still use it)\r\n if (platform === 'darwin') {\r\n return distro.includes('server');\r\n }\r\n\r\n return false;\r\n};\r\n\r\nexport function getLogLevelName(level: number): string {\r\n switch (level) {\r\n case 10:\r\n return 'trace';\r\n case 20:\r\n return 'debug';\r\n case 30:\r\n return 'info';\r\n case 40:\r\n return 'warn';\r\n case 50:\r\n return 'error';\r\n case 60:\r\n return 'fatal';\r\n default:\r\n return 'unknown';\r\n }\r\n}\r\n\r\n/**\r\n * Validates if a string is a valid email address\r\n * @param email - The email string to validate\r\n * @returns boolean - True if email is valid, false otherwise\r\n */\r\nexport const isValidEmail = (email: string): boolean => {\r\n if (!email || typeof email !== 'string') {\r\n return false;\r\n }\r\n\r\n const trimmedEmail = email.trim();\r\n\r\n // Check length limits\r\n if (trimmedEmail.length === 0 || trimmedEmail.length > 254) {\r\n return false;\r\n }\r\n\r\n // More strict email regex that requires proper TLD\r\n const emailRegex =\r\n /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;\r\n\r\n if (!emailRegex.test(trimmedEmail)) {\r\n return false;\r\n }\r\n\r\n // Split and validate local and domain parts\r\n const [localPart, domainPart] = trimmedEmail.split('@');\r\n\r\n // Validate local part (before @)\r\n if (!localPart || localPart.length > 64) {\r\n return false;\r\n }\r\n\r\n // Validate domain part (after @)\r\n if (!domainPart || domainPart.length > 253) {\r\n return false;\r\n }\r\n\r\n // Ensure domain has at least one dot and proper TLD\r\n if (!domainPart.includes('.')) {\r\n return false;\r\n }\r\n\r\n // Check TLD is at least 2 characters\r\n const domainParts = domainPart.split('.');\r\n const tld = domainParts[domainParts.length - 1];\r\n if (!tld || tld.length < 2) {\r\n return false;\r\n }\r\n\r\n // Check for invalid patterns\r\n if (\r\n localPart.startsWith('.') ||\r\n localPart.endsWith('.') ||\r\n localPart.includes('..') ||\r\n domainPart.startsWith('.') ||\r\n domainPart.endsWith('.') ||\r\n domainPart.includes('..')\r\n ) {\r\n return false;\r\n }\r\n\r\n return true;\r\n};\r\n\r\nexport const isValidURL = (url: string): boolean => {\r\n try {\r\n new URL(url);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\nexport const shouldDisplayStorageField = (field: storageOptionField, settings: Record<string, any>, allFields: storageOptionField[]): boolean => {\r\n // If no conditions, always display the field\r\n if (!field.condition || field.condition.length === 0) {\r\n return true;\r\n }\r\n\r\n // A field is displayed if ANY of its conditions are fully satisfied\r\n return field.condition.some((condition) => {\r\n // A condition is satisfied if ALL its key-value pairs match\r\n return Object.entries(condition).every(([condKey, condValue]) => {\r\n // Find the field that this condition refers to\r\n const targetField = allFields.find((f) => f.value === condKey);\r\n if (!targetField) return false;\r\n\r\n // Get the current value from settings, or use the default\r\n const currentValue = settings[condKey] !== undefined ? settings[condKey] : targetField.default;\r\n\r\n // Check if the condition value matches the field's value\r\n return currentValue === condValue;\r\n });\r\n });\r\n};\r\n\r\n// Calculate the size of each directory based on its files\r\nexport const calculateDirectorySizes = (files: Pick<FileItem, 'path' | 'size' | 'isDirectory'>[]) => {\r\n const dirSizes: { [path: string]: number } = {};\r\n\r\n // Initialize all directories with size 0\r\n files.forEach((file) => {\r\n if (file.isDirectory) {\r\n dirSizes[file.path] = 0;\r\n }\r\n });\r\n\r\n // Sum up file sizes for each directory\r\n files.forEach((file) => {\r\n if (!file.isDirectory && file.size) {\r\n // For each file, add its size to all parent directories\r\n let pathParts = file.path.split('/').filter(Boolean);\r\n let currentPath = '';\r\n\r\n // Add size to each parent directory\r\n for (let i = 0; i < pathParts.length - 1; i++) {\r\n currentPath = currentPath ? `${currentPath}/${pathParts[i]}` : `/${pathParts[i]}`;\r\n if (dirSizes[currentPath] !== undefined) {\r\n dirSizes[currentPath] += file.size;\r\n }\r\n }\r\n }\r\n });\r\n\r\n return dirSizes;\r\n};\r\n\r\nexport const sortFileItems = (items: FileItem[], sortField: keyof FileItem, sortDirection: 'asc' | 'desc') => {\r\n return [...items].sort((a, b) => {\r\n if (sortField === 'name') {\r\n const nameA = a.name.toLowerCase();\r\n const nameB = b.name.toLowerCase();\r\n return sortDirection === 'asc' ? nameA.localeCompare(nameB) : nameB.localeCompare(nameA);\r\n } else if (sortField === 'modifiedAt') {\r\n const dateA = new Date(a.modifiedAt).getTime();\r\n const dateB = new Date(b.modifiedAt).getTime();\r\n return sortDirection === 'asc' ? dateA - dateB : dateB - dateA;\r\n } else if (sortField === 'size') {\r\n const sizeA = a.size || 0;\r\n const sizeB = b.size || 0;\r\n return sortDirection === 'asc' ? sizeA - sizeB : sizeB - sizeA;\r\n } else {\r\n const multiplier = sortDirection === 'asc' ? 1 : -1;\r\n const valueA = a[sortField]?.toString() || '';\r\n const valueB = b[sortField]?.toString() || '';\r\n return valueA.localeCompare(valueB) * multiplier;\r\n }\r\n });\r\n};\r\n\r\nexport const getAvailableCliApps = (platform?: string) => {\r\n const availableShells: Record<string, { label: string; value: string }[]> = {\r\n Windows: [\r\n { label: 'PowerShell', value: 'powershell' },\r\n { label: 'Command Prompt (CMD)', value: 'cmd' },\r\n { label: 'Bash', value: 'bash' },\r\n ],\r\n MacOs: [\r\n { label: 'Zsh', value: 'zsh' },\r\n { label: 'Bash', value: '/bin/bash' },\r\n { label: 'sh', value: '/bin/sh' },\r\n ],\r\n Linux: [\r\n { label: 'Bash', value: '/bin/bash' },\r\n { label: 'sh', value: '/bin/sh' },\r\n { label: 'Zsh', value: 'zsh' },\r\n ],\r\n };\r\n type typeofOSType = keyof typeof availableShells;\r\n\r\n switch (platform) {\r\n case 'win32':\r\n case 'windows':\r\n case 'Windows':\r\n return availableShells.Windows;\r\n case 'darwin':\r\n return availableShells.MacOs;\r\n case 'linux':\r\n case 'Linux':\r\n return availableShells.Linux;\r\n default:\r\n const allShells: { label: string; value: string }[] = [];\r\n (Object.keys(availableShells) as typeofOSType[]).map((OSType) => {\r\n availableShells[OSType].forEach((shell) => {\r\n if (allShells.findIndex((s) => s.value === shell.value) === -1) {\r\n allShells.push({ label: `${shell.label} (${shell.value})`, value: shell.value });\r\n }\r\n });\r\n });\r\n return allShells;\r\n }\r\n};\r\n\r\nexport const secondsToMinutes = (seconds: number) => {\r\n if (seconds === 0) {\r\n return '';\r\n }\r\n return seconds > 60 ? `${Math.round(seconds / 60)} min` : `${seconds} sec`;\r\n};\r\n"],"names":["isMobile","userAgent","mobileRegex","hasTouch","smallScreen","formatter","timeAgo","input","date","ranges","secondsElapsed","key","delta","formatDuration","seconds","hours","minutes","remainingSeconds","formatDateTime","isoDate","options","formatBytes","bytes","units","value","unitIndex","formatNumberToK","num","formatPermissions","mode","formatSeconds","clipPath","path","charsOnSide","start","end","getOSIcon","os","osString","getProcessorIcon","brand","compareVersions","current","latest","currentParts","latestParts","i","curr","late","getUpdateDocLink","isPRO","installType","isServerEdition","distro","platform","getLogLevelName","level","isValidEmail","email","trimmedEmail","localPart","domainPart","domainParts","tld","isValidURL","url","shouldDisplayStorageField","field","settings","allFields","condition","condKey","condValue","targetField","f","calculateDirectorySizes","files","dirSizes","file","pathParts","currentPath","sortFileItems","items","sortField","sortDirection","a","b","_a","_b","nameA","nameB","dateA","dateB","sizeA","sizeB","multiplier","valueA","valueB","getAvailableCliApps","availableShells","allShells","OSType","shell","s","secondsToMinutes"],"mappings":"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"}
1
+ {"version":3,"file":"helpers.js","sources":["../../src/utils/helpers.ts"],"sourcesContent":["import { storageOptionField } from '../@types/storages';\r\nimport { FileItem } from '../@types/system';\r\nimport { PlanInterval } from '../@types/plans';\r\n\r\nexport const isMobile = (): boolean => {\r\n // Server-side rendering check\r\n if (typeof navigator === 'undefined' || typeof window === 'undefined') {\r\n return false;\r\n }\r\n\r\n const userAgent = navigator.userAgent || navigator.vendor || (window as any).opera || '';\r\n\r\n // Check for mobile user agents\r\n const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i;\r\n\r\n // Check for touch capability and screen size\r\n const hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\r\n const smallScreen = window.innerWidth <= 768;\r\n\r\n // Primary check: user agent\r\n if (mobileRegex.test(userAgent)) {\r\n return true;\r\n }\r\n\r\n // Secondary check: touch + small screen (for edge cases)\r\n if (hasTouch && smallScreen) {\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\nconst formatter = new Intl.RelativeTimeFormat('en');\r\nexport const timeAgo = (input: Date) => {\r\n const date = input instanceof Date ? input : new Date(input);\r\n const ranges: { [k: string]: number } = {\r\n years: 3600 * 24 * 365,\r\n months: 3600 * 24 * 30,\r\n weeks: 3600 * 24 * 7,\r\n days: 3600 * 24,\r\n hours: 3600,\r\n minutes: 60,\r\n seconds: 1,\r\n };\r\n const secondsElapsed = (date.getTime() - Date.now()) / 1000;\r\n for (const key in ranges) {\r\n if (ranges[key] < Math.abs(secondsElapsed)) {\r\n const delta = secondsElapsed / ranges[key];\r\n return formatter.format(Math.round(delta), key as Intl.RelativeTimeFormatUnit);\r\n }\r\n }\r\n};\r\n\r\n/** * Formats a duration in seconds to a human-readable string\r\n * @param seconds - Duration in seconds\r\n */\r\nexport const formatDuration = (seconds: number): string => {\r\n if (!seconds) return '0s';\r\n\r\n if (seconds < 1) {\r\n return `${Math.round(seconds * 1000)}ms`;\r\n }\r\n\r\n const hours = Math.floor(seconds / 3600);\r\n const minutes = Math.floor((seconds % 3600) / 60);\r\n const remainingSeconds = Math.floor(seconds % 60);\r\n\r\n if (hours >= 1) {\r\n return `${hours} h ${minutes} min`;\r\n }\r\n\r\n if (minutes >= 1) {\r\n return `${minutes} min`;\r\n }\r\n\r\n return `${remainingSeconds}s`;\r\n};\r\n\r\nexport const formatDateTime = (isoDate: string | number): string => {\r\n const date = new Date(isoDate);\r\n\r\n const options: Intl.DateTimeFormatOptions = {\r\n year: 'numeric',\r\n month: 'short',\r\n day: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n };\r\n\r\n return date.toLocaleString('en-US', options);\r\n};\r\n\r\nexport const formatBytes = (bytes: number): string => {\r\n const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];\r\n let value = bytes || 0;\r\n let unitIndex = 0;\r\n\r\n while (value >= 1024 && unitIndex < units.length - 1) {\r\n value /= 1024;\r\n unitIndex++;\r\n }\r\n\r\n return `${value.toFixed(2)} ${units[unitIndex]}`;\r\n};\r\n\r\nexport const formatNumberToK = (num: number): string => {\r\n if (num < 1000) return num.toString();\r\n const value = num / 1000;\r\n return `${value.toFixed(1)}k`;\r\n};\r\n\r\nexport const formatPermissions = (mode: number): string => {\r\n return (mode & 0o777).toString(8).padStart(3, '0');\r\n};\r\n\r\nexport const formatSeconds = (num: number): string => {\r\n // should convert seconds to minutes, hours or days if applicable\r\n if (num >= 86400) {\r\n return `${Math.floor(num / 86400)}d`;\r\n }\r\n\r\n if (num >= 3600) {\r\n return `${Math.floor(num / 3600)}h`;\r\n }\r\n\r\n if (num >= 60) {\r\n return `${Math.floor(num / 60)}m`;\r\n }\r\n\r\n return `${Math.floor(num)}s`;\r\n};\r\n\r\nexport const clipPath = (path: string, charsOnSide = 10) => {\r\n if (path.length <= charsOnSide * 2) return path;\r\n\r\n const start = path.slice(0, charsOnSide);\r\n const end = path.slice(-charsOnSide);\r\n\r\n return `${start}...${end}`;\r\n};\r\n\r\nexport const getOSIcon = (os: string) => {\r\n const osString = os.toLowerCase();\r\n if (osString.includes('windows')) {\r\n return 'windows';\r\n }\r\n if (osString.includes('mac')) {\r\n return 'macos';\r\n }\r\n if (osString.includes('centos')) {\r\n return 'centos';\r\n }\r\n if (osString.includes('fedora')) {\r\n return 'fedora';\r\n }\r\n if (osString.includes('debian')) {\r\n return 'debian';\r\n }\r\n if (osString.includes('mint')) {\r\n return 'mint';\r\n }\r\n if (osString.includes('pop')) {\r\n return 'popos';\r\n }\r\n if (osString.includes('ubuntu')) {\r\n return 'ubuntu';\r\n }\r\n if (osString.includes('kali')) {\r\n return 'kali';\r\n }\r\n if (osString.includes('arch')) {\r\n return 'arch';\r\n }\r\n if (osString.includes('zorin')) {\r\n return 'zorin';\r\n }\r\n if (osString.includes('manjaro')) {\r\n return 'manjaro';\r\n }\r\n return 'linux';\r\n};\r\n\r\nexport const getProcessorIcon = (brand: string) => {\r\n const osString = brand.toLowerCase();\r\n if (osString.includes('amd')) {\r\n return 'amd';\r\n }\r\n if (osString.includes('intel')) {\r\n return 'intel';\r\n }\r\n\r\n return 'processor';\r\n};\r\n\r\n// Compares two version strings (e.g., \"1.2.3\" and \"1.3.0\")\r\n// returns true if the latest version is newer than the current version\r\nexport const compareVersions = (current: string, latest: string) => {\r\n if (!current || !latest) return false;\r\n const currentParts = current.split('.').map(Number);\r\n const latestParts = latest.split('.').map(Number);\r\n\r\n for (let i = 0; i < 3; i++) {\r\n const curr = currentParts[i] || 0;\r\n const late = latestParts[i] || 0;\r\n\r\n if (curr < late) return true;\r\n if (curr > late) return false;\r\n }\r\n return false;\r\n};\r\n\r\nexport const getUpdateDocLink = (isPRO?: boolean) => {\r\n const installType = (window as any).plutonInstallType || 'unknown';\r\n console.log('installType :', installType);\r\n if (installType === 'binary') {\r\n if (isPRO) {\r\n return 'https://docs.usepluton.com/docs/pluton-pro/install-pluton-pro-desktop#updating';\r\n }\r\n return 'https://docs.usepluton.com/docs/getting-started/install-pluton-desktop#updating';\r\n }\r\n if (installType === 'server') {\r\n if (isPRO) {\r\n return 'https://docs.usepluton.com/docs/pluton-pro/install-pluton-pro-linux-server#updating';\r\n }\r\n return 'https://docs.usepluton.com/docs/getting-started/install-pluton-linux-server#updating-pluton';\r\n }\r\n if (installType === 'docker') {\r\n if (isPRO) {\r\n return 'https://docs.usepluton.com/docs/pluton-pro/deploy-pluton-pro-docker#updating';\r\n }\r\n return 'https://docs.usepluton.com/docs/getting-started/deploy-docker#quick-reference';\r\n }\r\n return 'https://github.com/plutonhq/pluton/releases/latest';\r\n};\r\n\r\nexport const isServerEdition = (distro: string, platform: string): boolean => {\r\n // Check Windows Server editions\r\n if (platform === 'win32') {\r\n return distro.includes('server') || distro.includes('windows server');\r\n }\r\n\r\n // Check Linux server distributions\r\n if (platform === 'linux') {\r\n return (\r\n distro.includes('server') ||\r\n distro.includes('enterprise') ||\r\n distro.includes('centos') ||\r\n distro.includes('redhat') ||\r\n distro.includes('ubuntu server') ||\r\n distro.includes('debian') ||\r\n distro.includes('fedora server')\r\n );\r\n }\r\n\r\n // Check macOS Server (though it's discontinued, some may still use it)\r\n if (platform === 'darwin') {\r\n return distro.includes('server');\r\n }\r\n\r\n return false;\r\n};\r\n\r\nexport function getLogLevelName(level: number): string {\r\n switch (level) {\r\n case 10:\r\n return 'trace';\r\n case 20:\r\n return 'debug';\r\n case 30:\r\n return 'info';\r\n case 40:\r\n return 'warn';\r\n case 50:\r\n return 'error';\r\n case 60:\r\n return 'fatal';\r\n default:\r\n return 'unknown';\r\n }\r\n}\r\n\r\n/**\r\n * Validates if a string is a valid email address\r\n * @param email - The email string to validate\r\n * @returns boolean - True if email is valid, false otherwise\r\n */\r\nexport const isValidEmail = (email: string): boolean => {\r\n if (!email || typeof email !== 'string') {\r\n return false;\r\n }\r\n\r\n const trimmedEmail = email.trim();\r\n\r\n // Check length limits\r\n if (trimmedEmail.length === 0 || trimmedEmail.length > 254) {\r\n return false;\r\n }\r\n\r\n // More strict email regex that requires proper TLD\r\n const emailRegex =\r\n /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;\r\n\r\n if (!emailRegex.test(trimmedEmail)) {\r\n return false;\r\n }\r\n\r\n // Split and validate local and domain parts\r\n const [localPart, domainPart] = trimmedEmail.split('@');\r\n\r\n // Validate local part (before @)\r\n if (!localPart || localPart.length > 64) {\r\n return false;\r\n }\r\n\r\n // Validate domain part (after @)\r\n if (!domainPart || domainPart.length > 253) {\r\n return false;\r\n }\r\n\r\n // Ensure domain has at least one dot and proper TLD\r\n if (!domainPart.includes('.')) {\r\n return false;\r\n }\r\n\r\n // Check TLD is at least 2 characters\r\n const domainParts = domainPart.split('.');\r\n const tld = domainParts[domainParts.length - 1];\r\n if (!tld || tld.length < 2) {\r\n return false;\r\n }\r\n\r\n // Check for invalid patterns\r\n if (\r\n localPart.startsWith('.') ||\r\n localPart.endsWith('.') ||\r\n localPart.includes('..') ||\r\n domainPart.startsWith('.') ||\r\n domainPart.endsWith('.') ||\r\n domainPart.includes('..')\r\n ) {\r\n return false;\r\n }\r\n\r\n return true;\r\n};\r\n\r\nexport const isValidURL = (url: string): boolean => {\r\n try {\r\n new URL(url);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\nexport const shouldDisplayStorageField = (field: storageOptionField, settings: Record<string, any>, allFields: storageOptionField[]): boolean => {\r\n // If no conditions, always display the field\r\n if (!field.condition || field.condition.length === 0) {\r\n return true;\r\n }\r\n\r\n // A field is displayed if ANY of its conditions are fully satisfied\r\n return field.condition.some((condition) => {\r\n // A condition is satisfied if ALL its key-value pairs match\r\n return Object.entries(condition).every(([condKey, condValue]) => {\r\n // Find the field that this condition refers to\r\n const targetField = allFields.find((f) => f.value === condKey);\r\n if (!targetField) return false;\r\n\r\n // Get the current value from settings, or use the default\r\n const currentValue = settings[condKey] !== undefined ? settings[condKey] : targetField.default;\r\n\r\n // Check if the condition value matches the field's value\r\n return currentValue === condValue;\r\n });\r\n });\r\n};\r\n\r\n// Calculate the size of each directory based on its files\r\nexport const calculateDirectorySizes = (files: Pick<FileItem, 'path' | 'size' | 'isDirectory'>[]) => {\r\n const dirSizes: { [path: string]: number } = {};\r\n\r\n // Initialize all directories with size 0\r\n files.forEach((file) => {\r\n if (file.isDirectory) {\r\n dirSizes[file.path] = 0;\r\n }\r\n });\r\n\r\n // Sum up file sizes for each directory\r\n files.forEach((file) => {\r\n if (!file.isDirectory && file.size) {\r\n // For each file, add its size to all parent directories\r\n let pathParts = file.path.split('/').filter(Boolean);\r\n let currentPath = '';\r\n\r\n // Add size to each parent directory\r\n for (let i = 0; i < pathParts.length - 1; i++) {\r\n currentPath = currentPath ? `${currentPath}/${pathParts[i]}` : `/${pathParts[i]}`;\r\n if (dirSizes[currentPath] !== undefined) {\r\n dirSizes[currentPath] += file.size;\r\n }\r\n }\r\n }\r\n });\r\n\r\n return dirSizes;\r\n};\r\n\r\nexport const sortFileItems = (items: FileItem[], sortField: keyof FileItem, sortDirection: 'asc' | 'desc') => {\r\n return [...items].sort((a, b) => {\r\n if (sortField === 'name') {\r\n const nameA = a.name.toLowerCase();\r\n const nameB = b.name.toLowerCase();\r\n return sortDirection === 'asc' ? nameA.localeCompare(nameB) : nameB.localeCompare(nameA);\r\n } else if (sortField === 'modifiedAt') {\r\n const dateA = new Date(a.modifiedAt).getTime();\r\n const dateB = new Date(b.modifiedAt).getTime();\r\n return sortDirection === 'asc' ? dateA - dateB : dateB - dateA;\r\n } else if (sortField === 'size') {\r\n const sizeA = a.size || 0;\r\n const sizeB = b.size || 0;\r\n return sortDirection === 'asc' ? sizeA - sizeB : sizeB - sizeA;\r\n } else {\r\n const multiplier = sortDirection === 'asc' ? 1 : -1;\r\n const valueA = a[sortField]?.toString() || '';\r\n const valueB = b[sortField]?.toString() || '';\r\n return valueA.localeCompare(valueB) * multiplier;\r\n }\r\n });\r\n};\r\n\r\nexport const getAvailableCliApps = (platform?: string) => {\r\n const availableShells: Record<string, { label: string; value: string }[]> = {\r\n Windows: [\r\n { label: 'PowerShell', value: 'powershell' },\r\n { label: 'Command Prompt (CMD)', value: 'cmd' },\r\n { label: 'Bash', value: 'bash' },\r\n ],\r\n MacOs: [\r\n { label: 'Zsh', value: 'zsh' },\r\n { label: 'Bash', value: '/bin/bash' },\r\n { label: 'sh', value: '/bin/sh' },\r\n ],\r\n Linux: [\r\n { label: 'Bash', value: '/bin/bash' },\r\n { label: 'sh', value: '/bin/sh' },\r\n { label: 'Zsh', value: 'zsh' },\r\n ],\r\n };\r\n type typeofOSType = keyof typeof availableShells;\r\n\r\n switch (platform) {\r\n case 'win32':\r\n case 'windows':\r\n case 'Windows':\r\n return availableShells.Windows;\r\n case 'darwin':\r\n return availableShells.MacOs;\r\n case 'linux':\r\n case 'Linux':\r\n return availableShells.Linux;\r\n default:\r\n const allShells: { label: string; value: string }[] = [];\r\n (Object.keys(availableShells) as typeofOSType[]).map((OSType) => {\r\n availableShells[OSType].forEach((shell) => {\r\n if (allShells.findIndex((s) => s.value === shell.value) === -1) {\r\n allShells.push({ label: `${shell.label} (${shell.value})`, value: shell.value });\r\n }\r\n });\r\n });\r\n return allShells;\r\n }\r\n};\r\n\r\nexport const formatIntervalDisplay = (interval: PlanInterval): string => {\r\n const time = interval.time ? ` at ${interval.time}` : '';\r\n switch (interval.type) {\r\n case 'hourly':\r\n return 'every hour';\r\n case 'hours':\r\n return `every ${interval.hours?.replace('hrs', '')} hours`;\r\n case 'minutes':\r\n return `every ${interval.minutes} minutes`;\r\n case 'daily':\r\n return `daily${time}`;\r\n case 'weekly':\r\n return `weekly on ${interval.days}${time}`;\r\n case 'days': {\r\n const dayList = interval.days?.replace(/-$/, '').replace(/-/g, ', ');\r\n return `every ${dayList}${time}`;\r\n }\r\n case 'monthly':\r\n return `monthly (${interval.days})${time}`;\r\n default:\r\n return interval.type;\r\n }\r\n};\r\n\r\nexport const secondsToMinutes = (seconds: number) => {\r\n if (seconds === 0) {\r\n return '';\r\n }\r\n return seconds > 60 ? `${Math.round(seconds / 60)} min` : `${seconds} sec`;\r\n};\r\n"],"names":["isMobile","userAgent","mobileRegex","hasTouch","smallScreen","formatter","timeAgo","input","date","ranges","secondsElapsed","key","delta","formatDuration","seconds","hours","minutes","remainingSeconds","formatDateTime","isoDate","options","formatBytes","bytes","units","value","unitIndex","formatNumberToK","num","formatPermissions","mode","formatSeconds","clipPath","path","charsOnSide","start","end","getOSIcon","os","osString","getProcessorIcon","brand","compareVersions","current","latest","currentParts","latestParts","i","curr","late","getUpdateDocLink","isPRO","installType","isServerEdition","distro","platform","getLogLevelName","level","isValidEmail","email","trimmedEmail","localPart","domainPart","domainParts","tld","isValidURL","url","shouldDisplayStorageField","field","settings","allFields","condition","condKey","condValue","targetField","f","calculateDirectorySizes","files","dirSizes","file","pathParts","currentPath","sortFileItems","items","sortField","sortDirection","a","b","_a","_b","nameA","nameB","dateA","dateB","sizeA","sizeB","multiplier","valueA","valueB","getAvailableCliApps","availableShells","allShells","OSType","shell","s","formatIntervalDisplay","interval","time","secondsToMinutes"],"mappings":"AAIO,MAAMA,IAAW,MAAe;AAEpC,MAAI,OAAO,YAAc,OAAe,OAAO,SAAW;AACvD,WAAO;AAGV,QAAMC,IAAY,UAAU,aAAa,UAAU,UAAW,OAAe,SAAS,IAGhFC,IAAc,sFAGdC,IAAW,kBAAkB,UAAU,UAAU,iBAAiB,GAClEC,IAAc,OAAO,cAAc;AAQzC,SALI,GAAAF,EAAY,KAAKD,CAAS,KAK1BE,KAAYC;AAKnB,GAEMC,IAAY,IAAI,KAAK,mBAAmB,IAAI,GACrCC,IAAU,CAACC,MAAgB;AACrC,QAAMC,IAAOD,aAAiB,OAAOA,IAAQ,IAAI,KAAKA,CAAK,GACrDE,IAAkC;AAAA,IACrC,OAAO,OAAO,KAAK;AAAA,IACnB,QAAQ,OAAO,KAAK;AAAA,IACpB,OAAO,OAAO,KAAK;AAAA,IACnB,MAAM,OAAO;AAAA,IACb,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,EAAA,GAENC,KAAkBF,EAAK,QAAA,IAAY,KAAK,SAAS;AACvD,aAAWG,KAAOF;AACf,QAAIA,EAAOE,CAAG,IAAI,KAAK,IAAID,CAAc,GAAG;AACzC,YAAME,IAAQF,IAAiBD,EAAOE,CAAG;AACzC,aAAON,EAAU,OAAO,KAAK,MAAMO,CAAK,GAAGD,CAAkC;AAAA,IAChF;AAEN,GAKaE,IAAiB,CAACC,MAA4B;AACxD,MAAI,CAACA,EAAS,QAAO;AAErB,MAAIA,IAAU;AACX,WAAO,GAAG,KAAK,MAAMA,IAAU,GAAI,CAAC;AAGvC,QAAMC,IAAQ,KAAK,MAAMD,IAAU,IAAI,GACjCE,IAAU,KAAK,MAAOF,IAAU,OAAQ,EAAE,GAC1CG,IAAmB,KAAK,MAAMH,IAAU,EAAE;AAEhD,SAAIC,KAAS,IACH,GAAGA,CAAK,MAAMC,CAAO,SAG3BA,KAAW,IACL,GAAGA,CAAO,SAGb,GAAGC,CAAgB;AAC7B,GAEaC,IAAiB,CAACC,MAAqC;AACjE,QAAMX,IAAO,IAAI,KAAKW,CAAO,GAEvBC,IAAsC;AAAA,IACzC,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAGX,SAAOZ,EAAK,eAAe,SAASY,CAAO;AAC9C,GAEaC,IAAc,CAACC,MAA0B;AACnD,QAAMC,IAAQ,CAAC,KAAK,MAAM,MAAM,MAAM,MAAM,IAAI;AAChD,MAAIC,IAAQF,KAAS,GACjBG,IAAY;AAEhB,SAAOD,KAAS,QAAQC,IAAYF,EAAM,SAAS;AAChD,IAAAC,KAAS,MACTC;AAGH,SAAO,GAAGD,EAAM,QAAQ,CAAC,CAAC,IAAID,EAAME,CAAS,CAAC;AACjD,GAEaC,IAAkB,CAACC,MACzBA,IAAM,MAAaA,EAAI,SAAA,IAEpB,IADOA,IAAM,KACJ,QAAQ,CAAC,CAAC,KAGhBC,IAAoB,CAACC,OACvBA,IAAO,KAAO,SAAS,CAAC,EAAE,SAAS,GAAG,GAAG,GAGvCC,IAAgB,CAACH,MAEvBA,KAAO,QACD,GAAG,KAAK,MAAMA,IAAM,KAAK,CAAC,MAGhCA,KAAO,OACD,GAAG,KAAK,MAAMA,IAAM,IAAI,CAAC,MAG/BA,KAAO,KACD,GAAG,KAAK,MAAMA,IAAM,EAAE,CAAC,MAG1B,GAAG,KAAK,MAAMA,CAAG,CAAC,KAGfI,IAAW,CAACC,GAAcC,IAAc,OAAO;AACzD,MAAID,EAAK,UAAUC,IAAc,EAAG,QAAOD;AAE3C,QAAME,IAAQF,EAAK,MAAM,GAAGC,CAAW,GACjCE,IAAMH,EAAK,MAAM,CAACC,CAAW;AAEnC,SAAO,GAAGC,CAAK,MAAMC,CAAG;AAC3B,GAEaC,IAAY,CAACC,MAAe;AACtC,QAAMC,IAAWD,EAAG,YAAA;AACpB,SAAIC,EAAS,SAAS,SAAS,IACrB,YAENA,EAAS,SAAS,KAAK,IACjB,UAENA,EAAS,SAAS,QAAQ,IACpB,WAENA,EAAS,SAAS,QAAQ,IACpB,WAENA,EAAS,SAAS,QAAQ,IACpB,WAENA,EAAS,SAAS,MAAM,IAClB,SAENA,EAAS,SAAS,KAAK,IACjB,UAENA,EAAS,SAAS,QAAQ,IACpB,WAENA,EAAS,SAAS,MAAM,IAClB,SAENA,EAAS,SAAS,MAAM,IAClB,SAENA,EAAS,SAAS,OAAO,IACnB,UAENA,EAAS,SAAS,SAAS,IACrB,YAEH;AACV,GAEaC,IAAmB,CAACC,MAAkB;AAChD,QAAMF,IAAWE,EAAM,YAAA;AACvB,SAAIF,EAAS,SAAS,KAAK,IACjB,QAENA,EAAS,SAAS,OAAO,IACnB,UAGH;AACV,GAIaG,IAAkB,CAACC,GAAiBC,MAAmB;AACjE,MAAI,CAACD,KAAW,CAACC,EAAQ,QAAO;AAChC,QAAMC,IAAeF,EAAQ,MAAM,GAAG,EAAE,IAAI,MAAM,GAC5CG,IAAcF,EAAO,MAAM,GAAG,EAAE,IAAI,MAAM;AAEhD,WAASG,IAAI,GAAGA,IAAI,GAAGA,KAAK;AACzB,UAAMC,IAAOH,EAAaE,CAAC,KAAK,GAC1BE,IAAOH,EAAYC,CAAC,KAAK;AAE/B,QAAIC,IAAOC,EAAM,QAAO;AACxB,QAAID,IAAOC,EAAM,QAAO;AAAA,EAC3B;AACA,SAAO;AACV,GAEaC,IAAmB,CAACC,MAAoB;AAClD,QAAMC,IAAe,OAAe,qBAAqB;AAEzD,SADA,QAAQ,IAAI,iBAAiBA,CAAW,GACpCA,MAAgB,WACbD,IACM,mFAEH,oFAENC,MAAgB,WACbD,IACM,wFAEH,gGAENC,MAAgB,WACbD,IACM,iFAEH,kFAEH;AACV,GAEaE,IAAkB,CAACC,GAAgBC,MAEzCA,MAAa,UACPD,EAAO,SAAS,QAAQ,KAAKA,EAAO,SAAS,gBAAgB,IAInEC,MAAa,UAEXD,EAAO,SAAS,QAAQ,KACxBA,EAAO,SAAS,YAAY,KAC5BA,EAAO,SAAS,QAAQ,KACxBA,EAAO,SAAS,QAAQ,KACxBA,EAAO,SAAS,eAAe,KAC/BA,EAAO,SAAS,QAAQ,KACxBA,EAAO,SAAS,eAAe,IAKjCC,MAAa,WACPD,EAAO,SAAS,QAAQ,IAG3B;AAGH,SAASE,EAAgBC,GAAuB;AACpD,UAAQA,GAAA;AAAA,IACL,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO;AAAA,IACV;AACG,aAAO;AAAA,EAAA;AAEhB;AAOO,MAAMC,IAAe,CAACC,MAA2B;AACrD,MAAI,CAACA,KAAS,OAAOA,KAAU;AAC5B,WAAO;AAGV,QAAMC,IAAeD,EAAM,KAAA;AAW3B,MARIC,EAAa,WAAW,KAAKA,EAAa,SAAS,OAQnD,CAFD,uIAEa,KAAKA,CAAY;AAC9B,WAAO;AAIV,QAAM,CAACC,GAAWC,CAAU,IAAIF,EAAa,MAAM,GAAG;AAatD,MAVI,CAACC,KAAaA,EAAU,SAAS,MAKjC,CAACC,KAAcA,EAAW,SAAS,OAKnC,CAACA,EAAW,SAAS,GAAG;AACzB,WAAO;AAIV,QAAMC,IAAcD,EAAW,MAAM,GAAG,GAClCE,IAAMD,EAAYA,EAAY,SAAS,CAAC;AAM9C,SALI,GAACC,KAAOA,EAAI,SAAS,KAMtBH,EAAU,WAAW,GAAG,KACxBA,EAAU,SAAS,GAAG,KACtBA,EAAU,SAAS,IAAI,KACvBC,EAAW,WAAW,GAAG,KACzBA,EAAW,SAAS,GAAG,KACvBA,EAAW,SAAS,IAAI;AAM9B,GAEaG,IAAa,CAACC,MAAyB;AACjD,MAAI;AACD,eAAI,IAAIA,CAAG,GACJ;AAAA,EACV,QAAQ;AACL,WAAO;AAAA,EACV;AACH,GAEaC,IAA4B,CAACC,GAA2BC,GAA+BC,MAE7F,CAACF,EAAM,aAAaA,EAAM,UAAU,WAAW,IACzC,KAIHA,EAAM,UAAU,KAAK,CAACG,MAEnB,OAAO,QAAQA,CAAS,EAAE,MAAM,CAAC,CAACC,GAASC,CAAS,MAAM;AAE9D,QAAMC,IAAcJ,EAAU,KAAK,CAACK,MAAMA,EAAE,UAAUH,CAAO;AAC7D,SAAKE,KAGgBL,EAASG,CAAO,MAAM,SAAYH,EAASG,CAAO,IAAIE,EAAY,aAG/DD,IANC;AAO5B,CAAC,CACH,GAISG,IAA0B,CAACC,MAA6D;AAClG,QAAMC,IAAuC,CAAA;AAG7C,SAAAD,EAAM,QAAQ,CAACE,MAAS;AACrB,IAAIA,EAAK,gBACND,EAASC,EAAK,IAAI,IAAI;AAAA,EAE5B,CAAC,GAGDF,EAAM,QAAQ,CAACE,MAAS;AACrB,QAAI,CAACA,EAAK,eAAeA,EAAK,MAAM;AAEjC,UAAIC,IAAYD,EAAK,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO,GAC/CE,IAAc;AAGlB,eAASlC,IAAI,GAAGA,IAAIiC,EAAU,SAAS,GAAGjC;AACvC,QAAAkC,IAAcA,IAAc,GAAGA,CAAW,IAAID,EAAUjC,CAAC,CAAC,KAAK,IAAIiC,EAAUjC,CAAC,CAAC,IAC3E+B,EAASG,CAAW,MAAM,WAC3BH,EAASG,CAAW,KAAKF,EAAK;AAAA,IAGvC;AAAA,EACH,CAAC,GAEMD;AACV,GAEaI,IAAgB,CAACC,GAAmBC,GAA2BC,MAClE,CAAC,GAAGF,CAAK,EAAE,KAAK,CAACG,GAAGC,MAAM;AAtZ7B,MAAAC,GAAAC;AAuZD,MAAIL,MAAc,QAAQ;AACvB,UAAMM,IAAQJ,EAAE,KAAK,YAAA,GACfK,IAAQJ,EAAE,KAAK,YAAA;AACrB,WAAOF,MAAkB,QAAQK,EAAM,cAAcC,CAAK,IAAIA,EAAM,cAAcD,CAAK;AAAA,EAC1F,WAAWN,MAAc,cAAc;AACpC,UAAMQ,IAAQ,IAAI,KAAKN,EAAE,UAAU,EAAE,QAAA,GAC/BO,IAAQ,IAAI,KAAKN,EAAE,UAAU,EAAE,QAAA;AACrC,WAAOF,MAAkB,QAAQO,IAAQC,IAAQA,IAAQD;AAAA,EAC5D,WAAWR,MAAc,QAAQ;AAC9B,UAAMU,IAAQR,EAAE,QAAQ,GAClBS,IAAQR,EAAE,QAAQ;AACxB,WAAOF,MAAkB,QAAQS,IAAQC,IAAQA,IAAQD;AAAA,EAC5D,OAAO;AACJ,UAAME,IAAaX,MAAkB,QAAQ,IAAI,IAC3CY,MAAST,IAAAF,EAAEF,CAAS,MAAX,gBAAAI,EAAc,eAAc,IACrCU,MAAST,IAAAF,EAAEH,CAAS,MAAX,gBAAAK,EAAc,eAAc;AAC3C,WAAOQ,EAAO,cAAcC,CAAM,IAAIF;AAAA,EACzC;AACH,CAAC,GAGSG,IAAsB,CAAC5C,MAAsB;AACvD,QAAM6C,IAAsE;AAAA,IACzE,SAAS;AAAA,MACN,EAAE,OAAO,cAAc,OAAO,aAAA;AAAA,MAC9B,EAAE,OAAO,wBAAwB,OAAO,MAAA;AAAA,MACxC,EAAE,OAAO,QAAQ,OAAO,OAAA;AAAA,IAAO;AAAA,IAElC,OAAO;AAAA,MACJ,EAAE,OAAO,OAAO,OAAO,MAAA;AAAA,MACvB,EAAE,OAAO,QAAQ,OAAO,YAAA;AAAA,MACxB,EAAE,OAAO,MAAM,OAAO,UAAA;AAAA,IAAU;AAAA,IAEnC,OAAO;AAAA,MACJ,EAAE,OAAO,QAAQ,OAAO,YAAA;AAAA,MACxB,EAAE,OAAO,MAAM,OAAO,UAAA;AAAA,MACtB,EAAE,OAAO,OAAO,OAAO,MAAA;AAAA,IAAM;AAAA,EAChC;AAIH,UAAQ7C,GAAA;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACF,aAAO6C,EAAgB;AAAA,IAC1B,KAAK;AACF,aAAOA,EAAgB;AAAA,IAC1B,KAAK;AAAA,IACL,KAAK;AACF,aAAOA,EAAgB;AAAA,IAC1B;AACG,YAAMC,IAAgD,CAAA;AACrD,oBAAO,KAAKD,CAAe,EAAqB,IAAI,CAACE,MAAW;AAC9D,QAAAF,EAAgBE,CAAM,EAAE,QAAQ,CAACC,MAAU;AACxC,UAAIF,EAAU,UAAU,CAACG,MAAMA,EAAE,UAAUD,EAAM,KAAK,MAAM,MACzDF,EAAU,KAAK,EAAE,OAAO,GAAGE,EAAM,KAAK,KAAKA,EAAM,KAAK,KAAK,OAAOA,EAAM,OAAO;AAAA,QAErF,CAAC;AAAA,MACJ,CAAC,GACMF;AAAA,EAAA;AAEhB,GAEaI,IAAwB,CAACC,MAAmC;AAvdlE,MAAAlB,GAAAC;AAwdJ,QAAMkB,IAAOD,EAAS,OAAO,OAAOA,EAAS,IAAI,KAAK;AACtD,UAAQA,EAAS,MAAA;AAAA,IACd,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO,UAASlB,IAAAkB,EAAS,UAAT,gBAAAlB,EAAgB,QAAQ,OAAO,GAAG;AAAA,IACrD,KAAK;AACF,aAAO,SAASkB,EAAS,OAAO;AAAA,IACnC,KAAK;AACF,aAAO,QAAQC,CAAI;AAAA,IACtB,KAAK;AACF,aAAO,aAAaD,EAAS,IAAI,GAAGC,CAAI;AAAA,IAC3C,KAAK;AAEF,aAAO,UADSlB,IAAAiB,EAAS,SAAT,gBAAAjB,EAAe,QAAQ,MAAM,IAAI,QAAQ,MAAM,KACxC,GAAGkB,CAAI;AAAA,IAEjC,KAAK;AACF,aAAO,YAAYD,EAAS,IAAI,IAAIC,CAAI;AAAA,IAC3C;AACG,aAAOD,EAAS;AAAA,EAAA;AAEzB,GAEaE,IAAmB,CAAC7F,MAC1BA,MAAY,IACN,KAEHA,IAAU,KAAK,GAAG,KAAK,MAAMA,IAAU,EAAE,CAAC,SAAS,GAAGA,CAAO;"}
@@ -11,11 +11,11 @@ function f(e) {
11
11
  case "monthly":
12
12
  return "Every Month";
13
13
  case "days":
14
- return `Every ${e.days} days`;
14
+ return `Every ${e.days}`;
15
15
  case "hours":
16
- return `Every ${e.hours} hrs`;
16
+ return `Every ${e.hours}`;
17
17
  case "minutes":
18
- return `Every ${e.minutes} mins`;
18
+ return `Every ${e.minutes}`;
19
19
  default:
20
20
  return "";
21
21
  }
@@ -51,9 +51,9 @@ function c(e, r = !1) {
51
51
  if ((r === 4 || r === !1) && e.settings.notification.webhook.enabled && !e.settings.notification.webhook.url)
52
52
  return t.error("Webhook URL is not provided"), !1;
53
53
  if ((r === 4 || r === !1) && e.settings.notification.email.emails) {
54
- const a = e.settings.notification.email.emails.split(",").filter((o) => s(o) === !1);
55
- if (console.log("invalidEmails: ", a), a.length > 0)
56
- return t.error(`Invalid Notification Email Provided: ${a.join(", ")}`), !1;
54
+ const o = e.settings.notification.email.emails.split(",").filter((a) => s(a) === !1);
55
+ if (console.log("invalidEmails: ", o), o.length > 0)
56
+ return t.error(`Invalid Notification Email Provided: ${o.join(", ")}`), !1;
57
57
  }
58
58
  return !0;
59
59
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plans.js","sources":["../../src/utils/plans.ts"],"sourcesContent":["import { toast } from 'react-toastify';\r\nimport { NewPlanSettings, PlanInterval } from '../@types/plans';\r\nimport { isValidEmail } from './helpers';\r\n\r\nexport function planIntervalName(interval: PlanInterval): string {\r\n switch (interval.type) {\r\n case 'hourly':\r\n return 'Every Hour';\r\n case 'daily':\r\n return 'Every Day';\r\n case 'weekly':\r\n return 'Every Week';\r\n case 'monthly':\r\n return 'Every Month';\r\n case 'days':\r\n return `Every ${interval.days} days`;\r\n case 'hours':\r\n return `Every ${interval.hours} hrs`;\r\n case 'minutes':\r\n return `Every ${interval.minutes} mins`;\r\n default:\r\n return '';\r\n }\r\n}\r\n\r\nexport function planIntervalAgeName(age: string) {\r\n //it could be 2w, 3m, 1d\r\n const match = age.match(/(\\d+)([wdm])/);\r\n if (!match) return age;\r\n\r\n const value = parseInt(match[1], 10);\r\n const unit = match[2];\r\n\r\n switch (unit) {\r\n case 'w':\r\n return `${value} week${value > 1 ? 's' : ''}`;\r\n case 'm':\r\n return `${value} month${value > 1 ? 's' : ''}`;\r\n case 'd':\r\n return `${value} day${value > 1 ? 's' : ''}`;\r\n default:\r\n return age;\r\n }\r\n}\r\n\r\nexport function isPlanSettingsValid(newPlan: NewPlanSettings, step: number | false = false): boolean {\r\n if ((step === 1 || step === false) && !newPlan.title) {\r\n toast.error(`Plan Title is required`);\r\n return false;\r\n }\r\n if ((step === 2 || step === false) && !newPlan.storage.name) {\r\n toast.error(`Storage is required`);\r\n return false;\r\n }\r\n if (step === 2 || step === false) {\r\n if (newPlan.sourceConfig.includes.length === 0) {\r\n toast.error(`Sources are required`);\r\n return false;\r\n }\r\n if (newPlan.storage.id === 'local' && newPlan.storagePath === '') {\r\n toast.error(`Storage Path is required`);\r\n return false;\r\n }\r\n }\r\n if ((step === 4 || step === false) && newPlan.settings.notification.email.enabled && !newPlan.settings.notification.email.emails) {\r\n toast.error(`Notification Email not provided`);\r\n return false;\r\n }\r\n if ((step === 4 || step === false) && newPlan.settings.notification.webhook.enabled && !newPlan.settings.notification.webhook.url) {\r\n toast.error(`Webhook URL is not provided`);\r\n return false;\r\n }\r\n if ((step === 4 || step === false) && newPlan.settings.notification.email.emails) {\r\n const notification_emails = newPlan.settings.notification.email.emails.split(',');\r\n const invalidEmails = notification_emails.filter((x) => isValidEmail(x) === false);\r\n console.log('invalidEmails: ', invalidEmails);\r\n if (invalidEmails.length > 0) {\r\n toast.error(`Invalid Notification Email Provided: ${invalidEmails.join(', ')}`);\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n"],"names":["planIntervalName","interval","planIntervalAgeName","age","match","value","isPlanSettingsValid","newPlan","step","toast","invalidEmails","x","isValidEmail"],"mappings":";;AAIO,SAASA,EAAiBC,GAAgC;AAC9D,UAAQA,EAAS,MAAA;AAAA,IACd,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO,SAASA,EAAS,IAAI;AAAA,IAChC,KAAK;AACF,aAAO,SAASA,EAAS,KAAK;AAAA,IACjC,KAAK;AACF,aAAO,SAASA,EAAS,OAAO;AAAA,IACnC;AACG,aAAO;AAAA,EAAA;AAEhB;AAEO,SAASC,EAAoBC,GAAa;AAE9C,QAAMC,IAAQD,EAAI,MAAM,cAAc;AACtC,MAAI,CAACC,EAAO,QAAOD;AAEnB,QAAME,IAAQ,SAASD,EAAM,CAAC,GAAG,EAAE;AAGnC,UAFaA,EAAM,CAAC,GAEZ;AAAA,IACL,KAAK;AACF,aAAO,GAAGC,CAAK,QAAQA,IAAQ,IAAI,MAAM,EAAE;AAAA,IAC9C,KAAK;AACF,aAAO,GAAGA,CAAK,SAASA,IAAQ,IAAI,MAAM,EAAE;AAAA,IAC/C,KAAK;AACF,aAAO,GAAGA,CAAK,OAAOA,IAAQ,IAAI,MAAM,EAAE;AAAA,IAC7C;AACG,aAAOF;AAAA,EAAA;AAEhB;AAEO,SAASG,EAAoBC,GAA0BC,IAAuB,IAAgB;AAClG,OAAKA,MAAS,KAAKA,MAAS,OAAU,CAACD,EAAQ;AAC5C,WAAAE,EAAM,MAAM,wBAAwB,GAC7B;AAEV,OAAKD,MAAS,KAAKA,MAAS,OAAU,CAACD,EAAQ,QAAQ;AACpD,WAAAE,EAAM,MAAM,qBAAqB,GAC1B;AAEV,MAAID,MAAS,KAAKA,MAAS,IAAO;AAC/B,QAAID,EAAQ,aAAa,SAAS,WAAW;AAC1C,aAAAE,EAAM,MAAM,sBAAsB,GAC3B;AAEV,QAAIF,EAAQ,QAAQ,OAAO,WAAWA,EAAQ,gBAAgB;AAC3D,aAAAE,EAAM,MAAM,0BAA0B,GAC/B;AAAA,EAEb;AACA,OAAKD,MAAS,KAAKA,MAAS,OAAUD,EAAQ,SAAS,aAAa,MAAM,WAAW,CAACA,EAAQ,SAAS,aAAa,MAAM;AACvH,WAAAE,EAAM,MAAM,iCAAiC,GACtC;AAEV,OAAKD,MAAS,KAAKA,MAAS,OAAUD,EAAQ,SAAS,aAAa,QAAQ,WAAW,CAACA,EAAQ,SAAS,aAAa,QAAQ;AAC3H,WAAAE,EAAM,MAAM,6BAA6B,GAClC;AAEV,OAAKD,MAAS,KAAKA,MAAS,OAAUD,EAAQ,SAAS,aAAa,MAAM,QAAQ;AAE/E,UAAMG,IADsBH,EAAQ,SAAS,aAAa,MAAM,OAAO,MAAM,GAAG,EACtC,OAAO,CAACI,MAAMC,EAAaD,CAAC,MAAM,EAAK;AAEjF,QADA,QAAQ,IAAI,mBAAmBD,CAAa,GACxCA,EAAc,SAAS;AACxB,aAAAD,EAAM,MAAM,wCAAwCC,EAAc,KAAK,IAAI,CAAC,EAAE,GACvE;AAAA,EAEb;AAEA,SAAO;AACV;"}
1
+ {"version":3,"file":"plans.js","sources":["../../src/utils/plans.ts"],"sourcesContent":["import { toast } from 'react-toastify';\r\nimport { NewPlanSettings, PlanInterval } from '../@types/plans';\r\nimport { isValidEmail } from './helpers';\r\n\r\nexport function planIntervalName(interval: PlanInterval): string {\r\n switch (interval.type) {\r\n case 'hourly':\r\n return 'Every Hour';\r\n case 'daily':\r\n return 'Every Day';\r\n case 'weekly':\r\n return 'Every Week';\r\n case 'monthly':\r\n return 'Every Month';\r\n case 'days':\r\n return `Every ${interval.days}`;\r\n case 'hours':\r\n return `Every ${interval.hours}`;\r\n case 'minutes':\r\n return `Every ${interval.minutes}`;\r\n default:\r\n return '';\r\n }\r\n}\r\n\r\nexport function planIntervalAgeName(age: string) {\r\n //it could be 2w, 3m, 1d\r\n const match = age.match(/(\\d+)([wdm])/);\r\n if (!match) return age;\r\n\r\n const value = parseInt(match[1], 10);\r\n const unit = match[2];\r\n\r\n switch (unit) {\r\n case 'w':\r\n return `${value} week${value > 1 ? 's' : ''}`;\r\n case 'm':\r\n return `${value} month${value > 1 ? 's' : ''}`;\r\n case 'd':\r\n return `${value} day${value > 1 ? 's' : ''}`;\r\n default:\r\n return age;\r\n }\r\n}\r\n\r\nexport function isPlanSettingsValid(newPlan: NewPlanSettings, step: number | false = false): boolean {\r\n if ((step === 1 || step === false) && !newPlan.title) {\r\n toast.error(`Plan Title is required`);\r\n return false;\r\n }\r\n if ((step === 2 || step === false) && !newPlan.storage.name) {\r\n toast.error(`Storage is required`);\r\n return false;\r\n }\r\n if (step === 2 || step === false) {\r\n if (newPlan.sourceConfig.includes.length === 0) {\r\n toast.error(`Sources are required`);\r\n return false;\r\n }\r\n if (newPlan.storage.id === 'local' && newPlan.storagePath === '') {\r\n toast.error(`Storage Path is required`);\r\n return false;\r\n }\r\n }\r\n if ((step === 4 || step === false) && newPlan.settings.notification.email.enabled && !newPlan.settings.notification.email.emails) {\r\n toast.error(`Notification Email not provided`);\r\n return false;\r\n }\r\n if ((step === 4 || step === false) && newPlan.settings.notification.webhook.enabled && !newPlan.settings.notification.webhook.url) {\r\n toast.error(`Webhook URL is not provided`);\r\n return false;\r\n }\r\n if ((step === 4 || step === false) && newPlan.settings.notification.email.emails) {\r\n const notification_emails = newPlan.settings.notification.email.emails.split(',');\r\n const invalidEmails = notification_emails.filter((x) => isValidEmail(x) === false);\r\n console.log('invalidEmails: ', invalidEmails);\r\n if (invalidEmails.length > 0) {\r\n toast.error(`Invalid Notification Email Provided: ${invalidEmails.join(', ')}`);\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n"],"names":["planIntervalName","interval","planIntervalAgeName","age","match","value","isPlanSettingsValid","newPlan","step","toast","invalidEmails","x","isValidEmail"],"mappings":";;AAIO,SAASA,EAAiBC,GAAgC;AAC9D,UAAQA,EAAS,MAAA;AAAA,IACd,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO;AAAA,IACV,KAAK;AACF,aAAO,SAASA,EAAS,IAAI;AAAA,IAChC,KAAK;AACF,aAAO,SAASA,EAAS,KAAK;AAAA,IACjC,KAAK;AACF,aAAO,SAASA,EAAS,OAAO;AAAA,IACnC;AACG,aAAO;AAAA,EAAA;AAEhB;AAEO,SAASC,EAAoBC,GAAa;AAE9C,QAAMC,IAAQD,EAAI,MAAM,cAAc;AACtC,MAAI,CAACC,EAAO,QAAOD;AAEnB,QAAME,IAAQ,SAASD,EAAM,CAAC,GAAG,EAAE;AAGnC,UAFaA,EAAM,CAAC,GAEZ;AAAA,IACL,KAAK;AACF,aAAO,GAAGC,CAAK,QAAQA,IAAQ,IAAI,MAAM,EAAE;AAAA,IAC9C,KAAK;AACF,aAAO,GAAGA,CAAK,SAASA,IAAQ,IAAI,MAAM,EAAE;AAAA,IAC/C,KAAK;AACF,aAAO,GAAGA,CAAK,OAAOA,IAAQ,IAAI,MAAM,EAAE;AAAA,IAC7C;AACG,aAAOF;AAAA,EAAA;AAEhB;AAEO,SAASG,EAAoBC,GAA0BC,IAAuB,IAAgB;AAClG,OAAKA,MAAS,KAAKA,MAAS,OAAU,CAACD,EAAQ;AAC5C,WAAAE,EAAM,MAAM,wBAAwB,GAC7B;AAEV,OAAKD,MAAS,KAAKA,MAAS,OAAU,CAACD,EAAQ,QAAQ;AACpD,WAAAE,EAAM,MAAM,qBAAqB,GAC1B;AAEV,MAAID,MAAS,KAAKA,MAAS,IAAO;AAC/B,QAAID,EAAQ,aAAa,SAAS,WAAW;AAC1C,aAAAE,EAAM,MAAM,sBAAsB,GAC3B;AAEV,QAAIF,EAAQ,QAAQ,OAAO,WAAWA,EAAQ,gBAAgB;AAC3D,aAAAE,EAAM,MAAM,0BAA0B,GAC/B;AAAA,EAEb;AACA,OAAKD,MAAS,KAAKA,MAAS,OAAUD,EAAQ,SAAS,aAAa,MAAM,WAAW,CAACA,EAAQ,SAAS,aAAa,MAAM;AACvH,WAAAE,EAAM,MAAM,iCAAiC,GACtC;AAEV,OAAKD,MAAS,KAAKA,MAAS,OAAUD,EAAQ,SAAS,aAAa,QAAQ,WAAW,CAACA,EAAQ,SAAS,aAAa,QAAQ;AAC3H,WAAAE,EAAM,MAAM,6BAA6B,GAClC;AAEV,OAAKD,MAAS,KAAKA,MAAS,OAAUD,EAAQ,SAAS,aAAa,MAAM,QAAQ;AAE/E,UAAMG,IADsBH,EAAQ,SAAS,aAAa,MAAM,OAAO,MAAM,GAAG,EACtC,OAAO,CAACI,MAAMC,EAAaD,CAAC,MAAM,EAAK;AAEjF,QADA,QAAQ,IAAI,mBAAmBD,CAAa,GACxCA,EAAc,SAAS;AACxB,aAAAD,EAAM,MAAM,wCAAwCC,EAAc,KAAK,IAAI,CAAC,EAAE,GACvE;AAAA,EAEb;AAEA,SAAO;AACV;"}
package/dist-lib/utils.js CHANGED
@@ -1,51 +1,52 @@
1
1
  import { API_URL as a, APP_NAME as r, DEFAULT_PLAN_SETTINGS as o, DEV_MODE as s } from "./utils/constants.js";
2
- import { calculateDirectorySizes as n, clipPath as g, compareVersions as l, formatBytes as m, formatDateTime as p, formatDuration as c, formatNumberToK as P, formatPermissions as f, formatSeconds as A, getAvailableCliApps as d, getLogLevelName as D, getOSIcon as M, getProcessorIcon as S, getUpdateDocLink as E, isMobile as u, isServerEdition as x, isValidEmail as I, isValidURL as N, secondsToMinutes as h, shouldDisplayStorageField as v, sortFileItems as L, timeAgo as T } from "./utils/helpers.js";
3
- import { isPlanSettingsValid as R, planIntervalAgeName as V, planIntervalName as _ } from "./utils/plans.js";
4
- import { extractResticData as U, generateBackupProgressMessage as k, generateMirrorProgressMessage as y, generateRestoreProgressMessage as B, getBackupEventActionMessage as z, getRestoreEventActionMessage as O } from "./utils/progressHelpers.js";
5
- import { getParentPath as G, getPathSeparator as K, normalizePath as j, splitPath as q } from "./utils/restore.js";
6
- import { getIconNameForFile as H } from "./utils/getIconNameforFile.js";
7
- import { default as Q } from "./utils/snapshotDatabase.js";
2
+ import { calculateDirectorySizes as n, clipPath as l, compareVersions as g, formatBytes as m, formatDateTime as p, formatDuration as c, formatIntervalDisplay as P, formatNumberToK as f, formatPermissions as A, formatSeconds as D, getAvailableCliApps as d, getLogLevelName as M, getOSIcon as S, getProcessorIcon as E, getUpdateDocLink as I, isMobile as u, isServerEdition as v, isValidEmail as x, isValidURL as N, secondsToMinutes as h, shouldDisplayStorageField as L, sortFileItems as T, timeAgo as F } from "./utils/helpers.js";
3
+ import { isPlanSettingsValid as V, planIntervalAgeName as _, planIntervalName as b } from "./utils/plans.js";
4
+ import { extractResticData as U, generateBackupProgressMessage as k, generateMirrorProgressMessage as B, generateRestoreProgressMessage as z, getBackupEventActionMessage as O, getRestoreEventActionMessage as C } from "./utils/progressHelpers.js";
5
+ import { getParentPath as K, getPathSeparator as j, normalizePath as q, splitPath as w } from "./utils/restore.js";
6
+ import { getIconNameForFile as J } from "./utils/getIconNameforFile.js";
7
+ import { default as W } from "./utils/snapshotDatabase.js";
8
8
  export {
9
9
  a as API_URL,
10
10
  r as APP_NAME,
11
11
  o as DEFAULT_PLAN_SETTINGS,
12
12
  s as DEV_MODE,
13
- Q as SnapshotDatabase,
13
+ W as SnapshotDatabase,
14
14
  n as calculateDirectorySizes,
15
- g as clipPath,
16
- l as compareVersions,
15
+ l as clipPath,
16
+ g as compareVersions,
17
17
  U as extractResticData,
18
18
  m as formatBytes,
19
19
  p as formatDateTime,
20
20
  c as formatDuration,
21
- P as formatNumberToK,
22
- f as formatPermissions,
23
- A as formatSeconds,
21
+ P as formatIntervalDisplay,
22
+ f as formatNumberToK,
23
+ A as formatPermissions,
24
+ D as formatSeconds,
24
25
  k as generateBackupProgressMessage,
25
- y as generateMirrorProgressMessage,
26
- B as generateRestoreProgressMessage,
26
+ B as generateMirrorProgressMessage,
27
+ z as generateRestoreProgressMessage,
27
28
  d as getAvailableCliApps,
28
- z as getBackupEventActionMessage,
29
- H as getIconNameForFile,
30
- D as getLogLevelName,
31
- M as getOSIcon,
32
- G as getParentPath,
33
- K as getPathSeparator,
34
- S as getProcessorIcon,
35
- O as getRestoreEventActionMessage,
36
- E as getUpdateDocLink,
29
+ O as getBackupEventActionMessage,
30
+ J as getIconNameForFile,
31
+ M as getLogLevelName,
32
+ S as getOSIcon,
33
+ K as getParentPath,
34
+ j as getPathSeparator,
35
+ E as getProcessorIcon,
36
+ C as getRestoreEventActionMessage,
37
+ I as getUpdateDocLink,
37
38
  u as isMobile,
38
- R as isPlanSettingsValid,
39
- x as isServerEdition,
40
- I as isValidEmail,
39
+ V as isPlanSettingsValid,
40
+ v as isServerEdition,
41
+ x as isValidEmail,
41
42
  N as isValidURL,
42
- j as normalizePath,
43
- V as planIntervalAgeName,
44
- _ as planIntervalName,
43
+ q as normalizePath,
44
+ _ as planIntervalAgeName,
45
+ b as planIntervalName,
45
46
  h as secondsToMinutes,
46
- v as shouldDisplayStorageField,
47
- L as sortFileItems,
48
- q as splitPath,
49
- T as timeAgo
47
+ L as shouldDisplayStorageField,
48
+ T as sortFileItems,
49
+ w as splitPath,
50
+ F as timeAgo
50
51
  };
51
52
  //# sourceMappingURL=utils.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@plutonhq/core-frontend",
3
3
  "description": "Pluton Core Frontend Library",
4
- "version": "0.1.26",
4
+ "version": "0.1.27",
5
5
  "author": "Plutonhq",
6
6
  "license": "Apache-2.0",
7
7
  "publishConfig": {
@@ -62,6 +62,9 @@ export type Backup = {
62
62
  changes: { new: number; modified: number; removed: number };
63
63
  active?: boolean;
64
64
  errorMsg?: string;
65
+ hasRevisions?: boolean;
66
+ revisionsSkipped?: boolean;
67
+ hasChangesFile?: boolean;
65
68
  download?: {
66
69
  status: string;
67
70
  storageId?: string;
@@ -10,6 +10,7 @@ export type PlanPrune = {
10
10
  keepWeeklySnaps?: number;
11
11
  keepMonthlySnaps?: number;
12
12
  revisions?: boolean; // for sync backups
13
+ revisionSkipThreshold?: number; // Auto-skip revisions when sync changes exceed this count (default: 50000, 0 = disabled)
13
14
  };
14
15
 
15
16
  export type PlanNotificationCase = 'start' | 'end' | 'success' | 'failure' | 'both';
@@ -100,6 +101,7 @@ export type PlanPerformanceSettings = {
100
101
  multiThreadCutoff?: string; //sync
101
102
  multiThreadWriteBufferSize?: string; //sync
102
103
  syncStrategy?: string;
104
+ maxChangeFiles?: number; // Max number of individual file changes stored per sync entry (default: 10000)
103
105
  };
104
106
 
105
107
  export type PlanIntegritySettings = {
@@ -2,6 +2,7 @@ export interface Restore {
2
2
  id: number;
3
3
  status: string;
4
4
  error: string | null;
5
+ inProgress: boolean;
5
6
  taskStats: {
6
7
  total_files: number;
7
8
  files_restored: number;
@@ -39,6 +40,7 @@ export interface RestoreSlim {
39
40
  id: string;
40
41
  status: 'completed' | 'cancelled' | 'failed' | 'started';
41
42
  error: string | null;
43
+ inProgress: boolean;
42
44
  taskStats: RestoredItemsStats | null;
43
45
  config: {
44
46
  target: string;
@@ -34,6 +34,7 @@
34
34
  .topComponents {
35
35
  display: flex;
36
36
  gap: 20px;
37
+ justify-content: space-between;
37
38
  margin-bottom: 30px;
38
39
 
39
40
  .widget {
@@ -16,6 +16,9 @@ const PlanBackups = ({ plan }: PlanBackupsProps) => {
16
16
 
17
17
  const { backups = [], stats, restores = [], method, sourceId, sourceType, settings, storage } = plan;
18
18
 
19
+ const finishedBackups = backups.filter((b) => b.inProgress === false);
20
+ const finishedRestores = restores.filter((r) => r.inProgress === false);
21
+
19
22
  const sortedHistory = [...(backups || [])].sort((a, b) => new Date(b.started).getTime() - new Date(a.started).getTime());
20
23
  const isSync = method === 'sync';
21
24
  const snapshotsCount = stats.snapshots?.length || 0;
@@ -25,10 +28,10 @@ const PlanBackups = ({ plan }: PlanBackupsProps) => {
25
28
  <div className={classes.backupsHeader}>
26
29
  <div className={classes.historyTabs}>
27
30
  <button onClick={() => setHistoryTab('backups')} className={historyTab === 'backups' ? classes.historyTabActive : ''}>
28
- {isSync ? 'Sync Tasks' : 'Backups'} <i>{sortedHistory.length}</i>
31
+ {isSync ? 'Sync Tasks' : 'Backups'} <i>{finishedBackups.length}</i>
29
32
  </button>
30
33
  <button onClick={() => setHistoryTab('restores')} className={historyTab === 'restores' ? classes.historyTabActive : ''}>
31
- Restores <i>{restores.length}</i>
34
+ Restores <i>{finishedRestores.length}</i>
32
35
  </button>
33
36
  </div>
34
37
  {!isSync && historyTab === 'backups' && (