pict-section-form 1.2.2 → 1.2.3
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pict-section-form",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "Pict dynamic form sections",
|
|
5
5
|
"main": "source/Pict-Section-Form.js",
|
|
6
6
|
"directories": {
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"browser-env": "^3.3.0",
|
|
35
35
|
"eslint": "^9.39.2",
|
|
36
36
|
"jquery": "^4.0.0",
|
|
37
|
-
"pict": "^1.0.
|
|
37
|
+
"pict": "^1.0.386",
|
|
38
38
|
"pict-application": "^1.0.34",
|
|
39
39
|
"pict-docuserve": "^1.4.19",
|
|
40
|
-
"pict-service-commandlineutility": "^1.0.
|
|
40
|
+
"pict-service-commandlineutility": "^1.0.20",
|
|
41
41
|
"quackage": "^1.3.0",
|
|
42
42
|
"tui-grid": "^4.21.22",
|
|
43
43
|
"typescript": "^5.9.3"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"marked": "^4.3.0",
|
|
49
49
|
"pict-provider": "^1.0.13",
|
|
50
50
|
"pict-section-excalidraw": "^1.0.3",
|
|
51
|
-
"pict-section-markdowneditor": "^1.0.
|
|
51
|
+
"pict-section-markdowneditor": "^1.0.19",
|
|
52
52
|
"pict-section-tuigrid": "^1.0.31",
|
|
53
53
|
"pict-template": "^1.0.15",
|
|
54
54
|
"pict-view": "^1.0.68"
|
|
@@ -318,13 +318,21 @@ class DynamicTabularData extends libPictProvider
|
|
|
318
318
|
this.log.error(`Dynamic View [${pView.UUID}]::[${pView.Hash}] Group ${tmpGroup.Hash} attempting to move row [${pRowIndex}] to [${pNewRowIndex}] but the index is out of bounds.`);
|
|
319
319
|
return false;
|
|
320
320
|
}
|
|
321
|
+
let tmpOriginalLength = tmpDestinationObject.length;
|
|
321
322
|
let tmpElementToBeMoved = tmpDestinationObject.splice(tmpRowIndex, 1);
|
|
322
323
|
tmpDestinationObject.splice(tmpNewRowIndex, 0, tmpElementToBeMoved[0]);
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
//
|
|
326
|
-
//
|
|
327
|
-
|
|
324
|
+
|
|
325
|
+
// Position-keyed DynamicColumns (KeyBy:"Position") store dependent cell data by the
|
|
326
|
+
// source row's INDEX, so a source reorder must apply the same permutation to every
|
|
327
|
+
// dependent row's positional cells -- otherwise user-entered values stay put while
|
|
328
|
+
// their column re-labels to a different source row. Must run BEFORE the dependent
|
|
329
|
+
// views re-resolve their columns below. No-op for value-keyed generators.
|
|
330
|
+
this._moveDependentPositionalColumns(tmpGroup.RecordSetAddress, tmpRowIndex, tmpNewRowIndex, tmpOriginalLength);
|
|
331
|
+
|
|
332
|
+
// Render (source + dependent views) BEFORE solving so dependent DynamicColumns tables
|
|
333
|
+
// don't blank until the next edit, and the solve's DOM side effects survive. Matches
|
|
334
|
+
// the add/delete handlers' order.
|
|
335
|
+
this._repaintAfterRowReorder(tmpGroup);
|
|
328
336
|
}
|
|
329
337
|
}
|
|
330
338
|
}
|
|
@@ -353,17 +361,23 @@ class DynamicTabularData extends libPictProvider
|
|
|
353
361
|
this.log.error(`Dynamic View [${pView.UUID}]::[${pView.Hash}] Group ${tmpGroup.Hash} attempting to move row [${pRowIndex}] down but it's already at the bottom.`);
|
|
354
362
|
return false;
|
|
355
363
|
}
|
|
364
|
+
let tmpOriginalLength = tmpDestinationObject.length;
|
|
356
365
|
let tmpElementToBeMoved = tmpDestinationObject.splice(tmpRowIndex, 1);
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
//
|
|
365
|
-
|
|
366
|
-
|
|
366
|
+
let tmpNewRowIndex = tmpRowIndex + 1;
|
|
367
|
+
tmpDestinationObject.splice(tmpNewRowIndex, 0, tmpElementToBeMoved[0]);
|
|
368
|
+
|
|
369
|
+
// Position-keyed DynamicColumns (KeyBy:"Position") store dependent cell data by the
|
|
370
|
+
// source row's INDEX, so a source reorder must apply the same permutation to every
|
|
371
|
+
// dependent row's positional cells -- otherwise user-entered values stay put while
|
|
372
|
+
// their column re-labels to a different source row. Must run BEFORE the dependent
|
|
373
|
+
// views re-resolve their columns below. No-op for value-keyed generators.
|
|
374
|
+
this._moveDependentPositionalColumns(tmpGroup.RecordSetAddress, tmpRowIndex, tmpNewRowIndex, tmpOriginalLength);
|
|
375
|
+
|
|
376
|
+
// Render (source + dependent views) BEFORE solving so the solve's DOM side effects
|
|
377
|
+
// (e.g. SetGroupVisibility hiding a validation message) act on the freshly rebuilt
|
|
378
|
+
// DOM and survive, and so dependent DynamicColumns tables don't blank until the next
|
|
379
|
+
// edit. Matches the add/delete handlers' order.
|
|
380
|
+
this._repaintAfterRowReorder(tmpGroup);
|
|
367
381
|
}
|
|
368
382
|
}
|
|
369
383
|
}
|
|
@@ -397,17 +411,23 @@ class DynamicTabularData extends libPictProvider
|
|
|
397
411
|
this.log.error(`Dynamic View [${pView.UUID}]::[${pView.Hash}] Group ${tmpGroup.Hash} attempting to move row [${pRowIndex}] but the index is out of bounds.`);
|
|
398
412
|
return false;
|
|
399
413
|
}
|
|
414
|
+
let tmpOriginalLength = tmpDestinationObject.length;
|
|
400
415
|
let tmpElementToBeMoved = tmpDestinationObject.splice(tmpRowIndex, 1);
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
//
|
|
405
|
-
//
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
//
|
|
409
|
-
|
|
410
|
-
|
|
416
|
+
let tmpNewRowIndex = tmpRowIndex - 1;
|
|
417
|
+
tmpDestinationObject.splice(tmpNewRowIndex, 0, tmpElementToBeMoved[0]);
|
|
418
|
+
|
|
419
|
+
// Position-keyed DynamicColumns (KeyBy:"Position") store dependent cell data by the
|
|
420
|
+
// source row's INDEX, so a source reorder must apply the same permutation to every
|
|
421
|
+
// dependent row's positional cells -- otherwise user-entered values stay put while
|
|
422
|
+
// their column re-labels to a different source row. Must run BEFORE the dependent
|
|
423
|
+
// views re-resolve their columns below. No-op for value-keyed generators.
|
|
424
|
+
this._moveDependentPositionalColumns(tmpGroup.RecordSetAddress, tmpRowIndex, tmpNewRowIndex, tmpOriginalLength);
|
|
425
|
+
|
|
426
|
+
// Render (source + dependent views) BEFORE solving so the solve's DOM side effects
|
|
427
|
+
// (e.g. SetGroupVisibility hiding a validation message) act on the freshly rebuilt
|
|
428
|
+
// DOM and survive, and so dependent DynamicColumns tables don't blank until the next
|
|
429
|
+
// edit. Matches the add/delete handlers' order.
|
|
430
|
+
this._repaintAfterRowReorder(tmpGroup);
|
|
411
431
|
}
|
|
412
432
|
}
|
|
413
433
|
}
|
|
@@ -656,6 +676,165 @@ class DynamicTabularData extends libPictProvider
|
|
|
656
676
|
}
|
|
657
677
|
}
|
|
658
678
|
}
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* For position-keyed DynamicColumns (KeyBy: "Position") sourced from
|
|
682
|
+
* pSourceRecordSetAddress, REORDER each dependent row's positional cells to
|
|
683
|
+
* mirror a source row that moved from pOldIndex to pNewIndex. The source array
|
|
684
|
+
* was already spliced (remove at pOldIndex, insert at pNewIndex); this applies
|
|
685
|
+
* the identical permutation to every dependent row's positional cell VALUES so
|
|
686
|
+
* the data stays attached to its column when the columns re-resolve to the new
|
|
687
|
+
* source order. Without it, a reorder leaves user-entered cells under the wrong
|
|
688
|
+
* (renamed) column. Solver-filled rows re-derive on the next solve regardless;
|
|
689
|
+
* applying the move to them too is harmless (the solve overwrites them). No-op
|
|
690
|
+
* for value-keyed generators (their data stays attached to the stable value).
|
|
691
|
+
*
|
|
692
|
+
* Must run AFTER the source splice and BEFORE the dependent views re-resolve +
|
|
693
|
+
* the marshal repaints them. Symmetric with _spliceDependentPositionalColumns.
|
|
694
|
+
*
|
|
695
|
+
* @param {string} pSourceRecordSetAddress - RecordSetAddress of the moved-within source.
|
|
696
|
+
* @param {number} pOldIndex - Source row's index before the move.
|
|
697
|
+
* @param {number} pNewIndex - Source row's index after the move.
|
|
698
|
+
* @param {number} pLength - Source row count (unchanged by a move).
|
|
699
|
+
*/
|
|
700
|
+
_moveDependentPositionalColumns(pSourceRecordSetAddress, pOldIndex, pNewIndex, pLength)
|
|
701
|
+
{
|
|
702
|
+
if ((typeof pSourceRecordSetAddress !== 'string') || (pSourceRecordSetAddress.length < 1))
|
|
703
|
+
{
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
if (pOldIndex === pNewIndex)
|
|
707
|
+
{
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
if (!this.pict.views.PictFormMetacontroller)
|
|
711
|
+
{
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
let tmpManifestFactory = this.fable.ManifestFactory;
|
|
715
|
+
if (!tmpManifestFactory || (typeof tmpManifestFactory._parseDynamicColumnTemplate !== 'function'))
|
|
716
|
+
{
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
let tmpViews = this.pict.views.PictFormMetacontroller.filterViews((pViewToTest) => { return pViewToTest.isPictSectionForm; });
|
|
720
|
+
for (let v = 0; v < tmpViews.length; v++)
|
|
721
|
+
{
|
|
722
|
+
let tmpView = tmpViews[v];
|
|
723
|
+
let tmpGroups = tmpView.getGroups();
|
|
724
|
+
for (let g = 0; g < tmpGroups.length; g++)
|
|
725
|
+
{
|
|
726
|
+
let tmpGroup = tmpGroups[g];
|
|
727
|
+
if (!Array.isArray(tmpGroup.DynamicColumns) || (tmpGroup.DynamicColumns.length < 1))
|
|
728
|
+
{
|
|
729
|
+
continue;
|
|
730
|
+
}
|
|
731
|
+
let tmpDependentRows = tmpView.sectionManifest.getValueByHash(tmpView.getMarshalDestinationObject(), tmpGroup.RecordSetAddress);
|
|
732
|
+
if (!Array.isArray(tmpDependentRows) || (tmpDependentRows.length < 1))
|
|
733
|
+
{
|
|
734
|
+
continue;
|
|
735
|
+
}
|
|
736
|
+
for (let c = 0; c < tmpGroup.DynamicColumns.length; c++)
|
|
737
|
+
{
|
|
738
|
+
let tmpGenerator = tmpGroup.DynamicColumns[c];
|
|
739
|
+
if (!tmpGenerator || (tmpGenerator.SourceAddress !== pSourceRecordSetAddress))
|
|
740
|
+
{
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
// Only position-keyed generators store data by index; value-keyed columns keep
|
|
744
|
+
// their data attached to the (stable) value, so they need no reordering.
|
|
745
|
+
if (tmpGenerator.KeyBy !== 'Position')
|
|
746
|
+
{
|
|
747
|
+
continue;
|
|
748
|
+
}
|
|
749
|
+
if (typeof tmpGenerator.InformaryDataAddressTemplate !== 'string')
|
|
750
|
+
{
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
753
|
+
// Resolve the positional cell address for each column index once.
|
|
754
|
+
let tmpAddresses = [];
|
|
755
|
+
for (let k = 0; k < pLength; k++)
|
|
756
|
+
{
|
|
757
|
+
tmpAddresses[k] = tmpManifestFactory._parseDynamicColumnTemplate(tmpGenerator.InformaryDataAddressTemplate, { __Index: k, __RowNumber: k + 1 });
|
|
758
|
+
}
|
|
759
|
+
for (let r = 0; r < tmpDependentRows.length; r++)
|
|
760
|
+
{
|
|
761
|
+
let tmpRow = tmpDependentRows[r];
|
|
762
|
+
if (!tmpRow || (typeof tmpRow !== 'object'))
|
|
763
|
+
{
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
// Read the current positional cell values, apply the identical
|
|
767
|
+
// remove-at-old / insert-at-new permutation, then write them back.
|
|
768
|
+
let tmpValues = [];
|
|
769
|
+
for (let k = 0; k < pLength; k++)
|
|
770
|
+
{
|
|
771
|
+
tmpValues[k] = tmpAddresses[k] ? tmpView.sectionManifest.getValueByHash(tmpRow, tmpAddresses[k]) : undefined;
|
|
772
|
+
}
|
|
773
|
+
let tmpMoved = tmpValues.splice(pOldIndex, 1);
|
|
774
|
+
tmpValues.splice(pNewIndex, 0, tmpMoved[0]);
|
|
775
|
+
for (let k = 0; k < pLength; k++)
|
|
776
|
+
{
|
|
777
|
+
if (tmpAddresses[k])
|
|
778
|
+
{
|
|
779
|
+
tmpView.sectionManifest.setValueByHash(tmpRow, tmpAddresses[k], tmpValues[k]);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
/**
|
|
789
|
+
* Shared tail for the row-reorder handlers (move up / move down / set index).
|
|
790
|
+
* Repaints the moved source table and every dependent view, in the RENDER phase
|
|
791
|
+
* BEFORE solving + marshaling, then solves and marshals. Mirrors what the add /
|
|
792
|
+
* delete handlers do so a reorder doesn't blank dependent DynamicColumns tables
|
|
793
|
+
* (or the rest of their section) until the next edit. Render happens before the
|
|
794
|
+
* solve so the solve's DOM side effects (e.g. SetGroupVisibility) land on the
|
|
795
|
+
* freshly rebuilt DOM and survive.
|
|
796
|
+
*
|
|
797
|
+
* @param {Object} pGroup - The reordered group (its RecordSetAddress drives dependents).
|
|
798
|
+
*/
|
|
799
|
+
_repaintAfterRowReorder(pGroup)
|
|
800
|
+
{
|
|
801
|
+
// Render every view that renders this record set as a table (the source table itself
|
|
802
|
+
// plus any sibling views bound to the same RecordSetAddress).
|
|
803
|
+
let tmpViewsToRender = this.pict.views.PictFormMetacontroller.filterViews(
|
|
804
|
+
(pViewToTestForGroup) =>
|
|
805
|
+
{
|
|
806
|
+
if (!pViewToTestForGroup.isPictSectionForm)
|
|
807
|
+
{
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
810
|
+
let tmpGroupsToTest = pViewToTestForGroup.getGroups();
|
|
811
|
+
for (let i = 0; i < tmpGroupsToTest.length; i++)
|
|
812
|
+
{
|
|
813
|
+
if (tmpGroupsToTest[i].RecordSetAddress == pGroup.RecordSetAddress)
|
|
814
|
+
{
|
|
815
|
+
return true;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
return false;
|
|
819
|
+
});
|
|
820
|
+
for (let i = 0; i < tmpViewsToRender.length; i++)
|
|
821
|
+
{
|
|
822
|
+
tmpViewsToRender[i].render();
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
// Rebuild any OTHER views whose DynamicColumns are sourced from this record set
|
|
826
|
+
// HERE, in the render phase -- BEFORE the marshal below -- so the column DOM is
|
|
827
|
+
// correct (and re-labeled to the new order) when the marshal fills it. Without
|
|
828
|
+
// this the dependent table is only rebuilt mid-marshal (onDataMarshalToForm),
|
|
829
|
+
// which renders AFTER the cells were filled and blanks them until the next edit.
|
|
830
|
+
this._rebuildDependentDynamicColumnViews(pGroup.RecordSetAddress);
|
|
831
|
+
|
|
832
|
+
// Run the solver
|
|
833
|
+
this.pict.providers.DynamicSolver.solveViews();
|
|
834
|
+
|
|
835
|
+
// We've re-rendered but we don't know what needs to be marshaled based on the solve that ran above so marshal everything
|
|
836
|
+
this.pict.views.PictFormMetacontroller.marshalFormSections();
|
|
837
|
+
}
|
|
659
838
|
}
|
|
660
839
|
|
|
661
840
|
module.exports = DynamicTabularData;
|
|
@@ -569,6 +569,96 @@ suite('PictSectionForm Tabular Features', () =>
|
|
|
569
569
|
}, fDone);
|
|
570
570
|
});
|
|
571
571
|
|
|
572
|
+
test('Moving a source row reorders dependent position-keyed cells (data follows the column)', (fDone) =>
|
|
573
|
+
{
|
|
574
|
+
let App = makeApplication({
|
|
575
|
+
Hash: 'Grades',
|
|
576
|
+
Layout: 'Tabular',
|
|
577
|
+
RecordSetAddress: 'Grades',
|
|
578
|
+
RecordManifest: 'GradeRowEditor',
|
|
579
|
+
DynamicColumns:
|
|
580
|
+
[
|
|
581
|
+
{
|
|
582
|
+
SourceAddress: 'Assignments',
|
|
583
|
+
KeyBy: 'Position',
|
|
584
|
+
HashTemplate: 'PassingCol_{~D:Record.__Index~}',
|
|
585
|
+
NameTemplate: '{~D:Record.Title~}',
|
|
586
|
+
InformaryDataAddressTemplate: 'PassingCol_{~D:Record.__Index~}',
|
|
587
|
+
DataType: 'String',
|
|
588
|
+
PictForm: { InputType: 'Text' }
|
|
589
|
+
}
|
|
590
|
+
]
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
// Each dependent row carries user-entered positional cells (one per source column).
|
|
594
|
+
Grades:
|
|
595
|
+
[
|
|
596
|
+
{ Section: 'A', StudentName: 'Alice', PassingCol_0: 'a0', PassingCol_1: 'a1', PassingCol_2: 'a2' },
|
|
597
|
+
{ Section: 'A', StudentName: 'Bob', PassingCol_0: 'b0', PassingCol_1: 'b1', PassingCol_2: 'b2' }
|
|
598
|
+
]
|
|
599
|
+
});
|
|
600
|
+
bootstrap(App, (_Pict) =>
|
|
601
|
+
{
|
|
602
|
+
// Source order is [Addition(0), Photosynthesis(1), Reading 1(2)]. Move row 0 -> 2,
|
|
603
|
+
// the way moveDynamicTableRowDown twice / setDynamicTableRowIndex(0,2) would, then
|
|
604
|
+
// apply the SAME permutation to every dependent row's positional cells.
|
|
605
|
+
_Pict.providers.DynamicTabularData._moveDependentPositionalColumns('Assignments', 0, 2, 3);
|
|
606
|
+
|
|
607
|
+
let tmpRow0 = _Pict.AppData.Grades[0];
|
|
608
|
+
let tmpRow1 = _Pict.AppData.Grades[1];
|
|
609
|
+
// [a0,a1,a2] with source 0->2 becomes [a1,a2,a0] -- the value under each column
|
|
610
|
+
// moved with its source position, so data stays attached to its column.
|
|
611
|
+
Expect(tmpRow0.PassingCol_0).to.equal('a1', 'row 0 col 0 took the value from old position 1');
|
|
612
|
+
Expect(tmpRow0.PassingCol_1).to.equal('a2', 'row 0 col 1 took the value from old position 2');
|
|
613
|
+
Expect(tmpRow0.PassingCol_2).to.equal('a0', 'row 0 col 2 took the moved value from old position 0');
|
|
614
|
+
Expect(tmpRow1.PassingCol_0).to.equal('b1', 'row 1 permuted identically');
|
|
615
|
+
Expect(tmpRow1.PassingCol_1).to.equal('b2', 'row 1 permuted identically');
|
|
616
|
+
Expect(tmpRow1.PassingCol_2).to.equal('b0', 'row 1 permuted identically');
|
|
617
|
+
}, fDone);
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
test('Reordering a source row re-labels dependent columns in the render phase (no blank-out on move)', (fDone) =>
|
|
621
|
+
{
|
|
622
|
+
let App = makeApplication({
|
|
623
|
+
Hash: 'Grades',
|
|
624
|
+
Layout: 'Tabular',
|
|
625
|
+
RecordSetAddress: 'Grades',
|
|
626
|
+
RecordManifest: 'GradeRowEditor',
|
|
627
|
+
DynamicColumns:
|
|
628
|
+
[
|
|
629
|
+
{
|
|
630
|
+
SourceAddress: 'Assignments',
|
|
631
|
+
KeyBy: 'Position',
|
|
632
|
+
HashTemplate: 'PassingCol_{~D:Record.__Index~}',
|
|
633
|
+
NameTemplate: '{~D:Record.Title~}',
|
|
634
|
+
InformaryDataAddressTemplate: 'PassingCol_{~D:Record.__Index~}',
|
|
635
|
+
DataType: 'String',
|
|
636
|
+
PictForm: { InputType: 'Text' }
|
|
637
|
+
}
|
|
638
|
+
]
|
|
639
|
+
});
|
|
640
|
+
bootstrap(App, (_Pict) =>
|
|
641
|
+
{
|
|
642
|
+
let tmpView = _Pict.views['PictSectionForm-Class'];
|
|
643
|
+
let tmpGroup = tmpView.sectionDefinition.Groups[0];
|
|
644
|
+
Expect(tmpGroup.supportingManifest.elementDescriptors['PassingCol_0'].Name).to.equal('Addition', 'col 0 header before move');
|
|
645
|
+
Expect(tmpGroup.supportingManifest.elementDescriptors['PassingCol_2'].Name).to.equal('Reading 1', 'col 2 header before move');
|
|
646
|
+
|
|
647
|
+
// Reorder the source the way the move handler splices it (move index 0 -> 2), then
|
|
648
|
+
// run the render-phase rebuild the move handler now performs BEFORE marshaling.
|
|
649
|
+
let tmpMoved = _Pict.AppData.Assignments.splice(0, 1);
|
|
650
|
+
_Pict.AppData.Assignments.splice(2, 0, tmpMoved[0]);
|
|
651
|
+
_Pict.providers.DynamicTabularData._rebuildDependentDynamicColumnViews('Assignments');
|
|
652
|
+
|
|
653
|
+
// Column hashes are position-keyed (stable), but their labels must re-resolve to the
|
|
654
|
+
// NEW source order here in the render phase -- not mid-marshal, which would blank the
|
|
655
|
+
// freshly filled cells until the next edit.
|
|
656
|
+
Expect(tmpGroup.supportingManifest.elementDescriptors['PassingCol_0'].Name).to.equal('Photosynthesis', 'col 0 re-labeled to new position 0');
|
|
657
|
+
Expect(tmpGroup.supportingManifest.elementDescriptors['PassingCol_1'].Name).to.equal('Reading 1', 'col 1 re-labeled to new position 1');
|
|
658
|
+
Expect(tmpGroup.supportingManifest.elementDescriptors['PassingCol_2'].Name).to.equal('Addition', 'col 2 re-labeled to the moved row');
|
|
659
|
+
}, fDone);
|
|
660
|
+
});
|
|
661
|
+
|
|
572
662
|
test('Renaming a source row reports namesChanged and refreshes the column header in place', (fDone) =>
|
|
573
663
|
{
|
|
574
664
|
let App = makeApplication({
|