has_mailbox 1.5.5
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.
- data/Gemfile +4 -0
- data/README.rdoc +95 -0
- data/Rakefile +2 -0
- data/app/controllers/mailboxes_controller.rb +3 -0
- data/has_mailbox.gemspec +24 -0
- data/lib/generators/has_mailbox/install/install_generator.rb +33 -0
- data/lib/generators/has_mailbox/install/templates/README +26 -0
- data/lib/generators/has_mailbox/install/templates/jquery.tokeninput.js +718 -0
- data/lib/generators/has_mailbox/install/templates/mailboxes.css +147 -0
- data/lib/generators/has_mailbox/install/templates/mailboxes.js +28 -0
- data/lib/generators/has_mailbox/install/templates/token-input-facebook.css +122 -0
- data/lib/generators/has_mailbox/install/templates/views/_head.html.erb +19 -0
- data/lib/generators/has_mailbox/install/templates/views/_messages.html.erb +39 -0
- data/lib/generators/has_mailbox/install/templates/views/_tabs_panel.html.erb +11 -0
- data/lib/generators/has_mailbox/install/templates/views/index.html.erb +10 -0
- data/lib/generators/has_mailbox/install/templates/views/index.js.erb +1 -0
- data/lib/generators/has_mailbox/install/templates/views/new.html.erb +28 -0
- data/lib/generators/has_mailbox/install/templates/views/show.html.erb +35 -0
- data/lib/generators/has_mailbox/migration/migration_generator.rb +22 -0
- data/lib/generators/has_mailbox/migration/templates/create_message_copies_table.rb +17 -0
- data/lib/generators/has_mailbox/migration/templates/create_messages_table.rb +19 -0
- data/lib/has_mailbox.rb +14 -0
- data/lib/has_mailbox/controllers/method_helpers.rb +112 -0
- data/lib/has_mailbox/has_mailbox.rb +95 -0
- data/lib/has_mailbox/mailboxes/engine.rb +6 -0
- data/lib/has_mailbox/mailboxes/routing.rb +22 -0
- data/lib/has_mailbox/models/message.rb +52 -0
- data/lib/has_mailbox/models/message_copies.rb +30 -0
- data/lib/has_mailbox/version.rb +3 -0
- metadata +96 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails/generators/migration'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
module HasMailbox
|
5
|
+
module Generators
|
6
|
+
class MigrationGenerator < Rails::Generators::Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
|
9
|
+
source_root File.join(File.dirname(__FILE__), 'templates')
|
10
|
+
|
11
|
+
def self.next_migration_number(dirname)
|
12
|
+
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_migration_file
|
16
|
+
migration_template 'create_messages_table.rb', 'db/migrate/create_messages_table.rb'
|
17
|
+
migration_template 'create_message_copies_table.rb', 'db/migrate/create_message_copies_table.rb'
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class CreateMessageCopiesTable < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :message_copies do |t|
|
4
|
+
t.references :sent_messageable, :polymorphic => true
|
5
|
+
t.integer :recipient_id
|
6
|
+
t.string :subject
|
7
|
+
t.text :body
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :message_copies, [:sent_messageable_id, :recipient_id], :name => "outbox_idx"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.down
|
15
|
+
drop_table :message_copies
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class CreateMessagesTable < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :messages do |t|
|
4
|
+
t.references :received_messageable, :polymorphic => true
|
5
|
+
t.integer :sender_id
|
6
|
+
t.string :subject
|
7
|
+
t.text :body
|
8
|
+
t.boolean :opened, :default => false
|
9
|
+
t.boolean :deleted, :default => false
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
|
13
|
+
add_index :messages, [:received_messageable_id, :sender_id], :name => "inbox_idx"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.down
|
17
|
+
drop_table :messages
|
18
|
+
end
|
19
|
+
end
|
data/lib/has_mailbox.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "active_record"
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require 'has_mailbox/has_mailbox'
|
6
|
+
require 'has_mailbox/models/message'
|
7
|
+
require 'has_mailbox/models/message_copies'
|
8
|
+
require 'has_mailbox/controllers/method_helpers'
|
9
|
+
require 'has_mailbox/mailboxes/routing'
|
10
|
+
require 'has_mailbox/mailboxes/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
11
|
+
|
12
|
+
$LOAD_PATH.shift
|
13
|
+
|
14
|
+
ActiveRecord::Base.extend HasMailbox::Models::ClassMethods if defined? ActiveRecord::Base
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module HasMailbox
|
2
|
+
module Controllers
|
3
|
+
module MethodHelpers
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def self.define_methods(user_class_name,mapping = {})
|
7
|
+
|
8
|
+
if mapping.empty?
|
9
|
+
mapping[:user_object_name] = "current_user"
|
10
|
+
mapping[:user_display_attribute] = "email"
|
11
|
+
end
|
12
|
+
|
13
|
+
class_eval <<-METHODS, __FILE__, __LINE__ + 1
|
14
|
+
|
15
|
+
def index
|
16
|
+
@mailbox = params[:mailbox].blank? ? "inbox" : params[:mailbox]
|
17
|
+
@messages = #{mapping[:user_object_name]}.send(@mailbox).paginate(:page => params[:page], :per_page => 10)
|
18
|
+
if @mailbox == "inbox"
|
19
|
+
@options = ["Read","Unread","Delete"]
|
20
|
+
elsif @mailbox == "outbox"
|
21
|
+
@options = ["Delete"]
|
22
|
+
elsif @mailbox == "trash"
|
23
|
+
@options = ["Read","Unread","Delete","Undelete"]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def show
|
28
|
+
unless params[:mailbox].blank?
|
29
|
+
@message = #{mapping[:user_object_name]}.send(params[:mailbox]).find(params[:id])
|
30
|
+
message_from = @message.from.#{mapping[:user_display_attribute]}
|
31
|
+
message_created_at = @message.created_at.strftime('%A, %B %d, %Y at %I:%M %p')
|
32
|
+
unless params[:mailbox] == "outbox"
|
33
|
+
read_unread_messages(true,@message)
|
34
|
+
@message_description = "On " + message_created_at +" <span class='recipient_name'>" + message_from + "</span> wrote :"
|
35
|
+
@user_tokens = @message.from.id
|
36
|
+
else
|
37
|
+
@message_description = "You wrote to <span class='recipient_name'>" + message_from + "</span> at " + message_created_at + " :"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def new
|
43
|
+
end
|
44
|
+
|
45
|
+
def create
|
46
|
+
unless params[:user_tokens].blank? or params[:subject].blank? or params[:body].blank?
|
47
|
+
recipients = #{user_class_name}.find(params[:user_tokens].split(",").collect { |id| id.to_i })
|
48
|
+
if #{mapping[:user_object_name]}.send_message?(params[:subject],params[:body],*recipients)
|
49
|
+
redirect_to mailboxes_url, :notice => 'Successfully send message.'
|
50
|
+
else
|
51
|
+
flash[:alert] = "Unable to send message."
|
52
|
+
render :action => "new"
|
53
|
+
end
|
54
|
+
else
|
55
|
+
flash[:alert] = "Invalid input for sending message."
|
56
|
+
render :action => "new"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def update
|
61
|
+
unless params[:messages].nil?
|
62
|
+
messages = #{mapping[:user_object_name]}.send(params[:mailbox]).find(params[:messages])
|
63
|
+
if params[:option].downcase == "read"
|
64
|
+
read_unread_messages(true,*messages)
|
65
|
+
elsif params[:option].downcase == "unread"
|
66
|
+
read_unread_messages(false,*messages)
|
67
|
+
elsif params[:option].downcase == "delete"
|
68
|
+
delete_messages(true,*messages)
|
69
|
+
elsif params[:option].downcase == "undelete"
|
70
|
+
delete_messages(false,*messages)
|
71
|
+
end
|
72
|
+
redirect_to box_mailboxes_url(params[:mailbox])
|
73
|
+
else
|
74
|
+
redirect_to box_mailboxes_url(params[:mailbox])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def token
|
79
|
+
query = "%" + params[:q] + "%"
|
80
|
+
recipients = #{user_class_name}.select("id,#{mapping[:user_display_attribute]}").where("#{mapping[:user_display_attribute]} like ?", query)
|
81
|
+
respond_to do |format|
|
82
|
+
format.json { render :json => recipients.map { |u| { "id" => u.id, "name" => u.#{mapping[:user_display_attribute]}} } }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def read_unread_messages(isRead, *messages)
|
87
|
+
messages.each do |msg|
|
88
|
+
if isRead
|
89
|
+
msg.mark_as_read unless msg.read?
|
90
|
+
else
|
91
|
+
msg.mark_as_unread if msg.read?
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def delete_messages(isDelete, *messages)
|
97
|
+
messages.each do |msg|
|
98
|
+
if isDelete
|
99
|
+
msg.delete
|
100
|
+
else
|
101
|
+
msg.undelete
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
METHODS
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module HasMailbox
|
2
|
+
module Models
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
def has_mailbox
|
6
|
+
class_eval do
|
7
|
+
has_many :sent_messages,
|
8
|
+
:as => :sent_messageable,
|
9
|
+
:class_name => "HasMailbox::Models::MessageCopy",
|
10
|
+
:dependent => :destroy
|
11
|
+
|
12
|
+
has_many :received_messages,
|
13
|
+
:as => :received_messageable,
|
14
|
+
:class_name => "HasMailbox::Models::Message",
|
15
|
+
:dependent => :destroy
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
include HasMailbox::Models::InstanceMethods
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module InstanceMethods
|
24
|
+
def has_unread_messages?
|
25
|
+
inbox.exists?(:opened => false)
|
26
|
+
end
|
27
|
+
|
28
|
+
# send message instance method
|
29
|
+
def send_message?(subject, body, *recipients)
|
30
|
+
begin
|
31
|
+
send_message(subject, body, *recipients)
|
32
|
+
true
|
33
|
+
rescue Exception => e
|
34
|
+
false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def send_message(subject, body, *recipients)
|
39
|
+
recipients.each do |rec|
|
40
|
+
create_message_copy(subject, body, rec)
|
41
|
+
create_message(subject, body, rec)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# retrieve all sent/outgoing messages
|
46
|
+
def outbox
|
47
|
+
self.sent_messages
|
48
|
+
end
|
49
|
+
|
50
|
+
# retrieve all receiving messages
|
51
|
+
def inbox
|
52
|
+
self.received_messages.where(:deleted => false)
|
53
|
+
end
|
54
|
+
|
55
|
+
# retrieve all messages that being deleted (still in the trash but not yet destroyed)
|
56
|
+
def trash
|
57
|
+
self.received_messages.where(:deleted => true)
|
58
|
+
end
|
59
|
+
|
60
|
+
# to delete empty all of the messages
|
61
|
+
# inbox message will be move as a trash message,
|
62
|
+
# outgoing messages / outbox will be deleted forever
|
63
|
+
# and trash messages also will be deleted forever from the tables.
|
64
|
+
#* ==== :options => :inbox, :outbox, :trash
|
65
|
+
#* ==== USAGE pass the parameter as boolean value
|
66
|
+
#* ==== i.e : @user_obj.empty_mailbox(:trash => true)
|
67
|
+
def empty_mailbox(options = {})
|
68
|
+
if options.empty?
|
69
|
+
self.sent_messages.delete_all
|
70
|
+
self.received_messages.delete_all
|
71
|
+
elsif options[:inbox]
|
72
|
+
self.inbox.update_all(:deleted => true)
|
73
|
+
elsif options[:outbox]
|
74
|
+
self.outbox.delete_all
|
75
|
+
elsif options[:trash]
|
76
|
+
self.trash.delete_all
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
# this is the private segment
|
82
|
+
def create_message_copy(subject, body, recipient)
|
83
|
+
msg = HasMailbox::Models::MessageCopy.create!(:recipient_id => recipient.id, :subject => subject, :body => body)
|
84
|
+
self.sent_messages << msg
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_message(subject, body, recipient)
|
88
|
+
msg = HasMailbox::Models::Message.create!(:sender_id => self.id, :subject => subject, :body => body)
|
89
|
+
recipient.received_messages << msg
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ActionDispatch::Routing
|
2
|
+
|
3
|
+
class Mapper
|
4
|
+
|
5
|
+
def mailboxes_for(user_class_name,mapping = {})
|
6
|
+
|
7
|
+
user_class_name = user_class_name.to_s.singularize.titleize
|
8
|
+
|
9
|
+
HasMailbox::Controllers::MethodHelpers.define_methods(user_class_name,mapping)
|
10
|
+
|
11
|
+
get "/mailboxes" => "mailboxes#index", :as => "mailboxes"
|
12
|
+
get "/mailboxes/:mailbox" => "mailboxes#index", :as => "box_mailboxes"
|
13
|
+
get "/mailbox/new" => "mailboxes#new", :as => "new_mailboxes"
|
14
|
+
post "/mailbox/create" => "mailboxes#create", :as => "create_mailboxes"
|
15
|
+
post "/mailbox/update" => "mailboxes#update", :as => "update_mailboxes"
|
16
|
+
get "/mailbox/token" => "mailboxes#token", :as => "token_mailboxes"
|
17
|
+
get "/mailbox/show/:mailbox/:id" => "mailboxes#show", :as => "show_mailboxes"
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module HasMailbox
|
2
|
+
module Models
|
3
|
+
class Message < ::ActiveRecord::Base
|
4
|
+
belongs_to :received_messageable, :polymorphic => true
|
5
|
+
|
6
|
+
attr_accessible :received_messageable_type,
|
7
|
+
:received_messageable_id,
|
8
|
+
:sender_id,
|
9
|
+
:subject,
|
10
|
+
:body,
|
11
|
+
:opened,
|
12
|
+
:deleted
|
13
|
+
|
14
|
+
validates_presence_of :sender_id, :subject, :body
|
15
|
+
|
16
|
+
default_scope order('created_at desc')
|
17
|
+
|
18
|
+
def read?
|
19
|
+
self.opened?
|
20
|
+
end
|
21
|
+
|
22
|
+
def mark_as_read
|
23
|
+
self.update_attributes!(:opened => true)
|
24
|
+
end
|
25
|
+
|
26
|
+
def mark_as_unread
|
27
|
+
self.update_attributes!(:opened => false)
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete
|
31
|
+
unless self.deleted?
|
32
|
+
self.update_attributes!(:deleted => true)
|
33
|
+
else
|
34
|
+
self.destroy
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def undelete
|
39
|
+
self.update_attributes!(:deleted => false)
|
40
|
+
end
|
41
|
+
|
42
|
+
def from
|
43
|
+
"#{self.received_messageable_type}".constantize.find_by_id(self.sender_id)
|
44
|
+
end
|
45
|
+
|
46
|
+
def to
|
47
|
+
"#{self.received_messageable_type}".constantize.find_by_id(self.received_messageable_id)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module HasMailbox
|
2
|
+
module Models
|
3
|
+
class MessageCopy < ::ActiveRecord::Base
|
4
|
+
belongs_to :sent_messageable, :polymorphic => true
|
5
|
+
|
6
|
+
attr_accessible :sent_messageable_type,
|
7
|
+
:sent_messageable_id,
|
8
|
+
:recipient_id,
|
9
|
+
:subject,
|
10
|
+
:body
|
11
|
+
|
12
|
+
validates_presence_of :recipient_id, :subject, :body
|
13
|
+
|
14
|
+
default_scope order('created_at desc')
|
15
|
+
|
16
|
+
def delete
|
17
|
+
self.destroy
|
18
|
+
end
|
19
|
+
|
20
|
+
def from
|
21
|
+
"#{self.sent_messageable_type}".constantize.find_by_id(self.sent_messageable_id)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to
|
25
|
+
"#{self.sent_messageable_type}".constantize.find_by_id(self.recipient_id)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: has_mailbox
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.5.5
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Fajri Fachriansyah
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-06-16 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: jquery-rails
|
16
|
+
requirement: &2161312500 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2161312500
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: will_paginate
|
27
|
+
requirement: &2161312080 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2161312080
|
36
|
+
description: This gem allowing each user to send and receive private messages
|
37
|
+
email:
|
38
|
+
- fajrif@hotmail.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- Gemfile
|
44
|
+
- README.rdoc
|
45
|
+
- Rakefile
|
46
|
+
- app/controllers/mailboxes_controller.rb
|
47
|
+
- has_mailbox.gemspec
|
48
|
+
- lib/generators/has_mailbox/install/install_generator.rb
|
49
|
+
- lib/generators/has_mailbox/install/templates/README
|
50
|
+
- lib/generators/has_mailbox/install/templates/jquery.tokeninput.js
|
51
|
+
- lib/generators/has_mailbox/install/templates/mailboxes.css
|
52
|
+
- lib/generators/has_mailbox/install/templates/mailboxes.js
|
53
|
+
- lib/generators/has_mailbox/install/templates/token-input-facebook.css
|
54
|
+
- lib/generators/has_mailbox/install/templates/views/_head.html.erb
|
55
|
+
- lib/generators/has_mailbox/install/templates/views/_messages.html.erb
|
56
|
+
- lib/generators/has_mailbox/install/templates/views/_tabs_panel.html.erb
|
57
|
+
- lib/generators/has_mailbox/install/templates/views/index.html.erb
|
58
|
+
- lib/generators/has_mailbox/install/templates/views/index.js.erb
|
59
|
+
- lib/generators/has_mailbox/install/templates/views/new.html.erb
|
60
|
+
- lib/generators/has_mailbox/install/templates/views/show.html.erb
|
61
|
+
- lib/generators/has_mailbox/migration/migration_generator.rb
|
62
|
+
- lib/generators/has_mailbox/migration/templates/create_message_copies_table.rb
|
63
|
+
- lib/generators/has_mailbox/migration/templates/create_messages_table.rb
|
64
|
+
- lib/has_mailbox.rb
|
65
|
+
- lib/has_mailbox/controllers/method_helpers.rb
|
66
|
+
- lib/has_mailbox/has_mailbox.rb
|
67
|
+
- lib/has_mailbox/mailboxes/engine.rb
|
68
|
+
- lib/has_mailbox/mailboxes/routing.rb
|
69
|
+
- lib/has_mailbox/models/message.rb
|
70
|
+
- lib/has_mailbox/models/message_copies.rb
|
71
|
+
- lib/has_mailbox/version.rb
|
72
|
+
homepage: ''
|
73
|
+
licenses: []
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project: has_mailbox
|
92
|
+
rubygems_version: 1.8.5
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: Add ability for each user to have a Mailbox
|
96
|
+
test_files: []
|