spree_cm_commissioner 1.16.0 → 1.17.0.pre.pre1

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +8 -8
  3. data/app/assets/images/cm-hangmeas-checkout_image.svg +63 -0
  4. data/app/assets/images/cm-hangmeas-failed.svg +56 -0
  5. data/app/assets/images/cm-hangmeas-loader.svg +50 -0
  6. data/app/assets/images/cm-hangmeas-success.svg +51 -0
  7. data/app/controllers/spree/admin/tenants_controller.rb +8 -0
  8. data/app/controllers/spree/api/v2/storefront/dynamic_field_options_controller.rb +28 -0
  9. data/app/controllers/spree/api/v2/storefront/guests_controller.rb +2 -1
  10. data/app/interactors/spree_cm_commissioner/create_event.rb +2 -1
  11. data/app/mailers/spree_cm_commissioner/team_invite_mailer.rb +13 -0
  12. data/app/models/concerns/spree_cm_commissioner/participation_type_bitwise.rb +47 -0
  13. data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +4 -0
  14. data/app/models/spree_cm_commissioner/dynamic_field.rb +20 -0
  15. data/app/models/spree_cm_commissioner/dynamic_field_option.rb +18 -0
  16. data/app/models/spree_cm_commissioner/guest.rb +5 -3
  17. data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +25 -0
  18. data/app/models/spree_cm_commissioner/invite_team.rb +44 -0
  19. data/app/models/spree_cm_commissioner/product_decorator.rb +2 -0
  20. data/app/models/spree_cm_commissioner/product_dynamic_field.rb +8 -0
  21. data/app/models/spree_cm_commissioner/taxon_decorator.rb +1 -0
  22. data/app/models/spree_cm_commissioner/user_decorator.rb +1 -0
  23. data/app/models/spree_cm_commissioner/user_taxon.rb +1 -0
  24. data/app/models/spree_cm_commissioner/vendor_decorator.rb +1 -0
  25. data/app/models/spree_cm_commissioner/vendor_place.rb +5 -7
  26. data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +1 -0
  27. data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +2 -0
  28. data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_option_serializer.rb +11 -0
  29. data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_serializer.rb +13 -0
  30. data/app/serializers/spree_cm_commissioner/v2/storefront/guest_dynamic_field_serializer.rb +13 -0
  31. data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +3 -2
  32. data/app/serializers/spree_cm_commissioner/v2/storefront/product_dynamic_field_serializer.rb +13 -0
  33. data/app/services/spree_cm_commissioner/organizer/export_guest_csv_service.rb +23 -15
  34. data/app/services/spree_cm_commissioner/user_roles_assigner.rb +0 -6
  35. data/app/views/spree/admin/tenants/_form.html.erb +253 -0
  36. data/app/views/spree_cm_commissioner/layouts/team_invite_mailer.html.erb +15 -0
  37. data/app/views/spree_cm_commissioner/team_invite_mailer/_mailer_stylesheets.html.erb +79 -0
  38. data/app/views/spree_cm_commissioner/team_invite_mailer/send_team_invite_email.html.erb +42 -0
  39. data/config/routes.rb +1 -0
  40. data/db/migrate/20250512072817_create_spree_cm_commissioner_invite_team.rb +15 -0
  41. data/db/migrate/20250605024523_add_participation_type_to_spree_taxon.rb +5 -0
  42. data/db/migrate/20250606020914_create_cm_dynamic_fields.rb +11 -0
  43. data/db/migrate/20250606020958_create_cm_guest_dynamic_fields.rb +11 -0
  44. data/db/migrate/20250606021044_create_cm_dynamic_field_options.rb +10 -0
  45. data/db/migrate/20250606021045_create_cm_product_dynamic_fields.rb +10 -0
  46. data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +2 -2
  47. data/lib/spree_cm_commissioner/version.rb +1 -1
  48. metadata +29 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 169845d2403406e562178fb3b438559b9d4cc42d93776513b5b7235399f69e2a
4
- data.tar.gz: 5d7526b7df7150bddd97deb2989f08a014437b4c4c9efc8a318405d335e35e27
3
+ metadata.gz: 3bfd7c55dbc9cdd4a8350cf03314306aa656b233423084e4e5cd6e85977270d6
4
+ data.tar.gz: a243e2ec33cd9ddf4980fd14d31d47c4a39c663e04609a1de6e92aafa1584441
5
5
  SHA512:
6
- metadata.gz: ba5ff297f04ed5f749794f56b8c38900d36ce76d5b78a7778c0e06007816004190745ad3664b038be3c84e30a540deb57715652ed6d8012593b57126a14dba9c
7
- data.tar.gz: d83b272f1fe458cc17fa833e2edd1a643ffa9c25f888c8432bc4e08d10ce1b16e8a2e870b52532995448043dda00eab8473f50e8f687dbf11ee6e45eca58556e
6
+ metadata.gz: 85ce5b60b28ab3c4daaf710134d89f81b5b77db09b67fb12ce633c2c50c6fbca66d5ea397fed87b17e44c44252e076d9af68b3e0f841aa41379652713f54937a
7
+ data.tar.gz: 5e0d6775a3ac52c9fadbf1842a589730f0b4551c5ee770b38ff39398cf994396f3cb62a4fa7b4bc3ecbbb480f6863d090f6c41187aa6ffcad0dab59338e4eb7a
data/Gemfile.lock CHANGED
@@ -34,7 +34,7 @@ GIT
34
34
  PATH
35
35
  remote: .
36
36
  specs:
37
- spree_cm_commissioner (1.16.0)
37
+ spree_cm_commissioner (1.17.0.pre.pre1)
38
38
  activerecord-multi-tenant
39
39
  activerecord_json_validator (~> 2.1, >= 2.1.3)
40
40
  aws-sdk-cloudfront
@@ -446,14 +446,14 @@ GEM
446
446
  google-cloud-recaptcha_enterprise-v1beta1 (0.10.0)
447
447
  gapic-common (>= 0.20.0, < 2.a)
448
448
  google-cloud-errors (~> 1.0)
449
- google-protobuf (3.25.6)
450
- google-protobuf (3.25.6-x86_64-darwin)
451
- google-protobuf (3.25.6-x86_64-linux)
449
+ google-protobuf (3.25.8)
450
+ google-protobuf (3.25.8-x86_64-darwin)
451
+ google-protobuf (3.25.8-x86_64-linux)
452
452
  googleapis-common-protos (1.4.0)
453
453
  google-protobuf (~> 3.14)
454
454
  googleapis-common-protos-types (~> 1.2)
455
455
  grpc (~> 1.27)
456
- googleapis-common-protos-types (1.18.0)
456
+ googleapis-common-protos-types (1.20.0)
457
457
  google-protobuf (>= 3.18, < 5.a)
458
458
  googleauth (1.8.1)
459
459
  faraday (>= 0.17.3, < 3.a)
@@ -461,13 +461,13 @@ GEM
461
461
  multi_json (~> 1.11)
462
462
  os (>= 0.9, < 2.0)
463
463
  signet (>= 0.16, < 2.a)
464
- grpc (1.70.1)
464
+ grpc (1.72.0)
465
465
  google-protobuf (>= 3.25, < 5.0)
466
466
  googleapis-common-protos-types (~> 1.0)
467
- grpc (1.70.1-x86_64-darwin)
467
+ grpc (1.72.0-x86_64-darwin)
468
468
  google-protobuf (>= 3.25, < 5.0)
469
469
  googleapis-common-protos-types (~> 1.0)
470
- grpc (1.70.1-x86_64-linux)
470
+ grpc (1.72.0-x86_64-linux)
471
471
  google-protobuf (>= 3.25, < 5.0)
472
472
  googleapis-common-protos-types (~> 1.0)
473
473
  hana (1.3.7)
@@ -0,0 +1,63 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg id="payment_proccessing" data-name="payment proccessing" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 334 200">
3
+ <defs>
4
+ <clipPath id="clippath">
5
+ <path d="m332.72,16.62v166.75c0,8.27-6.28,15.08-14.33,15.92-.55.05-1.11.08-1.67.08H16c-.48,0-.96-.02-1.43-.06-8.17-.73-14.57-7.59-14.57-15.94V16.62C0,7.78,7.16.62,16,.62h300.72c8.84,0,16,7.16,16,16Z" style="fill: none;"/>
6
+ </clipPath>
7
+ </defs>
8
+ <g style="clip-path: url(#clippath);">
9
+ <path d="m332.72,16.62v166.75c0,8.27-6.28,15.08-14.33,15.92-.55.05-1.11.08-1.67.08H16c-.48,0-.96-.02-1.43-.06-8.17-.73-14.57-7.59-14.57-15.94V16.62C0,7.78,7.16.62,16,.62h300.72c8.84,0,16,7.16,16,16Z" style="fill: #130d07;"/>
10
+ <path d="m160.11,89.69c1.41-5.81-3.61-9.74-10.21-9.27-6.6.47-26.31,10.68-28.51,12.26-2.2,1.57-29.54,6.6-34.25,3.77-4.71-2.83-12.46-7.49-12.46-7.49,0,0-23.81-23.81-40.47,2.86-16.67,26.66-13.99,61.42-13.99,61.42l-24.1,29.05s-10.95,10,3.81,19.05,22.11,18.14,31.15,21.3c9.04,3.16,14.46-7,14.46-7.68,0-.68,19.43-30.27,19.43-30.27,10.27-.69,20.53-1.41,30.79-2.17,10.81-.8,24.65.44,31.99-9.08,3.2-4.15,1.59-8.37-.02-12.85.06.18,3.68-1,4-1.13,1.81-.72,3.12-1.91,3.94-3.7,1.55-3.36,2.03-8.12.07-11.41-2.91-4.88-3.85-5.31-3.85-5.31.93.42,4.7-2.76,5.32-3.27,2.69-2.21,4.81-5.03,5.27-8.57,1.31-10.16-10.01-17.26-18.56-19.27,5.59,1.31,10.8,2.15,16.21-.39,3.01-1.41,5.69-3.43,8.35-5.44,4.02-3.03,10.38-7.18,11.65-12.41" style="fill: #e89875;"/>
11
+ <path d="m138.73,45.68c-1.83-.91-5.84-1.99-7.86-2.27-3.17-.44-12.78-.68-12.78-.68l-1.24,3.76-31.45-1.3c-4.73-.2-8.98,2.88-10.27,7.44l-27.87,101.59c-1.74,6.14,2.5,12.35,8.85,12.97l49.44,1.78c4.98.49,9.59-2.69,10.89-7.53l27.25-101.35c.17-.64.26-1.28.31-1.92,0-.02.01-.05.02-.07,1.59-7.52-1.35-10.47-5.29-12.43Z" style="fill: #302b31;"/>
12
+ <path d="m51.51,163.26l49.44,1.78c4.98.49,9.59-2.69,10.89-7.53l27.25-101.35c1.7-6.33-2.91-12.61-9.46-12.88l-48.82-2.02c-4.73-.2-8.98,2.88-10.27,7.44l-27.87,101.59c-1.74,6.14,2.5,12.35,8.85,12.97Z" style="fill: #212028;"/>
13
+ <path d="m108.45,126.85c-1.64.07-3.43-.23-5.08-.3-4.13-.18-8.26-.36-12.39-.54l-22.43-.98-.81-.04c-2.87-.41-4.61-1.99-3.7-4.96l.84-3.54c.55-2.49,2.89-4.15,5.42-3.86,13.54.41,27.15.41,40.66,1.23,2,.12,4.17.45,4.34,2.96.15,2.13-1.09,4.94-1.91,6.87-1.02,2.41-2.87,3.07-4.95,3.16Z" style="fill: #f59b1d;"/>
14
+ <path d="m117.78,96.1l-48.7-1.94c-2.03-.08-3.25-1.77-2.74-3.76l8.36-32.34c.52-2,2.58-3.55,4.61-3.47l48.7,1.94c2.03.08,3.25,1.77,2.74,3.76l-8.36,32.34c-.52,2-2.58,3.55-4.61,3.47Z" style="fill: #fffaf8;"/>
15
+ <path d="m85.83,77.72l-8.87-.35c-.88-.04-1.41-.77-1.19-1.63l1.23-4.78c.22-.87,1.12-1.54,2-1.51l8.87.35c.88.04,1.41.77,1.19,1.63l-1.23,4.78c-.22.87-1.12,1.54-2,1.51Z" style="fill: #d6d6d6;"/>
16
+ <path d="m124.55,64.16l-9.8-.39c-.62-.02-1-.54-.84-1.15l.45-1.74c.16-.61.79-1.09,1.41-1.06l9.8.39c.62.02,1,.54.84,1.15l-.45,1.74c-.16.61-.79,1.09-1.41,1.06Z" style="fill: #d6d6d6;"/>
17
+ <path d="m84.05,81.98l-8.95-.36c-.47-.02-.75-.41-.63-.87l.22-.86c.12-.46.59-.82,1.06-.8l8.95.36c.47.02.75.41.63.87l-.22.86c-.12.46-.59.82-1.06.8Z" style="fill: #d6d6d6;"/>
18
+ <path d="m99.83,91.71l-27.44-1.09c-.25-.01-.41-.22-.34-.47l.42-1.62c.06-.25.32-.44.57-.43l27.44,1.09c.25.01.41.22.34.47l-.42,1.62c-.06.25-.32.44-.57.43Z" style="fill: #d6d6d6;"/>
19
+ <path d="m95.54,82.43l-8.95-.36c-.47-.02-.75-.41-.63-.87l.22-.86c.12-.46.59-.82,1.06-.8l8.95.36c.47.02.75.41.63.87l-.22.86c-.12.46-.59.82-1.06.8Z" style="fill: #d6d6d6;"/>
20
+ <path d="m107.03,82.89l-8.95-.36c-.47-.02-.75-.41-.63-.87l.22-.86c.12-.46.59-.82,1.06-.8l8.95.36c.47.02.75.41.63.87l-.22.86c-.12.46-.59.82-1.06.8Z" style="fill: #d6d6d6;"/>
21
+ <path d="m118.52,83.35l-8.95-.36c-.47-.02-.75-.41-.63-.87l.22-.86c.12-.46.59-.82,1.06-.8l8.95.36c.47.02.75.41.63.87l-.22.86c-.12.46-.59.82-1.06.8Z" style="fill: #d6d6d6;"/>
22
+ <path d="m111.65,93.7c-.49.15-.94.45-1.44.61-2.03.64-4.12-.62-4.15-2.53-.02-1.28.45-2.44,1.6-3.42.84-.72,1.78-1.08,2.78-1.14.88-.05,1.65.12,2.24.65.12.11.29.16.44.24-.17.19.02.23.08.32.37.57.57,1.21.45,1.96-.2,1.22-.73,2.32-1.89,3.17-.05.03-.08.09-.11.14Z" style="fill: #d6d6d6;"/>
23
+ <path d="m111.65,93.7s.07-.11.11-.14c1.16-.85,1.69-1.95,1.89-3.17.12-.75-.08-1.39-.45-1.96-.06-.09-.25-.14-.08-.32.59-.27,1.16-.59,1.79-.67,2.25-.26,3.6.86,3.66,2.68.06,1.96-1.32,3.73-3.42,4.37-1.29.39-2.36.14-3.23-.58-.09-.07-.18-.15-.26-.22Z" style="fill: #5e5e5e;"/>
24
+ <path d="m53.69,110.12s1.51-5.75,5.56,2.51c4.05,8.27,15.38,11.23,20.41,6.86s-.79-23.41-15.54-36.21c-14.75-12.8-30.48,5.41-37.12,19.9-6.65,14.49-6.78,50.07-6.78,50.07l48.9,21.12s8.3-15.25.02-34.98c-4.68-11.15-9.08-16.86-12.8-21.88-3.73-5.02-2.64-7.37-2.64-7.37Z" style="fill: #e89875;"/>
25
+ <g>
26
+ <rect x="222.73" y="98.72" width="8.27" height="27.35" style="fill: #fbc01a;"/>
27
+ <polygon points="231 100.13 222.73 100.13 221.53 95.4 232.39 95.4 231 100.13" style="fill: #fbc01a;"/>
28
+ <line x1="223.67" y1="100.13" x2="231" y2="100.13" style="fill: none; stroke: #f9b500; stroke-miterlimit: 10; stroke-width: .5px;"/>
29
+ <polygon points="222.73 126.08 231 126.08 232.2 130.8 221.33 130.8 222.73 126.08" style="fill: #fbc01a;"/>
30
+ <line x1="231" y1="126.08" x2="222.73" y2="126.08" style="fill: none; stroke: #f9b500; stroke-miterlimit: 10; stroke-width: .5px;"/>
31
+ </g>
32
+ <g>
33
+ <rect x="240.34" y="98.72" width="8.27" height="27.35" style="fill: #f4b200;"/>
34
+ <polygon points="248.61 100.13 240.34 100.13 239.15 95.4 250.01 95.4 248.61 100.13" style="fill: #f4b200;"/>
35
+ <polygon points="240.35 126.08 248.62 126.08 249.81 130.8 238.95 130.8 240.35 126.08" style="fill: #f4b200;"/>
36
+ </g>
37
+ <g>
38
+ <rect x="257.95" y="98.72" width="8.27" height="27.35" style="fill: #fbc01a;"/>
39
+ <polygon points="266.22 100.13 257.95 100.13 256.76 95.4 267.62 95.4 266.22 100.13" style="fill: #fbc01a;"/>
40
+ <line x1="258.9" y1="100.13" x2="266.22" y2="100.13" style="fill: none; stroke: #f9b500; stroke-miterlimit: 10; stroke-width: .5px;"/>
41
+ <polygon points="257.96 126.08 266.23 126.08 267.42 130.8 256.56 130.8 257.96 126.08" style="fill: #fbc01a;"/>
42
+ <line x1="266.22" y1="126.08" x2="257.96" y2="126.08" style="fill: none; stroke: #f9b500; stroke-miterlimit: 10; stroke-width: .5px;"/>
43
+ </g>
44
+ <g>
45
+ <rect x="275.56" y="98.72" width="8.27" height="27.35" style="fill: #fbc01a;"/>
46
+ <polygon points="283.84 100.13 275.56 100.13 274.37 95.4 285.23 95.4 283.84 100.13" style="fill: #fbc01a;"/>
47
+ <line x1="276.51" y1="100.13" x2="283.84" y2="100.13" style="fill: none; stroke: #f9b500; stroke-miterlimit: 10; stroke-width: .5px;"/>
48
+ <polygon points="275.57 126.08 283.84 126.08 285.04 130.8 274.17 130.8 275.57 126.08" style="fill: #fbc01a;"/>
49
+ <line x1="283.84" y1="126.08" x2="275.57" y2="126.08" style="fill: none; stroke: #f9b500; stroke-miterlimit: 10; stroke-width: .5px;"/>
50
+ </g>
51
+ <rect x="218.79" y="91.42" width="69.46" height="3.98" style="fill: #f9b500;"/>
52
+ <rect x="218.79" y="130.8" width="69.46" height="3.98" style="fill: #fbc01a;"/>
53
+ <rect x="209.25" y="134.79" width="88.53" height="4.09" style="fill: #f4b200;"/>
54
+ <path d="m216.67,88.29l34.23-15.08c2.1-.93,4.5-.93,6.6,0l34.23,15.08c1.62.71,1.11,3.13-.66,3.13h-73.75c-1.77,0-2.28-2.42-.66-3.13Z" style="fill: #fbc01a;"/>
55
+ <path d="m230.81,86.16l21.33-9.4c1.31-.58,2.8-.58,4.11,0l21.33,9.4c1.01.44.69,1.95-.41,1.95h-45.96c-1.1,0-1.42-1.51-.41-1.95Z" style="fill: #f4b200;"/>
56
+ <path d="m256.72,83.21c0-1.39-1.13-2.51-2.51-2.51s-2.51,1.13-2.51,2.51,1.13,2.51,2.51,2.51,2.51-1.13,2.51-2.51Z" style="fill: none; stroke: #f9b500; stroke-miterlimit: 10; stroke-width: .5px;"/>
57
+ <line x1="218.8" y1="131.54" x2="288.24" y2="131.54" style="fill: none; stroke: #f9b500; stroke-miterlimit: 10; stroke-width: .5px;"/>
58
+ <path d="m143.42,43.43l2.99-1.92c34.81-22.3,81.11-12.16,103.41,22.65h0" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 4px;"/>
59
+ <polyline points="242.93 64.16 250.34 64.16 250.34 56.12" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 3px;"/>
60
+ <path d="m253.66,141.68l-3.52,4.34c-28.53,29.92-75.91,31.04-105.83,2.5h0" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 4px;"/>
61
+ <polyline points="151 146.9 143.8 148.65 145.77 156.76" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 3px;"/>
62
+ </g>
63
+ </svg>
@@ -0,0 +1,56 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 52 52"
5
+ width="100"
6
+ height="100"
7
+ >
8
+ <style>
9
+ .svg-failed {
10
+ stroke: white;
11
+ stroke-width: 5;
12
+ stroke-miterlimit: 10;
13
+ stroke-linecap: round;
14
+ stroke-linejoin: round;
15
+ fill: none;
16
+ animation: svg-failed-scale 0.3s ease-in-out 0.9s both;
17
+ }
18
+
19
+ .svg-failed-circle {
20
+ stroke: none;
21
+ fill: #FF5A5F;
22
+ }
23
+
24
+ .svg-failed-x {
25
+ stroke-dasharray: 48;
26
+ stroke-dashoffset: 48;
27
+ animation: svg-failed-draw 0.5s ease forwards 0.6s;
28
+ }
29
+
30
+ @keyframes svg-failed-draw {
31
+ to {
32
+ stroke-dashoffset: 0;
33
+ }
34
+ }
35
+
36
+ @keyframes svg-failed-scale {
37
+ 0%, 100% {
38
+ transform: scale(1);
39
+ }
40
+ 50% {
41
+ transform: scale(1.1);
42
+ }
43
+ }
44
+ </style>
45
+
46
+ <circle class="svg-failed-circle" cx="26" cy="26" r="25" />
47
+ <!-- X mark: two lines crossing -->
48
+ <path
49
+ class="svg-failed svg-failed-x"
50
+ d="M16 16 L36 36"
51
+ />
52
+ <path
53
+ class="svg-failed svg-failed-x"
54
+ d="M36 16 L16 36"
55
+ />
56
+ </svg>
@@ -0,0 +1,50 @@
1
+ <svg class="pl" width="300" height="300" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <style>
3
+ .pl__ring { animation: ringA 2s linear infinite; }
4
+ .pl__ring--a { stroke: #F79E1B; }
5
+ .pl__ring--b { animation-name: ringB; stroke: #F79E1B; }
6
+ .pl__ring--c { animation-name: ringC; stroke: #F79E1B; }
7
+ .pl__ring--d { animation-name: ringD; stroke: #F79E1B; }
8
+
9
+ @keyframes ringA {
10
+ from, 4% { stroke-dasharray: 0 660; stroke-width: 20; stroke-dashoffset: -330; }
11
+ 12% { stroke-dasharray: 60 600; stroke-width: 30; stroke-dashoffset: -335; }
12
+ 32% { stroke-dasharray: 60 600; stroke-width: 30; stroke-dashoffset: -595; }
13
+ 40%, 54% { stroke-dasharray: 0 660; stroke-width: 20; stroke-dashoffset: -660; }
14
+ 62% { stroke-dasharray: 60 600; stroke-width: 30; stroke-dashoffset: -665; }
15
+ 82% { stroke-dasharray: 60 600; stroke-width: 30; stroke-dashoffset: -925; }
16
+ 90%, to { stroke-dasharray: 0 660; stroke-width: 20; stroke-dashoffset: -990; }
17
+ }
18
+ @keyframes ringB {
19
+ from, 12% { stroke-dasharray: 0 220; stroke-width: 20; stroke-dashoffset: -110; }
20
+ 20% { stroke-dasharray: 20 200; stroke-width: 30; stroke-dashoffset: -115; }
21
+ 40% { stroke-dasharray: 20 200; stroke-width: 30; stroke-dashoffset: -195; }
22
+ 48%, 62% { stroke-dasharray: 0 220; stroke-width: 20; stroke-dashoffset: -220; }
23
+ 70% { stroke-dasharray: 20 200; stroke-width: 30; stroke-dashoffset: -225; }
24
+ 90% { stroke-dasharray: 20 200; stroke-width: 30; stroke-dashoffset: -305; }
25
+ 98%, to { stroke-dasharray: 0 220; stroke-width: 20; stroke-dashoffset: -330; }
26
+ }
27
+ @keyframes ringC {
28
+ from { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: 0; }
29
+ 8% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -5; }
30
+ 28% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -175; }
31
+ 36%, 58% { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: -220; }
32
+ 66% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -225; }
33
+ 86% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -395; }
34
+ 94%, to { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: -440; }
35
+ }
36
+ @keyframes ringD {
37
+ from, 8% { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: 0; }
38
+ 16% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -5; }
39
+ 36% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -175; }
40
+ 44%, 50% { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: -220; }
41
+ 58% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -225; }
42
+ 78% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -395; }
43
+ 86%, to { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: -440; }
44
+ }
45
+ </style>
46
+ <circle class="pl__ring pl__ring--a" cx="120" cy="120" r="105" fill="none" stroke-width="20" stroke-dasharray="0 660" stroke-dashoffset="-330" stroke-linecap="round"/>
47
+ <circle class="pl__ring pl__ring--b" cx="120" cy="120" r="35" fill="none" stroke-width="20" stroke-dasharray="0 220" stroke-dashoffset="-110" stroke-linecap="round"/>
48
+ <circle class="pl__ring pl__ring--c" cx="85" cy="120" r="70" fill="none" stroke-width="20" stroke-dasharray="0 440" stroke-linecap="round"/>
49
+ <circle class="pl__ring pl__ring--d" cx="155" cy="120" r="70" fill="none" stroke-width="20" stroke-dasharray="0 440" stroke-linecap="round"/>
50
+ </svg>
@@ -0,0 +1,51 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 52 52"
5
+ width="100"
6
+ height="100"
7
+ >
8
+ <style>
9
+ .svg-checkmark {
10
+ stroke: white;
11
+ stroke-width: 5;
12
+ stroke-miterlimit: 10;
13
+ stroke-linecap: round;
14
+ stroke-linejoin: round;
15
+ fill: none;
16
+ animation: svg-success-scale 0.3s ease-in-out 0.9s both;
17
+ }
18
+
19
+ .svg-checkmark-circle {
20
+ stroke: none;
21
+ fill: #00D290;
22
+ }
23
+
24
+ .svg-checkmark-check {
25
+ stroke-dasharray: 48;
26
+ stroke-dashoffset: 48;
27
+ animation: svg-success-draw 0.5s ease forwards 0.6s;
28
+ }
29
+
30
+ @keyframes svg-success-draw {
31
+ to {
32
+ stroke-dashoffset: 0;
33
+ }
34
+ }
35
+
36
+ @keyframes svg-success-scale {
37
+ 0%, 100% {
38
+ transform: scale(1);
39
+ }
40
+ 50% {
41
+ transform: scale(1.1);
42
+ }
43
+ }
44
+ </style>
45
+
46
+ <circle class="svg-checkmark-circle" cx="26" cy="26" r="25" />
47
+ <path
48
+ class="svg-checkmark svg-checkmark-check"
49
+ d="M14.1 27.2l7.1 7.2 16.7-16.8"
50
+ />
51
+ </svg>
@@ -1,6 +1,8 @@
1
1
  module Spree
2
2
  module Admin
3
3
  class TenantsController < Spree::Admin::ResourceController
4
+ before_action :load_vector_icons, only: %i[new edit]
5
+
4
6
  # override
5
7
  def collection
6
8
  params[:q] = {} if params[:q].blank?
@@ -31,6 +33,12 @@ module Spree
31
33
  def collection_url(options = {})
32
34
  admin_tenants_url(options)
33
35
  end
36
+
37
+ private
38
+
39
+ def load_vector_icons
40
+ @vector_icons = SpreeCmCommissioner::VectorIcon.all
41
+ end
34
42
  end
35
43
  end
36
44
  end
@@ -0,0 +1,28 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Storefront
5
+ class DynamicFieldOptionsController < ::Spree::Api::V2::ResourceController
6
+ # override
7
+ def collection
8
+ return @collection if defined?(@collection)
9
+ return SpreeCmCommissioner::DynamicFieldOption.none if params[:dynamic_field_id].blank?
10
+
11
+ @collection = SpreeCmCommissioner::DynamicFieldOption.where(dynamic_field_id: params[:dynamic_field_id])
12
+ @collection = @collection.where('value LIKE ?', "%#{params[:query]}%") if params[:query].present?
13
+ @collection
14
+ end
15
+
16
+ # override
17
+ def collection_serializer
18
+ SpreeCmCommissioner::V2::Storefront::DynamicFieldOptionSerializer
19
+ end
20
+
21
+ def model_class
22
+ SpreeCmCommissioner::DynamicFieldOption
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -75,7 +75,8 @@ module Spree
75
75
  :expectation,
76
76
  :upload_later,
77
77
  :country_code,
78
- :contact
78
+ :contact,
79
+ guest_dynamic_fields_attributes: %i[id dynamic_field_id value _destroy]
79
80
  )
80
81
  end
81
82
  end
@@ -23,7 +23,8 @@ module SpreeCmCommissioner
23
23
  from_date: context.params[:from_date],
24
24
  to_date: context.params[:to_date],
25
25
  parent_id: context.params[:parent_id],
26
- taxonomy_id: context.params[:taxonomy_id]
26
+ taxonomy_id: context.params[:taxonomy_id],
27
+ vendor_id: context.current_vendor.id
27
28
  )
28
29
 
29
30
  if @parent_taxon.save
@@ -0,0 +1,13 @@
1
+ module SpreeCmCommissioner
2
+ class TeamInviteMailer < Spree::BaseMailer
3
+ layout 'spree_cm_commissioner/layouts/team_invite_mailer'
4
+
5
+ def send_team_invite_email(invite_team_id)
6
+ @invite_team = SpreeCmCommissioner::InviteTeam.find(invite_team_id)
7
+
8
+ subject = Spree::Store.default.name.to_s
9
+
10
+ mail(from: from_address, to: @invite_team.email, subject: subject)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ module SpreeCmCommissioner
2
+ module ParticipationTypeBitwise
3
+ extend ActiveSupport::Concern
4
+
5
+ BIT_FIELDS = {
6
+ invitation_only: 0b1,
7
+ public: 0b10,
8
+ private: 0b100,
9
+ virtual: 0b1000,
10
+ free: 0b10000,
11
+ internal: 0b100000
12
+ }.freeze
13
+
14
+ ORDERED_BIT_FIELDS = %i[
15
+ invitation_only
16
+ public
17
+ private
18
+ virtual
19
+ free
20
+ internal
21
+ ].freeze
22
+
23
+ def participation_type? = participation_type != 0
24
+
25
+ BIT_FIELDS.each do |field, bit_value|
26
+ define_method "#{field}?" do
27
+ participation_type_enabled?(bit_value)
28
+ end
29
+ end
30
+
31
+ def unordered_participation_type_fields
32
+ BIT_FIELDS.filter_map do |field, bit_value|
33
+ field if participation_type & bit_value != 0
34
+ end
35
+ end
36
+
37
+ def participation_type_fields
38
+ unordered_participation_type_fields.sort_by { |item| ORDERED_BIT_FIELDS.index(item) }
39
+ end
40
+
41
+ def participation_type_enabled?(bit_value)
42
+ return false if participation_type.nil?
43
+
44
+ participation_type & bit_value != 0
45
+ end
46
+ end
47
+ end
@@ -5,6 +5,10 @@ module SpreeCmCommissioner
5
5
  included do
6
6
  preference :assetlinks, :string, default: ''
7
7
  preference :apple_app_site_association, :string, default: ''
8
+ preference :payment_checkout_image, :string, default: ''
9
+ preference :payment_failed_image, :string, default: ''
10
+ preference :payment_success_image, :string, default: ''
11
+ preference :payment_loader, :string, default: ''
8
12
  end
9
13
  end
10
14
  end
@@ -0,0 +1,20 @@
1
+ module SpreeCmCommissioner
2
+ class DynamicField < SpreeCmCommissioner::Base
3
+ belongs_to :vendor, class_name: 'Spree::Vendor', optional: false
4
+
5
+ has_many :dynamic_field_options, class_name: 'SpreeCmCommissioner::DynamicFieldOption', dependent: :destroy
6
+ has_many :guest_dynamic_fields, class_name: 'SpreeCmCommissioner::GuestDynamicField', dependent: :destroy
7
+ has_many :product_dynamic_fields, class_name: 'SpreeCmCommissioner::ProductDynamicField', dependent: :destroy
8
+
9
+ enum data_type: { string: 0, integer: 1, boolean: 2, checkbox: 3, radio: 4 }
10
+
11
+ accepts_nested_attributes_for :dynamic_field_options, allow_destroy: true, reject_if: :all_blank
12
+
13
+ validates :label, presence: true
14
+ validates :data_type, presence: true
15
+
16
+ def selection?
17
+ checkbox? || radio?
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module SpreeCmCommissioner
2
+ class DynamicFieldOption < SpreeCmCommissioner::Base
3
+ belongs_to :dynamic_field, class_name: 'SpreeCmCommissioner::DynamicField', optional: false
4
+
5
+ validates :value, presence: true, uniqueness: { scope: :dynamic_field_id }
6
+ validate :parent_field_must_be_selection_type
7
+
8
+ private
9
+
10
+ def parent_field_must_be_selection_type
11
+ return unless dynamic_field
12
+
13
+ return if dynamic_field.selection?
14
+
15
+ errors.add(:dynamic_field, 'must be a selection type field')
16
+ end
17
+ end
18
+ end
@@ -1,6 +1,6 @@
1
1
  # rubocop:disable Metrics/ClassLength
2
2
  module SpreeCmCommissioner
3
- class Guest < SpreeCmCommissioner::Base
3
+ class Guest < SpreeCmCommissioner::Base # rubocop:disable Metrics/ClassLength
4
4
  include SpreeCmCommissioner::KycBitwise
5
5
  include SpreeCmCommissioner::PhoneNumberSanitizer
6
6
 
@@ -32,6 +32,8 @@ module SpreeCmCommissioner
32
32
  scope :no_show, -> { left_outer_joins(:check_in).where(cm_check_ins: { id: nil }) }
33
33
 
34
34
  has_many :state_changes, as: :stateful, class_name: 'Spree::StateChange'
35
+ has_many :guest_dynamic_fields, dependent: :destroy, class_name: 'SpreeCmCommissioner::GuestDynamicField'
36
+ accepts_nested_attributes_for :guest_dynamic_fields, allow_destroy: true
35
37
 
36
38
  belongs_to :event, class_name: 'Spree::Taxon'
37
39
 
@@ -44,12 +46,12 @@ module SpreeCmCommissioner
44
46
  before_validation :set_event_id
45
47
  before_validation :assign_seat_number, if: -> { bib_number.present? }
46
48
 
47
- before_create :generate_bib, if: -> { variant.bib_pre_generation_on_create? }
49
+ before_create :generate_bib, if: -> { line_item.reload && variant.bib_pre_generation_on_create? }
48
50
 
49
51
  validates :seat_number, uniqueness: { scope: :event_id }, allow_nil: true, if: -> { event_id.present? }
50
52
  validates :bib_index, uniqueness: true, allow_nil: true
51
53
 
52
- self.whitelisted_ransackable_associations = %w[id_card event]
54
+ self.whitelisted_ransackable_associations = %w[id_card event line_item]
53
55
  self.whitelisted_ransackable_attributes = %w[first_name last_name phone_number gender contact occupation_id card_type created_at check_in_status]
54
56
 
55
57
  def self.csv_importable_columns
@@ -0,0 +1,25 @@
1
+ module SpreeCmCommissioner
2
+ class GuestDynamicField < SpreeCmCommissioner::Base
3
+ belongs_to :guest, class_name: 'SpreeCmCommissioner::Guest', optional: false
4
+ belongs_to :dynamic_field, class_name: 'SpreeCmCommissioner::DynamicField', optional: false
5
+
6
+ validates :value, presence: true
7
+ validate :validate_value_format, if: -> { value.present? && dynamic_field.present? }
8
+
9
+ private
10
+
11
+ def validate_value_format
12
+ return if dynamic_field.blank?
13
+
14
+ case dynamic_field.data_type.to_s
15
+ when 'integer'
16
+ errors.add(:value, 'must be a number') unless value.to_s.match?(/\A\d+\z/)
17
+ when 'boolean'
18
+ errors.add(:value, 'must be true or false') unless %w[true false 1 0].include?(value.to_s.downcase)
19
+ when 'checkbox', 'radio'
20
+ valid_options = dynamic_field.dynamic_field_options.pluck(:id).map(&:to_s)
21
+ errors.add(:value, 'is not a valid option') unless valid_options.include?(value)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,44 @@
1
+ module SpreeCmCommissioner
2
+ class InviteTeam < SpreeCmCommissioner::Base
3
+ belongs_to :user, class_name: 'Spree::User', optional: true
4
+ belongs_to :inviter, class_name: 'Spree::User'
5
+ belongs_to :vendor, class_name: 'Spree::Vendor'
6
+
7
+ attr_reader :user_id, :vendor_id
8
+
9
+ enum status: { pending: 0, accepted: 1 }, _default: 0
10
+
11
+ preference :role_ids, :array, default: []
12
+
13
+ validate :validate_roles
14
+
15
+ after_create :set_expiration
16
+ after_create :send_team_invite_email
17
+
18
+ def roles
19
+ Spree::Role.where(id: preferred_role_ids)
20
+ end
21
+
22
+ def validate_roles
23
+ return if preferred_role_ids.present?
24
+
25
+ errors.add(:base, I18n.t('user_roles_assigner.roles_required'))
26
+ end
27
+
28
+ def send_team_invite_email
29
+ SpreeCmCommissioner::TeamInviteMailer.send_team_invite_email(id).deliver_now
30
+ end
31
+
32
+ def set_expiration
33
+ update(expires_at: 3.days.from_now)
34
+ end
35
+
36
+ def invitation_link
37
+ "http://#{ENV.fetch('APP_HOST')}/organizer/invite_teams/#{token}?utm_source=email"
38
+ end
39
+
40
+ def url_valid?
41
+ expires_at.present? && expires_at > Time.current
42
+ end
43
+ end
44
+ end
@@ -37,6 +37,8 @@ module SpreeCmCommissioner
37
37
 
38
38
  base.has_many :product_places, class_name: 'SpreeCmCommissioner::ProductPlace', dependent: :destroy
39
39
  base.has_many :places, through: :product_places
40
+ base.has_many :product_dynamic_fields, class_name: 'SpreeCmCommissioner::ProductDynamicField', dependent: :destroy
41
+ base.has_many :dynamic_fields, through: :product_dynamic_fields, class_name: 'SpreeCmCommissioner::DynamicField'
40
42
 
41
43
  base.has_one :venue, -> { where(type: :venue) }, class_name: 'SpreeCmCommissioner::ProductPlace', dependent: :destroy
42
44
 
@@ -0,0 +1,8 @@
1
+ module SpreeCmCommissioner
2
+ class ProductDynamicField < SpreeCmCommissioner::Base
3
+ belongs_to :product, class_name: 'Spree::Product', optional: false
4
+ belongs_to :dynamic_field, class_name: 'SpreeCmCommissioner::DynamicField', optional: false
5
+
6
+ validates :dynamic_field_id, uniqueness: { scope: :product_id }
7
+ end
8
+ end
@@ -3,6 +3,7 @@ module SpreeCmCommissioner
3
3
  def self.prepended(base) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
4
4
  base.include SpreeCmCommissioner::TaxonKind
5
5
  base.include SpreeCmCommissioner::Transit::TaxonBitwise
6
+ base.include SpreeCmCommissioner::ParticipationTypeBitwise
6
7
 
7
8
  base.preference :background_color, :string
8
9
  base.preference :foreground_color, :string
@@ -33,6 +33,7 @@ module SpreeCmCommissioner
33
33
 
34
34
  base.multi_tenant :tenant, class_name: 'SpreeCmCommissioner::Tenant'
35
35
  base.scope :by_tenant, -> (tenant_id) { where(tenant_id: tenant_id) }
36
+ base.scope :vendor_users, -> (vendor_id) { joins(:role_users => :role).where(spree_roles: { vendor_id: vendor_id }).distinct }
36
37
 
37
38
  base.whitelisted_ransackable_attributes = %w[email first_name last_name gender phone_number]
38
39
 
@@ -2,5 +2,6 @@ module SpreeCmCommissioner
2
2
  class UserTaxon < Base
3
3
  belongs_to :user, class_name: Spree.user_class.to_s, optional: false
4
4
  belongs_to :taxon, class_name: 'Spree::Taxon', optional: false
5
+ has_many :invite_user_taxons, class_name: 'SpreeCmCommissioner::InviteUserTaxon', dependent: :destroy
5
6
  end
6
7
  end
@@ -51,6 +51,7 @@ module SpreeCmCommissioner
51
51
  through: :vendor_stops, source: :stop, class_name: 'SpreeCmCommissioner::Place'
52
52
  base.has_many :drop_off_points, -> { where(cm_vendor_stops: { stop_type: 1 }) },
53
53
  through: :vendor_stops, source: :stop, class_name: 'SpreeCmCommissioner::Place'
54
+ base.has_many :dynamic_fields, class_name: 'SpreeCmCommissioner::DynamicField', foreign_key: :vendor_id, dependent: :destroy
54
55
 
55
56
  base.has_one :logo, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::VendorLogo'
56
57
  base.has_one :payment_qrcode, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::VendorPaymentQrcode'