@duplicati/ngclient 0.0.1 → 0.0.5

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 (197) hide show
  1. package/chunk-2DCEAXBG.js +1 -0
  2. package/chunk-2WYEYW3N.js +1 -0
  3. package/chunk-43IMNGQL.js +1 -0
  4. package/chunk-63RKHEAK.js +1 -0
  5. package/chunk-6HCEXB2Z.js +1 -0
  6. package/chunk-7POJIDMZ.js +1 -0
  7. package/chunk-7PZ2UDVE.js +1 -0
  8. package/chunk-AYLGFKRR.js +1 -0
  9. package/chunk-BFEHLVAY.js +1 -0
  10. package/chunk-BHHWIMLQ.js +1 -0
  11. package/chunk-BOT7P6RM.js +1 -0
  12. package/chunk-BRNQESTL.js +1 -0
  13. package/chunk-EIZWLO2R.js +2 -0
  14. package/chunk-EJZT4TGZ.js +1 -0
  15. package/chunk-F3A4UEZK.js +1 -0
  16. package/chunk-GAT3R5MA.js +2 -0
  17. package/chunk-GBVLF3BS.js +1 -0
  18. package/chunk-GY2VPOAT.js +1 -0
  19. package/chunk-HHIFLECY.js +1 -0
  20. package/chunk-IMLDBH2T.js +1 -0
  21. package/chunk-IOM7KF2W.js +1 -0
  22. package/chunk-J6KTHSHX.js +1 -0
  23. package/chunk-JRXXG6O7.js +1 -0
  24. package/chunk-LD5EWOQM.js +1 -0
  25. package/chunk-LT6J7X37.js +1 -0
  26. package/chunk-OP5BV4PG.js +1 -0
  27. package/chunk-OX435KV6.js +1 -0
  28. package/chunk-PJNE2N54.js +1 -0
  29. package/chunk-QTQWYR6H.js +1 -0
  30. package/chunk-RCES7NCR.js +1 -0
  31. package/chunk-RL2VWNJG.js +8 -0
  32. package/chunk-RZUDMW24.js +1 -0
  33. package/chunk-S2HNK7TK.js +1 -0
  34. package/chunk-S2YPSAFD.js +1 -0
  35. package/chunk-TGC6GY4N.js +1 -0
  36. package/chunk-UJYJZACJ.js +1 -0
  37. package/chunk-VAAR5GXC.js +1 -0
  38. package/chunk-VF6HT3GY.js +1 -0
  39. package/chunk-XBN37RRV.js +1 -0
  40. package/chunk-YC5LTBFM.js +1 -0
  41. package/index.html +15 -0
  42. package/main-TLCKWB2W.js +1 -0
  43. package/package.json +3 -40
  44. package/sparkle-ui-assets/fonts/InterTight-VariableFont_wght.ttf +0 -0
  45. package/sparkle-ui-assets/fonts/InterTight-VariableFont_wght.woff2 +0 -0
  46. package/styles-6W7ZCKNM.css +1 -0
  47. package/.dockerignore +0 -13
  48. package/.github/workflows/npm-publish.yml +0 -59
  49. package/.prettierignore +0 -13
  50. package/.prettierrc +0 -12
  51. package/.vscode/extensions.json +0 -4
  52. package/.vscode/launch.json +0 -13
  53. package/.vscode/settings.json +0 -8
  54. package/.vscode/tasks.json +0 -24
  55. package/Dockerfile +0 -38
  56. package/LICENSE +0 -21
  57. package/README.md +0 -27
  58. package/angular.json +0 -98
  59. package/bun.lockb +0 -0
  60. package/openapi-ts.config.ts +0 -13
  61. package/scripts/generate-package-json.ts +0 -15
  62. package/src/app/about/about.component.html +0 -15
  63. package/src/app/about/about.component.scss +0 -19
  64. package/src/app/about/about.component.ts +0 -13
  65. package/src/app/about/changelog/changelog.component.html +0 -3
  66. package/src/app/about/changelog/changelog.component.scss +0 -7
  67. package/src/app/about/changelog/changelog.component.ts +0 -18
  68. package/src/app/about/general/general.component.html +0 -9
  69. package/src/app/about/general/general.component.scss +0 -23
  70. package/src/app/about/general/general.component.ts +0 -30
  71. package/src/app/about/libraries/libraries.component.html +0 -3
  72. package/src/app/about/libraries/libraries.component.scss +0 -7
  73. package/src/app/about/libraries/libraries.component.ts +0 -18
  74. package/src/app/about/logs/logs.component.html +0 -5
  75. package/src/app/about/logs/logs.component.scss +0 -7
  76. package/src/app/about/logs/logs.component.ts +0 -18
  77. package/src/app/about/system-info/system-info.component.html +0 -3
  78. package/src/app/about/system-info/system-info.component.scss +0 -7
  79. package/src/app/about/system-info/system-info.component.ts +0 -17
  80. package/src/app/add-backup/add-backup.component.html +0 -29
  81. package/src/app/add-backup/add-backup.component.scss +0 -38
  82. package/src/app/add-backup/add-backup.component.ts +0 -14
  83. package/src/app/app.component.ts +0 -35
  84. package/src/app/app.config.ts +0 -23
  85. package/src/app/app.routes.ts +0 -121
  86. package/src/app/core/components/file-tree/file-tree.component.html +0 -87
  87. package/src/app/core/components/file-tree/file-tree.component.scss +0 -80
  88. package/src/app/core/components/file-tree/file-tree.component.ts +0 -485
  89. package/src/app/core/components/logo/logo.component.html +0 -22
  90. package/src/app/core/components/logo/logo.component.scss +0 -12
  91. package/src/app/core/components/logo/logo.component.ts +0 -11
  92. package/src/app/core/components/status-bar/status-bar.component.html +0 -38
  93. package/src/app/core/components/status-bar/status-bar.component.scss +0 -27
  94. package/src/app/core/components/status-bar/status-bar.component.ts +0 -33
  95. package/src/app/core/components/status-bar/status-bar.state.ts +0 -182
  96. package/src/app/core/components/toggle-card/toggle-card.component.html +0 -11
  97. package/src/app/core/components/toggle-card/toggle-card.component.scss +0 -49
  98. package/src/app/core/components/toggle-card/toggle-card.component.ts +0 -28
  99. package/src/app/core/interceptors/http.interceptor.ts +0 -69
  100. package/src/app/core/interceptors/websocket.interceptor.ts +0 -66
  101. package/src/app/core/openapi/core/ApiError.ts +0 -21
  102. package/src/app/core/openapi/core/ApiRequestOptions.ts +0 -21
  103. package/src/app/core/openapi/core/ApiResult.ts +0 -7
  104. package/src/app/core/openapi/core/OpenAPI.ts +0 -55
  105. package/src/app/core/openapi/core/request.ts +0 -337
  106. package/src/app/core/openapi/index.ts +0 -6
  107. package/src/app/core/openapi/schemas.gen.ts +0 -3611
  108. package/src/app/core/openapi/services.gen.ts +0 -1460
  109. package/src/app/core/openapi/types.gen.ts +0 -1510
  110. package/src/app/core/pipes/duration.pipe.ts +0 -27
  111. package/src/app/core/pipes/relative-time.pipe.ts +0 -14
  112. package/src/app/core/providers/dayjs.ts +0 -16
  113. package/src/app/core/services/dict.en.ts +0 -0
  114. package/src/app/core/services/dictionary.service.ts +0 -12
  115. package/src/app/core/services/localstorage.token.ts +0 -82
  116. package/src/app/core/services/password-generator.service.ts +0 -39
  117. package/src/app/core/services/relay-websocket.service.ts +0 -268
  118. package/src/app/core/services/timespan-literals.service.ts +0 -25
  119. package/src/app/core/states/app-auth.state.ts +0 -87
  120. package/src/app/core/states/backups.state.ts +0 -71
  121. package/src/app/core/states/relayconfig.state.ts +0 -23
  122. package/src/app/core/states/sysinfo.state.ts +0 -31
  123. package/src/app/core/states/tasks.state.ts +0 -34
  124. package/src/app/core/types/subscribed.ts +0 -7
  125. package/src/app/core/validators/custom.validators.ts +0 -120
  126. package/src/app/create-edit-backup/create-edit-backup.component.html +0 -28
  127. package/src/app/create-edit-backup/create-edit-backup.component.scss +0 -15
  128. package/src/app/create-edit-backup/create-edit-backup.component.ts +0 -33
  129. package/src/app/create-edit-backup/create-edit-backup.state.ts +0 -582
  130. package/src/app/create-edit-backup/destination/destination.component.html +0 -367
  131. package/src/app/create-edit-backup/destination/destination.component.scss +0 -85
  132. package/src/app/create-edit-backup/destination/destination.component.ts +0 -249
  133. package/src/app/create-edit-backup/destination/destination.config.ts +0 -103
  134. package/src/app/create-edit-backup/destination/destination.mapper.ts +0 -177
  135. package/src/app/create-edit-backup/general/general.component.html +0 -108
  136. package/src/app/create-edit-backup/general/general.component.scss +0 -34
  137. package/src/app/create-edit-backup/general/general.component.ts +0 -136
  138. package/src/app/create-edit-backup/options/options.component.html +0 -95
  139. package/src/app/create-edit-backup/options/options.component.scss +0 -42
  140. package/src/app/create-edit-backup/options/options.component.ts +0 -113
  141. package/src/app/create-edit-backup/schedule/schedule.component.html +0 -102
  142. package/src/app/create-edit-backup/schedule/schedule.component.scss +0 -38
  143. package/src/app/create-edit-backup/schedule/schedule.component.ts +0 -137
  144. package/src/app/create-edit-backup/source-data/source-data.component.html +0 -93
  145. package/src/app/create-edit-backup/source-data/source-data.component.scss +0 -41
  146. package/src/app/create-edit-backup/source-data/source-data.component.ts +0 -114
  147. package/src/app/home/backup.const.ts +0 -167
  148. package/src/app/home/home.component.html +0 -98
  149. package/src/app/home/home.component.scss +0 -88
  150. package/src/app/home/home.component.ts +0 -54
  151. package/src/app/layout/layout.component.html +0 -64
  152. package/src/app/layout/layout.component.scss +0 -24
  153. package/src/app/layout/layout.component.ts +0 -51
  154. package/src/app/layout/layout.state.ts +0 -70
  155. package/src/app/login/login.component.html +0 -12
  156. package/src/app/login/login.component.scss +0 -25
  157. package/src/app/login/login.component.ts +0 -34
  158. package/src/app/logout/logout.component.html +0 -1
  159. package/src/app/logout/logout.component.scss +0 -3
  160. package/src/app/logout/logout.component.ts +0 -18
  161. package/src/app/restore/restore.component.html +0 -56
  162. package/src/app/restore/restore.component.scss +0 -37
  163. package/src/app/restore/restore.component.ts +0 -55
  164. package/src/app/restore-flow/options/options.component.html +0 -57
  165. package/src/app/restore-flow/options/options.component.scss +0 -16
  166. package/src/app/restore-flow/options/options.component.ts +0 -58
  167. package/src/app/restore-flow/restore-flow.component.html +0 -14
  168. package/src/app/restore-flow/restore-flow.component.scss +0 -15
  169. package/src/app/restore-flow/restore-flow.component.ts +0 -23
  170. package/src/app/restore-flow/restore-flow.state.ts +0 -120
  171. package/src/app/restore-flow/select-files/select-files.component.html +0 -42
  172. package/src/app/restore-flow/select-files/select-files.component.scss +0 -16
  173. package/src/app/restore-flow/select-files/select-files.component.ts +0 -129
  174. package/src/app/settings/settings.component.html +0 -256
  175. package/src/app/settings/settings.component.scss +0 -106
  176. package/src/app/settings/settings.component.ts +0 -475
  177. package/src/environments/environment-token.ts +0 -4
  178. package/src/environments/environment.prod.ts +0 -6
  179. package/src/environments/environment.ts +0 -6
  180. package/src/index.html +0 -15
  181. package/src/main.ts +0 -6
  182. package/src/proxy.conf.mjs +0 -6
  183. package/src/styles.scss +0 -41
  184. package/tsconfig.app.json +0 -15
  185. package/tsconfig.json +0 -30
  186. /package/{src/assets → assets}/duplicati-logo.png +0 -0
  187. /package/{src/assets → assets}/duplicati-logo.svg +0 -0
  188. /package/{src/assets → assets}/favicon.ico +0 -0
  189. /package/{src/assets → assets}/images/backup.png +0 -0
  190. /package/{src/assets → assets}/images/dark-theme.png +0 -0
  191. /package/{src/assets → assets}/images/folder.png +0 -0
  192. /package/{src/assets → assets}/images/light-theme.png +0 -0
  193. /package/{src/assets → assets}/images/new-backup.png +0 -0
  194. /package/{src/assets → assets}/images/restore.png +0 -0
  195. /package/{src/assets → assets}/images/system-theme.png +0 -0
  196. /package/{src/assets → assets}/spk.css +0 -0
  197. /package/{src/assets → assets}/spk.woff2 +0 -0
@@ -1,38 +0,0 @@
1
- <div class="current-backup">
2
- <div class="current-backup-progress">
3
- @if (statusData()?.task?.Status && statusData()?.task?.Status !== 'Completed') {
4
- <div class="label">{{ statusData()?.task?.Status }} - {{ statusData()?.backup?.Backup?.Name }}</div>
5
-
6
- <spk-progress-bar
7
- class="raised primary"
8
- [value]="statusData()?.OverallProgress ? statusData()?.OverallProgress! * 100 : 3"></spk-progress-bar>
9
- } @else if (nextBackup()) {
10
- <div class="label">{{ nextBackup().backup?.Backup?.Name }} - {{ nextBackup().time | appRelativeTime }}</div>
11
- <spk-progress-bar class="raised" [value]="3"></spk-progress-bar>
12
- } @else if (!statusData() || statusData()?.task?.Status === 'Completed') {
13
- <div class="label">No scheduled tasks</div>
14
- <spk-progress-bar class="raised" [value]="3"></spk-progress-bar>
15
- } @else {
16
- <div class="label">Loading...</div>
17
- <spk-progress-bar class="raised" [value]="3"></spk-progress-bar>
18
- }
19
- </div>
20
-
21
- <!-- <div class="current-backup-actions">
22
- <button spk-button>
23
- <spk-icon>play-circle</spk-icon>
24
- Start
25
- </button>
26
-
27
- <button spk-button disabled>
28
- <spk-icon>x-circle</spk-icon>
29
- </button>
30
- </div> -->
31
- </div>
32
-
33
- <!-- <div class="actions">
34
- <button spk-button>
35
- <spk-icon>gauge</spk-icon>
36
- Throttle settings
37
- </button>
38
- </div> -->
@@ -1,27 +0,0 @@
1
- @use '@sparkle-ui/core/styles/helpers' as *;
2
-
3
- :host {
4
- display: flex;
5
- align-items: center;
6
- justify-content: space-between;
7
- padding: p2r(16);
8
- border-bottom: 1px solid var(--base-level-40);
9
- }
10
-
11
- .current-backup {
12
- display: flex;
13
- align-items: center;
14
- gap: p2r(8);
15
- }
16
-
17
- .current-backup-progress {
18
- display: flex;
19
- flex-direction: column;
20
- gap: p2r(4);
21
- min-width: p2r(300);
22
- }
23
-
24
- .current-backup-actions {
25
- display: flex;
26
- gap: p2r(8);
27
- }
@@ -1,33 +0,0 @@
1
- import { JsonPipe } from '@angular/common';
2
- import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core';
3
- import { SparkleButtonComponent, SparkleIconComponent, SparkleProgressBarComponent } from '@sparkle-ui/core';
4
- import { RelativeTimePipe } from '../../pipes/relative-time.pipe';
5
- import { StatusBarState } from './status-bar.state';
6
-
7
- @Component({
8
- selector: 'app-status-bar',
9
- standalone: true,
10
- imports: [SparkleButtonComponent, SparkleIconComponent, SparkleProgressBarComponent, RelativeTimePipe, JsonPipe],
11
- templateUrl: './status-bar.component.html',
12
- styleUrl: './status-bar.component.scss',
13
- changeDetection: ChangeDetectionStrategy.OnPush,
14
- })
15
- export default class StatusBarComponent {
16
- #statusBarState = inject(StatusBarState);
17
-
18
- statusData = this.#statusBarState.statusData;
19
- serverState = this.#statusBarState.serverState;
20
-
21
- nextBackup = computed(() => ({
22
- backup: (this.serverState()?.ProposedSchedule?.[0] as any)?.backup,
23
- time: (this.serverState()?.ProposedSchedule?.[0] as any)?.Item2,
24
- }));
25
-
26
- ngOnInit() {
27
- this.#statusBarState.start();
28
- }
29
-
30
- ngOnDestroy() {
31
- this.#statusBarState.stop();
32
- }
33
- }
@@ -1,182 +0,0 @@
1
- import { computed, effect, inject, Injectable, signal } from '@angular/core';
2
- import { finalize, map, of, switchMap } from 'rxjs';
3
- import {
4
- DuplicatiServerService,
5
- GetApiV1ProgressstateResponse,
6
- GetApiV1ServerstateData,
7
- GetApiV1TaskByTaskidResponse,
8
- ProgressStateService,
9
- ServerStatusDto,
10
- } from '../../openapi';
11
- import { Backup, BackupsState } from '../../states/backups.state';
12
-
13
- type Task = GetApiV1TaskByTaskidResponse;
14
-
15
- export type Status = GetApiV1ProgressstateResponse & {
16
- task?: Task | null;
17
- backup?: Backup | null;
18
- };
19
-
20
- @Injectable({
21
- providedIn: 'root',
22
- })
23
- export class StatusBarState {
24
- #MIN_POLL_INTERVAL = 1000;
25
- #progState = inject(ProgressStateService);
26
- #dupServer = inject(DuplicatiServerService);
27
- #backupState = inject(BackupsState);
28
- #isPolling = signal(false);
29
- #isFetching = signal(false);
30
- #pollingInterval = signal<number | null>(this.#MIN_POLL_INTERVAL);
31
- #statusData = signal<Status | null>(null);
32
- #isGettingServerState = signal(false);
33
- #serverStateLoading = signal(false);
34
- #serverState = signal<ServerStatusDto | null>(null);
35
- #blocker = signal<boolean>(false);
36
-
37
- statusData = this.#statusData.asReadonly();
38
- serverState = computed(() => {
39
- const serverState = this.#serverState();
40
-
41
- if (!serverState) return null;
42
-
43
- serverState.ProposedSchedule = serverState?.ProposedSchedule?.map((x) => {
44
- const backup = x.Item1 ? this.#backupState.getBackupById(x.Item1) : null;
45
-
46
- return {
47
- ...x,
48
- backup,
49
- };
50
- });
51
-
52
- return serverState;
53
- });
54
- isFetching = this.#isFetching.asReadonly();
55
-
56
- #activeInterval: number | null = null;
57
-
58
- #polling = effect(() => {
59
- const isPolling = this.#isPolling();
60
- const pollingInterval = this.#pollingInterval();
61
-
62
- if (!isPolling || !pollingInterval || pollingInterval < this.#MIN_POLL_INTERVAL) {
63
- this.#activeInterval && window.clearInterval(this.#activeInterval);
64
- return;
65
- }
66
-
67
- this.#activeInterval = window.setInterval(() => {
68
- this.#getStatus();
69
- }, pollingInterval);
70
- });
71
-
72
- start() {
73
- this.#isGettingServerState.set(true);
74
- this.#getServerState();
75
- }
76
-
77
- stop() {
78
- this.#isGettingServerState.set(false);
79
- }
80
-
81
- startPollingProgress() {
82
- this.#getStatus();
83
- this.#isPolling.set(true);
84
- }
85
-
86
- stopPollingProgress() {
87
- this.#isPolling.set(false);
88
- }
89
-
90
- setPollingInterval(time: number) {
91
- if (time < this.#MIN_POLL_INTERVAL) {
92
- console.error(`Polling interval must be at least ${this.#MIN_POLL_INTERVAL}ms`);
93
-
94
- return;
95
- }
96
-
97
- this.#pollingInterval.set(time);
98
- }
99
-
100
- serverStateEffect = effect(
101
- () => {
102
- if (this.#blocker()) {
103
- this.stopPollingProgress();
104
- return;
105
- }
106
-
107
- if (!this.#serverStateLoading() && this.#isGettingServerState()) {
108
- setTimeout(() => {
109
- this.startPollingProgress();
110
- this.#getServerState();
111
- }, 1000);
112
- } else {
113
- this.stopPollingProgress();
114
- }
115
- },
116
- {
117
- allowSignalWrites: true,
118
- }
119
- );
120
-
121
- #getServerState() {
122
- if (this.#serverStateLoading()) return;
123
-
124
- this.#serverStateLoading.set(true);
125
- const lastEventId = this.#serverState()?.LastEventID;
126
-
127
- const params: GetApiV1ServerstateData = lastEventId === null || lastEventId === undefined
128
- ? {}
129
- : {
130
- lastEventId: lastEventId,
131
- longpoll: true,
132
- duration: '299s',
133
- };
134
-
135
- this.#dupServer
136
- .getApiV1Serverstate(params)
137
- .pipe(finalize(() => this.#serverStateLoading.set(false)))
138
- .subscribe({
139
- next: (res) => {
140
- if (this.#serverState()?.LastDataUpdateID !== res.LastDataUpdateID) {
141
- this.#backupState.getBackups();
142
- }
143
-
144
- this.#serverState.set(res);
145
- },
146
- });
147
- }
148
-
149
- #getStatus() {
150
- this.#isFetching.set(true);
151
- this.#progState
152
- .getApiV1Progressstate()
153
- .pipe(
154
- switchMap((x) => {
155
- const taskId = x.TaskID ?? null;
156
-
157
- if (taskId === null) return of(x);
158
-
159
- return this.#dupServer
160
- .getApiV1TaskByTaskid({
161
- taskid: taskId,
162
- })
163
- .pipe(map((res) => ({ ...x, task: res ?? null })));
164
- }),
165
- finalize(() => this.#isFetching.set(false))
166
- )
167
- .subscribe({
168
- next: (res: Status) => {
169
- const taskId = res.TaskID ?? null;
170
- const backupId = res.BackupID ?? null;
171
-
172
- if (taskId !== null && backupId !== null) {
173
- const backup = this.#backupState.getBackupById(backupId);
174
-
175
- res.backup = backup;
176
- }
177
-
178
- this.#statusData.set(res);
179
- },
180
- });
181
- }
182
- }
@@ -1,11 +0,0 @@
1
- <h3 (click)="disallowToggle() || toggle()">
2
- <ng-content select="[title]">Title</ng-content>
3
-
4
- @if (!disallowToggle()) {
5
- <spk-icon>caret-down</spk-icon>
6
- }
7
- </h3>
8
-
9
- <div class="content">
10
- <ng-content></ng-content>
11
- </div>
@@ -1,49 +0,0 @@
1
- @use '@sparkle-ui/core/styles/helpers' as *;
2
-
3
- :host {
4
- display: flex;
5
- flex-direction: column;
6
- border-radius: var(--shape-3);
7
- background-color: var(--base-level-20);
8
-
9
- &.active {
10
- .content {
11
- max-height: 1000px;
12
- transition: max-height 1s linear;
13
- padding: p2r(0 16 16);
14
- }
15
-
16
- spk-icon {
17
- transform: rotate(180deg);
18
- }
19
- }
20
-
21
- h3 {
22
- display: flex;
23
- align-items: center;
24
- justify-content: space-between;
25
- font: var(--paragraph-10);
26
- padding: p2r(16);
27
- cursor: pointer;
28
- user-select: none;
29
- }
30
-
31
- spk-icon {
32
- transform: rotate(0);
33
- transform-origin: center;
34
- transition: transform 200ms ease;
35
- }
36
- }
37
-
38
- .content {
39
- display: flex;
40
- flex-direction: column;
41
- gap: p2r(16);
42
-
43
- padding: p2r(0 16 0);
44
- overflow: hidden;
45
- max-height: 0;
46
- transition:
47
- max-height 250ms linear,
48
- padding 250ms linear;
49
- }
@@ -1,28 +0,0 @@
1
- import { ChangeDetectionStrategy, Component, input, model } from '@angular/core';
2
- import { SparkleIconComponent } from '@sparkle-ui/core';
3
-
4
- @Component({
5
- selector: 'app-toggle-card',
6
- standalone: true,
7
- imports: [SparkleIconComponent],
8
- templateUrl: './toggle-card.component.html',
9
- styleUrl: './toggle-card.component.scss',
10
- changeDetection: ChangeDetectionStrategy.OnPush,
11
- host: {
12
- '[class.active]': 'isActive()',
13
- },
14
- })
15
- export default class ToggleCardComponent {
16
- isActive = model(false);
17
- disallowToggle = input(false);
18
-
19
- ngOnInit() {
20
- if (this.disallowToggle()) {
21
- this.isActive.set(true);
22
- }
23
- }
24
-
25
- toggle() {
26
- this.isActive.set(!this.isActive());
27
- }
28
- }
@@ -1,69 +0,0 @@
1
- import { HttpInterceptorFn } from '@angular/common/http';
2
- import { inject } from '@angular/core';
3
- import { Router } from '@angular/router';
4
- import { SparkleAlertService } from '@sparkle-ui/core';
5
- import { catchError, switchMap, throwError } from 'rxjs';
6
- import { ENVIRONMENT_TOKEN } from '../../../environments/environment-token';
7
- import { AccessTokenOutput } from '../openapi';
8
- import { AppAuthState } from '../states/app-auth.state';
9
-
10
- let count = 0;
11
-
12
- export const httpInterceptor: HttpInterceptorFn = (req, next) => {
13
- const auth = inject(AppAuthState);
14
- const router = inject(Router);
15
- const env = inject(ENVIRONMENT_TOKEN);
16
- const sparkleAlertService = inject(SparkleAlertService);
17
-
18
- let modifiedRequest = req;
19
-
20
- // Refresh token if it's older than 15 minutes
21
- if (auth.tokenSetTime() && Date.now() - auth.tokenSetTime()! > 15 * 60 * 1000 && count < 1) {
22
- count++;
23
-
24
- return auth.refreshToken().pipe(
25
- switchMap((newToken: AccessTokenOutput) => {
26
- modifiedRequest = req.clone({
27
- headers: req.headers.set('Authorization', `Bearer ${newToken.AccessToken}`),
28
- });
29
-
30
- return next(modifiedRequest);
31
- })
32
- );
33
- }
34
-
35
- // Add Authorization header if token exists and request URL matches base URL
36
- if (auth.token() && req.url.startsWith(env.baseUrl)) {
37
- modifiedRequest = req.clone({
38
- headers: req.headers.set('Authorization', `Bearer ${auth.token()}`),
39
- });
40
- }
41
-
42
- // Handle HTTP errors
43
- return next(modifiedRequest).pipe(
44
- catchError((error) => {
45
- sparkleAlertService.error(error.message);
46
-
47
- // If 401 error, attempt to refresh token and retry request (uncomment if needed)
48
- if (error.status === 401 && count < 1) {
49
- count++;
50
-
51
- return auth.refreshToken().pipe(
52
- switchMap(() => {
53
- return next(
54
- req.clone({
55
- headers: req.headers.set('Authorization', `Bearer ${auth.token()}`),
56
- })
57
- );
58
- })
59
- );
60
- } else if (error.status === 401) {
61
- router.navigate(['/logout']);
62
- count = 0;
63
- }
64
-
65
- const errorMsg = `Error Code: ${error.status}, Message: ${error.message}`;
66
- return throwError(() => errorMsg);
67
- })
68
- );
69
- };
@@ -1,66 +0,0 @@
1
- import { HttpEvent, HttpHeaders, HttpInterceptorFn, HttpResponse } from '@angular/common/http';
2
- import { inject } from '@angular/core';
3
- import { Observable } from 'rxjs';
4
- import { ENVIRONMENT_TOKEN } from '../../../environments/environment-token';
5
- import { RelayWebsocketService, RequestMethod } from '../services/relay-websocket.service';
6
- import { RelayconfigState } from '../states/relayconfig.state';
7
-
8
- function bufferToStringBase64(str: any) {
9
- // TODO - Handle files... (Probably a buffer already and should just be returned as is)
10
- if (typeof str !== 'string') {
11
- return null;
12
- }
13
-
14
- const encoder = new TextEncoder();
15
- const uint8Array = encoder.encode(str);
16
- return window.btoa(String.fromCharCode(...uint8Array));
17
- }
18
-
19
- export const httpInterceptorWebsocketRelay: HttpInterceptorFn = (req, next) => {
20
- const relayconfigState = inject(RelayconfigState);
21
- const relayconfig = relayconfigState.config();
22
- const environment = inject(ENVIRONMENT_TOKEN);
23
-
24
- if (relayconfig === null) return next(req);
25
-
26
- const relayWebsocket = inject(RelayWebsocketService);
27
- const bodyBase64 = bufferToStringBase64(req.body);
28
- const headers: { [key: string]: string } = {};
29
- req.headers.keys().forEach((key) => {
30
- headers[key] = req.headers.get(key) ?? '';
31
- });
32
-
33
- const timeoutHeaderValue = req.headers.get('timeout');
34
- const timeoutValue = timeoutHeaderValue !== null ? parseInt(timeoutHeaderValue) : environment.defaultTimeout;
35
-
36
- const p = relayWebsocket.sendCommand(
37
- relayconfig.accessToken,
38
- relayconfig.clientId,
39
- req.method as RequestMethod,
40
- req.url,
41
- bodyBase64,
42
- headers,
43
- timeoutValue
44
- );
45
-
46
- return new Observable<HttpEvent<any>>((observer) => {
47
- p.then((response) => {
48
- const httpHeaders = new HttpHeaders();
49
- if (headers != null) {
50
- Object.keys(headers).forEach((key) => {
51
- httpHeaders.set(key, headers[key]);
52
- });
53
- }
54
-
55
- const httpResponse = new HttpResponse({
56
- body: response.body,
57
- status: response.code,
58
- statusText: 'OK',
59
- headers: httpHeaders,
60
- });
61
-
62
- observer.next(httpResponse);
63
- observer.complete();
64
- });
65
- });
66
- };
@@ -1,21 +0,0 @@
1
- import type { ApiRequestOptions } from './ApiRequestOptions';
2
- import type { ApiResult } from './ApiResult';
3
-
4
- export class ApiError extends Error {
5
- public readonly url: string;
6
- public readonly status: number;
7
- public readonly statusText: string;
8
- public readonly body: unknown;
9
- public readonly request: ApiRequestOptions;
10
-
11
- constructor(request: ApiRequestOptions, response: ApiResult, message: string) {
12
- super(message);
13
-
14
- this.name = 'ApiError';
15
- this.url = response.url;
16
- this.status = response.status;
17
- this.statusText = response.statusText;
18
- this.body = response.body;
19
- this.request = request;
20
- }
21
- }
@@ -1,21 +0,0 @@
1
- export type ApiRequestOptions<T = unknown> = {
2
- readonly body?: any;
3
- readonly cookies?: Record<string, unknown>;
4
- readonly errors?: Record<number | string, string>;
5
- readonly formData?: Record<string, unknown> | any[] | Blob | File;
6
- readonly headers?: Record<string, unknown>;
7
- readonly mediaType?: string;
8
- readonly method:
9
- | 'DELETE'
10
- | 'GET'
11
- | 'HEAD'
12
- | 'OPTIONS'
13
- | 'PATCH'
14
- | 'POST'
15
- | 'PUT';
16
- readonly path?: Record<string, unknown>;
17
- readonly query?: Record<string, unknown>;
18
- readonly responseHeader?: string;
19
- readonly responseTransformer?: (data: unknown) => Promise<T>;
20
- readonly url: string;
21
- };
@@ -1,7 +0,0 @@
1
- export type ApiResult<TData = any> = {
2
- readonly body: TData;
3
- readonly ok: boolean;
4
- readonly status: number;
5
- readonly statusText: string;
6
- readonly url: string;
7
- };
@@ -1,55 +0,0 @@
1
- import type { HttpResponse } from '@angular/common/http';
2
- import type { ApiRequestOptions } from './ApiRequestOptions';
3
-
4
- type Headers = Record<string, string>;
5
- type Middleware<T> = (value: T) => T | Promise<T>;
6
- type Resolver<T> = (options: ApiRequestOptions<T>) => Promise<T>;
7
-
8
- export class Interceptors<T> {
9
- _fns: Middleware<T>[];
10
-
11
- constructor() {
12
- this._fns = [];
13
- }
14
-
15
- eject(fn: Middleware<T>): void {
16
- const index = this._fns.indexOf(fn);
17
- if (index !== -1) {
18
- this._fns = [...this._fns.slice(0, index), ...this._fns.slice(index + 1)];
19
- }
20
- }
21
-
22
- use(fn: Middleware<T>): void {
23
- this._fns = [...this._fns, fn];
24
- }
25
- }
26
-
27
- export type OpenAPIConfig = {
28
- BASE: string;
29
- CREDENTIALS: 'include' | 'omit' | 'same-origin';
30
- ENCODE_PATH?: ((path: string) => string) | undefined;
31
- HEADERS?: Headers | Resolver<Headers> | undefined;
32
- PASSWORD?: string | Resolver<string> | undefined;
33
- TOKEN?: string | Resolver<string> | undefined;
34
- USERNAME?: string | Resolver<string> | undefined;
35
- VERSION: string;
36
- WITH_CREDENTIALS: boolean;
37
- interceptors: {
38
- response: Interceptors<HttpResponse<any>>;
39
- };
40
- };
41
-
42
- export const OpenAPI: OpenAPIConfig = {
43
- BASE: '',
44
- CREDENTIALS: 'include',
45
- ENCODE_PATH: undefined,
46
- HEADERS: undefined,
47
- PASSWORD: undefined,
48
- TOKEN: undefined,
49
- USERNAME: undefined,
50
- VERSION: '1',
51
- WITH_CREDENTIALS: false,
52
- interceptors: {
53
- response: new Interceptors(),
54
- },
55
- };