rmails 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +15 -0
  4. data/Vagrantfile +1 -1
  5. data/app/assets/javascripts/controls/domains.coffee.erb +68 -75
  6. data/app/assets/javascripts/models/domain.coffee.erb +4 -3
  7. data/app/assets/stylesheets/application.sass +5 -13
  8. data/app/assets/stylesheets/base.css.sass +0 -4
  9. data/app/controllers/domains_controller.rb +1 -1
  10. data/app/models/virtual_domain.rb +6 -0
  11. data/app/models/virtual_user.rb +2 -2
  12. data/app/views/admin_users/first.html.haml +0 -1
  13. data/app/views/aliases/_templates.html.haml +29 -0
  14. data/app/views/domains/_templates.html.haml +71 -0
  15. data/app/views/domains/index.html.haml +9 -114
  16. data/app/views/users/_form.html.haml +4 -2
  17. data/app/views/users/_templates.html.haml +27 -0
  18. data/bin/rmails +14 -5
  19. data/config/locales/server/help/dovecot/cz.yml +4 -2
  20. data/config/locales/server/key/dovecot/en.yml +17 -17
  21. data/config/locales/views/aliases/cz.yml +3 -1
  22. data/config/locales/views/aliases/en.yml +20 -0
  23. data/config/locales/views/domains/cz.yml +1 -1
  24. data/config/locales/views/domains/en.yml +11 -10
  25. data/config/locales/views/server/cz.yml +1 -0
  26. data/config/locales/views/users/cz.yml +8 -2
  27. data/config/locales/views/users/en.yml +22 -0
  28. data/db/migrate/20121112201341_virtual_user.rb +0 -8
  29. data/lib/rmails/installer.rb +12 -3
  30. data/lib/rmails/version.rb +2 -2
  31. data/public/assets/{application-83367ef0d1b7ecb80fbc1ba279811151.js → application-3b8b925cdaedaadcce73613bb5c35985.js} +1 -1
  32. data/public/assets/{application-83367ef0d1b7ecb80fbc1ba279811151.js.gz → application-3b8b925cdaedaadcce73613bb5c35985.js.gz} +0 -0
  33. data/public/assets/application-ab23db04de6609ba65d1ee5a378d5735.css +1 -0
  34. data/public/assets/{application-7b6b5d175d26fb23a5584728dc35220f.css.gz → application-ab23db04de6609ba65d1ee5a378d5735.css.gz} +0 -0
  35. data/public/assets/application.css +1 -1
  36. data/public/assets/application.css.gz +0 -0
  37. data/public/assets/application.js +1 -1
  38. data/public/assets/application.js.gz +0 -0
  39. data/public/assets/manifest.yml +26 -26
  40. data/system/dist/rmails/Gemfile.2 +1 -0
  41. metadata +10 -6
  42. data/public/assets/application-7b6b5d175d26fb23a5584728dc35220f.css +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 722089a297589f3b84c92117564200adf61dece2
4
- data.tar.gz: ec16435e608b9048f3734515a211a05ede2ae13b
3
+ metadata.gz: f401f448f9d918ccaf166213e68aab5c2e960a68
4
+ data.tar.gz: b0005de980f5159a5095ab98c32ef7af3f6c7bfb
5
5
  SHA512:
6
- metadata.gz: fd2906efb59ddb99d0a2ec8e2f19cc834d3b91b66a519bfe945a77e6a1982d6ea0f70ec33424494a0afa0e5781a29a6ea5c54755979e1dc310be2c1e1dcf480f
7
- data.tar.gz: 8e0ac9b713f62e2c020fd508940c4bbf27c94db6e52974cf31538e2bcdfcef8b244dae5b641f932f24757cf181cb3e804c8ac08ee8e4dc83737347dd8168aff2
6
+ metadata.gz: 9d03c6d4acacde0f7c16a54d146f2b02585720e9bf30da126fd4221c5ef6c67d915ff66583be37e9f5ca8480f8bd07ca6d86f8e7600874645342c798b6bb0344
7
+ data.tar.gz: 1d53cfbc754550f2849e9235f1b1162bfbde10474bc7a40f4b0ea2657d5cc2ff91ba30ce8698e7b4bc204cc148e0b98869e963563c7724dc37ce3e95c304bd31
data/.gitignore CHANGED
@@ -6,6 +6,7 @@ doc/*
6
6
  config/database.yml
7
7
  db/*.sqlite3
8
8
  db/schema.rb
9
+ db/data.yml
9
10
  *~
10
11
  start
11
12
  *.swp
@@ -0,0 +1,15 @@
1
+ Changelog
2
+ =========
3
+
4
+ v0.2.3 - 2013-06-xx
5
+ --------------------
6
+
7
+
8
+ ### Features and improvements ###
9
+
10
+ - Domains management use routes to edit, delete and manage actions.
11
+
12
+ ### Bug fixes ###
13
+
14
+
15
+
@@ -21,7 +21,7 @@ Vagrant::Config.run do |config|
21
21
  c.vm.box = "debian32"
22
22
  c.vm.forward_port 80, 8091
23
23
  c.vm.forward_port 3000, 4001
24
- c.vm.forward_port 25, 1125
24
+ c.vm.forward_port 25, 1125
25
25
  c.vm.forward_port 587, 11587
26
26
  c.vm.forward_port 110, 11110
27
27
  c.vm.forward_port 995, 11995
@@ -1,3 +1,7 @@
1
+ can.route( ':action/:id' )
2
+ can.route( ':action' )
3
+
4
+
1
5
  window.Domains = can.Control({
2
6
 
3
7
  init: (el, opt) ->
@@ -5,6 +9,27 @@ window.Domains = can.Control({
5
9
  @model = Domain.models JSON.parse($('#domains_JSON').text())
6
10
  return
7
11
 
12
+ render_manage_area: (li, item) ->
13
+ li.addClass('open').find('.item').append( can.view( 'manage_area_EJS' ) )
14
+ users = new Users(li.find('.item .users'), {
15
+ items: item["virtual_users"]
16
+ domain_id: item.id
17
+ domain_name: item.name
18
+ })
19
+ aliases = new Aliases(li.find('.item .aliases'), {
20
+ items: item["virtual_aliases"]
21
+ domain_id: item.id
22
+ domain_name: item.name
23
+ })
24
+
25
+ close_manage_area: (li) ->
26
+ li.find('.nomanage').hide()
27
+ li.find('.manage').show()
28
+ li.removeClass('open')
29
+ it = li.find('.item .item-content:last')
30
+ if it.hasClass('out')
31
+ it.remove()
32
+
8
33
  "form reset": (el, ev) ->
9
34
  li = el.parents('li')
10
35
  if li.hasClass('empty')
@@ -16,22 +41,12 @@ window.Domains = can.Control({
16
41
  li.find('.item').html(
17
42
  can.view( 'domain_item_EJS', { item: item } )
18
43
  )
19
-
20
- ".add-domain click": (el, ev) ->
21
- ev.preventDefault()
22
- $('#domains .empty').remove()
23
- $('#domains').prepend(can.view( 'domain_form_EJS', { item: new Domain } ))
24
- $('.add-domain').toggle()
25
-
26
- ".rm-domain click": (el, ev) ->
27
- ev.preventDefault()
28
- $('#domains .empty').remove()
29
- $('.add-domain').toggle()
44
+ can.route.attr('action', '' )
30
45
 
31
46
  "#new_virtual_domain submit": (el, ev) ->
32
47
  ev.preventDefault()
33
- self = this
34
48
  values = el.formParams()
49
+ self = this
35
50
  item = new Domain(values["virtual_domain"])
36
51
  if item.errors() # validation error
37
52
  item.alert()
@@ -45,71 +60,49 @@ window.Domains = can.Control({
45
60
  )
46
61
  else
47
62
  # post-creation hook
48
- item.attr('id', json.id)
49
- li.removeClass('empty').attr('id', 'domain_'+json.id)
50
- # show links to edit and remove with right id
51
- li.find('.item').html(
52
- can.view( 'domain_item_EJS', { item: item } )
53
- ).find('.btn-group a').attr('href', (i, v) ->
54
- return unescape(v).replace(/{id}/g, json.id)
55
- )
56
- self.model.unshift(item)
57
- $('.add-domain').toggle()
63
+ item.attr(json.domain)
64
+ li.removeClass('empty').attr('id', 'domain_'+item.attr('id'))
58
65
  )
66
+ # show links to edit and remove with right id
67
+ li.find('.item').html( can.view( 'domain_item_EJS', { item: item } ) )
68
+ @model.unshift(item)
69
+ $('.add-domain').toggle()
59
70
 
71
+ ":action route": (a) ->
72
+ # action NEW
73
+ if a["action"] == 'new'
74
+ $('#domains .empty').remove()
75
+ $('#domains').prepend(can.view( 'domain_form_EJS', { item: new Domain } ))
76
+ $('.add-domain').toggle()
60
77
 
61
-
62
- ".edit click": (el, ev) ->
63
- ev.preventDefault()
64
- li = el.parents('li')
65
- id = li.attr('id').replace('domain_','')
66
- item = @model.with_id(parseInt(id))
67
- li.find('.item').html(can.view( 'domain_edit_EJS', { item: item } ))
68
- li.addClass('inedit')
69
- return false
70
-
71
- ".delete click": (el, ev) ->
72
- ev.preventDefault()
73
- if not confirm('Are You sure?')
74
- return false
75
- li = el.parents('li')
76
- id = li.attr('id').replace('domain_','')
77
- item = @model.with_id(parseInt(id))
78
- @model.splice(@model.indexOf(item), 1)
79
- item.destroy()
80
- li.remove()
81
- return false
82
-
83
- ".manage click": (el, ev) ->
84
- ev.preventDefault()
85
- li = el.parents('li')
86
- txt = el.text()
87
- el.text(el.data('inverse'))
88
- el.data('inverse', txt)
89
- if el.hasClass('label-info')
90
- el.removeClass('label-info')
91
- else
92
- el.addClass('label-info')
93
- li.find('.item-content:last').remove()
94
- return false
95
-
96
- id = li.attr('id').replace('domain_','')
97
- item = @model.with_id(parseInt(id))
98
- if li.find('.item .item-content:last').hasClass('out')
99
- return false
100
- li.find('.item').append(
101
- can.view( 'manage_area_EJS' )
102
- )
103
- users = new Users(li.find('.item .users'), {
104
- items: item["virtual_users"]
105
- domain_id: id
106
- domain_name: item.name
107
- })
108
- aliases = new Aliases(li.find('.item .aliases'), {
109
- items: item["virtual_aliases"]
110
- domain_id: id
111
- domain_name: item.name
112
- })
113
- return false
78
+ ":action/:id route": (params) ->
79
+ li = $("#domain_" + params["id"])
80
+ item = @model.with_id(parseInt(params["id"]))
81
+ self = this
82
+ # action EDIT
83
+ if params["action"] == 'edit'
84
+ li.find('.item').html(can.view( 'domain_edit_EJS', { item: item } ))
85
+ li.addClass('inedit')
86
+ # action DELETE
87
+ else if params["action"] == 'delete'
88
+ if confirm(li.find('.rm').data('msg'))
89
+ Domain.destroy(item, (json) ->
90
+ if json["errors"]
91
+ alert(json["errors"])
92
+ else
93
+ # delete from local Model.list
94
+ self.model.splice(self.model.indexOf(item), 1)
95
+ li.remove()
96
+ )
97
+ can.route.attr({action:''})
98
+ # action SHOW
99
+ else if params["action"] == 'show'
100
+ li.find('.manage').hide()
101
+ li.find('.nomanage').show()
102
+ @close_manage_area($('.open'))
103
+ @render_manage_area(li, item)
104
+ # action HIDE
105
+ else if params["action"] == 'hide'
106
+ @close_manage_area(li)
114
107
 
115
108
  })
@@ -11,7 +11,9 @@ window.Domain = can.Model({
11
11
  url = unescape('<%= Rails.application.routes.url_helpers.domain_path('{id}') %>').replace('{id}', domain.id)
12
12
  return $.post(url, attrs, null, "json")
13
13
 
14
- destroy : ('DELETE ' + unescape('<%= Rails.application.routes.url_helpers.domain_path('{id}') %>'))
14
+ destroy : (item, callback) ->
15
+ url = unescape('<%= Rails.application.routes.url_helpers.domain_path('{id}') %>').replace("{id}", item.id)
16
+ return $.post(url, {"_method":"DELETE"}, callback, "json")
15
17
 
16
18
 
17
19
  attributes: {
@@ -20,8 +22,7 @@ window.Domain = can.Model({
20
22
  },
21
23
 
22
24
  init: () ->
23
- @validatePresenceOf ['name']
24
- #@validateFormatOf ['name'], /\A(?:[-a-z0-9]+\.)+[a-z]{2,}\Z/i
25
+ @validateFormatOf ['name'], /^(?:[-a-z0-9]+\.)+[a-z]{2,}$/i
25
26
 
26
27
  }, {})
27
28
 
@@ -91,8 +91,7 @@ header
91
91
  display: inline-block
92
92
  background: transparent
93
93
  border: none
94
- *
95
- display: inline
94
+
96
95
  //.actions
97
96
  float: right
98
97
  //.inputs
@@ -103,15 +102,12 @@ header
103
102
  #rmails
104
103
  .list .table
105
104
  tr td
106
- *
105
+ .aliases
107
106
  display: inline-block
108
107
  .help-block
109
108
  display: block !important
110
109
 
111
- .label
112
- display: inline !important
113
-
114
- .aliases, .users
110
+ .aliases
115
111
  margin: 0
116
112
  label
117
113
  display: block !important
@@ -126,9 +122,6 @@ header
126
122
  width: 100%
127
123
  .control-group
128
124
  vertical-align: top
129
-
130
- .aliases
131
- .control-group
132
125
  float: left
133
126
  input.string, textarea
134
127
  display: block !important
@@ -144,9 +137,8 @@ header
144
137
  padding: 3px
145
138
 
146
139
  .users
147
- input.string, input.password
148
- width: 254px !important
149
- display: inline-block !important
140
+
141
+
150
142
 
151
143
  #system
152
144
  /*.control-label
@@ -188,13 +188,9 @@ body#comfy, body#rmails
188
188
  font-size: 15px
189
189
  font-weight: 700
190
190
  .label
191
- display: none
192
191
  opacity: 0.7
193
192
  &:hover
194
193
  opacity: 1
195
- &:hover
196
- .label
197
- display: inline
198
194
  .btn-group
199
195
  float: right
200
196
  li ul
@@ -21,7 +21,7 @@ class DomainsController < ApplicationController
21
21
  def create # JSON only
22
22
  @domain = current_admin_user.build_domain(params[:virtual_domain])
23
23
  if @domain.save
24
- render :json => {:id => @domain.id}
24
+ render :json => {:domain => @domain}
25
25
  else
26
26
  render :json => {:errors => @domain.errors}
27
27
  end
@@ -12,4 +12,10 @@ class VirtualDomain < ActiveRecord::Base
12
12
 
13
13
  default_scope order('id DESC').includes([:virtual_users, :virtual_aliases])
14
14
 
15
+ def as_json(opt={})
16
+ super opt.merge({
17
+ :include => [:virtual_users, :virtual_aliases]
18
+ })
19
+ end
20
+
15
21
  end
@@ -1,12 +1,12 @@
1
1
  class VirtualUser < ActiveRecord::Base
2
2
 
3
3
  devise :database_authenticatable, :encryptable,
4
- :recoverable, :rememberable, :trackable, :validatable,
4
+ :recoverable, :rememberable, :validatable,
5
5
  :encryptor => :dovecot_ssha512, :stretches => 1
6
6
 
7
7
  belongs_to :virtual_domain
8
8
 
9
- attr_accessible :name, :email, :password, :password_confirmation
9
+ attr_accessible :name, :email, :password, :quota_kb, :quota_messages
10
10
 
11
11
  before_validation :repair_email_format
12
12
 
@@ -7,6 +7,5 @@
7
7
  = f.input :name, :label => t('.name')
8
8
  = f.input :email, :label => t('.email')
9
9
  = f.input :password, :label => t('.pass'), :required => true
10
- = f.input :password_confirmation, :label => t('.passs')
11
10
 
12
11
  = f.button :button, t('.create'), :type => 'submit', :class => 'btn-primary'
@@ -0,0 +1,29 @@
1
+ %script#aliass_each_EJS{"type" => "text/ejs"}
2
+ :plain
3
+ <% list (items, function(item, index) { %>
4
+ <tr id="alias_<%= index %>">
5
+ %td.tar
6
+ :plain
7
+ <%= item.source %>
8
+ %td
9
+ %b
10
+ :plain
11
+ @<%= domain_name %>
12
+ %i.icon-hand-right
13
+ %td
14
+ :plain
15
+ <%= item.destination %>
16
+ %td.tar
17
+ = link_to t(".edit"), edit_domain_alias_path('{domain_id}', '{id}'), :class => 'label edit-alias'
18
+ = link_to "&times;".html_safe, domain_alias_path('{domain_id}', '{id}'), :class => 'rm-alias', :title => t(".delete")
19
+ :plain
20
+ </tr>
21
+ <% }) %>
22
+
23
+ %script#aliass_tabr_EJS{"type" => "text/ejs"}
24
+ %tr.new
25
+
26
+ %script#aliass_form_EJS{"type" => "text/ejs"}
27
+ %td{:colspan => "4"}
28
+ = render :partial => '/aliases/form', :locals => { :virtual_alias => alias_ejs_object }
29
+
@@ -0,0 +1,71 @@
1
+ %script#domain_form_EJS{"type" => "text/ejs"}
2
+ %li.empty
3
+ .item
4
+ .iconat @
5
+ = render :partial => 'form', :locals => { :domain => domain_ejs_object }
6
+ .out
7
+
8
+ %script#domain_edit_EJS{"type" => "text/ejs"}
9
+ .iconat @
10
+ = render :partial => 'form', :locals => { :domain => domain_ejs_object }
11
+ .out
12
+
13
+ %script#domain_item_EJS{"type" => "text/ejs"}
14
+ .iconat @
15
+ .btn-group
16
+ :plain
17
+ <a href="#!edit/<%= item.attr('id') %>" class="label edit">
18
+ = t("domains.index.edit")
19
+ :plain
20
+ </a>
21
+ :plain
22
+ <a href="#!delete/<%= item.attr('id') %>" class="label label-warning rm" data-msg="#{t("domains.index.confirm")}">
23
+ = t("domains.index.delete")
24
+ :plain
25
+ </a>
26
+
27
+ .item-content
28
+ :plain
29
+ <a href="#!show/<%= item.attr('id') %>" class="item-label">
30
+ <%= item.attr('name') %>
31
+ </a>
32
+ :plain
33
+ <a href="#!show/<%= item.attr('id') %>" class="label label-info manage">
34
+ = t("domains.index.manage")
35
+ :plain
36
+ </a>
37
+
38
+ :plain
39
+ <a href="#!hide/<%= item.attr('id') %>" class="label dn nomanage">
40
+ = t("domains.index.nomanage")
41
+ :plain
42
+ </a>
43
+
44
+ %script#errors_EJS{"type" => "text/ejs"}
45
+ .errors
46
+ %h6= t('domains.index.errors')
47
+ :plain
48
+ <% for (attr in errors) { %>
49
+ <% list (errors[attr], function(error) { %>
50
+ <p><%= error %></p>
51
+ <% }) %>
52
+ <% } %>
53
+
54
+ %script#manage_area_EJS{"type" => "text/ejs"}
55
+ .item-content.out.row-fluid
56
+ .span5.users
57
+ %h4
58
+ %span.title= t('users.index.title')
59
+ %span.dn.title_new= t('users.index.title_new')
60
+ %span.dn.title_edit= t('users.index.title_edit')
61
+ .label-info.label.new-user=t 'users.form.create'
62
+ %table.table.table-condensed
63
+ .span5.aliases
64
+ %h4
65
+ %span.title= t('aliases.index.title')
66
+ %span.dn.title_new= t('aliases.index.title_new')
67
+ %span.dn.title_edit= t('aliases.index.title_edit')
68
+ .label-info.label.new-alias=t 'aliases.form.create'
69
+ %table.table.table-condensed
70
+
71
+