ghost 4.37.0 → 4.39.0

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 (125) hide show
  1. package/.c8rc.json +1 -1
  2. package/README.md +26 -18
  3. package/content/themes/casper/LICENSE +1 -1
  4. package/content/themes/casper/README.md +1 -1
  5. package/content/themes/casper/assets/built/global.css +1 -1
  6. package/content/themes/casper/assets/built/global.css.map +1 -1
  7. package/content/themes/casper/assets/built/screen.css +1 -1
  8. package/content/themes/casper/assets/built/screen.css.map +1 -1
  9. package/content/themes/casper/assets/css/global.css +14 -6
  10. package/content/themes/casper/assets/css/screen.css +9 -1
  11. package/content/themes/casper/package.json +2 -2
  12. package/content/themes/casper/partials/post-card.hbs +1 -1
  13. package/content/themes/casper/post.hbs +18 -19
  14. package/content/themes/casper/yarn.lock +186 -217
  15. package/core/built/assets/{chunk.3.4906cf0b01d6d8e33374.js → chunk.3.6e2ed2d00856e12bd81a.js} +19 -19
  16. package/core/built/assets/ghost-dark-498ff8339a89bb68c3f78f59bee4146e.css +1 -0
  17. package/core/built/assets/ghost.min-77b93478f83b0def6ddc5a4f23ce963e.css +1 -0
  18. package/core/built/assets/{ghost.min-c1938f6ee696bf08bd6bf93cac341ea2.js → ghost.min-e6559d901897066aa6a6d4145e3728ed.js} +466 -413
  19. package/core/built/assets/icons/{event-changed-subscription.svg → event-subscriptions.svg} +0 -1
  20. package/core/built/assets/icons/eye.svg +4 -1
  21. package/core/built/assets/icons/member-add.svg +3 -0
  22. package/core/built/assets/icons/member.svg +3 -0
  23. package/core/built/assets/icons/pin.svg +4 -1
  24. package/core/built/assets/{vendor.min-6dc30be68238b5c55df0cdc1f2dc8b8d.js → vendor.min-c39476bced9adb98ee2b292d01c7a8f4.js} +2303 -1372
  25. package/core/frontend/apps/private-blogging/lib/middleware.js +1 -1
  26. package/core/frontend/apps/private-blogging/lib/views/private.hbs +9 -10
  27. package/core/frontend/helpers/get.js +4 -0
  28. package/core/frontend/helpers/match.js +12 -0
  29. package/core/frontend/helpers/prev_post.js +11 -1
  30. package/core/frontend/helpers/tiers.js +59 -0
  31. package/core/frontend/helpers/tpl/content-cta.hbs +1 -1
  32. package/core/frontend/public/ghost.css +205 -143
  33. package/core/frontend/services/routing/router-manager.js +1 -1
  34. package/core/frontend/views/unsubscribe.hbs +28 -33
  35. package/core/frontend/web/middleware/error-handler.js +2 -2
  36. package/core/frontend/web/site.js +10 -0
  37. package/core/server/api/canary/authentication.js +7 -0
  38. package/core/server/api/canary/index.js +4 -0
  39. package/core/server/api/canary/members.js +9 -2
  40. package/core/server/api/canary/products.js +3 -6
  41. package/core/server/api/canary/tiers-public.js +34 -0
  42. package/core/server/api/canary/tiers.js +6 -7
  43. package/core/server/api/canary/utils/serializers/input/pages.js +1 -1
  44. package/core/server/api/canary/utils/serializers/input/posts.js +1 -1
  45. package/core/server/api/canary/utils/serializers/output/email-posts.js +7 -1
  46. package/core/server/api/canary/utils/serializers/output/pages.js +9 -2
  47. package/core/server/api/canary/utils/serializers/output/posts.js +8 -2
  48. package/core/server/api/canary/utils/serializers/output/preview.js +7 -1
  49. package/core/server/api/canary/utils/serializers/output/products.js +3 -1
  50. package/core/server/api/canary/utils/serializers/output/tiers.js +4 -2
  51. package/core/server/api/canary/utils/serializers/output/utils/mapper.js +17 -7
  52. package/core/server/api/shared/serializers/handle.js +2 -2
  53. package/core/server/api/v2/utils/serializers/input/pages.js +1 -1
  54. package/core/server/api/v2/utils/serializers/input/posts.js +1 -1
  55. package/core/server/api/v3/utils/serializers/input/pages.js +1 -1
  56. package/core/server/api/v3/utils/serializers/input/posts.js +1 -1
  57. package/core/server/data/db/connection.js +3 -2
  58. package/core/server/data/importer/import-manager.js +152 -113
  59. package/core/server/data/migrations/versions/3.29/01-remove-duplicate-subscriptions.js +2 -1
  60. package/core/server/data/migrations/versions/3.29/02-remove-duplicate-customers.js +2 -1
  61. package/core/server/data/migrations/versions/3.29/03-remove-orphaned-customers.js +2 -1
  62. package/core/server/data/migrations/versions/3.29/04-remove-orphaned-subscriptions.js +2 -1
  63. package/core/server/data/migrations/versions/3.29/05-add-member-constraints.js +3 -2
  64. package/core/server/data/migrations/versions/3.39/06-add-email-recipient-index.js +4 -3
  65. package/core/server/data/migrations/versions/4.0/14-remove-orphaned-stripe-records.js +2 -1
  66. package/core/server/data/migrations/versions/4.0/26-add-cascade-on-delete.js +2 -1
  67. package/core/server/data/migrations/versions/4.0/29-fix-foreign-key-for-members-stripe-customers-subscriptions.js +2 -1
  68. package/core/server/data/migrations/versions/4.1/02-add-unique-constraint-for-member-stripe-tables.js +2 -1
  69. package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +3 -2
  70. package/core/server/data/migrations/versions/4.33/2022-01-14-11-51-add-default-free-tier.js +3 -0
  71. package/core/server/data/migrations/versions/4.33/2022-01-18-09-07-remove-duplicate-offer-redemptions.js +2 -2
  72. package/core/server/data/migrations/versions/4.35/2022-02-01-11-48-update-email-recipient-filter-column-type.js +2 -1
  73. package/core/server/data/migrations/versions/4.35/2022-02-01-12-03-update-recipient-filter-column-type.js +2 -1
  74. package/core/server/data/migrations/versions/4.37/2022-02-21-09-53-backfill-members-last-seen-at-column.js +3 -2
  75. package/core/server/data/migrations/versions/4.38/2022-03-01-08-46-add-visibility-to-tiers.js +11 -0
  76. package/core/server/data/migrations/versions/4.38/2022-03-03-16-12-add-visibility-to-tiers.js +8 -0
  77. package/core/server/data/migrations/versions/4.38/2022-03-03-16-17-drop-tiers-visible-column.js +7 -0
  78. package/core/server/data/migrations/versions/4.39/2022-03-07-10-57-update-free-products-visibility-column.js +66 -0
  79. package/core/server/data/migrations/versions/4.39/2022-03-07-10-57-update-products-visibility-column.js +36 -0
  80. package/core/server/data/schema/clients/index.js +1 -1
  81. package/core/server/data/schema/clients/mysql.js +4 -4
  82. package/core/server/data/schema/commands.js +42 -50
  83. package/core/server/data/schema/default-settings/default-settings.json +2 -2
  84. package/core/server/data/schema/fixtures/fixtures.json +18 -161
  85. package/core/server/data/schema/schema.js +7 -0
  86. package/core/server/frontend/ghost.min.css +1 -1
  87. package/core/server/lib/image/image-size.js +12 -4
  88. package/core/server/models/base/plugins/generate-slug.js +13 -1
  89. package/core/server/models/base/plugins/raw-knex.js +1 -1
  90. package/core/server/models/post.js +16 -6
  91. package/core/server/models/product.js +2 -1
  92. package/core/server/models/user.js +1 -1
  93. package/core/server/services/auth/api-key/admin.js +15 -6
  94. package/core/server/services/auth/setup.js +34 -13
  95. package/core/server/services/email-analytics/lib/event-processor.js +18 -1
  96. package/core/server/services/mega/mega.js +4 -4
  97. package/core/server/services/mega/template.js +1 -1
  98. package/core/server/services/members/content-gating.js +1 -1
  99. package/core/server/services/members/middleware.js +4 -0
  100. package/core/server/services/members/service.js +13 -1
  101. package/core/server/services/posts/posts-service.js +1 -1
  102. package/core/server/services/url/UrlGenerator.js +1 -1
  103. package/core/server/services/webhooks/webhooks-service.js +2 -0
  104. package/core/server/views/maintenance.html +2 -2
  105. package/core/server/web/admin/views/default-prod.html +4 -4
  106. package/core/server/web/admin/views/default.html +4 -4
  107. package/core/server/web/api/app.js +3 -0
  108. package/core/server/web/api/canary/admin/middleware.js +2 -0
  109. package/core/server/web/api/canary/content/routes.js +1 -0
  110. package/core/server/web/members/app.js +1 -1
  111. package/core/server/web/parent/backend.js +2 -1
  112. package/core/server/web/shared/middleware/uncapitalise.js +3 -2
  113. package/core/shared/config/defaults.json +2 -2
  114. package/core/shared/config/utils.js +5 -1
  115. package/core/shared/labs.js +8 -9
  116. package/core/shared/url-utils.js +4 -1
  117. package/package.json +56 -52
  118. package/yarn.lock +809 -607
  119. package/core/built/assets/ghost-dark-d54723f7267e66fa2595f897076e86c2.css +0 -1
  120. package/core/built/assets/ghost.min-02a5f8954bd85fe28817b8c8b111b8aa.css +0 -1
  121. package/core/built/assets/icons/event-started-subscription.svg +0 -6
  122. package/core/built/assets/icons/locked-email-back.svg +0 -1
  123. package/core/built/assets/icons/locked-email-front.svg +0 -1
  124. package/core/built/assets/icons/locked-email-lock.svg +0 -1
  125. package/core/built/assets/img/ghost-logo-de2acf283f53ba1fd1149928faeaaa74.png +0 -0
@@ -13,7 +13,7 @@ const privateRoute = '/private/';
13
13
 
14
14
  const messages = {
15
15
  pageNotFound: 'Page not found.',
16
- wrongPassword: 'Wrong password'
16
+ wrongPassword: 'Incorrect password.'
17
17
  };
18
18
 
19
19
  function verifySessionHash(salt, hash) {
@@ -22,23 +22,22 @@
22
22
  <main class="gh-main" role="main">
23
23
  <div class="gh-flow">
24
24
  <div class="gh-flow-content-wrap">
25
- <section class="gh-flow-content">
25
+ {{#if @site.icon}}
26
+ <img class="site-icon" src="{{img_url @site.icon absolute="true"}}" alt="icon">
27
+ {{/if}}
28
+ <section class="gh-flow-content private">
26
29
  <header>
27
- <h1>This site is private</h1>
30
+ <h1>This site is private.</h1>
28
31
  </header>
29
32
  <form class="gh-signin" method="post" novalidate="novalidate">
30
33
  <div class="form-group{{#if error}} error{{/if}}">
31
- <span class="gh-input-icon gh-icon-lock">
32
- <svg version="1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g><path d="M12 14c-.552 0-1 .449-1 1 0 .365.207.672.5.846v2.654c0 .276.224.5.5.5s.5-.224.5-.5v-2.654c.293-.174.5-.481.5-.846 0-.551-.448-1-1-1zM20.5 9h-2.5v-3c0-3.309-2.691-6-6-6s-6 2.691-6 6v3h-2.5c-.276 0-.5.224-.5.5v14c0 .276.224.5.5.5h17c.276 0 .5-.224.5-.5v-14c0-.276-.224-.5-.5-.5zm-13.5-3c0-2.757 2.243-5 5-5s5 2.243 5 5v3h-10v-3zm13 17h-16v-13h16v13z"/></g></svg>
33
34
  {{input_password class="gh-input" placeholder="Password"}}
34
- </span>
35
+ {{#if error}}
36
+ <p class="main-error">{{error.message}}</p>
37
+ {{/if}}
35
38
  </div>
36
- <button class="gh-btn gh-btn-blue gh-btn-block" type="submit"><span>Enter Now</span></button>
39
+ <button class="gh-btn" type="submit"><span>Access site &rarr;</span></button>
37
40
  </form>
38
-
39
- {{#if error}}
40
- <p class="main-error">{{error.message}}</p>
41
- {{/if}}
42
41
  </section>
43
42
  </div>
44
43
  </div>
@@ -31,6 +31,9 @@ const RESOURCES = {
31
31
  },
32
32
  authors: {
33
33
  alias: 'authorsPublic'
34
+ },
35
+ tiers: {
36
+ alias: 'tiersPublic'
34
37
  }
35
38
  };
36
39
 
@@ -153,6 +156,7 @@ module.exports = function get(resource, options) {
153
156
 
154
157
  // Parse the options we're going to pass to the API
155
158
  apiOptions = parseOptions(ghostGlobals, this, apiOptions);
159
+ apiOptions.context = {member: data.member};
156
160
 
157
161
  // @TODO: https://github.com/TryGhost/Ghost/issues/10548
158
162
  return controller[action](apiOptions).then(function success(result) {
@@ -45,6 +45,18 @@ const handleMatch = (data, operator, value) => {
45
45
  case '!=':
46
46
  result = data !== value;
47
47
  break;
48
+ case '<':
49
+ result = data < value;
50
+ break;
51
+ case '>':
52
+ result = data > value;
53
+ break;
54
+ case '>=':
55
+ result = data >= value;
56
+ break;
57
+ case '<=':
58
+ result = data <= value;
59
+ break;
48
60
  default:
49
61
  result = data === value;
50
62
  }
@@ -32,7 +32,8 @@ const buildApiOptions = function buildApiOptions(options, post) {
32
32
  limit: 1,
33
33
  // This line deliberately uses double quotes because GQL cannot handle either double quotes
34
34
  // or escaped singles, see TryGhost/GQL#34
35
- filter: "slug:-" + slug + "+published_at:" + op + "'" + publishedAt + "'" // eslint-disable-line quotes
35
+ filter: "slug:-" + slug + "+published_at:" + op + "'" + publishedAt + "'", // eslint-disable-line quotes
36
+ context: {member: options.data.member}
36
37
  };
37
38
 
38
39
  if (get(options, 'hash.in')) {
@@ -48,6 +49,11 @@ const buildApiOptions = function buildApiOptions(options, post) {
48
49
  return apiOptions;
49
50
  };
50
51
 
52
+ /**
53
+ * @param {*} options
54
+ * @param {*} data
55
+ * @returns {Promise<any>}
56
+ */
51
57
  const fetch = function fetch(options, data) {
52
58
  const self = this;
53
59
  const apiOptions = buildApiOptions(options, this);
@@ -77,6 +83,10 @@ const fetch = function fetch(options, data) {
77
83
  // If prevNext method is called without valid post data then we must return a promise, if there is valid post data
78
84
  // then the promise is handled in the api call.
79
85
 
86
+ /**
87
+ * @param {*} options
88
+ * @returns {Promise<any>}
89
+ */
80
90
  module.exports = function prevNext(options) {
81
91
  options = options || {};
82
92
 
@@ -0,0 +1,59 @@
1
+ // # Tiers Helper
2
+ // Usage: `{{tiers}}`, `{{tiers separator=' - ' prefix=' : ' suffix=''}}`
3
+ //
4
+ // Returns a string of the tiers with access to the post.
5
+ // By default, tiers are separated by commas.
6
+ const {labs} = require('../services/proxy');
7
+ const {SafeString, escapeExpression} = require('../services/rendering');
8
+
9
+ const isString = require('lodash/isString');
10
+
11
+ function tiers(options = {}) {
12
+ options = options || {};
13
+ options.hash = options.hash || {};
14
+
15
+ const separator = isString(options.hash.separator) ? options.hash.separator : ', ';
16
+ const lastSeparator = isString(options.hash.lastSeparator) ? options.hash.lastSeparator : ' and ';
17
+ const prefix = isString(options.hash.prefix) ? options.hash.prefix : '';
18
+ let suffix = isString(options.hash.suffix) ? options.hash.suffix : '';
19
+
20
+ let output = '';
21
+
22
+ let accessProductsList = this.tiers;
23
+
24
+ if (accessProductsList && accessProductsList.length > 0) {
25
+ const tierNames = accessProductsList.map((tier) => {
26
+ return escapeExpression(tier.name);
27
+ });
28
+
29
+ if (tierNames.length === 1) {
30
+ output = tierNames[0];
31
+ suffix = isString(options.hash.suffix) ? options.hash.suffix : ' tier';
32
+ } else {
33
+ suffix = isString(options.hash.suffix) ? options.hash.suffix : ' tiers';
34
+ const firsts = tierNames.slice(0, tierNames.length - 1);
35
+ const last = tierNames[tierNames.length - 1];
36
+ output = firsts.join(separator) + lastSeparator + last;
37
+ }
38
+ }
39
+
40
+ if (output) {
41
+ output = prefix + output + suffix;
42
+ }
43
+
44
+ return new SafeString(output);
45
+ }
46
+
47
+ module.exports = function productsLabsWrapper() {
48
+ let self = this;
49
+ let args = arguments;
50
+
51
+ return labs.enabledHelper({
52
+ flagKey: 'multipleProducts',
53
+ flagName: 'Tiers',
54
+ helperName: 'tiers',
55
+ helpUrl: 'https://ghost.org/docs/themes/'
56
+ }, () => {
57
+ return tiers.apply(self, args);
58
+ });
59
+ };
@@ -8,7 +8,7 @@
8
8
  <h2>This post is for subscribers only</h2>
9
9
  {{/has}}
10
10
  {{#has visibility="tiers"}}
11
- <h2>This post is for subscribers on the {{products}} only </h2>
11
+ <h2>This post is for subscribers on the {{tiers}} only </h2>
12
12
  {{/has}}
13
13
  {{#if @member}}
14
14
  <a class="gh-btn" data-portal="account/plans" style="color:{{accentColor}}">Upgrade your account</a>
@@ -349,49 +349,66 @@ th {
349
349
  }
350
350
  /* Colour classes
351
351
  /* ---------------------------------------------------------- */
352
+ .black {
353
+ color: #15171A;
354
+ }
355
+
352
356
  .darkgrey {
353
- color: #343f44;
357
+ color: #394047;
354
358
  }
359
+
355
360
  .midgrey {
356
- color: #738a94;
361
+ color: #7C8B9A;
357
362
  }
363
+
358
364
  .lightgrey {
359
- color: #e5eff5;
365
+ color: #CED4D9;
360
366
  }
367
+
361
368
  .blue {
362
- color: #3eb0ef;
369
+ color: #14b8ff;
363
370
  }
371
+
364
372
  .red {
365
- color: #f05230;
373
+ color: #f50b23;
366
374
  }
375
+
367
376
  .orange {
368
- color: #fecd35;
377
+ color: #ffb41f;
369
378
  }
379
+
370
380
  .green {
371
- color: #a4d037;
381
+ color: #30cf43;
372
382
  }
383
+
373
384
  /* Colour classes (hover)
374
385
  /* ---------------------------------------------------------- */
375
386
  .darkgrey-hover:hover {
376
- color: #343f44;
387
+ color: #394047
377
388
  }
389
+
378
390
  .midgrey-hover:hover {
379
- color: #738a94;
391
+ color: #7C8B9A;
380
392
  }
393
+
381
394
  .lightgrey-hover:hover {
382
- color: #e5eff5;
395
+ color: #CED4D9;
383
396
  }
397
+
384
398
  .blue-hover:hover {
385
- color: #3eb0ef;
399
+ color: #14b8ff;
386
400
  }
401
+
387
402
  .red-hover:hover {
388
- color: #f05230;
403
+ color: #f50b23;
389
404
  }
405
+
390
406
  .orange-hover:hover {
391
- color: #fecd35;
407
+ color: #ffb41f;
392
408
  }
409
+
393
410
  .green-hover:hover {
394
- color: #a4d037;
411
+ color: #30cf43;
395
412
  }
396
413
 
397
414
  /* Layout
@@ -493,7 +510,6 @@ h2 {
493
510
  outline: none;
494
511
  border: 1px solid rgb(214, 227, 235);
495
512
  color: rgb(130, 154, 168);
496
- text-shadow: 0 1px 0 #fff;
497
513
  text-decoration: none !important;
498
514
  -webkit-user-select: none;
499
515
  -moz-user-select: none;
@@ -608,6 +624,7 @@ h2 {
608
624
  overflow: hidden;
609
625
  height: 100%;
610
626
  }
627
+
611
628
  /* Content viewport, contains everything else */
612
629
  .gh-viewport {
613
630
  -ms-flex-positive: 1;
@@ -617,6 +634,7 @@ h2 {
617
634
  overflow: hidden;
618
635
  max-height: 100%;
619
636
  }
637
+
620
638
  .gh-main {
621
639
  position: relative;
622
640
  -ms-flex-positive: 1;
@@ -630,185 +648,229 @@ h2 {
630
648
  /* Full screen workflow
631
649
  /* ---------------------------------------------------------- */
632
650
  .gh-flow {
633
- -ms-flex-positive: 1;
634
- flex-grow: 1;
635
- display: -ms-flexbox;
651
+ flex-grow: 1;
636
652
  display: flex;
637
- -ms-flex-direction: column;
638
- flex-direction: column;
653
+ flex-direction: column;
639
654
  overflow-y: auto;
640
655
  min-height: 100%;
656
+ background: linear-gradient(315deg,#efefef,#fff);
641
657
  }
642
- .gh-flow-head {
643
- -ms-flex-negative: 0;
644
- flex-shrink: 0;
645
- display: -ms-flexbox;
646
- display: flex;
647
- -ms-flex-pack: justify;
648
- justify-content: space-between;
649
- padding-top: 4vh;
650
- padding-bottom: 20px;
651
- }
658
+
652
659
  .gh-flow-content-wrap {
653
- -ms-flex-positive: 1;
654
- flex-grow: 1;
655
- -ms-flex-negative: 0;
656
- flex-shrink: 0;
657
- display: -ms-flexbox;
658
660
  display: flex;
659
- -ms-flex-pack: center;
660
- justify-content: center;
661
- -ms-flex-align: center;
662
- align-items: center;
663
- margin: 0 5%;
661
+ flex-direction: column;
662
+ flex-grow: 1;
663
+ flex-shrink: 0;
664
+ justify-content: center;
665
+ align-items: center;
666
+ margin: 0 24px;
664
667
  padding-bottom: 8vh;
665
668
  }
666
- .gh-flow-back {
667
- position: absolute;
668
- top: 0;
669
- left: 0;
670
- display: -ms-flexbox;
671
- display: flex;
672
- -ms-flex-align: center;
673
- align-items: center;
674
- margin: 0 0 0 3%;
675
- padding: 2px 9px 2px 5px;
676
- border: transparent 1px solid;
677
- border-radius: 4px;
678
- color: #7d878a;
679
- font-weight: 100;
680
- transition: all 0.3s ease;
681
- }
682
- .gh-flow-back svg {
683
- margin-right: 4px;
684
- height: 12px;
685
- line-height: 14px;
686
- }
687
- .gh-flow-back svg path {
688
- stroke: #7d878a;
689
- stroke-width: 1.2px;
690
- }
691
- .gh-flow-back:hover {
692
- border: #dae1e3 1px solid;
693
- }
694
- .gh-flow-back-plain {
695
- position: absolute;
696
- top: 0;
697
- left: 0;
698
- display: -ms-flexbox;
699
- display: flex;
700
- -ms-flex-align: center;
701
- align-items: center;
702
- margin: 0 0 0 3%;
703
- padding: 2px 9px 2px 5px;
704
- color: #7d878a;
705
- font-weight: 300;
706
- transition: all 0.3s ease;
707
- text-decoration: none;
708
- }
709
- .gh-flow-back-plain svg {
710
- margin-right: 4px;
711
- height: 12px;
712
- line-height: 14px;
713
- }
714
- .gh-flow-back-plain svg path {
715
- stroke: #7d878a;
716
- stroke-width: 1.2px;
717
- }
718
- .gh-flow-back-plain:hover {
719
- color: #15212A;
720
- }
721
- .gh-flow-nav {
722
- position: relative;
723
- -ms-flex: 1;
724
- flex: 1;
669
+
670
+ .gh-flow-content-wrap .site-icon {
671
+ width: 70px;
672
+ height: 70px;
673
+ border-radius: 3px;
725
674
  }
675
+
726
676
  .gh-flow-content {
727
- display: -ms-flexbox;
728
677
  display: flex;
729
- -ms-flex-direction: column;
730
- flex-direction: column;
731
- max-width: 700px;
678
+ flex-direction: column;
679
+ max-width: 520px;
732
680
  width: 100%;
733
- color: #738a94;
734
- text-align: center;
681
+ margin: 4rem 0 6rem;
682
+ padding: 40px;
683
+ background: #fff;
684
+ color: var(--darkgrey);
735
685
  font-size: 1.9rem;
736
686
  line-height: 1.5em;
737
- font-weight: 100;
738
- }
739
-
740
- .gh-flow-content .gh-input-icon input {
741
- padding-left: 35px;
687
+ font-weight: 300;
688
+ border-radius: 3px;
689
+ box-shadow:
690
+ 0 2.8px 2.2px rgba(0,0,0,.02),
691
+ 0 6.7px 5.3px rgba(0,0,0,.02),
692
+ 0 12.5px 10px rgba(0,0,0,.02),
693
+ 0 22.3px 17.9px rgba(0,0,0,.03),
694
+ 0 41.8px 33.4px rgba(0,0,0,.03),
695
+ 0 100px 80px rgba(0,0,0,.05);
742
696
  }
743
697
 
744
- .gh-flow-content-unsubscribe {
745
- font-weight: 300;
698
+ .gh-flow-content.unsubscribe {
699
+ align-items: center;
700
+ justify-content: center;
701
+ max-width: 560px;
702
+ min-height: 200px;
703
+ margin: 4rem 0;
704
+ text-align: center;
746
705
  }
747
706
 
748
707
  @media (max-width: 500px) {
749
- .gh-flow-head-unsubscribe {
750
- padding-top: 2.8vh;
751
- }
752
708
  .gh-flow-content {
753
- font-size: 4vw;
754
- }
755
- .gh-flow-content-unsubscribe {
756
- font-size: 1.8rem;
757
- line-height: 1.6em;
709
+ padding: 0;
710
+ background: transparent;
711
+ box-shadow: none;
758
712
  }
759
713
  }
714
+
760
715
  .gh-flow-content header {
761
- margin: 0 auto;
762
- max-width: 520px;
716
+ display: flex;
717
+ flex-direction: column;
718
+ align-items: center;
763
719
  }
720
+
764
721
  .gh-flow-content h1 {
765
- font-size: 4.2rem;
766
- font-weight: 100;
722
+ margin-bottom: 24px;
723
+ color: #15171A;
724
+ font-size: 4.1rem;
725
+ font-weight: 700;
726
+ line-height: 1.15em;
727
+ }
728
+
729
+ .gh-flow-content.unsubscribe h1 {
730
+ font-size: 3.2rem;
767
731
  }
732
+
768
733
  @media (max-width: 600px) {
769
- .gh-flow-content h1 {
770
- font-size: 7vw;
734
+ .gh-flow-content h1,
735
+ .gh-flow-content.unsubscribe h1 {
736
+ font-size: 6vw;
737
+ }
738
+ }
739
+
740
+ .gh-flow-content.unsubscribe p {
741
+ margin: 0 0 .4em;
742
+ color: #394047;
743
+ font-size: 1.8rem;
744
+ }
745
+
746
+ @media (max-width: 500px) {
747
+ .gh-flow-content.unsubscribe p {
748
+ font-size: 1.6rem;
749
+ line-height: 1.5;
771
750
  }
772
751
  }
752
+
773
753
  .gh-flow-content .gh-btn {
774
754
  display: block;
775
755
  margin: 20px auto 0;
776
756
  max-width: 400px;
777
757
  }
758
+
778
759
  .gh-flow-content .form-group {
760
+ position: relative;
779
761
  margin-bottom: 2.5rem;
780
762
  }
781
- .gh-flow-content input {
782
- padding: 10px;
783
- border: #dae1e3 1px solid;
784
- font-size: 1.6rem;
785
- line-height: 1.4em;
786
- font-weight: 100;
763
+
764
+ .gh-flow-content .form-group.error .gh-input {
765
+ border-color: #f50b23;
766
+ box-shadow: 0 0 0 3px rgba(239,24,24,.15);
767
+ }
768
+
769
+ .gh-flow-content .main-error {
770
+ position: absolute;
771
+ right: 0;
772
+ margin: 0;
773
+ color: #7C8B9A;
774
+ font-size: 1.35rem;
775
+ font-weight: 400;
776
+ text-align: center;
777
+ user-select: text;
787
778
  }
779
+
788
780
  .gh-flow-em {
789
781
  font-weight: 500;
790
782
  }
791
783
 
784
+ .unsubscribe-footer {
785
+ text-align: center;
786
+ font-size: 1.5rem;
787
+ }
788
+
789
+ @media (max-width: 500px) {
790
+ .unsubscribe-footer {
791
+ padding: 0 24px;
792
+ font-size: 1.4rem;
793
+ line-height: 1.4em;
794
+ }
795
+ }
796
+
797
+ .unsubscribe-footer p {
798
+ color: #7C8B9A;
799
+ margin: 0 0 .4rem;
800
+ }
801
+
802
+ .unsubscribe-footer a {
803
+ color: #15171A;
804
+ text-decoration: none;
805
+ }
806
+
807
+ .unsubscribe-footer a:hover {
808
+ text-decoration: underline;
809
+ }
810
+
792
811
  /* Sign in
793
812
  /* ---------------------------------------------------------- */
794
813
  .gh-signin {
795
- position: relative;
796
- margin: 30px auto;
797
- padding: 40px;
798
- max-width: 400px;
799
- width: 100%;
800
- border: #dae1e3 1px solid;
801
- background: #f8fbfd;
802
- border-radius: 5px;
803
- text-align: left;
804
- }
805
- .gh-signin .form-group {
806
814
  margin-bottom: 1.5rem;
807
815
  }
816
+
817
+ .gh-signin .gh-input,
818
+ .gh-signin .gh-input:-webkit-autofill::first-line {
819
+ height: 54px;
820
+ padding: 12px 16px;
821
+ font-size: 1.8rem;
822
+ border-radius: 8px;
823
+ }
824
+
825
+ .gh-signin .gh-input::placeholder {
826
+ color: #abb4be;
827
+ font-weight: 400;
828
+ opacity: 1;
829
+ }
830
+
831
+ .gh-signin .gh-input::-webkit-input-placeholder {
832
+ color: #abb4be;
833
+ font-weight: 400;
834
+ }
835
+
836
+ .gh-signin .gh-input:-ms-input-placeholder {
837
+ color: #abb4be;
838
+ font-weight: 400;
839
+ }
840
+
841
+ .gh-signin .gh-input::-moz-placeholder {
842
+ color: #abb4be;
843
+ font-weight: 400;
844
+ opacity: 1;
845
+ }
846
+
847
+ .gh-signin .gh-input:focus {
848
+ border-color: #30cf43;
849
+ box-shadow: 0 0 0 3px rgba(26,170,96,.15);
850
+ }
851
+
808
852
  .gh-signin .gh-btn {
809
853
  margin: 0;
810
854
  }
811
855
 
856
+ .gh-signin .gh-btn {
857
+ width: 100%;
858
+ height: 54px;
859
+ max-width: unset;
860
+ margin-top: 32px;
861
+ background: #15171A;
862
+ font-weight: 300;
863
+ line-height: 54px;
864
+ border-radius: 8px;
865
+ transition: all 0.4s ease;
866
+ -webkit-font-smoothing: subpixel-antialiased;
867
+ }
868
+
869
+ .gh-signin .gh-btn span {
870
+ color: #fff;
871
+ font-size: 1.8rem;
872
+ }
873
+
812
874
  /* Error /ghost/404/
813
875
  /* ---------------------------------------------------------- */
814
876
 
@@ -35,7 +35,7 @@ class RouterManager {
35
35
  routerCreated(router) {
36
36
  // NOTE: this event should be become an "internal frontend even"
37
37
  // and should not be consumed by the modules outside the frontend
38
- events.emit('router.created', this);
38
+ events.emit('router.created', router);
39
39
 
40
40
  // CASE: there are router types which do not generate resource urls
41
41
  // e.g. static route router, in this case we don't want ot notify the URL service