@duplicati/ngclient 0.0.1 → 0.0.6

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-22HCWJS5.js +1 -0
  2. package/chunk-24PLBY6C.js +1 -0
  3. package/chunk-3MM4GLBS.js +1 -0
  4. package/chunk-3MTW6FJP.js +1 -0
  5. package/chunk-4FK75Z4C.js +1 -0
  6. package/chunk-4MMHXTNF.js +1 -0
  7. package/chunk-57M4MADC.js +1 -0
  8. package/chunk-6XUWDRDE.js +1 -0
  9. package/chunk-77NTMJCT.js +1 -0
  10. package/chunk-7X6SBNMU.js +1 -0
  11. package/chunk-A66Z6362.js +1 -0
  12. package/chunk-AC6VDRLC.js +1 -0
  13. package/chunk-BNNZKRIC.js +1 -0
  14. package/chunk-CKPPU3GS.js +2 -0
  15. package/chunk-DYANEO5K.js +1 -0
  16. package/chunk-GJTW7UUU.js +1 -0
  17. package/chunk-GMANGOGH.js +1 -0
  18. package/chunk-I6QIKK6M.js +1 -0
  19. package/chunk-IOWSWUHM.js +1 -0
  20. package/chunk-IQSBPGVL.js +1 -0
  21. package/chunk-L47VTK2X.js +1 -0
  22. package/chunk-LVLU6MPQ.js +1 -0
  23. package/chunk-N5US3SKW.js +1 -0
  24. package/chunk-NIMPOFJV.js +1 -0
  25. package/chunk-ORDBF5MR.js +8 -0
  26. package/chunk-PH6AAOK4.js +1 -0
  27. package/chunk-PY5HJ5U2.js +1 -0
  28. package/chunk-QQDSFTZV.js +1 -0
  29. package/chunk-RANWFSNY.js +1 -0
  30. package/chunk-RLJJFBQ2.js +1 -0
  31. package/chunk-S76TN27U.js +1 -0
  32. package/chunk-UTPCUNNU.js +1 -0
  33. package/chunk-VPEVWKGB.js +1 -0
  34. package/chunk-VVUYO7E4.js +1 -0
  35. package/chunk-WLI4RZYL.js +1 -0
  36. package/chunk-X2NZ4CJ5.js +2 -0
  37. package/chunk-XU7PNEZO.js +1 -0
  38. package/chunk-XYJYUMYL.js +1 -0
  39. package/chunk-YRXI477O.js +1 -0
  40. package/chunk-ZD3JEKWI.js +1 -0
  41. package/index.html +15 -0
  42. package/main-5KJRELCN.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,367 +0,0 @@
1
- @if (destinationOptions().length && sysIsLoaded() && destinationIsLoaded()) {
2
- <form [formGroup]="destinationForm" #formRef (submit)="next()">
3
- <header>
4
- <h3 class="title-30">Backup destination</h3>
5
- @if (destinationCount() > 0) {
6
- <p (click)="removeDestinationFormGroup(destinationCount() - 1)">
7
- Wanna select another destination?
8
- <span class="spk-primary">Click here</span>
9
- </p>
10
- }
11
- </header>
12
-
13
- @if (destinationCount() === 0) {
14
- <div class="most-common-destinations">
15
- <div class="tile" (click)="addDestinationFormGroup('file')">
16
- <h3>File system</h3>
17
- <p>Store backups on your local file system.</p>
18
- </div>
19
-
20
- <div class="tile" (click)="addDestinationFormGroup('gcs')">
21
- <h3>Google Cloud Storage</h3>
22
- <p>Store backups in Google Cloud Storage.</p>
23
- </div>
24
-
25
- <div class="tile" (click)="addDestinationFormGroup('s3')">
26
- <h3>S3 compatible bucket</h3>
27
- <p>Store backups in any S3 compatible bucket.</p>
28
- </div>
29
-
30
- <div class="tile" (click)="addDestinationFormGroup('ssh')">
31
- <h3>SSH</h3>
32
- <p>Store backups in SSH.</p>
33
- </div>
34
- <div class="tile" (click)="addDestinationFormGroup('googledrive')">
35
- <h3>Google Drive</h3>
36
- <p>Store backups in Google Drive.</p>
37
- </div>
38
- </div>
39
-
40
- <p>More destinations are coming soon.</p>
41
- <!-- <spk-menu>
42
- <button spk-button type="button" class="outlined">Other destinations</button>
43
-
44
- <ng-container menu>
45
- @for (destination of destinationOptions(); track $index) {
46
- <button spk-menu-item type="button" (click)="addDestinationFormGroup(destination.Key)">
47
- {{ destination.DisplayName }}
48
- </button>
49
- }
50
- </ng-container>
51
- </spk-menu> -->
52
- }
53
-
54
- @if (destinationFormSignal()?.destinations?.length) {
55
- <ng-container formArrayName="destinations">
56
- <ng-container formGroupName="0">
57
- @if (destinationFormPair().custom.length) {
58
- <ng-container>
59
- @for (destination of destinationFormPair().custom; track $index) {
60
- <ng-container
61
- *ngTemplateOutlet="
62
- fieldTemplate;
63
- context: {
64
- $implicit: {
65
- destination: destination,
66
- destinationType: destinationFormSignal()?.destinations?.[0]?.destinationType,
67
- index: $index,
68
- formGroupName: 'custom',
69
- oauthField: destinationFormPair().oauthField,
70
- },
71
- }
72
- "></ng-container>
73
- }
74
- </ng-container>
75
- }
76
-
77
- @if (destinationFormPair().dynamic.length) {
78
- <ng-container>
79
- @for (destination of destinationFormPair().dynamic; track $index) {
80
- <ng-container
81
- *ngTemplateOutlet="
82
- fieldTemplate;
83
- context: {
84
- $implicit: {
85
- destination: destination,
86
- destinationType: destinationFormSignal()?.destinations?.[0]?.destinationType,
87
- index: $index,
88
- formGroupName: 'dynamic',
89
- oauthField: destinationFormPair().oauthField,
90
- },
91
- }
92
- "></ng-container>
93
- }
94
- </ng-container>
95
- }
96
-
97
- @if (destinationFormPair().advanced.length) {
98
- <app-toggle-card [disallowToggle]="true">
99
- <ng-container title>
100
- Advanced options
101
-
102
- <spk-menu>
103
- <button spk-button type="button" class="outlined small">
104
- Add advanced option
105
- <spk-icon>plus</spk-icon>
106
- </button>
107
-
108
- <ng-container menu>
109
- @for (option of notSelectedAdvancedFormPair(); track $index) {
110
- <button spk-menu-item type="button" (click)="addAdvancedFormPair(option)">
111
- {{ option.name }}
112
- </button>
113
- }
114
- </ng-container>
115
- </spk-menu>
116
- </ng-container>
117
-
118
- <ng-container>
119
- @for (destination of selectedAdvancedFormPair(); track $index) {
120
- <ng-container
121
- *ngTemplateOutlet="
122
- fieldTemplate;
123
- context: {
124
- $implicit: {
125
- destination: destination,
126
- destinationType: destinationFormSignal()?.destinations?.[0]?.destinationType,
127
- index: $index,
128
- formGroupName: 'advanced',
129
- oauthField: destinationFormPair().oauthField,
130
- },
131
- }
132
- "></ng-container>
133
- }
134
- </ng-container>
135
- </app-toggle-card>
136
- }
137
-
138
- <ng-template #fieldTemplate let-item>
139
- <ng-container [formGroupName]="item.formGroupName">
140
- @if (item.destination.type === 'file-tree') {
141
- <app-file-tree
142
- [startingPath]="getFormFieldValue(item.index, item.formGroupName, item.destination.name)">
143
- <label for="destination-{{ item.formGroupName }}-{{ item.formGroupName }}-{{ item.index }}">
144
- {{ item.destination.shortDescription ?? item.destination.name }}
145
- @if (item.destination.longDescription) {
146
- <spk-icon [attr.spk-tooltip-primary]="item.destination.longDescription" spk-tooltip-right>
147
- question
148
- </spk-icon>
149
- }
150
- </label>
151
- <input
152
- type="text"
153
- id="destination-{{ item.formGroupName }}-{{ item.index }}"
154
- formControlName="{{ item.destination.name }}" />
155
- </app-file-tree>
156
- } @else if (item.destination.type === 'String' || item.destination.type === 'Path') {
157
- <spk-form-field>
158
- <label for="destination-{{ item.formGroupName }}-{{ item.index }}">
159
- {{ item.destination.shortDescription ?? item.destination.name }}
160
- @if (item.destination.longDescription) {
161
- <spk-icon [attr.spk-tooltip-primary]="item.destination.longDescription" spk-tooltip-right>
162
- question
163
- </spk-icon>
164
- }
165
- </label>
166
-
167
- <input
168
- type="text"
169
- id="destination-{{ item.formGroupName }}-{{ item.index }}"
170
- formControlName="{{ item.destination.name }}" />
171
-
172
- @if (item.destination.type === 'Path') {
173
- <spk-icon spkPrefix>link</spk-icon>
174
- } @else {
175
- <spk-icon spkPrefix>textbox</spk-icon>
176
- }
177
- </spk-form-field>
178
- } @else if (item.destination.type === 'Password') {
179
- <spk-form-field>
180
- <label for="destination-{{ item.formGroupName }}-{{ item.index }}">
181
- {{ item.destination.shortDescription ?? item.destination.name }} -- {{ item.oauthField }}
182
- {{ item.destinationType }} {{ item.destination.name }}
183
- </label>
184
- <input
185
- [type]="$any(item.destination).showPassword ? 'text' : 'password'"
186
- id="destination-{{ item.formGroupName }}-{{ item.index }}"
187
- formControlName="{{ item.destination.name }}" />
188
-
189
- @if (item.oauthField === item.destination.name) {
190
- <span spkPrefix class="link" (click)="oauthStartTokenCreation(item.destinationType)">AuthID</span>
191
- } @else {
192
- <spk-icon spkPrefix>password</spk-icon>
193
- }
194
- @if ($any(item.destination).showPassword) {
195
- <spk-icon
196
- class="clickable"
197
- spkSuffix
198
- (click)="$any(item.destination).showPassword = !$any(item.destination).showPassword">
199
- eye
200
- </spk-icon>
201
- } @else {
202
- <spk-icon
203
- class="clickable"
204
- spkSuffix
205
- (click)="$any(item.destination).showPassword = !$any(item.destination).showPassword">
206
- eye-slash
207
- </spk-icon>
208
- }
209
- </spk-form-field>
210
- } @else if (item.destination.type === 'Enumeration') {
211
- <spk-select>
212
- <label for="destination-{{ item.formGroupName }}-{{ item.index }}">
213
- {{ item.destination.shortDescription ?? item.destination.name }}
214
-
215
- @if (item.destination.longDescription) {
216
- <spk-icon [attr.spk-tooltip-primary]="item.destination.longDescription" spk-tooltip-right>
217
- question
218
- </spk-icon>
219
- }
220
- </label>
221
- <input
222
- type="search"
223
- id="destination-{{ item.formGroupName }}-{{ item.index }}"
224
- formControlName="{{ item.destination.name }}" />
225
-
226
- <ng-container options>
227
- @for (option of item.destination.options; track $index) {
228
- <option [value]="option">{{ option }}</option>
229
- }
230
- </ng-container>
231
- </spk-select>
232
- } @else if (item.destination.type === 'Size') {
233
- <div class="form-column" [formGroupName]="item.destination.name">
234
- <label for="destination-{{ item.formGroupName }}-{{ item.index }}">
235
- {{ item.destination.shortDescription ?? item.destination.name }}
236
-
237
- @if (item.destination.longDescription) {
238
- <spk-icon [attr.spk-tooltip-primary]="item.destination.longDescription" spk-tooltip-right>
239
- question
240
- </spk-icon>
241
- }
242
- </label>
243
-
244
- <div class="form-row">
245
- <spk-form-field>
246
- <input
247
- type="number"
248
- id="destination-{{ item.formGroupName }}-{{ item.index }}"
249
- formControlName="size" />
250
-
251
- <spk-icon spkPrefix>resize</spk-icon>
252
- </spk-form-field>
253
-
254
- <spk-select>
255
- <label></label>
256
- <input type="search" formControlName="unit" />
257
-
258
- <ng-container options>
259
- @for (option of sizeOptions(); track $index) {
260
- <option [value]="option">{{ option }}</option>
261
- }
262
- </ng-container>
263
- </spk-select>
264
- </div>
265
- </div>
266
- } @else if (item.destination.type === 'Integer') {
267
- <spk-form-field>
268
- <label for="destination-{{ item.formGroupName }}-{{ item.index }}">
269
- {{ item.destination.shortDescription ?? item.destination.name }}
270
- @if (item.destination.longDescription) {
271
- <spk-icon [attr.spk-tooltip-primary]="item.destination.longDescription" spk-tooltip-right>
272
- question
273
- </spk-icon>
274
- }
275
- </label>
276
- <input
277
- type="number"
278
- id="destination-{{ item.formGroupName }}-{{ item.index }}"
279
- formControlName="{{ item.destination.name }}" />
280
- <spk-icon spkPrefix>numpad</spk-icon>
281
- </spk-form-field>
282
- } @else if (item.destination.type === 'Boolean') {
283
- <spk-toggle class="primary raised">
284
- <label for="destination-{{ item.formGroupName }}-{{ item.index }}">
285
- {{ item.destination.shortDescription ?? item.destination.name }}
286
- @if (item.destination.longDescription) {
287
- <spk-icon [attr.spk-tooltip-primary]="item.destination.longDescription" spk-tooltip-right>
288
- question
289
- </spk-icon>
290
- }
291
- </label>
292
- <input
293
- type="checkbox"
294
- id="destination-{{ item.formGroupName }}-{{ item.index }}"
295
- formControlName="{{ item.destination.name }}" />
296
- </spk-toggle>
297
- } @else if (item.destination.type === 'Flags') {
298
- <spk-select [selectMultiple]="true" class="primary">
299
- <label for="destination-{{ item.formGroupName }}-{{ item.index }}">
300
- {{ item.destination.shortDescription ?? item.destination.name }}
301
- @if (item.destination.longDescription) {
302
- <spk-icon [attr.spk-tooltip-primary]="item.destination.longDescription" spk-tooltip-right>
303
- question
304
- </spk-icon>
305
- }
306
- </label>
307
- <input type="text" id="text" formControlName="{{ item.destination.name }}" />
308
-
309
- <ng-container options>
310
- @for (option of item.destination.options; track $index) {
311
- @if (option === 'None') {
312
- <spk-option [value]="'None'" deselect>None</spk-option>
313
- } @else {
314
- <spk-option [value]="option">
315
- {{ option }}
316
-
317
- <spk-checkbox class="raised primary" />
318
- </spk-option>
319
- }
320
- }
321
- </ng-container>
322
- </spk-select>
323
- } @else if (item.destination.type === 'Timespan') {
324
- <spk-form-field>
325
- <label for="destination-{{ item.formGroupName }}-{{ item.index }}">
326
- {{ item.destination.shortDescription ?? item.destination.name }}
327
- @if (item.destination.longDescription) {
328
- <spk-icon [attr.spk-tooltip-primary]="item.destination.longDescription" spk-tooltip-right>
329
- question
330
- </spk-icon>
331
- }
332
- </label>
333
- <input
334
- type="text"
335
- id="destination-{{ item.formGroupName }}-{{ item.index }}"
336
- formControlName="{{ item.destination.name }}" />
337
-
338
- <span spkError>
339
- <!-- {{ destinationForm.controls.destinations.controls[index]?.hasError('pattern') }} -->
340
- </span>
341
- </spk-form-field>
342
- }
343
- </ng-container>
344
- </ng-template>
345
- </ng-container>
346
- </ng-container>
347
- }
348
-
349
- <div class="form-actions">
350
- <button spk-button type="button" (click)="goBack()">
351
- <spk-icon>arrow-left</spk-icon>
352
- Go back
353
- </button>
354
-
355
- <button spk-button class="raised primary" type="submit">
356
- <spk-icon>arrow-right</spk-icon>
357
- Continue
358
- </button>
359
- </div>
360
- </form>
361
-
362
- <!-- <pre>{{ destinationFormSignal() | json }}</pre> -->
363
- <!-- <pre style="white-space: wrap">{{ targetUrl() }}</pre>
364
- <pre>{{ destinationFormSignal() | json }}</pre> -->
365
- <!-- <pre>{{ targetUrlsAsFormObjects() | json }}</pre>
366
- <pre>{{ formObjectsAsTargetUrls() | json }}</pre> -->
367
- }
@@ -1,85 +0,0 @@
1
- @use '@sparkle-ui/core/styles/helpers' as *;
2
-
3
- :host {
4
- display: block;
5
- }
6
-
7
- header {
8
- display: flex;
9
- flex-direction: column;
10
- gap: p2r(8);
11
-
12
- p {
13
- span {
14
- cursor: pointer;
15
- text-decoration: underline;
16
- }
17
- }
18
- }
19
-
20
- form {
21
- display: flex;
22
- flex-direction: column;
23
- gap: p2r(24);
24
- }
25
-
26
- .form-actions {
27
- display: flex;
28
- justify-content: space-between;
29
- }
30
-
31
- .form-column {
32
- display: flex;
33
- flex-direction: column;
34
-
35
- label {
36
- display: flex;
37
- align-items: center;
38
- gap: p2r(4);
39
- }
40
-
41
- spk-icon {
42
- font-size: p2r(16);
43
- }
44
- }
45
-
46
- .form-row {
47
- display: grid;
48
- grid-template-columns: 2fr 1fr;
49
- gap: p2r(8);
50
- align-items: flex-end;
51
- }
52
-
53
- .clickable {
54
- cursor: pointer;
55
- color: var(--primary-500);
56
- }
57
-
58
- .most-common-destinations {
59
- display: grid;
60
- grid-template-columns: 1fr 1fr;
61
- gap: p2r(16);
62
-
63
- .tile {
64
- display: flex;
65
- flex-direction: column;
66
- gap: p2r(8);
67
- padding: p2r(16);
68
- border: 1px solid var(--base-level-40);
69
- border-radius: var(--shape-3);
70
- box-shadow: var(--shadow-1);
71
- background-color: var(--base-level-20);
72
- cursor: pointer;
73
-
74
- h3 {
75
- font: var(--paragraph-10);
76
- margin: 0;
77
- }
78
- }
79
- }
80
-
81
- [spkprefix].link {
82
- cursor: pointer;
83
- text-decoration: underline;
84
- color: var(--primary-500);
85
- }
@@ -1,249 +0,0 @@
1
- import { JsonPipe, NgTemplateOutlet } from '@angular/common';
2
- import { HttpClient } from '@angular/common/http';
3
- import { ChangeDetectionStrategy, Component, computed, ElementRef, inject, signal, viewChild } from '@angular/core';
4
- import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
5
- import { ActivatedRoute, Router } from '@angular/router';
6
- import {
7
- SparkleButtonGroupComponent,
8
- SparkleCheckboxComponent,
9
- SparkleDividerComponent,
10
- SparkleFormFieldComponent,
11
- SparkleIconComponent,
12
- SparkleMenuComponent,
13
- SparkleOptionComponent,
14
- SparkleSelectComponent,
15
- SparkleToggleComponent,
16
- } from '@sparkle-ui/core';
17
- import { finalize } from 'rxjs';
18
- import FileTreeComponent from '../../core/components/file-tree/file-tree.component';
19
- import ToggleCardComponent from '../../core/components/toggle-card/toggle-card.component';
20
- import { IDynamicModule } from '../../core/openapi';
21
- import { SysinfoState } from '../../core/states/sysinfo.state';
22
- import { CreateEditBackupState } from '../create-edit-backup.state';
23
- import { FormView } from './destination.config';
24
- import { toTargetPath } from './destination.mapper';
25
-
26
- const SIZE_OPTIONS = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'] as const;
27
-
28
- export type Size = (typeof SIZE_OPTIONS)[number];
29
- const fb = new FormBuilder();
30
-
31
- export const createDestinationForm = (
32
- defaults = {
33
- destinations: [],
34
- }
35
- ) => {
36
- return fb.group({
37
- destinations: fb.array<DestinationFormGroup>(defaults.destinations),
38
- });
39
- };
40
-
41
- export const createDestinationFormGroup = ({
42
- key,
43
- customGroup,
44
- dynamicGroup,
45
- advancedGroup,
46
- }: {
47
- key: string;
48
- customGroup: FormGroup;
49
- dynamicGroup: FormGroup;
50
- advancedGroup: FormGroup;
51
- }) => {
52
- return fb.group({
53
- destinationType: fb.control<string>(key),
54
- custom: customGroup,
55
- dynamic: dynamicGroup,
56
- advanced: advancedGroup,
57
- });
58
- };
59
-
60
- export type DestinationFormGroup = ReturnType<typeof createDestinationFormGroup>;
61
- export type DestinationFormGroupValue = ReturnType<typeof createDestinationFormGroup>['value'];
62
-
63
- @Component({
64
- selector: 'app-destination',
65
- standalone: true,
66
- imports: [
67
- ReactiveFormsModule,
68
- NgTemplateOutlet,
69
-
70
- SparkleFormFieldComponent,
71
- SparkleSelectComponent,
72
- SparkleMenuComponent,
73
- SparkleCheckboxComponent,
74
- SparkleOptionComponent,
75
- SparkleButtonGroupComponent,
76
- SparkleIconComponent,
77
- SparkleToggleComponent,
78
- SparkleDividerComponent,
79
-
80
- ToggleCardComponent,
81
- FileTreeComponent,
82
- JsonPipe,
83
- ],
84
- templateUrl: './destination.component.html',
85
- styleUrl: './destination.component.scss',
86
- changeDetection: ChangeDetectionStrategy.OnPush,
87
- })
88
- export default class DestinationComponent {
89
- #router = inject(Router);
90
- #route = inject(ActivatedRoute);
91
- #sysinfo = inject(SysinfoState);
92
- #httpClient = inject(HttpClient);
93
- #createEditBackupState = inject(CreateEditBackupState);
94
-
95
- formRef = viewChild.required<ElementRef<HTMLFormElement>>('formRef');
96
-
97
- sysIsLoaded = this.#sysinfo.isLoaded;
98
- destinationIsLoaded = this.#createEditBackupState.destinationIsLoaded;
99
- destinationForm = this.#createEditBackupState.destinationForm;
100
- destinationFormPair = this.#createEditBackupState.destinationFormPair;
101
- selectedAdvancedFormPair = this.#createEditBackupState.selectedAdvancedFormPair;
102
- notSelectedAdvancedFormPair = this.#createEditBackupState.notSelectedAdvancedFormPair;
103
- destinationOptions = this.#createEditBackupState.destinationOptions;
104
- destinationFormSignal = this.#createEditBackupState.destinationFormSignal;
105
- destinationCount = computed(() => this.destinationFormSignal()?.destinations?.length ?? 0);
106
- sizeOptions = signal(SIZE_OPTIONS);
107
-
108
- getFormFieldValue(
109
- destinationIndex: number,
110
- formGroupName: 'custom' | 'dynamic' | 'advanced',
111
- formControlName: string
112
- ) {
113
- const dest = this.destinationForm.controls.destinations.controls?.[destinationIndex];
114
- const group = dest.controls?.[formGroupName];
115
-
116
- return group.controls[formControlName].value;
117
- }
118
-
119
- addDestinationFormGroup(key: IDynamicModule['Key']) {
120
- this.#createEditBackupState.addDestinationFormGroup(key);
121
- }
122
-
123
- addAdvancedFormPair(item: FormView) {
124
- this.selectedAdvancedFormPair.update((y) => {
125
- y.push(item);
126
-
127
- return y;
128
- });
129
-
130
- this.notSelectedAdvancedFormPair.update((y) => {
131
- y = y.filter((x) => x.name !== item.name);
132
-
133
- return y;
134
- });
135
- }
136
-
137
- targetUrl = computed(() => {
138
- const destinationGroup = this.destinationFormSignal()?.destinations?.[0];
139
-
140
- if (!destinationGroup) return '';
141
-
142
- return toTargetPath(destinationGroup);
143
- });
144
- mapToTargetUrl(destinationGroup: DestinationFormGroup) {
145
- return toTargetPath(destinationGroup.value);
146
- }
147
-
148
- removeDestinationFormGroup(index: number) {
149
- this.destinationForm.controls.destinations.removeAt(index);
150
- }
151
-
152
- displayFn(key: IDynamicModule['Key']) {
153
- const item = this.destinationOptions().find((x) => x.Key === key);
154
-
155
- return item ? `${item.DisplayName}` : '';
156
- }
157
-
158
- goBack() {
159
- this.#router.navigate(['general'], { relativeTo: this.#route.parent });
160
- }
161
-
162
- next() {
163
- this.#router.navigate(['source-data'], { relativeTo: this.#route.parent });
164
- }
165
-
166
- #oauthServiceLink = signal('https://duplicati-oauth-handler.appspot.com/').asReadonly();
167
- #oauthCreateToken = signal(
168
- Math.random().toString(36).substring(2) + Math.random().toString(36).substring(2)
169
- ).asReadonly();
170
- #oauthInProgress = signal(false);
171
- #oauthId = signal(null);
172
-
173
- keyCreation() {}
174
-
175
- oauthStartTokenCreation(backendKey: string) {
176
- // if (!servicelink.endsWith('/')) servicelink += '/';
177
-
178
- this.#oauthInProgress.set(true);
179
-
180
- const w = 450;
181
- const h = 600;
182
- const startlink = this.#oauthServiceLink() + '?type=' + backendKey + '&token=' + this.#oauthCreateToken();
183
-
184
- // const countDown = 100;
185
- // const ft = oauthCreateToken;
186
- const left = screen.width / 2 - w / 2;
187
- const top = screen.height / 2 - h / 2;
188
- const wnd = window.open(
189
- startlink,
190
- '_blank',
191
- 'height=' + h + ',width=' + w + ',menubar=0,status=0,titlebar=0,toolbar=0,left=' + left + ',top=' + top
192
- );
193
-
194
- wnd?.addEventListener('blur', (event) => {
195
- console.log('event blur', event);
196
- });
197
-
198
- wnd?.addEventListener('beforeunload', (event) => {
199
- console.log('event beforeunload', event);
200
- this.#httpClient
201
- .get(this.#oauthServiceLink() + 'fetch?callback=JSON_CALLBACK', {
202
- params: { token: this.#oauthCreateToken() },
203
- })
204
- .pipe(finalize(() => this.#oauthInProgress.set(false)))
205
- .subscribe({
206
- next: (res: any) => {
207
- console.log('res', res);
208
-
209
- if (res?.authid) {
210
- this.#oauthId.set(res.authid);
211
-
212
- // wnd.close();
213
- }
214
- },
215
- });
216
- });
217
-
218
- // var recheck = function () {
219
- // countDown--;
220
- // if (countDown > 0 && ft == oauthCreateToken) {
221
- // $http
222
- // .jsonp(servicelink + "fetch?callback=JSON_CALLBACK", {
223
- // params: { token: ft },
224
- // })
225
- // .then(
226
- // function (response) {
227
- // if (response.data.authid) {
228
- // const AuthID = response.data.authid;
229
- // const oauth_in_progress = false;
230
- // wnd.close();
231
- // } else {
232
- // setTimeout(recheck, 3000);
233
- // }
234
- // },
235
- // function (response) {
236
- // setTimeout(recheck, 3000);
237
- // }
238
- // );
239
- // } else {
240
- // const oauth_in_progress = false;
241
- // if (wnd != null) wnd.close();
242
- // }
243
- // };
244
-
245
- // setTimeout(recheck, 6000);
246
-
247
- // return false;
248
- }
249
- }