auction_fun_core 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +12 -0
  3. data/.env.development.template +7 -0
  4. data/.env.test.template +7 -0
  5. data/.rspec +3 -0
  6. data/.standard.yml +3 -0
  7. data/.tool-versions +5 -0
  8. data/CHANGELOG.md +145 -0
  9. data/CODE_OF_CONDUCT.md +84 -0
  10. data/LICENSE.txt +21 -0
  11. data/Procfile +4 -0
  12. data/README.md +141 -0
  13. data/Rakefile +13 -0
  14. data/auction_fun_core.gemspec +57 -0
  15. data/config/app.rb +5 -0
  16. data/config/application.rb +37 -0
  17. data/config/boot.rb +15 -0
  18. data/db/migrate/20240216200926_enable_postgres_extensions.rb +13 -0
  19. data/db/migrate/20240217115734_create_users.rb +28 -0
  20. data/db/migrate/20240220140151_create_custom_types.rb +11 -0
  21. data/db/migrate/20240220140254_create_staffs.rb +20 -0
  22. data/db/migrate/20240229142933_create_custom_types.rb +13 -0
  23. data/db/migrate/20240229143000_create_auctions.rb +29 -0
  24. data/db/migrate/20240304144422_create_bids.rb +19 -0
  25. data/db/seeds.rb +116 -0
  26. data/i18n/en-US/contracts/contracts.en-US.yml +72 -0
  27. data/i18n/en-US/mail/user_context/registration.en-US.yml +11 -0
  28. data/i18n/pt-BR/contracts/contracts.pt-BR.yml +72 -0
  29. data/i18n/pt-BR/mail/user_context/registration.pt-BR.yml +12 -0
  30. data/lib/auction_fun_core/business/configuration.rb +18 -0
  31. data/lib/auction_fun_core/business/token_generator.rb +17 -0
  32. data/lib/auction_fun_core/commands/auction_context/create_auction.rb +19 -0
  33. data/lib/auction_fun_core/commands/auction_context/delete_auction.rb +15 -0
  34. data/lib/auction_fun_core/commands/auction_context/update_auction.rb +18 -0
  35. data/lib/auction_fun_core/commands/bid_context/create_bid.rb +19 -0
  36. data/lib/auction_fun_core/commands/bid_context/delete_bid.rb +15 -0
  37. data/lib/auction_fun_core/commands/bid_context/update_bid.rb +18 -0
  38. data/lib/auction_fun_core/commands/staff_context/create_staff.rb +19 -0
  39. data/lib/auction_fun_core/commands/user_context/create_user.rb +19 -0
  40. data/lib/auction_fun_core/contracts/application_contract.rb +55 -0
  41. data/lib/auction_fun_core/contracts/auction_context/create_contract.rb +101 -0
  42. data/lib/auction_fun_core/contracts/auction_context/processor/finish_contract.rb +27 -0
  43. data/lib/auction_fun_core/contracts/auction_context/processor/pause_contract.rb +34 -0
  44. data/lib/auction_fun_core/contracts/auction_context/processor/start_contract.rb +46 -0
  45. data/lib/auction_fun_core/contracts/auction_context/processor/unpause_contract.rb +34 -0
  46. data/lib/auction_fun_core/contracts/bid_context/create_bid_closed_contract.rb +79 -0
  47. data/lib/auction_fun_core/contracts/bid_context/create_bid_penny_contract.rb +69 -0
  48. data/lib/auction_fun_core/contracts/bid_context/create_bid_standard_contract.rb +68 -0
  49. data/lib/auction_fun_core/contracts/staff_context/authentication_contract.rb +47 -0
  50. data/lib/auction_fun_core/contracts/staff_context/registration_contract.rb +52 -0
  51. data/lib/auction_fun_core/contracts/user_context/authentication_contract.rb +47 -0
  52. data/lib/auction_fun_core/contracts/user_context/email_confirmation_contract.rb +40 -0
  53. data/lib/auction_fun_core/contracts/user_context/phone_confirmation_contract.rb +40 -0
  54. data/lib/auction_fun_core/contracts/user_context/registration_contract.rb +63 -0
  55. data/lib/auction_fun_core/entities/auction.rb +17 -0
  56. data/lib/auction_fun_core/entities/bid.rb +10 -0
  57. data/lib/auction_fun_core/entities/staff.rb +21 -0
  58. data/lib/auction_fun_core/entities/user.rb +37 -0
  59. data/lib/auction_fun_core/events/app.rb +27 -0
  60. data/lib/auction_fun_core/events/listener.rb +89 -0
  61. data/lib/auction_fun_core/operations/auction_context/create_operation.rb +77 -0
  62. data/lib/auction_fun_core/operations/auction_context/processor/finish_operation.rb +61 -0
  63. data/lib/auction_fun_core/operations/auction_context/processor/pause_operation.rb +57 -0
  64. data/lib/auction_fun_core/operations/auction_context/processor/start_operation.rb +84 -0
  65. data/lib/auction_fun_core/operations/auction_context/processor/unpause_operation.rb +57 -0
  66. data/lib/auction_fun_core/operations/base.rb +11 -0
  67. data/lib/auction_fun_core/operations/bid_context/create_bid_closed_operation.rb +64 -0
  68. data/lib/auction_fun_core/operations/bid_context/create_bid_penny_operation.rb +64 -0
  69. data/lib/auction_fun_core/operations/bid_context/create_bid_standard_operation.rb +74 -0
  70. data/lib/auction_fun_core/operations/staff_context/authentication_operation.rb +52 -0
  71. data/lib/auction_fun_core/operations/staff_context/registration_operation.rb +76 -0
  72. data/lib/auction_fun_core/operations/user_context/authentication_operation.rb +52 -0
  73. data/lib/auction_fun_core/operations/user_context/email_confirmation_operation.rb +67 -0
  74. data/lib/auction_fun_core/operations/user_context/phone_confirmation_operation.rb +67 -0
  75. data/lib/auction_fun_core/operations/user_context/registration_operation.rb +105 -0
  76. data/lib/auction_fun_core/relations/auctions.rb +119 -0
  77. data/lib/auction_fun_core/relations/bids.rb +28 -0
  78. data/lib/auction_fun_core/relations/staffs.rb +27 -0
  79. data/lib/auction_fun_core/relations/users.rb +26 -0
  80. data/lib/auction_fun_core/repos/auction_context/auction_repository.rb +42 -0
  81. data/lib/auction_fun_core/repos/bid_context/bid_repository.rb +27 -0
  82. data/lib/auction_fun_core/repos/staff_context/staff_repository.rb +64 -0
  83. data/lib/auction_fun_core/repos/user_context/user_repository.rb +78 -0
  84. data/lib/auction_fun_core/services/mail/templates/layout.html.erb +72 -0
  85. data/lib/auction_fun_core/services/mail/templates/user_context/registration.html.erb +170 -0
  86. data/lib/auction_fun_core/services/mail/user_context/registration_mailer.rb +25 -0
  87. data/lib/auction_fun_core/version.rb +8 -0
  88. data/lib/auction_fun_core/workers/application_job.rb +22 -0
  89. data/lib/auction_fun_core/workers/operations/auction_context/processor/finish_operation_job.rb +32 -0
  90. data/lib/auction_fun_core/workers/operations/auction_context/processor/start_operation_job.rb +32 -0
  91. data/lib/auction_fun_core/workers/services/mail/user_context/registration_mailer_job.rb +40 -0
  92. data/lib/auction_fun_core.rb +21 -0
  93. data/lib/tasks/database.rake +87 -0
  94. data/system/providers/background_job.rb +15 -0
  95. data/system/providers/core.rb +35 -0
  96. data/system/providers/db.rb +26 -0
  97. data/system/providers/events.rb +13 -0
  98. data/system/providers/logger.rb +11 -0
  99. data/system/providers/mail.rb +25 -0
  100. data/system/providers/persistence.rb +18 -0
  101. data/system/providers/settings.rb +26 -0
  102. metadata +400 -0
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AuctionFunCore
4
+ module Relations
5
+ # SQL relation for auctions.
6
+ # @see https://rom-rb.org/5.0/learn/sql/relations/
7
+ class Auctions < ROM::Relation[:sql]
8
+ use :pagination, per_page: 10
9
+
10
+ KINDS = Types::Coercible::String.default("standard").enum("standard", "penny", "closed")
11
+ STATUSES = Types::Coercible::String.default("scheduled")
12
+ .enum("scheduled", "running", "paused", "canceled", "finished")
13
+
14
+ schema(:auctions, infer: true) do
15
+ attribute :id, Types::Integer
16
+ attribute :staff_id, Types::ForeignKey(:staffs)
17
+ attribute :title, Types::String
18
+ attribute :description, Types::String
19
+ attribute :kind, KINDS
20
+ attribute :status, STATUSES
21
+ attribute :started_at, Types::DateTime
22
+ attribute :finished_at, Types::DateTime
23
+ attribute :stopwatch, Types::Integer
24
+ attribute :initial_bid_cents, Types::Integer
25
+ attribute :initial_bid_currency, Types::String
26
+ attribute :minimal_bid_cents, Types::Integer
27
+ attribute :minimal_bid_currency, Types::String
28
+
29
+ attribute :metadata, Types::PG::JSONB
30
+ attribute :statistics, Types::PG::JSONB
31
+ primary_key :id
32
+
33
+ associations do
34
+ belongs_to :staff, as: :staff, relation: :staffs
35
+ has_many :bids, as: :bids, relation: :bids
36
+ end
37
+ end
38
+
39
+ struct_namespace Entities
40
+ auto_struct(true)
41
+
42
+ def all(page = 1, per_page = 10, options = {bidders_count: 3})
43
+ offset = ((page - 1) * per_page)
44
+
45
+ read(all_auctions_with_bid_info(per_page, offset, options))
46
+ end
47
+
48
+ def info(auction_id, options = {bidders_count: 3})
49
+ raise "Invalid argument" unless auction_id.is_a?(Integer)
50
+
51
+ read(auction_with_bid_info(auction_id, options))
52
+ end
53
+
54
+ private
55
+
56
+ def auction_with_bid_info(auction_id, options = {bidders_count: 3})
57
+ "SELECT a.id, a.title, a.description, a.kind, a.status, a.started_at, a.finished_at, a.stopwatch, a.initial_bid_cents,
58
+ (SELECT COUNT(*) FROM (SELECT * FROM bids WHERE bids.auction_id = #{auction_id}) dt) AS total_bids,
59
+ CASE
60
+ WHEN a.kind = 'standard' THEN
61
+ json_build_object(
62
+ 'current', a.minimal_bid_cents,
63
+ 'minimal', a.minimal_bid_cents,
64
+ 'bidders', COALESCE(
65
+ json_agg(json_build_object('id', bi.id, 'user_id', users.id, 'name', users.name, 'value', bi.value_cents, 'date', bi.created_at) ORDER BY value_cents DESC)
66
+ FILTER (where bi.id IS NOT NULL AND users.id IS NOT NULL), '[]'::json
67
+ )
68
+ )
69
+ WHEN a.kind = 'penny' THEN
70
+ json_build_object(
71
+ 'value', a.initial_bid_cents,
72
+ 'bidders', COALESCE(
73
+ json_agg(json_build_object('id', bi.id, 'user_id', users.id, 'name', users.name, 'value', bi.value_cents, 'date', bi.created_at) ORDER BY value_cents DESC)
74
+ FILTER (where bi.id IS NOT NULL AND users.id IS NOT NULL), '[]'::json
75
+ )
76
+ )
77
+ WHEN a.kind = 'closed' THEN
78
+ json_build_object('minimal', (a.initial_bid_cents + (a.initial_bid_cents * 0.10))::int)
79
+ END as bids
80
+ FROM auctions as a
81
+ LEFT JOIN LATERAL (SELECT * FROM bids WHERE auction_id = a.id ORDER BY value_cents DESC LIMIT #{options[:bidders_count]}) as bi ON a.id = bi.auction_id AND a.id = #{auction_id}
82
+ LEFT JOIN users ON bi.user_id = users.id AND bi.auction_id = a.id
83
+ WHERE a.id = #{auction_id}
84
+ GROUP BY a.id"
85
+ end
86
+
87
+ def all_auctions_with_bid_info(per_page, offset, options = {bidders_count: 3})
88
+ "SELECT a.id, a.title, a.description, a.kind, a.status, a.started_at, a.finished_at, a.stopwatch, a.initial_bid_cents,
89
+ (SELECT COUNT(*) FROM (SELECT * FROM bids WHERE bids.auction_id = a.id) dt) AS total_bids,
90
+ CASE
91
+ WHEN a.kind = 'standard' THEN
92
+ json_build_object(
93
+ 'current', a.minimal_bid_cents,
94
+ 'minimal', a.minimal_bid_cents,
95
+ 'bidders', COALESCE(
96
+ json_agg(json_build_object('id', bi.id, 'user_id', users.id, 'name', users.name, 'value', bi.value_cents, 'date', bi.created_at) ORDER BY value_cents DESC)
97
+ FILTER (where bi.id IS NOT NULL AND users.id IS NOT NULL), '[]'::json
98
+ )
99
+ )
100
+ WHEN a.kind = 'penny' THEN
101
+ json_build_object(
102
+ 'value', a.initial_bid_cents,
103
+ 'bidders', COALESCE(
104
+ json_agg(json_build_object('id', bi.id, 'user_id', users.id, 'name', users.name, 'value', bi.value_cents, 'date', bi.created_at) ORDER BY value_cents DESC)
105
+ FILTER (where bi.id IS NOT NULL AND users.id IS NOT NULL), '[]'::json
106
+ )
107
+ )
108
+ WHEN a.kind = 'closed' THEN
109
+ json_build_object('minimal', (a.initial_bid_cents + (a.initial_bid_cents * 0.10))::int)
110
+ END as bids
111
+ FROM auctions as a
112
+ LEFT JOIN LATERAL (SELECT * FROM bids WHERE auction_id = a.id ORDER BY value_cents DESC LIMIT #{options[:bidders_count]}) as bi ON a.id = bi.auction_id
113
+ LEFT JOIN users ON bi.user_id = users.id AND bi.auction_id = a.id
114
+ GROUP BY a.id
115
+ LIMIT #{per_page} OFFSET #{offset}"
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AuctionFunCore
4
+ module Relations
5
+ # SQL relation for bids
6
+ # @see https://rom-rb.org/5.0/learn/sql/relations/
7
+ class Bids < ROM::Relation[:sql]
8
+ use :pagination, per_page: 3
9
+
10
+ schema(:bids, infer: true) do
11
+ attribute :id, Types::Integer
12
+
13
+ attribute :auction_id, Types::ForeignKey(:auctions)
14
+ attribute :user_id, Types::ForeignKey(:users)
15
+
16
+ associations do
17
+ belongs_to :auction
18
+ belongs_to :user
19
+ end
20
+
21
+ primary_key :id
22
+ end
23
+
24
+ struct_namespace Entities
25
+ auto_struct(true)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AuctionFunCore
4
+ module Relations
5
+ # SQL relation for staffs.
6
+ # @see https://rom-rb.org/5.0/learn/sql/relations/
7
+ class Staffs < ROM::Relation[:sql]
8
+ use :pagination, per_page: 10
9
+
10
+ STAFF_KINDS = Types::Coercible::String.default("common").enum("root", "common")
11
+
12
+ schema(:staffs, infer: true) do
13
+ attribute :id, Types::Integer
14
+ attribute :name, Types::String
15
+ attribute :email, Types::String
16
+ attribute :phone, Types::String
17
+ attribute :kind, STAFF_KINDS
18
+ attribute :active, Types::Bool
19
+
20
+ primary_key :id
21
+ end
22
+
23
+ struct_namespace Entities
24
+ auto_struct(true)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AuctionFunCore
4
+ module Relations
5
+ # SQL relation for users.
6
+ # @see https://rom-rb.org/5.0/learn/sql/relations/
7
+ class Users < ROM::Relation[:sql]
8
+ use :pagination, per_page: 10
9
+
10
+ schema(:users, infer: true) do
11
+ attribute :id, Types::Integer
12
+ attribute :name, Types::String
13
+ attribute :email, Types::String
14
+ attribute :phone, Types::String
15
+ attribute :active, Types::Bool
16
+ attribute :balance_cents, Types::Integer
17
+ attribute :balance_currency, Types::String
18
+
19
+ primary_key :id
20
+ end
21
+
22
+ struct_namespace Entities
23
+ auto_struct(true)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AuctionFunCore
4
+ module Repos
5
+ module AuctionContext
6
+ # SQL repository for auctions.
7
+ class AuctionRepository < ROM::Repository[:auctions]
8
+ include Import["container"]
9
+
10
+ struct_namespace Entities
11
+ commands :create, update: :by_pk, delete: :by_pk
12
+
13
+ # Returns all auctions in the database.
14
+ # @return [Array<ROM::Struct::Auction>, []]
15
+ def all
16
+ auctions.to_a
17
+ end
18
+
19
+ # Returns the total number of auctions in database.
20
+ # @return [Integer]
21
+ def count
22
+ auctions.count
23
+ end
24
+
25
+ # Search auction in database by primary key.
26
+ # @param id [Integer] Auction ID
27
+ # @return [ROM::Struct::Auction, nil]
28
+ def by_id(id)
29
+ auctions.by_pk(id).one
30
+ end
31
+
32
+ # Search auction in database by primary key.
33
+ # @param id [Integer] Auction ID
34
+ # @raise [ROM::TupleCountMismatchError] if not found on database
35
+ # @return [ROM::Struct::Auction]
36
+ def by_id!(id)
37
+ auctions.by_pk(id).one!
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AuctionFunCore
4
+ module Repos
5
+ module BidContext
6
+ # SQL repository for bids.
7
+ class BidRepository < ROM::Repository[:bids]
8
+ include Import["container"]
9
+
10
+ struct_namespace Entities
11
+ commands :create, update: :by_pk, delete: :by_pk
12
+
13
+ # Returns the total number of bids in database.
14
+ # @return [Integer]
15
+ def count
16
+ bids.count
17
+ end
18
+
19
+ # @param conditions [Hash] DSL Dataset
20
+ # @return [Boolean]
21
+ def exists?(conditions)
22
+ bids.exist?(conditions)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AuctionFunCore
4
+ module Repos
5
+ module StaffContext
6
+ # SQL repository for staffs.
7
+ class StaffRepository < ROM::Repository[:staffs]
8
+ include Import["container"]
9
+
10
+ struct_namespace Entities
11
+ commands :create, update: :by_pk, delete: :by_pk
12
+
13
+ # Returns all staffs in database.
14
+ # @return [Array<ROM::Struct::Staff>, []]
15
+ def all
16
+ staffs.to_a
17
+ end
18
+
19
+ # Returns the total number of staffs in database.
20
+ # @return [Integer]
21
+ def count
22
+ staffs.count
23
+ end
24
+
25
+ # Mount SQL conditions in query for search in database.
26
+ # @param conditions [Hash] DSL Dataset
27
+ # @return [AuctionFunCore::Relations::Staffs]
28
+ def query(conditions)
29
+ staffs.where(conditions)
30
+ end
31
+
32
+ # Search staff in database by primary key.
33
+ # @param id [Integer] Staff ID
34
+ # @return [ROM::Struct::Staff, nil]
35
+ def by_id(id)
36
+ staffs.by_pk(id).one
37
+ end
38
+
39
+ # Search staffs in database by primary key.
40
+ # @param id [Integer] Staff ID
41
+ # @raise [ROM::TupleCountMismatchError] if not found on database
42
+ # @return [ROM::Struct::Auction]
43
+ def by_id!(id)
44
+ staffs.by_pk(id).one!
45
+ end
46
+
47
+ # Search staff in database by email of phone keys.
48
+ # @param login [String] Staff email or phone
49
+ # @return [ROM::Struct::Staff, nil]
50
+ def by_login(login)
51
+ staffs.where(Sequel[email: login] | Sequel[phone: login]).one
52
+ end
53
+
54
+ # Checks if it returns any staff given one or more conditions.
55
+ # @param conditions [Hash] DSL Dataset
56
+ # @return [true] when some staff is returned from the given condition.
57
+ # @return [false] when no staff is returned from the given condition.
58
+ def exists?(conditions)
59
+ staffs.exist?(conditions)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AuctionFunCore
4
+ module Repos
5
+ module UserContext
6
+ # SQL repository for users.
7
+ class UserRepository < ROM::Repository[:users]
8
+ include Import["container"]
9
+
10
+ struct_namespace Entities
11
+ commands :create, update: :by_pk, delete: :by_pk
12
+
13
+ # Returns all users in database.
14
+ # @return [Array<ROM::Struct::User>, []]
15
+ def all
16
+ users.to_a
17
+ end
18
+
19
+ # Returns the total number of users in database.
20
+ # @return [Integer]
21
+ def count
22
+ users.count
23
+ end
24
+
25
+ # Mount SQL conditions in query for search in database.
26
+ # @param conditions [Hash] DSL Dataset
27
+ # @return [AuctionFunCore::Relations::Users]
28
+ def query(conditions)
29
+ users.where(conditions)
30
+ end
31
+
32
+ # Search user in database by primary key.
33
+ # @param id [Integer] User ID
34
+ # @return [ROM::Struct::User, nil]
35
+ def by_id(id)
36
+ users.by_pk(id).one
37
+ end
38
+
39
+ # Search user in database by primary key.
40
+ # @param id [Integer] User ID
41
+ # @raise [ROM::TupleCountMismatchError] if not found on database
42
+ # @return [ROM::Struct::Auction]
43
+ def by_id!(id)
44
+ users.by_pk(id).one!
45
+ end
46
+
47
+ # Search user in database by email of phone keys.
48
+ # @param login [String] User email or phone
49
+ # @return [ROM::Struct::User, nil]
50
+ def by_login(login)
51
+ users.where(Sequel[email: login] | Sequel[phone: login]).one
52
+ end
53
+
54
+ # Search user in database by email_confirmation_token key.
55
+ # @param email_confirmation_token [String] User email confirmation token
56
+ # @return [ROM::Struct::User, nil]
57
+ def by_email_confirmation_token(email_confirmation_token)
58
+ users.where(Sequel[email_confirmation_token: email_confirmation_token]).one
59
+ end
60
+
61
+ # Search user in database by phone_confirmation_token of phone keys.
62
+ # @param phone [String] User phone confirmation token
63
+ # @return [ROM::Struct::User, nil]
64
+ def by_phone_confirmation_token(phone_confirmation_token)
65
+ users.where(Sequel[phone_confirmation_token: phone_confirmation_token]).one
66
+ end
67
+
68
+ # Checks if it returns any user given one or more conditions.
69
+ # @param conditions [Hash] DSL Dataset
70
+ # @return [true] when some user is returned from the given condition.
71
+ # @return [false] when no user is returned from the given condition.
72
+ def exists?(conditions)
73
+ users.exist?(conditions)
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,72 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
3
+ <head>
4
+ <title>AuctionFun</title>
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
6
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
8
+ <style type="text/css">
9
+ #outlook a {
10
+ padding: 0;
11
+ }
12
+ body {
13
+ margin: 0;
14
+ padding: 0;
15
+ -webkit-text-size-adjust: 100%;
16
+ -ms-text-size-adjust: 100%;
17
+ }
18
+ table,
19
+ td {
20
+ border-collapse: collapse;
21
+ mso-table-lspace: 0pt;
22
+ mso-table-rspace: 0pt;
23
+ }
24
+ img {
25
+ border: 0;
26
+ height: auto;
27
+ line-height: 100%;
28
+ outline: none;
29
+ text-decoration: none;
30
+ -ms-interpolation-mode: bicubic;
31
+ }
32
+ p {
33
+ display: block;
34
+ margin: 13px 0;
35
+ }
36
+ </style>
37
+ <style type="text/css">
38
+ .mj-outlook-group-fix { width:100% !important; }
39
+ </style>
40
+ <style type="text/css">
41
+ @media only screen and (min-width:480px) {
42
+ .mj-column-per-100 {
43
+ width: 100% !important;
44
+ max-width: 100%;
45
+ }
46
+ }
47
+ </style>
48
+ <style type="text/css">
49
+ @media only screen and (max-width:480px) {
50
+ table.mj-full-width-mobile {
51
+ width: 100% !important;
52
+ }
53
+ td.mj-full-width-mobile {
54
+ width: auto !important;
55
+ }
56
+ }
57
+ </style>
58
+ <style type="text/css">
59
+ a,
60
+ span,
61
+ td,
62
+ th {
63
+ -webkit-font-smoothing: antialiased !important;
64
+ -moz-osx-font-smoothing: grayscale !important;
65
+ }
66
+ </style>
67
+ </head>
68
+ <body style="background-color:#ffffff;">
69
+ <%= yield %>
70
+ </div>
71
+ </body>
72
+ </html>
@@ -0,0 +1,170 @@
1
+ <table align="center" border="0" cellpadding="0" cellspacing="0" style="width:600px;" width="600">
2
+ <tr>
3
+ <td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
4
+ <div style="margin:0px auto;max-width:600px;">
5
+ <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
6
+ <tbody>
7
+ <tr>
8
+ <td style="direction:ltr;font-size:0px;padding:20px 0;padding-bottom:0px;text-align:center;">
9
+ <table role="presentation" border="0" cellpadding="0" cellspacing="0">
10
+ <tr>
11
+ <td style="vertical-align:top;width:600px;">
12
+ <div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
13
+ <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
14
+ <tbody>
15
+ <tr>
16
+ <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
17
+ <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;">
18
+ <tbody>
19
+ <tr>
20
+ <td style="width:50px;">
21
+ <img alt="image description" height="auto" src="https://codedmails.com/images/logo-circle.png" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:14px;" width="50" />
22
+ </td>
23
+ </tr>
24
+ </tbody>
25
+ </table>
26
+ </td>
27
+ </tr>
28
+ <tr>
29
+ <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
30
+ <div style="font-family:Helvetica, Arial, sans-serif;font-size:18px;font-weight:400;line-height:24px;text-align:left;color:#434245;">
31
+ <h1 style="margin: 0; font-size: 24px; line-height: normal; font-weight: bold;">
32
+ <%= I18n.t("mail.general.hello", name: @user.name) %>,
33
+ </h1>
34
+ </div>
35
+ </td>
36
+ </tr>
37
+ </tbody>
38
+ </table>
39
+ </div>
40
+ </td>
41
+ </tr>
42
+ </table>
43
+ </td>
44
+ </tr>
45
+ </tbody>
46
+ </table>
47
+ </div>
48
+ </td>
49
+ </tr>
50
+ </table>
51
+ <table align="center" border="0" cellpadding="0" cellspacing="0" style="width:600px;" width="600">
52
+ <tr>
53
+ <td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
54
+ <div style="margin:0px auto;max-width:600px;">
55
+ <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
56
+ <tbody>
57
+ <tr>
58
+ <td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
59
+ <table role="presentation" border="0" cellpadding="0" cellspacing="0">
60
+ <tr>
61
+ <td style="vertical-align:top;width:600px;">
62
+ <div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
63
+ <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
64
+ <tbody>
65
+ <tr>
66
+ <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
67
+ <div style="font-family:Helvetica, Arial, sans-serif;font-size:18px;font-weight:400;line-height:24px;text-align:left;color:#434245;">
68
+ <%= I18n.t("mail.user_context.registration.body.description") %>
69
+ </div>
70
+ </td>
71
+ </tr>
72
+ <tr>
73
+ <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
74
+ <div style="font-family:Helvetica, Arial, sans-serif;font-size:18px;font-weight:400;line-height:24px;text-align:left;color:#434245;">
75
+ <%= raw I18n.t("mail.user_context.registration.body.email_confirmation_token", token: @user.email_confirmation_token) %>
76
+ </div>
77
+ </td>
78
+ </tr>
79
+ <tr>
80
+ <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
81
+ <div style="font-family:Helvetica, Arial, sans-serif;font-size:18px;font-weight:bold;line-height:24px;text-align:left;color:#434245;">
82
+ <%= I18n.t("mail.general.team") %>
83
+ </div>
84
+ </td>
85
+ </tr>
86
+ <tr>
87
+ <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
88
+ <table align="left" border="0" cellpadding="0" cellspacing="0" role="presentation">
89
+ <tr>
90
+ <td>
91
+ <table align="left" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
92
+ <tbody>
93
+ <tr>
94
+ <td style="padding:4px;">
95
+ <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:18px;">
96
+ <tbody>
97
+ <tr>
98
+ <td style="font-size:0;height:18px;vertical-align:middle;width:18px;">
99
+ <a href="https://twitter.com/auctionfun" target="_blank" style="color: #2e58ff; text-decoration: none;">
100
+ <img alt="twitter-logo" height="18" src="https://codedmails.com/images/social/black/twitter-logo-transparent-black.png" style="border-radius:3px;display:block;" width="18" />
101
+ </a>
102
+ </td>
103
+ </tr>
104
+ </tbody>
105
+ </table>
106
+ </td>
107
+ </tr>
108
+ </tbody>
109
+ </table>
110
+ </td>
111
+ <td>
112
+ <table align="left" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
113
+ <tbody>
114
+ <tr>
115
+ <td style="padding:4px;">
116
+ <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:18px;">
117
+ <tbody>
118
+ <tr>
119
+ <td style="font-size:0;height:18px;vertical-align:middle;width:18px;">
120
+ <a href="https://facebook.com/auctionfun" target="_blank" style="color: #2e58ff; text-decoration: none;">
121
+ <img alt="facebook-logo" height="18" src="https://codedmails.com/images/social/black/facebook-logo-transparent-black.png" style="border-radius:3px;display:block;" width="18" />
122
+ </a>
123
+ </td>
124
+ </tr>
125
+ </tbody>
126
+ </table>
127
+ </td>
128
+ </tr>
129
+ </tbody>
130
+ </table>
131
+ </td>
132
+ <td>
133
+ <table align="left" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
134
+ <tbody>
135
+ <tr>
136
+ <td style="padding:4px;">
137
+ <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:18px;">
138
+ <tbody>
139
+ <tr>
140
+ <td style="font-size:0;height:18px;vertical-align:middle;width:18px;">
141
+ <a href="https://instagram.com/auctionfun" target="_blank" style="color: #2e58ff; text-decoration: none;">
142
+ <img alt="instagram-logo" height="18" src="https://codedmails.com/images/social/black/instagram-logo-transparent-black.png" style="border-radius:3px;display:block;" width="18" />
143
+ </a>
144
+ </td>
145
+ </tr>
146
+ </tbody>
147
+ </table>
148
+ </td>
149
+ </tr>
150
+ </tbody>
151
+ </table>
152
+ </td>
153
+ </tr>
154
+ </table>
155
+ </td>
156
+ </tr>
157
+ </tbody>
158
+ </table>
159
+ </div>
160
+ </td>
161
+ </tr>
162
+ </table>
163
+ </td>
164
+ </tr>
165
+ </tbody>
166
+ </table>
167
+ </div>
168
+ </td>
169
+ </tr>
170
+ </table>