jazz-tools 0.19.2 → 0.19.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/.turbo/turbo-build.log +60 -60
- package/CHANGELOG.md +10 -0
- package/dist/{chunk-NCNM6UDZ.js → chunk-JPWM4CS2.js} +4 -2
- package/dist/{chunk-NCNM6UDZ.js.map → chunk-JPWM4CS2.js.map} +1 -1
- package/dist/index.js +1 -1
- package/dist/inspector/{custom-element-ABVPHX53.js → custom-element-3JAYHXWQ.js} +25 -8
- package/dist/inspector/custom-element-3JAYHXWQ.js.map +1 -0
- package/dist/inspector/index.js +24 -7
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/inspector/utils/permissions.d.ts +3 -0
- package/dist/inspector/utils/permissions.d.ts.map +1 -0
- package/dist/inspector/viewer/co-map-view.d.ts.map +1 -1
- package/dist/inspector/viewer/grid-view.d.ts.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/tools/implementation/zodSchema/unionUtils.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/inspector/tests/viewer/comap-view.test.tsx +309 -1
- package/src/inspector/utils/permissions.ts +10 -0
- package/src/inspector/viewer/co-map-view.tsx +27 -15
- package/src/inspector/viewer/grid-view.tsx +2 -1
- package/src/inspector/viewer/history-view.tsx +3 -1
- package/src/tools/implementation/zodSchema/unionUtils.ts +3 -4
- package/dist/inspector/custom-element-ABVPHX53.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../src/inspector/utils/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,GAAG,OAAO,CAOxD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"co-map-view.d.ts","sourceRoot":"","sources":["../../../src/inspector/viewer/co-map-view.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"co-map-view.d.ts","sourceRoot":"","sources":["../../../src/inspector/viewer/co-map-view.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AASnC,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,IAAI,EACJ,IAAI,EACJ,UAAU,GACX,EAAE;IACD,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;CACzC,2CAmBA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid-view.d.ts","sourceRoot":"","sources":["../../../src/inspector/viewer/grid-view.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAQ,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACrD,OAAO,EAAE,UAAU,EAAa,MAAM,QAAQ,CAAC;AAI/C,OAAO,EAAE,QAAQ,EAAU,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"grid-view.d.ts","sourceRoot":"","sources":["../../../src/inspector/viewer/grid-view.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAQ,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACrD,OAAO,EAAE,UAAU,EAAa,MAAM,QAAQ,CAAC;AAI/C,OAAO,EAAE,QAAQ,EAAU,MAAM,YAAY,CAAC;AAoJ9C,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,UAAU,EACV,IAAI,EACJ,OAAO,GACR,EAAE;IACD,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;IACxC,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,CAAC,EAAE,UAAU,CAAC;CACtB,2CAgBA"}
|
package/dist/testing.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unionUtils.d.ts","sourceRoot":"","sources":["../../../../src/tools/implementation/zodSchema/unionUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAErB,KAAK,EACL,8BAA8B,EAE9B,2BAA2B,EAE3B,wBAAwB,EAEzB,MAAM,mBAAmB,CAAC;AAO3B,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,8BAA8B,CAAC,2BAA2B,CAAC,
|
|
1
|
+
{"version":3,"file":"unionUtils.d.ts","sourceRoot":"","sources":["../../../../src/tools/implementation/zodSchema/unionUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAErB,KAAK,EACL,8BAA8B,EAE9B,2BAA2B,EAE3B,wBAAwB,EAEzB,MAAM,mBAAmB,CAAC;AAO3B,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,8BAA8B,CAAC,2BAA2B,CAAC,mCA4HpE;AAsBD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,qBAAqB,WAMtE"}
|
package/package.json
CHANGED
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
},
|
|
188
188
|
"type": "module",
|
|
189
189
|
"license": "MIT",
|
|
190
|
-
"version": "0.19.
|
|
190
|
+
"version": "0.19.3",
|
|
191
191
|
"dependencies": {
|
|
192
192
|
"@manuscripts/prosemirror-recreate-steps": "^0.1.4",
|
|
193
193
|
"@scure/base": "1.2.1",
|
|
@@ -204,9 +204,9 @@
|
|
|
204
204
|
"prosemirror-transform": "^1.9.0",
|
|
205
205
|
"use-sync-external-store": "^1.5.0",
|
|
206
206
|
"zod": "4.1.11",
|
|
207
|
-
"cojson
|
|
208
|
-
"cojson-
|
|
209
|
-
"cojson": "0.19.
|
|
207
|
+
"cojson": "0.19.3",
|
|
208
|
+
"cojson-storage-indexeddb": "0.19.3",
|
|
209
|
+
"cojson-transport-ws": "0.19.3"
|
|
210
210
|
},
|
|
211
211
|
"devDependencies": {
|
|
212
212
|
"@scure/bip39": "^1.3.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @vitest-environment happy-dom
|
|
2
|
-
import { afterEach, beforeAll, describe, expect, it } from "vitest";
|
|
2
|
+
import { afterEach, assert, beforeAll, describe, expect, it } from "vitest";
|
|
3
3
|
import { createJazzTestAccount, setupJazzTestSync } from "jazz-tools/testing";
|
|
4
4
|
import { co, z } from "jazz-tools";
|
|
5
5
|
import {
|
|
@@ -578,4 +578,312 @@ describe("CoMapView", async () => {
|
|
|
578
578
|
});
|
|
579
579
|
});
|
|
580
580
|
});
|
|
581
|
+
|
|
582
|
+
describe("Permissions", () => {
|
|
583
|
+
it("should disable Add Property button for reader account", async () => {
|
|
584
|
+
const reader = await createJazzTestAccount();
|
|
585
|
+
const group = co.group().create({ owner: account });
|
|
586
|
+
group.addMember(reader, "reader");
|
|
587
|
+
|
|
588
|
+
const schema = co.map({
|
|
589
|
+
pet: z.string(),
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
const value = schema.create({ pet: "dog" }, group);
|
|
593
|
+
|
|
594
|
+
const valueOnReader = await schema.load(value.$jazz.id, {
|
|
595
|
+
loadAs: reader,
|
|
596
|
+
});
|
|
597
|
+
assert(valueOnReader.$isLoaded);
|
|
598
|
+
const data = valueOnReader.$jazz.raw.toJSON() as JsonObject;
|
|
599
|
+
|
|
600
|
+
render(
|
|
601
|
+
<CoMapView
|
|
602
|
+
coValue={valueOnReader.$jazz.raw}
|
|
603
|
+
data={data}
|
|
604
|
+
node={reader.$jazz.localNode}
|
|
605
|
+
onNavigate={() => {}}
|
|
606
|
+
/>,
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
const addButton = screen.getByTitle("Add Property");
|
|
610
|
+
expect(addButton).toBeDefined();
|
|
611
|
+
expect((addButton as HTMLButtonElement).disabled).toBe(true);
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
it("should enable Add Property button for writer account", async () => {
|
|
615
|
+
const writer = await createJazzTestAccount();
|
|
616
|
+
const group = co.group().create({ owner: account });
|
|
617
|
+
group.addMember(writer, "writer");
|
|
618
|
+
|
|
619
|
+
const schema = co.map({
|
|
620
|
+
pet: z.string(),
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
const value = schema.create({ pet: "dog" }, group);
|
|
624
|
+
|
|
625
|
+
const valueOnWriter = await schema.load(value.$jazz.id, {
|
|
626
|
+
loadAs: writer,
|
|
627
|
+
});
|
|
628
|
+
assert(valueOnWriter.$isLoaded);
|
|
629
|
+
const data = valueOnWriter.$jazz.raw.toJSON() as JsonObject;
|
|
630
|
+
|
|
631
|
+
render(
|
|
632
|
+
<CoMapView
|
|
633
|
+
coValue={valueOnWriter.$jazz.raw}
|
|
634
|
+
data={data}
|
|
635
|
+
node={writer.$jazz.localNode}
|
|
636
|
+
onNavigate={() => {}}
|
|
637
|
+
/>,
|
|
638
|
+
);
|
|
639
|
+
|
|
640
|
+
const addButton = screen.getByTitle("Add Property");
|
|
641
|
+
expect(addButton).toBeDefined();
|
|
642
|
+
expect((addButton as HTMLButtonElement).disabled).toBe(false);
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
it("should hide restore buttons for reader account when multiple timestamps exist", async () => {
|
|
646
|
+
const reader = await createJazzTestAccount();
|
|
647
|
+
const group = co.group().create({ owner: account });
|
|
648
|
+
group.addMember(reader, "reader");
|
|
649
|
+
|
|
650
|
+
const schema = co.map({
|
|
651
|
+
pet: z.string(),
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
const value = schema.create({ pet: "dog" }, group);
|
|
655
|
+
await sleep(2);
|
|
656
|
+
value.$jazz.set("pet", "cat");
|
|
657
|
+
|
|
658
|
+
const valueOnReader = await schema.load(value.$jazz.id, {
|
|
659
|
+
loadAs: reader,
|
|
660
|
+
});
|
|
661
|
+
assert(valueOnReader.$isLoaded);
|
|
662
|
+
const data = valueOnReader.$jazz.raw.toJSON() as JsonObject;
|
|
663
|
+
|
|
664
|
+
render(
|
|
665
|
+
<CoMapView
|
|
666
|
+
coValue={valueOnReader.$jazz.raw}
|
|
667
|
+
data={data}
|
|
668
|
+
node={reader.$jazz.localNode}
|
|
669
|
+
onNavigate={() => {}}
|
|
670
|
+
/>,
|
|
671
|
+
);
|
|
672
|
+
|
|
673
|
+
const restoreButton = screen.getByTitle("Timeline");
|
|
674
|
+
fireEvent.click(restoreButton);
|
|
675
|
+
|
|
676
|
+
await waitFor(() => {
|
|
677
|
+
expect(screen.getByText("Select Timestamp")).toBeDefined();
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
expect(screen.queryByText("Restore")).toBeNull();
|
|
681
|
+
expect(screen.queryByRole("checkbox")).toBeNull();
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
it("should show restore buttons for writer account when multiple timestamps exist", async () => {
|
|
685
|
+
const writer = await createJazzTestAccount();
|
|
686
|
+
const group = co.group().create({ owner: account });
|
|
687
|
+
group.addMember(writer, "writer");
|
|
688
|
+
|
|
689
|
+
const schema = co.map({
|
|
690
|
+
pet: z.string(),
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
const value = schema.create({ pet: "dog" }, group);
|
|
694
|
+
await sleep(2);
|
|
695
|
+
value.$jazz.set("pet", "cat");
|
|
696
|
+
|
|
697
|
+
const valueOnWriter = await schema.load(value.$jazz.id, {
|
|
698
|
+
loadAs: writer,
|
|
699
|
+
});
|
|
700
|
+
assert(valueOnWriter.$isLoaded);
|
|
701
|
+
const data = valueOnWriter.$jazz.raw.toJSON() as JsonObject;
|
|
702
|
+
|
|
703
|
+
render(
|
|
704
|
+
<CoMapView
|
|
705
|
+
coValue={valueOnWriter.$jazz.raw}
|
|
706
|
+
data={data}
|
|
707
|
+
node={writer.$jazz.localNode}
|
|
708
|
+
onNavigate={() => {}}
|
|
709
|
+
/>,
|
|
710
|
+
);
|
|
711
|
+
|
|
712
|
+
const restoreButton = screen.getByTitle("Timeline");
|
|
713
|
+
fireEvent.click(restoreButton);
|
|
714
|
+
|
|
715
|
+
await waitFor(() => {
|
|
716
|
+
expect(screen.getByText("Restore")).toBeDefined();
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
expect(screen.getByRole("checkbox")).toBeDefined();
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
it("should hide edit buttons in GridView for reader account", async () => {
|
|
723
|
+
const reader = await createJazzTestAccount();
|
|
724
|
+
const group = co.group().create({ owner: account });
|
|
725
|
+
group.addMember(reader, "reader");
|
|
726
|
+
|
|
727
|
+
const schema = co.map({
|
|
728
|
+
pet: z.string(),
|
|
729
|
+
age: z.number(),
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
const value = schema.create({ pet: "dog", age: 10 }, group);
|
|
733
|
+
|
|
734
|
+
const valueOnReader = await schema.load(value.$jazz.id, {
|
|
735
|
+
loadAs: reader,
|
|
736
|
+
});
|
|
737
|
+
assert(valueOnReader.$isLoaded);
|
|
738
|
+
const data = valueOnReader.$jazz.raw.toJSON() as JsonObject;
|
|
739
|
+
|
|
740
|
+
render(
|
|
741
|
+
<CoMapView
|
|
742
|
+
coValue={valueOnReader.$jazz.raw}
|
|
743
|
+
data={data}
|
|
744
|
+
node={reader.$jazz.localNode}
|
|
745
|
+
onNavigate={() => {}}
|
|
746
|
+
/>,
|
|
747
|
+
);
|
|
748
|
+
|
|
749
|
+
expect(screen.getByText("pet")).toBeDefined();
|
|
750
|
+
expect(screen.getByText("age")).toBeDefined();
|
|
751
|
+
|
|
752
|
+
const editButtons = screen.queryAllByLabelText("Edit");
|
|
753
|
+
const deleteButtons = screen.queryAllByLabelText("Delete");
|
|
754
|
+
|
|
755
|
+
expect(editButtons).toHaveLength(0);
|
|
756
|
+
expect(deleteButtons).toHaveLength(0);
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
it("should show edit buttons in GridView for writer account", async () => {
|
|
760
|
+
const writer = await createJazzTestAccount();
|
|
761
|
+
const group = co.group().create({ owner: account });
|
|
762
|
+
group.addMember(writer, "writer");
|
|
763
|
+
|
|
764
|
+
const schema = co.map({
|
|
765
|
+
pet: z.string(),
|
|
766
|
+
age: z.number(),
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
const value = schema.create({ pet: "dog", age: 10 }, group);
|
|
770
|
+
|
|
771
|
+
const valueOnWriter = await schema.load(value.$jazz.id, {
|
|
772
|
+
loadAs: writer,
|
|
773
|
+
});
|
|
774
|
+
assert(valueOnWriter.$isLoaded);
|
|
775
|
+
const data = valueOnWriter.$jazz.raw.toJSON() as JsonObject;
|
|
776
|
+
|
|
777
|
+
render(
|
|
778
|
+
<CoMapView
|
|
779
|
+
coValue={valueOnWriter.$jazz.raw}
|
|
780
|
+
data={data}
|
|
781
|
+
node={writer.$jazz.localNode}
|
|
782
|
+
onNavigate={() => {}}
|
|
783
|
+
/>,
|
|
784
|
+
);
|
|
785
|
+
|
|
786
|
+
expect(screen.getByText("pet")).toBeDefined();
|
|
787
|
+
expect(screen.getByText("age")).toBeDefined();
|
|
788
|
+
|
|
789
|
+
const editButtons = screen.queryAllByLabelText("Edit");
|
|
790
|
+
const deleteButtons = screen.queryAllByLabelText("Delete");
|
|
791
|
+
|
|
792
|
+
expect(editButtons.length).toBeGreaterThan(0);
|
|
793
|
+
expect(deleteButtons.length).toBeGreaterThan(0);
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
it("should enable Add Property button for admin account", async () => {
|
|
797
|
+
const admin = await createJazzTestAccount();
|
|
798
|
+
const group = co.group().create({ owner: account });
|
|
799
|
+
group.addMember(admin, "admin");
|
|
800
|
+
|
|
801
|
+
const schema = co.map({
|
|
802
|
+
pet: z.string(),
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
const value = schema.create({ pet: "dog" }, group);
|
|
806
|
+
|
|
807
|
+
const valueOnAdmin = await schema.load(value.$jazz.id, {
|
|
808
|
+
loadAs: admin,
|
|
809
|
+
});
|
|
810
|
+
assert(valueOnAdmin.$isLoaded);
|
|
811
|
+
const data = valueOnAdmin.$jazz.raw.toJSON() as JsonObject;
|
|
812
|
+
|
|
813
|
+
render(
|
|
814
|
+
<CoMapView
|
|
815
|
+
coValue={valueOnAdmin.$jazz.raw}
|
|
816
|
+
data={data}
|
|
817
|
+
node={admin.$jazz.localNode}
|
|
818
|
+
onNavigate={() => {}}
|
|
819
|
+
/>,
|
|
820
|
+
);
|
|
821
|
+
|
|
822
|
+
const addButton = screen.getByTitle("Add Property");
|
|
823
|
+
expect(addButton).toBeDefined();
|
|
824
|
+
expect((addButton as HTMLButtonElement).disabled).toBe(false);
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
it("should enable Add Property button for manager account", async () => {
|
|
828
|
+
const manager = await createJazzTestAccount();
|
|
829
|
+
const group = co.group().create({ owner: account });
|
|
830
|
+
group.addMember(manager, "manager");
|
|
831
|
+
|
|
832
|
+
const schema = co.map({
|
|
833
|
+
pet: z.string(),
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
const value = schema.create({ pet: "dog" }, group);
|
|
837
|
+
|
|
838
|
+
const valueOnManager = await schema.load(value.$jazz.id, {
|
|
839
|
+
loadAs: manager,
|
|
840
|
+
});
|
|
841
|
+
assert(valueOnManager.$isLoaded);
|
|
842
|
+
const data = valueOnManager.$jazz.raw.toJSON() as JsonObject;
|
|
843
|
+
|
|
844
|
+
render(
|
|
845
|
+
<CoMapView
|
|
846
|
+
coValue={valueOnManager.$jazz.raw}
|
|
847
|
+
data={data}
|
|
848
|
+
node={manager.$jazz.localNode}
|
|
849
|
+
onNavigate={() => {}}
|
|
850
|
+
/>,
|
|
851
|
+
);
|
|
852
|
+
|
|
853
|
+
const addButton = screen.getByTitle("Add Property");
|
|
854
|
+
expect(addButton).toBeDefined();
|
|
855
|
+
expect((addButton as HTMLButtonElement).disabled).toBe(false);
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
it("should enable Add Property button for writeOnly account", async () => {
|
|
859
|
+
const writeOnly = await createJazzTestAccount();
|
|
860
|
+
const group = co.group().create({ owner: account });
|
|
861
|
+
group.addMember(writeOnly, "writeOnly");
|
|
862
|
+
|
|
863
|
+
const schema = co.map({
|
|
864
|
+
pet: z.string(),
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
const value = schema.create({ pet: "dog" }, group);
|
|
868
|
+
|
|
869
|
+
const valueOnWriteOnly = await schema.load(value.$jazz.id, {
|
|
870
|
+
loadAs: writeOnly,
|
|
871
|
+
});
|
|
872
|
+
assert(valueOnWriteOnly.$isLoaded);
|
|
873
|
+
const data = valueOnWriteOnly.$jazz.raw.toJSON() as JsonObject;
|
|
874
|
+
|
|
875
|
+
render(
|
|
876
|
+
<CoMapView
|
|
877
|
+
coValue={valueOnWriteOnly.$jazz.raw}
|
|
878
|
+
data={data}
|
|
879
|
+
node={writeOnly.$jazz.localNode}
|
|
880
|
+
onNavigate={() => {}}
|
|
881
|
+
/>,
|
|
882
|
+
);
|
|
883
|
+
|
|
884
|
+
const addButton = screen.getByTitle("Add Property");
|
|
885
|
+
expect(addButton).toBeDefined();
|
|
886
|
+
expect((addButton as HTMLButtonElement).disabled).toBe(false);
|
|
887
|
+
});
|
|
888
|
+
});
|
|
581
889
|
});
|
|
@@ -6,6 +6,7 @@ import { Button, Icon, Input, Modal } from "../ui";
|
|
|
6
6
|
import { styled } from "goober";
|
|
7
7
|
import { restoreCoMapToTimestamp } from "../utils/history";
|
|
8
8
|
import { CoValueEditor } from "./co-value-editor.js";
|
|
9
|
+
import { isWriter } from "../utils/permissions";
|
|
9
10
|
|
|
10
11
|
export function CoMapView({
|
|
11
12
|
coValue,
|
|
@@ -27,7 +28,11 @@ export function CoMapView({
|
|
|
27
28
|
coValue={coValue}
|
|
28
29
|
/>
|
|
29
30
|
<div>
|
|
30
|
-
<AddPropertyModal
|
|
31
|
+
<AddPropertyModal
|
|
32
|
+
disabled={!isWriter(coValue.group.myRole())}
|
|
33
|
+
coValue={coValue}
|
|
34
|
+
node={node}
|
|
35
|
+
/>{" "}
|
|
31
36
|
<RestoreSnapshotModal coValue={coValue} />
|
|
32
37
|
</div>
|
|
33
38
|
</>
|
|
@@ -37,9 +42,11 @@ export function CoMapView({
|
|
|
37
42
|
function AddPropertyModal({
|
|
38
43
|
coValue,
|
|
39
44
|
node,
|
|
45
|
+
disabled,
|
|
40
46
|
}: {
|
|
41
47
|
coValue: RawCoMap;
|
|
42
48
|
node: LocalNode;
|
|
49
|
+
disabled: boolean;
|
|
43
50
|
}) {
|
|
44
51
|
const [isAddPropertyModalOpen, setIsAddPropertyModalOpen] = useState(false);
|
|
45
52
|
const [propertyName, setPropertyName] = useState("");
|
|
@@ -59,9 +66,10 @@ function AddPropertyModal({
|
|
|
59
66
|
<Button
|
|
60
67
|
title="Add Property"
|
|
61
68
|
variant="secondary"
|
|
69
|
+
disabled={disabled}
|
|
62
70
|
onClick={openAddPropertyModal}
|
|
63
71
|
>
|
|
64
|
-
<Icon name="
|
|
72
|
+
<Icon name="add" />
|
|
65
73
|
</Button>
|
|
66
74
|
|
|
67
75
|
<Modal
|
|
@@ -132,6 +140,8 @@ function RestoreSnapshotModal({ coValue }: { coValue: RawCoMap }) {
|
|
|
132
140
|
setIsRestoreModalOpen(false);
|
|
133
141
|
};
|
|
134
142
|
|
|
143
|
+
const canRestore = isWriter(coValue.group.myRole());
|
|
144
|
+
|
|
135
145
|
return (
|
|
136
146
|
<>
|
|
137
147
|
<Button title="Timeline" variant="secondary" onClick={openRestoreModal}>
|
|
@@ -146,7 +156,7 @@ function RestoreSnapshotModal({ coValue }: { coValue: RawCoMap }) {
|
|
|
146
156
|
cancelText="Cancel"
|
|
147
157
|
onConfirm={handleRestore}
|
|
148
158
|
onCancel={handleClose}
|
|
149
|
-
showButtons={timestamps.length > 1}
|
|
159
|
+
showButtons={timestamps.length > 1 && canRestore}
|
|
150
160
|
>
|
|
151
161
|
{timestamps.length > 1 && (
|
|
152
162
|
<>
|
|
@@ -167,18 +177,20 @@ function RestoreSnapshotModal({ coValue }: { coValue: RawCoMap }) {
|
|
|
167
177
|
</TimestampDisplay>
|
|
168
178
|
</RangeContainer>
|
|
169
179
|
|
|
170
|
-
|
|
171
|
-
<
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
{canRestore && (
|
|
181
|
+
<CheckboxContainer>
|
|
182
|
+
<CheckboxInput
|
|
183
|
+
type="checkbox"
|
|
184
|
+
id="remove-unknown-properties"
|
|
185
|
+
checked={removeUnknownProperties}
|
|
186
|
+
onChange={(e) => setRemoveUnknownProperties(e.target.checked)}
|
|
187
|
+
/>
|
|
188
|
+
<CheckboxLabel htmlFor="remove-unknown-properties">
|
|
189
|
+
Remove unknown properties (properties that don't exist in the
|
|
190
|
+
selected snapshot)
|
|
191
|
+
</CheckboxLabel>
|
|
192
|
+
</CheckboxContainer>
|
|
193
|
+
)}
|
|
182
194
|
</>
|
|
183
195
|
)}
|
|
184
196
|
|
|
@@ -12,6 +12,7 @@ import { Card, CardBody, CardHeader } from "../ui/card.js";
|
|
|
12
12
|
import { Grid } from "../ui/grid.js";
|
|
13
13
|
import { Icon } from "../ui/icon.js";
|
|
14
14
|
import { Text } from "../ui/text.js";
|
|
15
|
+
import { isWriter } from "../utils/permissions.js";
|
|
15
16
|
|
|
16
17
|
function GridItem({
|
|
17
18
|
entry,
|
|
@@ -115,7 +116,7 @@ function GridItem({
|
|
|
115
116
|
<Text strong>{key}</Text>
|
|
116
117
|
)}
|
|
117
118
|
</div>
|
|
118
|
-
{coValue && (
|
|
119
|
+
{coValue && isWriter(coValue.group.myRole()) && (
|
|
119
120
|
<ActionButtons>
|
|
120
121
|
<EditButton
|
|
121
122
|
onClick={handleEditClick}
|
|
@@ -115,7 +115,9 @@ function getTransactionChanges(
|
|
|
115
115
|
if (tx.isValid === false && tx.tx.privacy === "private") {
|
|
116
116
|
const readKey = coValue.core.getReadKey(tx.tx.keyUsed);
|
|
117
117
|
if (!readKey) {
|
|
118
|
-
|
|
118
|
+
return [
|
|
119
|
+
`Unable to decrypt transaction: read key ${tx.tx.keyUsed} not found.`,
|
|
120
|
+
];
|
|
119
121
|
}
|
|
120
122
|
|
|
121
123
|
return (
|
|
@@ -108,10 +108,9 @@ export function schemaUnionDiscriminatorFor(
|
|
|
108
108
|
const coValueSchema = hydrateCoreCoValueSchema(option as any);
|
|
109
109
|
const coValueClass = coValueSchema.getCoValueClass() as typeof CoMap;
|
|
110
110
|
|
|
111
|
-
const dummyFieldNames = allNestedRefKeys
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
.toArray();
|
|
111
|
+
const dummyFieldNames = Array.from(allNestedRefKeys).filter(
|
|
112
|
+
(key) => !optionDef.shape[key],
|
|
113
|
+
);
|
|
115
114
|
|
|
116
115
|
if (dummyFieldNames.length === 0) {
|
|
117
116
|
return coValueClass;
|