@goodandready/dsh-goal 0.1.3 → 0.1.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.
- package/docs/design/DESIGN.md +7 -0
- package/lib/client.js +400 -213
- package/lib/command-handler.js +192 -189
- package/lib/goal-engine.js +255 -104
- package/lib/index.js +182 -78
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -3,7 +3,7 @@ window.__ModuleLoader__.load({
|
|
|
3
3
|
factory: (require) => {
|
|
4
4
|
const module = { exports: {} };
|
|
5
5
|
const React = require('react');
|
|
6
|
-
const { useState, useEffect, useRef, useCallback } = React;
|
|
6
|
+
const { useState, useEffect, useRef, useCallback, useMemo } = React;
|
|
7
7
|
|
|
8
8
|
const NS = 'dsh-goal';
|
|
9
9
|
|
|
@@ -108,7 +108,6 @@ window.__ModuleLoader__.load({
|
|
|
108
108
|
strokeWidth: 2.5,
|
|
109
109
|
strokeLinecap: 'round',
|
|
110
110
|
strokeLinejoin: 'round',
|
|
111
|
-
style: { color: 'var(--dsw-alias-status-success)' },
|
|
112
111
|
className,
|
|
113
112
|
},
|
|
114
113
|
React.createElement('polyline', { points: '20 6 9 17 4 12' }),
|
|
@@ -173,7 +172,7 @@ window.__ModuleLoader__.load({
|
|
|
173
172
|
);
|
|
174
173
|
}
|
|
175
174
|
|
|
176
|
-
// --- СТИЛИ И CSS ПРАВИЛА (
|
|
175
|
+
// --- СТИЛИ И CSS ПРАВИЛА (СТАНДАРТ DSH-CLINEBOT & ДИЗАЙН-СИСТЕМА DSH) ---
|
|
177
176
|
const CSS_STYLES = `
|
|
178
177
|
.dsh-goal-dock {
|
|
179
178
|
box-sizing: border-box;
|
|
@@ -189,16 +188,23 @@ window.__ModuleLoader__.load({
|
|
|
189
188
|
display: flex;
|
|
190
189
|
align-items: center;
|
|
191
190
|
justify-content: space-between;
|
|
192
|
-
background: var(--dsw-alias-bg-layer-
|
|
191
|
+
background: var(--dsw-alias-bg-layer-3);
|
|
193
192
|
border: 1px solid var(--dsw-alias-border-l2);
|
|
194
193
|
border-radius: 12px;
|
|
195
|
-
padding:
|
|
194
|
+
padding: 7px 14px;
|
|
196
195
|
font-family: inherit;
|
|
197
196
|
font-size: 13px;
|
|
198
197
|
color: var(--dsw-alias-label-primary);
|
|
199
198
|
user-select: none;
|
|
200
199
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
|
201
|
-
transition: all 0.
|
|
200
|
+
transition: all 0.15s ease;
|
|
201
|
+
}
|
|
202
|
+
.dsh-goal-banner:hover {
|
|
203
|
+
border-color: var(--dsw-alias-label-tertiary);
|
|
204
|
+
}
|
|
205
|
+
.dsh-goal-banner.completed {
|
|
206
|
+
border-color: var(--dsw-alias-state-success-primary);
|
|
207
|
+
background: var(--dsw-alias-bg-layer-3);
|
|
202
208
|
}
|
|
203
209
|
.dsh-goal-left {
|
|
204
210
|
display: flex;
|
|
@@ -213,13 +219,36 @@ window.__ModuleLoader__.load({
|
|
|
213
219
|
display: flex;
|
|
214
220
|
align-items: center;
|
|
215
221
|
}
|
|
222
|
+
.dsh-goal-badge {
|
|
223
|
+
font-size: 11px;
|
|
224
|
+
padding: 2px 8px;
|
|
225
|
+
border-radius: 999px;
|
|
226
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
227
|
+
display: inline-flex;
|
|
228
|
+
align-items: center;
|
|
229
|
+
gap: 4px;
|
|
230
|
+
font-weight: 600;
|
|
231
|
+
white-space: nowrap;
|
|
232
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
233
|
+
color: var(--dsw-alias-label-primary);
|
|
234
|
+
}
|
|
235
|
+
.dsh-goal-badge-ok {
|
|
236
|
+
border-color: var(--dsw-alias-state-success-primary);
|
|
237
|
+
color: var(--dsw-alias-state-success-primary);
|
|
238
|
+
background: rgba(16, 185, 129, 0.08);
|
|
239
|
+
}
|
|
240
|
+
.dsh-goal-badge-warn {
|
|
241
|
+
border-color: var(--dsw-alias-state-warning-primary);
|
|
242
|
+
color: var(--dsw-alias-state-warning-primary);
|
|
243
|
+
background: rgba(245, 158, 11, 0.08);
|
|
244
|
+
}
|
|
216
245
|
.dsh-goal-label {
|
|
217
246
|
font-weight: 600;
|
|
218
247
|
color: var(--dsw-alias-label-primary);
|
|
219
248
|
white-space: nowrap;
|
|
220
249
|
}
|
|
221
250
|
.dsh-goal-label.completed {
|
|
222
|
-
color: var(--dsw-alias-
|
|
251
|
+
color: var(--dsw-alias-state-success-primary);
|
|
223
252
|
}
|
|
224
253
|
.dsh-goal-title {
|
|
225
254
|
color: var(--dsw-alias-label-secondary);
|
|
@@ -249,21 +278,38 @@ window.__ModuleLoader__.load({
|
|
|
249
278
|
flex-shrink: 0;
|
|
250
279
|
}
|
|
251
280
|
.dsh-goal-btn {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
281
|
+
appearance: none;
|
|
282
|
+
font: inherit;
|
|
283
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
284
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
285
|
+
padding: 5px 8px;
|
|
255
286
|
margin: 0;
|
|
256
|
-
color: var(--dsw-alias-label-
|
|
287
|
+
color: var(--dsw-alias-label-primary);
|
|
257
288
|
cursor: pointer;
|
|
258
|
-
display: flex;
|
|
289
|
+
display: inline-flex;
|
|
259
290
|
align-items: center;
|
|
260
291
|
justify-content: center;
|
|
261
|
-
|
|
292
|
+
gap: 5px;
|
|
293
|
+
border-radius: 8px;
|
|
294
|
+
font-size: 12px;
|
|
295
|
+
font-weight: 500;
|
|
262
296
|
transition: all 0.15s ease;
|
|
263
297
|
}
|
|
264
|
-
.dsh-goal-btn:hover {
|
|
298
|
+
.dsh-goal-btn:hover:not(:disabled) {
|
|
299
|
+
background: var(--dsw-alias-bg-layer-4, var(--dsw-alias-bg-layer-2));
|
|
300
|
+
border-color: var(--dsw-alias-label-dimmed, var(--dsw-alias-border-l2));
|
|
301
|
+
}
|
|
302
|
+
.dsh-goal-btn.icon-only {
|
|
303
|
+
padding: 4px 6px;
|
|
304
|
+
border-radius: 6px;
|
|
305
|
+
border-color: transparent;
|
|
306
|
+
background: transparent;
|
|
307
|
+
color: var(--dsw-alias-label-tertiary);
|
|
308
|
+
}
|
|
309
|
+
.dsh-goal-btn.icon-only:hover {
|
|
265
310
|
color: var(--dsw-alias-label-primary);
|
|
266
|
-
background: var(--dsw-alias-bg-layer-
|
|
311
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
312
|
+
border-color: var(--dsw-alias-border-l2);
|
|
267
313
|
}
|
|
268
314
|
.dsh-goal-btn.close {
|
|
269
315
|
font-size: 13px;
|
|
@@ -271,10 +317,23 @@ window.__ModuleLoader__.load({
|
|
|
271
317
|
padding: 3px 6px;
|
|
272
318
|
}
|
|
273
319
|
.dsh-goal-btn.close:hover {
|
|
274
|
-
color: var(--dsw-alias-
|
|
320
|
+
color: var(--dsw-alias-state-error-primary);
|
|
321
|
+
}
|
|
322
|
+
.dsh-goal-btn-primary {
|
|
323
|
+
background: var(--dsw-alias-label-primary);
|
|
324
|
+
color: var(--dsw-alias-bg-layer-3);
|
|
325
|
+
border-color: transparent;
|
|
326
|
+
}
|
|
327
|
+
.dsh-goal-btn-primary:hover:not(:disabled) {
|
|
328
|
+
opacity: 0.88;
|
|
275
329
|
}
|
|
276
|
-
.dsh-goal-btn
|
|
277
|
-
color: var(--dsw-alias-
|
|
330
|
+
.dsh-goal-btn-danger {
|
|
331
|
+
color: var(--dsw-alias-state-error-primary);
|
|
332
|
+
border-color: rgba(239, 68, 68, 0.3);
|
|
333
|
+
}
|
|
334
|
+
.dsh-goal-btn-danger:hover:not(:disabled) {
|
|
335
|
+
background: rgba(239, 68, 68, 0.12) !important;
|
|
336
|
+
border-color: rgba(239, 68, 68, 0.5);
|
|
278
337
|
}
|
|
279
338
|
|
|
280
339
|
/* Modal Details */
|
|
@@ -292,7 +351,7 @@ window.__ModuleLoader__.load({
|
|
|
292
351
|
background: var(--dsw-alias-bg-layer-3);
|
|
293
352
|
border: 1px solid var(--dsw-alias-border-l2);
|
|
294
353
|
border-radius: 12px;
|
|
295
|
-
width:
|
|
354
|
+
width: 560px;
|
|
296
355
|
max-width: 90vw;
|
|
297
356
|
max-height: 80vh;
|
|
298
357
|
display: flex;
|
|
@@ -300,48 +359,81 @@ window.__ModuleLoader__.load({
|
|
|
300
359
|
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.4);
|
|
301
360
|
}
|
|
302
361
|
.dsh-goal-modal-head {
|
|
303
|
-
padding:
|
|
362
|
+
padding: 16px 20px;
|
|
304
363
|
border-bottom: 1px solid var(--dsw-alias-border-l2);
|
|
305
364
|
display: flex;
|
|
306
365
|
align-items: center;
|
|
307
366
|
justify-content: space-between;
|
|
308
367
|
}
|
|
309
368
|
.dsh-goal-modal-title {
|
|
310
|
-
font-size:
|
|
369
|
+
font-size: 16px;
|
|
311
370
|
font-weight: 600;
|
|
312
371
|
color: var(--dsw-alias-label-primary);
|
|
372
|
+
display: flex;
|
|
373
|
+
align-items: center;
|
|
374
|
+
gap: 8px;
|
|
313
375
|
}
|
|
314
376
|
.dsh-goal-modal-body {
|
|
315
|
-
padding:
|
|
377
|
+
padding: 18px 20px;
|
|
316
378
|
overflow-y: auto;
|
|
317
379
|
display: flex;
|
|
318
380
|
flex-direction: column;
|
|
319
|
-
gap:
|
|
381
|
+
gap: 14px;
|
|
382
|
+
}
|
|
383
|
+
.dsh-goal-stat-grid {
|
|
384
|
+
display: grid;
|
|
385
|
+
grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
|
|
386
|
+
gap: 10px;
|
|
387
|
+
}
|
|
388
|
+
.dsh-goal-stat-box {
|
|
389
|
+
padding: 10px 12px;
|
|
390
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
391
|
+
border-radius: 8px;
|
|
392
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
393
|
+
display: flex;
|
|
394
|
+
flex-direction: column;
|
|
395
|
+
gap: 2px;
|
|
396
|
+
}
|
|
397
|
+
.dsh-goal-stat-val {
|
|
398
|
+
font-size: 16px;
|
|
399
|
+
font-weight: 700;
|
|
400
|
+
color: var(--dsw-alias-label-primary);
|
|
401
|
+
}
|
|
402
|
+
.dsh-goal-stat-lbl {
|
|
403
|
+
font-size: 11px;
|
|
404
|
+
color: var(--dsw-alias-label-secondary);
|
|
320
405
|
}
|
|
321
406
|
.dsh-goal-milestone-item {
|
|
322
407
|
display: flex;
|
|
323
408
|
align-items: flex-start;
|
|
324
409
|
gap: 10px;
|
|
325
|
-
padding:
|
|
410
|
+
padding: 10px 12px;
|
|
326
411
|
border-radius: 8px;
|
|
327
412
|
background: var(--dsw-alias-bg-layer-2);
|
|
413
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
328
414
|
font-size: 13px;
|
|
415
|
+
transition: all 0.15s ease;
|
|
329
416
|
}
|
|
330
417
|
.dsh-goal-modal-foot {
|
|
331
|
-
padding:
|
|
418
|
+
padding: 14px 20px;
|
|
332
419
|
border-top: 1px solid var(--dsw-alias-border-l2);
|
|
333
420
|
display: flex;
|
|
334
421
|
justify-content: flex-end;
|
|
335
|
-
|
|
422
|
+
align-items: center;
|
|
423
|
+
gap: 10px;
|
|
336
424
|
}
|
|
337
425
|
|
|
338
|
-
/* Settings Card */
|
|
426
|
+
/* Settings Card (clinebot pattern) */
|
|
339
427
|
.dsh-goal-card {
|
|
340
428
|
border: 1px solid var(--dsw-alias-border-l2);
|
|
341
429
|
background: var(--dsw-alias-bg-layer-3);
|
|
342
430
|
border-radius: 12px;
|
|
343
431
|
list-style: none;
|
|
344
|
-
margin-bottom:
|
|
432
|
+
margin-bottom: 12px;
|
|
433
|
+
transition: border-color 0.15s ease;
|
|
434
|
+
}
|
|
435
|
+
.dsh-goal-card:hover {
|
|
436
|
+
border-color: var(--dsw-alias-label-tertiary);
|
|
345
437
|
}
|
|
346
438
|
.dsh-goal-card-head {
|
|
347
439
|
appearance: none;
|
|
@@ -350,13 +442,13 @@ window.__ModuleLoader__.load({
|
|
|
350
442
|
color: inherit;
|
|
351
443
|
text-align: left;
|
|
352
444
|
cursor: pointer;
|
|
353
|
-
background:
|
|
445
|
+
background: transparent;
|
|
354
446
|
border: 0;
|
|
355
447
|
border-radius: 12px;
|
|
356
448
|
display: flex;
|
|
357
449
|
align-items: center;
|
|
358
450
|
gap: 12px;
|
|
359
|
-
padding:
|
|
451
|
+
padding: 16px 20px;
|
|
360
452
|
}
|
|
361
453
|
.dsh-goal-card-title {
|
|
362
454
|
color: var(--dsw-alias-label-primary);
|
|
@@ -370,14 +462,16 @@ window.__ModuleLoader__.load({
|
|
|
370
462
|
}
|
|
371
463
|
.dsh-goal-card-body {
|
|
372
464
|
border-top: 1px solid var(--dsw-alias-border-l2);
|
|
373
|
-
margin: 0
|
|
374
|
-
padding
|
|
465
|
+
margin: 0 20px;
|
|
466
|
+
padding: 16px 0 16px;
|
|
467
|
+
display: flex;
|
|
468
|
+
flex-direction: column;
|
|
469
|
+
gap: 14px;
|
|
375
470
|
}
|
|
376
471
|
.dsh-goal-card-field {
|
|
377
472
|
display: flex;
|
|
378
473
|
flex-direction: column;
|
|
379
474
|
gap: 6px;
|
|
380
|
-
padding: 12px 0;
|
|
381
475
|
}
|
|
382
476
|
.dsh-goal-field-label-row {
|
|
383
477
|
display: flex;
|
|
@@ -385,6 +479,7 @@ window.__ModuleLoader__.load({
|
|
|
385
479
|
justify-content: space-between;
|
|
386
480
|
font-size: 13px;
|
|
387
481
|
font-weight: 500;
|
|
482
|
+
color: var(--dsw-alias-label-primary);
|
|
388
483
|
}
|
|
389
484
|
.dsh-goal-field-meta {
|
|
390
485
|
display: flex;
|
|
@@ -395,28 +490,35 @@ window.__ModuleLoader__.load({
|
|
|
395
490
|
}
|
|
396
491
|
.dsh-goal-override-tag {
|
|
397
492
|
font-size: 11px;
|
|
398
|
-
padding:
|
|
493
|
+
padding: 2px 6px;
|
|
399
494
|
border-radius: 4px;
|
|
400
495
|
background: var(--dsw-alias-bg-layer-2);
|
|
401
496
|
color: var(--dsw-alias-label-secondary);
|
|
497
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
402
498
|
}
|
|
403
499
|
.dsh-goal-card-input {
|
|
404
|
-
height:
|
|
500
|
+
height: 36px;
|
|
405
501
|
border: 1px solid var(--dsw-alias-border-l2);
|
|
406
|
-
background: var(--dsw-alias-bg-layer-
|
|
502
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
407
503
|
color: var(--dsw-alias-label-primary);
|
|
408
504
|
border-radius: 8px;
|
|
409
505
|
padding: 0 12px;
|
|
410
506
|
font-size: 13px;
|
|
507
|
+
width: 100%;
|
|
508
|
+
box-sizing: border-box;
|
|
509
|
+
}
|
|
510
|
+
.dsh-goal-card-input:focus {
|
|
511
|
+
outline: none;
|
|
512
|
+
border-color: var(--dsw-alias-state-brand-primary);
|
|
411
513
|
}
|
|
412
514
|
.dsh-goal-card-input[aria-invalid="true"] {
|
|
413
|
-
border-color: var(--dsw-alias-
|
|
515
|
+
border-color: var(--dsw-alias-state-error-primary);
|
|
414
516
|
}
|
|
415
517
|
.dsh-goal-chev {
|
|
416
518
|
margin-left: auto;
|
|
417
519
|
flex: none;
|
|
418
520
|
color: var(--dsw-alias-label-tertiary);
|
|
419
|
-
transition: transform .16s;
|
|
521
|
+
transition: transform .16s ease;
|
|
420
522
|
}
|
|
421
523
|
.dsh-goal-chev-open {
|
|
422
524
|
transform: rotate(180deg);
|
|
@@ -425,7 +527,7 @@ window.__ModuleLoader__.load({
|
|
|
425
527
|
display: flex;
|
|
426
528
|
align-items: center;
|
|
427
529
|
justify-content: space-between;
|
|
428
|
-
padding:
|
|
530
|
+
padding: 6px 0;
|
|
429
531
|
}
|
|
430
532
|
.dsh-goal-check {
|
|
431
533
|
display: flex;
|
|
@@ -440,11 +542,11 @@ window.__ModuleLoader__.load({
|
|
|
440
542
|
display: flex;
|
|
441
543
|
justify-content: flex-end;
|
|
442
544
|
align-items: center;
|
|
443
|
-
gap:
|
|
444
|
-
padding:
|
|
545
|
+
gap: 10px;
|
|
546
|
+
padding: 14px 0 4px;
|
|
445
547
|
}
|
|
446
548
|
.dsh-goal-foot-note {
|
|
447
|
-
color: var(--dsw-alias-
|
|
549
|
+
color: var(--dsw-alias-state-error-primary);
|
|
448
550
|
font-size: 12px;
|
|
449
551
|
margin-right: auto;
|
|
450
552
|
}
|
|
@@ -452,7 +554,7 @@ window.__ModuleLoader__.load({
|
|
|
452
554
|
background: transparent;
|
|
453
555
|
border: 0;
|
|
454
556
|
cursor: pointer;
|
|
455
|
-
padding: 2px
|
|
557
|
+
padding: 2px 6px;
|
|
456
558
|
display: flex;
|
|
457
559
|
align-items: center;
|
|
458
560
|
gap: 4px;
|
|
@@ -470,19 +572,19 @@ window.__ModuleLoader__.load({
|
|
|
470
572
|
cursor: pointer;
|
|
471
573
|
border: 1px solid var(--dsw-alias-border-l2);
|
|
472
574
|
border-radius: 8px;
|
|
473
|
-
padding:
|
|
575
|
+
padding: 6px 14px;
|
|
474
576
|
font-size: 13px;
|
|
475
|
-
background:
|
|
476
|
-
color: var(--dsw-alias-label-
|
|
577
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
578
|
+
color: var(--dsw-alias-label-primary);
|
|
477
579
|
transition: all 0.15s ease;
|
|
478
580
|
}
|
|
479
581
|
.dsh-goal-discard:hover:not(:disabled) {
|
|
480
|
-
|
|
481
|
-
|
|
582
|
+
background: var(--dsw-alias-bg-layer-4, var(--dsw-alias-bg-layer-2));
|
|
583
|
+
border-color: var(--dsw-alias-label-dimmed, var(--dsw-alias-border-l2));
|
|
482
584
|
}
|
|
483
585
|
.dsh-goal-discard:disabled {
|
|
484
586
|
opacity: 0.4;
|
|
485
|
-
cursor:
|
|
587
|
+
cursor: not-allowed;
|
|
486
588
|
}
|
|
487
589
|
.dsh-goal-save {
|
|
488
590
|
appearance: none;
|
|
@@ -490,16 +592,19 @@ window.__ModuleLoader__.load({
|
|
|
490
592
|
cursor: pointer;
|
|
491
593
|
border: 1px solid transparent;
|
|
492
594
|
border-radius: 8px;
|
|
493
|
-
padding:
|
|
595
|
+
padding: 6px 16px;
|
|
494
596
|
font-size: 13px;
|
|
495
597
|
background: var(--dsw-alias-label-primary);
|
|
496
598
|
color: var(--dsw-alias-bg-layer-3);
|
|
497
599
|
font-weight: 500;
|
|
498
600
|
transition: opacity 0.15s ease;
|
|
499
601
|
}
|
|
602
|
+
.dsh-goal-save:hover:not(:disabled) {
|
|
603
|
+
opacity: 0.88;
|
|
604
|
+
}
|
|
500
605
|
.dsh-goal-save:disabled {
|
|
501
606
|
opacity: 0.4;
|
|
502
|
-
cursor:
|
|
607
|
+
cursor: not-allowed;
|
|
503
608
|
}
|
|
504
609
|
`;
|
|
505
610
|
|
|
@@ -508,6 +613,7 @@ window.__ModuleLoader__.load({
|
|
|
508
613
|
if (document.getElementById('dsh-goal-styles')) return;
|
|
509
614
|
const style = document.createElement('style');
|
|
510
615
|
style.id = 'dsh-goal-styles';
|
|
616
|
+
style.dataset.dshPlugin = NS;
|
|
511
617
|
style.textContent = CSS_STYLES;
|
|
512
618
|
document.head.appendChild(style);
|
|
513
619
|
}
|
|
@@ -521,31 +627,31 @@ window.__ModuleLoader__.load({
|
|
|
521
627
|
|
|
522
628
|
return React.createElement(
|
|
523
629
|
'div',
|
|
524
|
-
{
|
|
525
|
-
className: 'dsh-goal-modal-overlay',
|
|
526
|
-
onClick: (e) => {
|
|
527
|
-
if (e.target === e.currentTarget) onClose();
|
|
528
|
-
},
|
|
529
|
-
},
|
|
630
|
+
{ className: 'dsh-goal-modal-overlay', onClick: onClose },
|
|
530
631
|
React.createElement(
|
|
531
632
|
'div',
|
|
532
|
-
{
|
|
633
|
+
{
|
|
634
|
+
className: 'dsh-goal-modal',
|
|
635
|
+
onClick: (e) => e.stopPropagation(),
|
|
636
|
+
},
|
|
533
637
|
React.createElement(
|
|
534
638
|
'div',
|
|
535
639
|
{ className: 'dsh-goal-modal-head' },
|
|
536
640
|
React.createElement(
|
|
537
641
|
'div',
|
|
538
|
-
{
|
|
539
|
-
isCompleted
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
isCompleted ? (t('modalTitleCompleted') || 'Цель выполнена: план и результаты') : (t('modalTitle') || 'План и статус цели'),
|
|
544
|
-
),
|
|
642
|
+
{ className: 'dsh-goal-modal-title' },
|
|
643
|
+
isCompleted
|
|
644
|
+
? React.createElement(IconCheck, { size: 18, className: 'cb-badge-ok' })
|
|
645
|
+
: React.createElement(IconTarget, { size: 18 }),
|
|
646
|
+
isCompleted ? (t('modalTitleCompleted') || 'Цель выполнена: план и результаты') : (t('modalTitle') || 'План и статус цели'),
|
|
545
647
|
),
|
|
546
648
|
React.createElement(
|
|
547
649
|
'button',
|
|
548
|
-
{
|
|
650
|
+
{
|
|
651
|
+
className: 'dsh-goal-btn icon-only close',
|
|
652
|
+
onClick: onClose,
|
|
653
|
+
title: t('close') || 'Закрыть',
|
|
654
|
+
},
|
|
549
655
|
'✕',
|
|
550
656
|
),
|
|
551
657
|
),
|
|
@@ -555,25 +661,42 @@ window.__ModuleLoader__.load({
|
|
|
555
661
|
React.createElement(
|
|
556
662
|
'div',
|
|
557
663
|
null,
|
|
558
|
-
React.createElement('div', { style: { fontWeight: 600, fontSize:
|
|
559
|
-
state.description ? React.createElement('div', { style: { color: 'var(--dsw-alias-label-secondary)', fontSize: 13, marginBottom: 4 } }, state.description) : null,
|
|
664
|
+
React.createElement('div', { style: { fontWeight: 600, fontSize: 16, marginBottom: 4, color: 'var(--dsw-alias-label-primary)' } }, state.title),
|
|
665
|
+
state.description ? React.createElement('div', { style: { color: 'var(--dsw-alias-label-secondary)', fontSize: 13, marginBottom: 6, lineHeight: 1.4 } }, state.description) : null,
|
|
560
666
|
),
|
|
561
667
|
React.createElement(
|
|
562
668
|
'div',
|
|
563
|
-
{
|
|
564
|
-
React.createElement(
|
|
669
|
+
{ className: 'dsh-goal-stat-grid' },
|
|
670
|
+
React.createElement(
|
|
671
|
+
'div',
|
|
672
|
+
{ className: 'dsh-goal-stat-box' },
|
|
673
|
+
React.createElement('span', { className: 'dsh-goal-stat-val' }, state.formattedElapsed || '0s'),
|
|
674
|
+
React.createElement('span', { className: 'dsh-goal-stat-lbl' }, t('time') || 'Время работы'),
|
|
675
|
+
),
|
|
676
|
+
React.createElement(
|
|
677
|
+
'div',
|
|
678
|
+
{ className: 'dsh-goal-stat-box' },
|
|
679
|
+
React.createElement('span', { className: 'dsh-goal-stat-val' }, `${state.iterationsCount || 0}/${state.maxIterations || 25}`),
|
|
680
|
+
React.createElement('span', { className: 'dsh-goal-stat-lbl' }, 'Итерации'),
|
|
681
|
+
),
|
|
682
|
+
React.createElement(
|
|
683
|
+
'div',
|
|
684
|
+
{ className: 'dsh-goal-stat-box' },
|
|
685
|
+
React.createElement('span', { className: 'dsh-goal-stat-val' }, `${state.progressPercent || 0}%`),
|
|
686
|
+
React.createElement('span', { className: 'dsh-goal-stat-lbl' }, 'Прогресс'),
|
|
687
|
+
),
|
|
565
688
|
),
|
|
566
689
|
React.createElement(
|
|
567
690
|
'div',
|
|
568
691
|
{ style: { display: 'flex', flexDirection: 'column', gap: 8, marginTop: 4 } },
|
|
569
|
-
React.createElement('div', { style: { fontWeight: 600, fontSize: 13 } }, t('milestones') || 'План работ:'),
|
|
692
|
+
React.createElement('div', { style: { fontWeight: 600, fontSize: 13, color: 'var(--dsw-alias-label-primary)' } }, t('milestones') || 'План работ:'),
|
|
570
693
|
milestones.length === 0
|
|
571
694
|
? React.createElement('div', { style: { color: 'var(--dsw-alias-label-tertiary)', fontSize: 12, padding: '8px 0' } }, t('noMilestones') || 'Агент формирует план работ...')
|
|
572
695
|
: milestones.map((m, i) =>
|
|
573
696
|
React.createElement(
|
|
574
697
|
'div',
|
|
575
698
|
{ key: m.id || i, className: 'dsh-goal-milestone-item' },
|
|
576
|
-
React.createElement('span', { style: { fontSize:
|
|
699
|
+
React.createElement('span', { style: { fontSize: 15 } }, m.status === 'completed' ? '✅' : m.status === 'in_progress' ? '🔄' : '⏳'),
|
|
577
700
|
React.createElement(
|
|
578
701
|
'div',
|
|
579
702
|
{ style: { flex: 1, minWidth: 0 } },
|
|
@@ -601,12 +724,11 @@ window.__ModuleLoader__.load({
|
|
|
601
724
|
? React.createElement(
|
|
602
725
|
'button',
|
|
603
726
|
{
|
|
604
|
-
className: 'dsh-goal-btn danger',
|
|
727
|
+
className: 'dsh-goal-btn dsh-goal-btn-danger',
|
|
605
728
|
onClick: () => {
|
|
606
729
|
onAction('clear');
|
|
607
730
|
onClose();
|
|
608
731
|
},
|
|
609
|
-
style: { padding: '6px 12px', fontSize: 13 },
|
|
610
732
|
},
|
|
611
733
|
t('closeBanner') || 'Закрыть плашку цели',
|
|
612
734
|
)
|
|
@@ -614,9 +736,8 @@ window.__ModuleLoader__.load({
|
|
|
614
736
|
React.createElement(
|
|
615
737
|
'button',
|
|
616
738
|
{
|
|
617
|
-
className: 'dsh-goal-
|
|
739
|
+
className: 'dsh-goal-btn dsh-goal-btn-primary',
|
|
618
740
|
onClick: onClose,
|
|
619
|
-
style: { padding: '6px 16px' },
|
|
620
741
|
},
|
|
621
742
|
t('close') || 'Закрыть',
|
|
622
743
|
),
|
|
@@ -625,12 +746,32 @@ window.__ModuleLoader__.load({
|
|
|
625
746
|
);
|
|
626
747
|
}
|
|
627
748
|
|
|
749
|
+
function sessionIdOf(ctx, props) {
|
|
750
|
+
try {
|
|
751
|
+
if (props?.session?.id) return String(props.session.id);
|
|
752
|
+
if (props?.session?.sessionId) return String(props.session.sessionId);
|
|
753
|
+
if (props?.input?.sessionId) return String(props.input.sessionId);
|
|
754
|
+
if (ctx?.scope?.session) return String(ctx.scope.session.id || ctx.scope.session.header?.id || '');
|
|
755
|
+
if (typeof ctx?.scope?.id === 'string') return ctx.scope.id;
|
|
756
|
+
if (ctx?.session) return String(ctx.session.id || ctx.session.header?.id || '');
|
|
757
|
+
if (typeof window !== 'undefined' && window.location) {
|
|
758
|
+
const params = new URLSearchParams(window.location.search);
|
|
759
|
+
const fromUrl = params.get('session') || params.get('sessionId');
|
|
760
|
+
if (fromUrl) return fromUrl;
|
|
761
|
+
}
|
|
762
|
+
} catch (_) {}
|
|
763
|
+
return 'default';
|
|
764
|
+
}
|
|
765
|
+
|
|
628
766
|
// --- ПАНЕЛЬ ЦЕЛИ НАД ПОЛЕМ ВВОДА (COMPOSER DOCK WIDGET) ---
|
|
629
767
|
function GoalTopBanner(props) {
|
|
630
768
|
const { ctx } = props || {};
|
|
769
|
+
const sid = sessionIdOf(ctx, props);
|
|
631
770
|
const [state, setState] = useState(null);
|
|
632
771
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
633
772
|
const [now, setNow] = useState(() => Date.now());
|
|
773
|
+
const stateRef = useRef(null);
|
|
774
|
+
stateRef.current = state;
|
|
634
775
|
|
|
635
776
|
const t = (key) => {
|
|
636
777
|
if (ctx?.locale?.getSnapshot) {
|
|
@@ -655,26 +796,76 @@ window.__ModuleLoader__.load({
|
|
|
655
796
|
|
|
656
797
|
const fetchState = useCallback(async () => {
|
|
657
798
|
try {
|
|
658
|
-
const
|
|
799
|
+
const query = sid && sid !== 'default' ? `?sessionId=${encodeURIComponent(sid)}` : '';
|
|
800
|
+
const res = await fetch(`/dsh-goal/state${query}`, {
|
|
801
|
+
headers: { 'x-dsh-session-id': sid },
|
|
802
|
+
});
|
|
659
803
|
if (res.ok) {
|
|
660
804
|
const data = await res.json();
|
|
661
805
|
setState(data);
|
|
662
806
|
}
|
|
663
807
|
} catch (_) {}
|
|
664
|
-
}, []);
|
|
808
|
+
}, [sid]);
|
|
665
809
|
|
|
810
|
+
// Адаптивный поллинг: 1.5s когда RUNNING и вкладка активна, 8s когда IDLE/PAUSED/COMPLETED или вкладка скрыта
|
|
666
811
|
useEffect(() => {
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
812
|
+
let timer = null;
|
|
813
|
+
let isDisposed = false;
|
|
814
|
+
|
|
815
|
+
const scheduleNextPoll = () => {
|
|
816
|
+
if (isDisposed) return;
|
|
817
|
+
const currentState = stateRef.current;
|
|
818
|
+
const isDocHidden = typeof document !== 'undefined' && document.hidden;
|
|
819
|
+
const isRunning = currentState?.hasActiveGoal && currentState?.state === 'RUNNING';
|
|
820
|
+
|
|
821
|
+
let delay = 1500;
|
|
822
|
+
if (isDocHidden) {
|
|
823
|
+
delay = 10000;
|
|
824
|
+
} else if (!isRunning) {
|
|
825
|
+
delay = 8000;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
timer = setTimeout(async () => {
|
|
829
|
+
await fetchState();
|
|
830
|
+
scheduleNextPoll();
|
|
831
|
+
}, delay);
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
fetchState().then(() => {
|
|
835
|
+
scheduleNextPoll();
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
const onVisibilityChange = () => {
|
|
839
|
+
if (typeof document !== 'undefined' && !document.hidden) {
|
|
840
|
+
if (timer) clearTimeout(timer);
|
|
841
|
+
fetchState().then(() => {
|
|
842
|
+
scheduleNextPoll();
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
|
|
847
|
+
if (typeof document !== 'undefined' && document.addEventListener) {
|
|
848
|
+
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
return () => {
|
|
852
|
+
isDisposed = true;
|
|
853
|
+
if (timer) clearTimeout(timer);
|
|
854
|
+
if (typeof document !== 'undefined' && document.removeEventListener) {
|
|
855
|
+
document.removeEventListener('visibilitychange', onVisibilityChange);
|
|
856
|
+
}
|
|
857
|
+
};
|
|
670
858
|
}, [fetchState]);
|
|
671
859
|
|
|
672
860
|
const handleAction = async (action, extra = {}) => {
|
|
673
861
|
try {
|
|
674
862
|
const res = await fetch('/dsh-goal/action', {
|
|
675
863
|
method: 'POST',
|
|
676
|
-
headers: {
|
|
677
|
-
|
|
864
|
+
headers: {
|
|
865
|
+
'Content-Type': 'application/json',
|
|
866
|
+
'x-dsh-session-id': sid,
|
|
867
|
+
},
|
|
868
|
+
body: JSON.stringify({ action, sessionId: sid, ...extra }),
|
|
678
869
|
});
|
|
679
870
|
if (res.ok) {
|
|
680
871
|
const data = await res.json();
|
|
@@ -719,8 +910,10 @@ window.__ModuleLoader__.load({
|
|
|
719
910
|
),
|
|
720
911
|
React.createElement(
|
|
721
912
|
'span',
|
|
722
|
-
{
|
|
723
|
-
|
|
913
|
+
{
|
|
914
|
+
className: `dsh-goal-badge ${isCompleted ? 'dsh-goal-badge-ok' : isPaused ? 'dsh-goal-badge-warn' : ''}`,
|
|
915
|
+
},
|
|
916
|
+
isCompleted ? (t('goalCompleted') || 'Цель выполнена') : isPaused ? (t('pause') || 'На паузе') : (t('goalLabel') || 'Текущая цель'),
|
|
724
917
|
),
|
|
725
918
|
React.createElement('span', { className: 'dsh-goal-title', title: state.title }, state.title),
|
|
726
919
|
),
|
|
@@ -736,7 +929,7 @@ window.__ModuleLoader__.load({
|
|
|
736
929
|
? React.createElement(
|
|
737
930
|
'button',
|
|
738
931
|
{
|
|
739
|
-
className: 'dsh-goal-btn',
|
|
932
|
+
className: 'dsh-goal-btn icon-only',
|
|
740
933
|
title: isPaused ? (t('resume') || 'Возобновить') : (t('pause') || 'Приостановить'),
|
|
741
934
|
onClick: () => handleAction(isPaused ? 'resume' : 'pause'),
|
|
742
935
|
},
|
|
@@ -746,7 +939,7 @@ window.__ModuleLoader__.load({
|
|
|
746
939
|
React.createElement(
|
|
747
940
|
'button',
|
|
748
941
|
{
|
|
749
|
-
className: 'dsh-goal-btn',
|
|
942
|
+
className: 'dsh-goal-btn icon-only',
|
|
750
943
|
title: t('details') || 'Развернуть детали цели',
|
|
751
944
|
onClick: () => setIsModalOpen(true),
|
|
752
945
|
},
|
|
@@ -756,7 +949,7 @@ window.__ModuleLoader__.load({
|
|
|
756
949
|
? React.createElement(
|
|
757
950
|
'button',
|
|
758
951
|
{
|
|
759
|
-
className: 'dsh-goal-btn close',
|
|
952
|
+
className: 'dsh-goal-btn icon-only close',
|
|
760
953
|
title: t('closeBanner') || 'Закрыть плашку цели',
|
|
761
954
|
onClick: () => handleAction('clear'),
|
|
762
955
|
},
|
|
@@ -778,12 +971,6 @@ window.__ModuleLoader__.load({
|
|
|
778
971
|
}
|
|
779
972
|
|
|
780
973
|
// --- ЛОГИКА ФОРМЫ НАСТРОЕК ---
|
|
781
|
-
// Архитектурное решение (Issue #23):
|
|
782
|
-
// Чистая логика состояния формы настроек вынесена в `lib/card-form-state.js` для запуска
|
|
783
|
-
// быстрых изолированных unit-тестов через `node --test`. В `lib/client.js` эти функции
|
|
784
|
-
// продублированы встроенным образом, поскольку клиентский бандл загружается браузерным
|
|
785
|
-
// загрузчиком DSH (`window.__ModuleLoader__`) как самодостаточный автономный скрипт
|
|
786
|
-
// без этапа сборки (bundler / webpack) и не может динамически импортировать локальные файлы.
|
|
787
974
|
const DEFAULT_SETTINGS = {
|
|
788
975
|
maxIterations: 25,
|
|
789
976
|
autoDrive: true,
|
|
@@ -829,7 +1016,7 @@ window.__ModuleLoader__.load({
|
|
|
829
1016
|
}
|
|
830
1017
|
} else {
|
|
831
1018
|
if (draftValue !== undefined) {
|
|
832
|
-
isDirty = draftValue !== (userVal !== undefined ? userVal : baseVal);
|
|
1019
|
+
isDirty = Boolean(draftValue) !== (userVal !== undefined ? Boolean(userVal) : Boolean(baseVal));
|
|
833
1020
|
}
|
|
834
1021
|
}
|
|
835
1022
|
|
|
@@ -846,8 +1033,8 @@ window.__ModuleLoader__.load({
|
|
|
846
1033
|
function computeSavePlan(draft, snap) {
|
|
847
1034
|
if (!draft) return [];
|
|
848
1035
|
|
|
849
|
-
const writes = [];
|
|
850
1036
|
const fields = ['maxIterations', 'autoDrive', 'enableSound'];
|
|
1037
|
+
const writes = [];
|
|
851
1038
|
|
|
852
1039
|
for (const f of fields) {
|
|
853
1040
|
if (draft[f] === undefined) continue;
|
|
@@ -996,124 +1183,124 @@ window.__ModuleLoader__.load({
|
|
|
996
1183
|
React.createElement(
|
|
997
1184
|
'div',
|
|
998
1185
|
{ className: 'dsh-goal-card-field' },
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1186
|
+
React.createElement(
|
|
1187
|
+
'div',
|
|
1188
|
+
{ className: 'dsh-goal-field-label-row' },
|
|
1189
|
+
React.createElement('label', { htmlFor: 'dsh-goal-max-iter' }, t('maxIterLabel') || 'Максимум итераций (Safety Limit):'),
|
|
1190
|
+
React.createElement(
|
|
1191
|
+
'div',
|
|
1192
|
+
{ className: 'dsh-goal-field-meta' },
|
|
1193
|
+
maxIterStatus.isOverridden
|
|
1194
|
+
? React.createElement('span', { className: 'dsh-goal-override-tag' }, t('overridden') || 'изменено')
|
|
1195
|
+
: null,
|
|
1196
|
+
maxIterStatus.isOverridden
|
|
1197
|
+
? React.createElement(
|
|
1198
|
+
'button',
|
|
1199
|
+
{
|
|
1200
|
+
type: 'button',
|
|
1201
|
+
className: 'dsh-goal-btn-inline-reset',
|
|
1202
|
+
title: t('resetField') || 'Сбросить к значению по умолчанию',
|
|
1203
|
+
onClick: () => resetFieldToDefault('maxIterations'),
|
|
1204
|
+
},
|
|
1205
|
+
React.createElement(IconRotateCcw, { size: 12 }),
|
|
1206
|
+
t('resetField') || 'По умолчанию',
|
|
1207
|
+
)
|
|
1208
|
+
: null,
|
|
1209
|
+
),
|
|
1210
|
+
),
|
|
1211
|
+
React.createElement('input', {
|
|
1212
|
+
id: 'dsh-goal-max-iter',
|
|
1213
|
+
type: 'number',
|
|
1214
|
+
min: 1,
|
|
1215
|
+
placeholder: String(maxIterStatus.baseValue),
|
|
1216
|
+
className: 'dsh-goal-card-input',
|
|
1217
|
+
value: maxIterStatus.value !== undefined ? maxIterStatus.value : '',
|
|
1218
|
+
disabled,
|
|
1219
|
+
'aria-invalid': invalid,
|
|
1220
|
+
onChange: (e) => edit('maxIterations', e.target.value),
|
|
1221
|
+
}),
|
|
1222
|
+
),
|
|
1223
|
+
React.createElement(
|
|
1224
|
+
'div',
|
|
1225
|
+
{ className: 'dsh-goal-check-row' },
|
|
1226
|
+
React.createElement(
|
|
1227
|
+
'label',
|
|
1228
|
+
{ className: 'dsh-goal-check' },
|
|
1229
|
+
React.createElement('input', {
|
|
1230
|
+
type: 'checkbox',
|
|
1231
|
+
checked: autoDriveStatus.value === true,
|
|
1232
|
+
disabled,
|
|
1233
|
+
onChange: (e) => edit('autoDrive', e.target.checked),
|
|
1234
|
+
}),
|
|
1235
|
+
t('autoDriveLabel') || 'Авто-драйв: продолжать цикл автоматически',
|
|
1236
|
+
),
|
|
1237
|
+
autoDriveStatus.isOverridden
|
|
1238
|
+
? React.createElement(
|
|
1239
|
+
'button',
|
|
1240
|
+
{
|
|
1241
|
+
type: 'button',
|
|
1242
|
+
className: 'dsh-goal-btn-inline-reset',
|
|
1243
|
+
title: t('resetField') || 'Сбросить к значению по умолчанию',
|
|
1244
|
+
onClick: () => resetFieldToDefault('autoDrive'),
|
|
1245
|
+
},
|
|
1246
|
+
React.createElement(IconRotateCcw, { size: 12 }),
|
|
1247
|
+
)
|
|
1248
|
+
: null,
|
|
1249
|
+
),
|
|
1250
|
+
React.createElement(
|
|
1251
|
+
'div',
|
|
1252
|
+
{ className: 'dsh-goal-check-row' },
|
|
1253
|
+
React.createElement(
|
|
1254
|
+
'label',
|
|
1255
|
+
{ className: 'dsh-goal-check' },
|
|
1256
|
+
React.createElement('input', {
|
|
1257
|
+
type: 'checkbox',
|
|
1258
|
+
checked: enableSoundStatus.value === true,
|
|
1259
|
+
disabled,
|
|
1260
|
+
onChange: (e) => edit('enableSound', e.target.checked),
|
|
1261
|
+
}),
|
|
1262
|
+
t('soundLabel') || 'Звук по завершении цели',
|
|
1263
|
+
),
|
|
1264
|
+
enableSoundStatus.isOverridden
|
|
1265
|
+
? React.createElement(
|
|
1266
|
+
'button',
|
|
1267
|
+
{
|
|
1268
|
+
type: 'button',
|
|
1269
|
+
className: 'dsh-goal-btn-inline-reset',
|
|
1270
|
+
title: t('resetField') || 'Сбросить к значению по умолчанию',
|
|
1271
|
+
onClick: () => resetFieldToDefault('enableSound'),
|
|
1272
|
+
},
|
|
1273
|
+
React.createElement(IconRotateCcw, { size: 12 }),
|
|
1274
|
+
)
|
|
1275
|
+
: null,
|
|
1276
|
+
),
|
|
1277
|
+
React.createElement(
|
|
1278
|
+
'div',
|
|
1279
|
+
{ className: 'dsh-goal-foot' },
|
|
1280
|
+
failed
|
|
1281
|
+
? React.createElement('span', { className: 'dsh-goal-foot-note' }, t('saveFailed') || 'Не сохранено — исправьте и повторите')
|
|
1282
|
+
: null,
|
|
1283
|
+
React.createElement(
|
|
1011
1284
|
'button',
|
|
1012
1285
|
{
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1286
|
+
className: 'dsh-goal-discard',
|
|
1287
|
+
disabled: !dirty || disabled,
|
|
1288
|
+
onClick: () => {
|
|
1289
|
+
setFailed(false);
|
|
1290
|
+
setDraft(null);
|
|
1291
|
+
},
|
|
1017
1292
|
},
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
min: 1,
|
|
1028
|
-
placeholder: String(maxIterStatus.baseValue),
|
|
1029
|
-
className: 'dsh-goal-card-input',
|
|
1030
|
-
value: maxIterStatus.value !== undefined ? maxIterStatus.value : '',
|
|
1031
|
-
disabled,
|
|
1032
|
-
'aria-invalid': invalid,
|
|
1033
|
-
onChange: (e) => edit('maxIterations', e.target.value),
|
|
1034
|
-
}),
|
|
1035
|
-
),
|
|
1036
|
-
React.createElement(
|
|
1037
|
-
'div',
|
|
1038
|
-
{ className: 'dsh-goal-check-row' },
|
|
1039
|
-
React.createElement(
|
|
1040
|
-
'label',
|
|
1041
|
-
{ className: 'dsh-goal-check' },
|
|
1042
|
-
React.createElement('input', {
|
|
1043
|
-
type: 'checkbox',
|
|
1044
|
-
checked: autoDriveStatus.value === true,
|
|
1045
|
-
disabled,
|
|
1046
|
-
onChange: (e) => edit('autoDrive', e.target.checked),
|
|
1047
|
-
}),
|
|
1048
|
-
t('autoDriveLabel') || 'Авто-драйв: продолжать цикл автоматически',
|
|
1049
|
-
),
|
|
1050
|
-
autoDriveStatus.isOverridden
|
|
1051
|
-
? React.createElement(
|
|
1052
|
-
'button',
|
|
1053
|
-
{
|
|
1054
|
-
type: 'button',
|
|
1055
|
-
className: 'dsh-goal-btn-inline-reset',
|
|
1056
|
-
title: t('resetField') || 'Сбросить к значению по умолчанию',
|
|
1057
|
-
onClick: () => resetFieldToDefault('autoDrive'),
|
|
1058
|
-
},
|
|
1059
|
-
React.createElement(IconRotateCcw, { size: 12 }),
|
|
1060
|
-
)
|
|
1061
|
-
: null,
|
|
1062
|
-
),
|
|
1063
|
-
React.createElement(
|
|
1064
|
-
'div',
|
|
1065
|
-
{ className: 'dsh-goal-check-row' },
|
|
1066
|
-
React.createElement(
|
|
1067
|
-
'label',
|
|
1068
|
-
{ className: 'dsh-goal-check' },
|
|
1069
|
-
React.createElement('input', {
|
|
1070
|
-
type: 'checkbox',
|
|
1071
|
-
checked: enableSoundStatus.value === true,
|
|
1072
|
-
disabled,
|
|
1073
|
-
onChange: (e) => edit('enableSound', e.target.checked),
|
|
1074
|
-
}),
|
|
1075
|
-
t('soundLabel') || 'Звук по завершении цели',
|
|
1076
|
-
),
|
|
1077
|
-
enableSoundStatus.isOverridden
|
|
1078
|
-
? React.createElement(
|
|
1079
|
-
'button',
|
|
1080
|
-
{
|
|
1081
|
-
type: 'button',
|
|
1082
|
-
className: 'dsh-goal-btn-inline-reset',
|
|
1083
|
-
title: t('resetField') || 'Сбросить к значению по умолчанию',
|
|
1084
|
-
onClick: () => resetFieldToDefault('enableSound'),
|
|
1085
|
-
},
|
|
1086
|
-
React.createElement(IconRotateCcw, { size: 12 }),
|
|
1087
|
-
)
|
|
1088
|
-
: null,
|
|
1089
|
-
),
|
|
1090
|
-
React.createElement(
|
|
1091
|
-
'div',
|
|
1092
|
-
{ className: 'dsh-goal-foot' },
|
|
1093
|
-
failed
|
|
1094
|
-
? React.createElement('span', { className: 'dsh-goal-foot-note' }, t('saveFailed') || 'Не сохранено — исправьте и повторите')
|
|
1095
|
-
: null,
|
|
1096
|
-
React.createElement(
|
|
1097
|
-
'button',
|
|
1098
|
-
{
|
|
1099
|
-
className: 'dsh-goal-discard',
|
|
1100
|
-
disabled: !dirty || disabled,
|
|
1101
|
-
onClick: () => {
|
|
1102
|
-
setFailed(false);
|
|
1103
|
-
setDraft(null);
|
|
1104
|
-
},
|
|
1105
|
-
},
|
|
1106
|
-
t('discard') || 'Отменить правки',
|
|
1107
|
-
),
|
|
1108
|
-
React.createElement(
|
|
1109
|
-
'button',
|
|
1110
|
-
{ className: 'dsh-goal-save', disabled: !dirty || disabled || invalid, onClick: save },
|
|
1111
|
-
saving ? t('saving') || 'Сохранение…' : t('save') || 'Сохранить',
|
|
1112
|
-
),
|
|
1113
|
-
),
|
|
1293
|
+
t('discard') || 'Отменить правки',
|
|
1294
|
+
),
|
|
1295
|
+
React.createElement(
|
|
1296
|
+
'button',
|
|
1297
|
+
{ className: 'dsh-goal-save', disabled: !dirty || disabled || invalid, onClick: save },
|
|
1298
|
+
saving ? t('saving') || 'Сохранение…' : t('save') || 'Сохранить',
|
|
1299
|
+
),
|
|
1300
|
+
),
|
|
1301
|
+
),
|
|
1114
1302
|
)
|
|
1115
|
-
|
|
1116
|
-
: null,
|
|
1303
|
+
: null,
|
|
1117
1304
|
);
|
|
1118
1305
|
}
|
|
1119
1306
|
|
|
@@ -1129,7 +1316,7 @@ window.__ModuleLoader__.load({
|
|
|
1129
1316
|
details: 'Развернуть детали цели',
|
|
1130
1317
|
modalTitle: 'План и статус цели',
|
|
1131
1318
|
modalTitleCompleted: 'Цель выполнена: план и результаты',
|
|
1132
|
-
time: 'Время',
|
|
1319
|
+
time: 'Время работы',
|
|
1133
1320
|
milestones: 'План работ:',
|
|
1134
1321
|
noMilestones: 'Агент формирует план работ...',
|
|
1135
1322
|
close: 'Закрыть',
|
|
@@ -1157,7 +1344,7 @@ window.__ModuleLoader__.load({
|
|
|
1157
1344
|
details: 'Expand Goal Details',
|
|
1158
1345
|
modalTitle: 'Goal Plan & Status',
|
|
1159
1346
|
modalTitleCompleted: 'Goal Completed: Plan & Results',
|
|
1160
|
-
time: '
|
|
1347
|
+
time: 'Running time',
|
|
1161
1348
|
milestones: 'Plan of work:',
|
|
1162
1349
|
noMilestones: 'Agent is preparing the plan of work...',
|
|
1163
1350
|
close: 'Close',
|
|
@@ -1212,7 +1399,7 @@ window.__ModuleLoader__.load({
|
|
|
1212
1399
|
id: '@goodandready/dsh-goal',
|
|
1213
1400
|
order: 10,
|
|
1214
1401
|
locale: NS,
|
|
1215
|
-
inject: () => ({ ctx }),
|
|
1402
|
+
inject: (slotProps) => ({ ctx, ...slotProps }),
|
|
1216
1403
|
},
|
|
1217
1404
|
GoalTopBanner,
|
|
1218
1405
|
);
|