rmails 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
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
+