concen 0.1

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 (67) hide show
  1. data/app/controllers/concen/application_controller.rb +25 -0
  2. data/app/controllers/concen/grid_files_controller.rb +75 -0
  3. data/app/controllers/concen/pages_controller.rb +95 -0
  4. data/app/controllers/concen/performances_controller.rb +35 -0
  5. data/app/controllers/concen/sessions_controller.rb +30 -0
  6. data/app/controllers/concen/statuses_controller.rb +63 -0
  7. data/app/controllers/concen/traffics_controller.rb +43 -0
  8. data/app/controllers/concen/users_controller.rb +118 -0
  9. data/app/controllers/concen/visits_controller.rb +38 -0
  10. data/app/helpers/concen/application_helper.rb +10 -0
  11. data/app/helpers/concen/pages_helper.rb +5 -0
  12. data/app/helpers/concen/visits_helper.rb +4 -0
  13. data/app/models/concen/grid_file.rb +67 -0
  14. data/app/models/concen/page.rb +342 -0
  15. data/app/models/concen/response.rb +45 -0
  16. data/app/models/concen/user.rb +88 -0
  17. data/app/models/concen/visit/page.rb +100 -0
  18. data/app/models/concen/visit/referral.rb +45 -0
  19. data/app/stylesheets/application.sass +445 -0
  20. data/app/stylesheets/config.rb +9 -0
  21. data/app/stylesheets/ie.sass +4 -0
  22. data/app/stylesheets/non_ios.sass +16 -0
  23. data/app/stylesheets/partials/_base.sass +92 -0
  24. data/app/stylesheets/partials/_fileuploader.sass +75 -0
  25. data/app/stylesheets/partials/_flot.sass +8 -0
  26. data/app/stylesheets/partials/_form.sass +74 -0
  27. data/app/stylesheets/partials/_mixins.sass +8 -0
  28. data/app/stylesheets/partials/_variables.sass +17 -0
  29. data/app/stylesheets/print.sass +4 -0
  30. data/app/views/concen/grid_files/_form.html.haml +15 -0
  31. data/app/views/concen/grid_files/edit.html.haml +9 -0
  32. data/app/views/concen/pages/_file_list.haml +7 -0
  33. data/app/views/concen/pages/_files.haml +24 -0
  34. data/app/views/concen/pages/_form.html.haml +18 -0
  35. data/app/views/concen/pages/_nested_list.html.haml +15 -0
  36. data/app/views/concen/pages/edit.html.haml +15 -0
  37. data/app/views/concen/pages/index.html.haml +9 -0
  38. data/app/views/concen/pages/new.html.haml +9 -0
  39. data/app/views/concen/performances/_runtimes.html.haml +5 -0
  40. data/app/views/concen/performances/show.html.haml +30 -0
  41. data/app/views/concen/sessions/new.html.haml +12 -0
  42. data/app/views/concen/statuses/_server.html.haml +19 -0
  43. data/app/views/concen/statuses/show.html.haml +18 -0
  44. data/app/views/concen/traffics/_pages.html.haml +5 -0
  45. data/app/views/concen/traffics/_referrals.html.haml +9 -0
  46. data/app/views/concen/traffics/show.html.haml +30 -0
  47. data/app/views/concen/users/_form.html.haml +29 -0
  48. data/app/views/concen/users/_password_reset.html.haml +0 -0
  49. data/app/views/concen/users/_settings.html.haml +15 -0
  50. data/app/views/concen/users/edit.html.haml +9 -0
  51. data/app/views/concen/users/index.html.haml +32 -0
  52. data/app/views/concen/users/new.html.haml +4 -0
  53. data/app/views/concen/users/new_invite.html.haml +15 -0
  54. data/app/views/concen/users/new_reset_password.html.haml +15 -0
  55. data/app/views/concen/visits/visit_recorder_js.erb +13 -0
  56. data/app/views/layouts/concen/_additional_header_links.haml +0 -0
  57. data/app/views/layouts/concen/_header.html.haml +18 -0
  58. data/app/views/layouts/concen/_iphone.html.haml +6 -0
  59. data/app/views/layouts/concen/application.html.haml +48 -0
  60. data/app/views/layouts/concen/maintenance.html.haml +0 -0
  61. data/config/routes.rb +64 -0
  62. data/lib/concen.rb +11 -0
  63. data/lib/concen/engine.rb +14 -0
  64. data/lib/concen/railties/page.rake +12 -0
  65. data/lib/concen/railties/setup.rake +23 -0
  66. data/lib/concen/version.rb +3 -0
  67. metadata +246 -0
@@ -0,0 +1,25 @@
1
+ module Concen
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery
4
+
5
+ layout "concen/application"
6
+
7
+ before_filter :set_concen
8
+
9
+ helper_method :current_concen_user, :authenticate_concen_user
10
+
11
+ protected
12
+
13
+ def set_concen
14
+ @concen = true
15
+ end
16
+
17
+ def current_concen_user
18
+ @current_concen_user ||= User.where(:auth_token => cookies[:auth_token]).first if cookies[:auth_token]
19
+ end
20
+
21
+ def authenticate_concen_user
22
+ redirect_to concen_signin_path unless current_concen_user
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,75 @@
1
+ module Concen
2
+ class GridFilesController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ def new
6
+ @page = Page.find(params[:page_id])
7
+ @grid_file = @page.grid_files.build
8
+ end
9
+
10
+ def create
11
+ @page = Page.find(params[:page_id])
12
+ @grid_file = @page.grid_files.build
13
+ filename = params[:filename]
14
+ if ["css", "js"].include?(params[:file_type])
15
+ unless MIME::Types.type_for(filename).first.to_s.include?(params[:file_type])
16
+ filename << "." + params[:file_type]
17
+ end
18
+ end
19
+ if @grid_file.store("", filename)
20
+ content = render_to_string(:partial => "concen/pages/files")
21
+ render :json => {:success => true, :content => content}
22
+ else
23
+ render :json => {:success => false}
24
+ end
25
+ end
26
+
27
+ def edit
28
+ @page = Page.find(params[:page_id])
29
+ @grid_file = @page.grid_files.find(params[:id])
30
+ end
31
+
32
+ def update
33
+ @page = Page.find(params[:page_id])
34
+ @grid_file = @page.grid_files.find(params[:id])
35
+ if @grid_file.store(params[:concen_grid_file_page], @grid_file.original_filename)
36
+ redirect_to edit_concen_page_grid_file_path(@page, @grid_file)
37
+ else
38
+ render :edit
39
+ end
40
+ end
41
+
42
+ def destroy
43
+ @page = Page.find(params[:page_id])
44
+ @grid_file = @page.grid_files.find(params[:id])
45
+ respond_to do |format|
46
+ if @grid_file.destroy
47
+ format.html { redirect_to edit_concen_page_path(@page) }
48
+ format.json { render :json => {:success => true} }
49
+ else
50
+ format.html { redirect_to edit_concen_page_path(@page) }
51
+ format.json { render :json => {:success => false} }
52
+ end
53
+ end
54
+ end
55
+
56
+ def upload
57
+ # logger.info { "----#{env['rack.input']}" }
58
+ # logger.info { "----#{env['HTTP_X_FILE_NAME']}" }
59
+ # logger.info { "----#{env['CONTENT_TYPE']}" }
60
+ @page = Page.find(params[:page_id])
61
+ @grid_file = @page.grid_files.build
62
+ if env["rack.input"]
63
+ file = env["rack.input"]
64
+ filename = CGI::unescape(env["HTTP_X_FILE_NAME"])
65
+ else
66
+ file = params[:qqfile].read
67
+ filename = params[:qqfile].original_filename
68
+ end
69
+ if @grid_file.store(file, filename)
70
+ content = render_to_string(:partial => "concen/pages/files")
71
+ render :json => {:success => true, :content => content}
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,95 @@
1
+ module Concen
2
+ class PagesController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ before_filter :authenticate_concen_user
6
+
7
+ def index
8
+ @page_title = "Pages"
9
+ @page = Page.where(:level => 0).first
10
+ end
11
+
12
+ def new
13
+ if params[:parent_id]
14
+ @page = Page.find(params[:parent_id]).children.build
15
+ else
16
+ @page = Page.new
17
+ end
18
+ @page.level = params[:level].to_i if params[:level]
19
+ end
20
+
21
+ def create
22
+ @page = Page.new(params[:concen_page])
23
+ @page.authors = [current_concen_user.username]
24
+ if @page.save
25
+ redirect_to(edit_concen_page_path(@page), :notice => "Page was successfully created.")
26
+ else
27
+ render :new
28
+ end
29
+ end
30
+
31
+ def edit
32
+ @page = Page.find(params[:id])
33
+ unless current_concen_user.full_control || @page.authors_as_user.include?(current_concen_user)
34
+ flash[:notice] = "Only author can edit page."
35
+ redirect_to concen_pages_path
36
+ end
37
+ end
38
+
39
+ def update
40
+ @page = Page.find(params[:id])
41
+ if current_concen_user.full_control || @page.authors_as_user.include?(current_concen_user)
42
+ if @page.update_attributes(params[:concen_page])
43
+ redirect_to(edit_concen_page_path(@page), :notice => "Page was successfully created.")
44
+ else
45
+ render :edit
46
+ end
47
+ else
48
+ render :edit, :notice => "Only author can modify page content."
49
+ end
50
+ end
51
+
52
+ def destroy
53
+ if current_concen_user.full_control || @page.authors_as_user.include?(current_concen_user)
54
+ @page = Page.find(params[:id])
55
+ @page.destroy
56
+ redirect_to concen_pages_path
57
+ else
58
+ flash[:notice] = "Only author can delete page."
59
+ redirect_to concen_pages_path
60
+ end
61
+ end
62
+
63
+ def sort
64
+ if params[:page]
65
+ if current_concen_user.full_control
66
+ child_count = {}
67
+ params[:page].each do |key, value|
68
+ if value == "root"
69
+ root = Page.find(key)
70
+ root.parent_id = nil
71
+ root.level = 0
72
+ root.save
73
+ else
74
+ child = Page.find(key)
75
+ parent = Page.find(value)
76
+ child.parent_id = parent.id
77
+ child.level = parent.level + 1
78
+ if child_count[value]
79
+ child.position = child_count[value] + 1
80
+ child_count[value] += 1
81
+ else
82
+ child.position = 1
83
+ child_count[value] = 1
84
+ end
85
+ child.save
86
+ end
87
+ end
88
+ render :json => {:success => true}
89
+ else
90
+ render :json => {:success => false, :message => "Only user with full control can sort pages."}
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,35 @@
1
+ module Concen
2
+ class PerformancesController < ApplicationController
3
+ def show
4
+ @page_title = "Performance"
5
+ end
6
+
7
+ def responses
8
+ @stats = {}
9
+ @stats[:total_runtime] = Response.where(:created_at.gte => Time.now - 1.hour).asc(:created_at).map do |response|
10
+ [(response.created_at.utc.to_f + response.created_at.utc_offset)*1000, response.total_runtime]
11
+ end
12
+ @stats[:view_runtime] = Response.where(:created_at.gte => Time.now - 1.hour).asc(:created_at).map do |response|
13
+ if response.respond_to?("view_runtime")
14
+ [(response.created_at.utc.to_f + response.created_at.utc_offset)*1000, response.view_runtime]
15
+ end
16
+ end
17
+ @stats[:mongo_runtime] = Response.where(:created_at.gte => Time.now - 1.hour).asc(:created_at).map do |response|
18
+ if response.respond_to?("mongo_runtime")
19
+ [(response.created_at.utc.to_f + response.created_at.utc_offset)*1000, response.mongo_runtime]
20
+ end
21
+ end
22
+
23
+ respond_to do |format|
24
+ format.json { render :json => @stats }
25
+ end
26
+ end
27
+
28
+ def runtimes
29
+ @runtimes_stats = Response.aggregate_average_runtime(:type => params[:type])
30
+ respond_to do |format|
31
+ format.html { render :partial => "concen/performances/runtimes" }
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,30 @@
1
+ module Concen
2
+ class SessionsController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ def new
6
+ if User.all.any?
7
+ render
8
+ else
9
+ redirect_to new_concen_user_path
10
+ end
11
+ end
12
+
13
+ def create
14
+ user = User.where(:username => /#{params[:username]}/i).first
15
+
16
+ if user && user.authenticate(params[:password])
17
+ cookies.permanent[:auth_token] = user.auth_token
18
+ redirect_to root_path, :notice => "You have successfully signed in!"
19
+ else
20
+ flash.now.alert = "Invalid email or password"
21
+ render "new"
22
+ end
23
+ end
24
+
25
+ def destroy
26
+ cookies.delete(:auth_token)
27
+ redirect_to root_path, :notice => "You have successfully signed out!"
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,63 @@
1
+ module Concen
2
+ class StatusesController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ before_filter :authenticate_concen_user
6
+
7
+ def show
8
+ @page_title = "Status"
9
+ render
10
+ end
11
+
12
+ def counts
13
+ respond_to do |format|
14
+ format.json {
15
+ render :json => {:pages => Page.count, :users => User.count}
16
+ }
17
+ end
18
+ end
19
+
20
+ def server
21
+ processor_stat = []
22
+ memory_stat = []
23
+ @server_stats = {}
24
+ if RUBY_PLATFORM.downcase.include?("darwin")
25
+ top = `top -l 1 -pid 0`.split(/\n+/)
26
+ if top.present?
27
+ processor_stat = top[3].scan(/[0-9]+\.\d+/)
28
+ memory_stat = top[6].scan(/[0-9]\d+/)
29
+ @server_stats = {
30
+ :processor => {:user => processor_stat[0], :sys => processor_stat[1], :idle => processor_stat[2]},
31
+ :memory => {:wired => memory_stat[0], :active => memory_stat[1], :inactive => memory_stat[2], :used => memory_stat[3], :free => memory_stat[4]}
32
+ }
33
+ end
34
+ elsif RUBY_PLATFORM.downcase.include?("linux")
35
+ top = `top -b -n 1 -p 0`.split(/\n+/)
36
+ if top.present?
37
+ processor_stat = top[2].scan(/[0-9]+\.\d+/)
38
+ memory_stat = top[3].scan(/[0-9]\d+/)
39
+ @server_stats = {
40
+ :processor => {:user => processor_stat[0], :sys => processor_stat[1], :idle => processor_stat[3]},
41
+ :memory => {:total => memory_stat[0].to_i/1024, :used => memory_stat[1].to_i/1024, :free => memory_stat[2].to_i/1024}
42
+ }
43
+ end
44
+ end
45
+ uptime_array = `uptime`.split("up")[1].strip.split("user")[0].split(","); uptime_array.delete_at(uptime_array.length - 1)
46
+ if uptime_array.present?
47
+ uptime = uptime_array.join(",")
48
+ @server_stats[:uptime] = uptime
49
+ end
50
+
51
+ @mongodb_stats = Mongoid.database.stats
52
+
53
+ begin
54
+ @mongodb_grid_fs_stats = Mongoid.database.collection("fs.chunks").stats["storageSize"]
55
+ rescue
56
+ @mongodb_grid_fs_stats = 0
57
+ end
58
+ respond_to do |format|
59
+ format.html { render :partial => "concen/statuses/server" }
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,43 @@
1
+ module Concen
2
+ class TrafficsController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ before_filter :authenticate_concen_user
6
+
7
+ # Supports OS X and Linux, require top command.
8
+ # @current_month_visits = Statistic.visits_for_current :month
9
+ # Real time visits
10
+ # Historical statistics
11
+ # Month: visits
12
+ def show
13
+ @page_title = "Traffic"
14
+ end
15
+
16
+ def visits_counts
17
+ if @stats = Visit::Page.aggregate_count_by_time(:hour => params[:hour], :precision => "millisecond")
18
+ # Readjust timestamp because flot graph doesn't handle time zone.
19
+ @stats.map! do |s|
20
+ time = Time.zone.at s[0]/1000
21
+ [(time.utc.to_i + time.utc_offset)*1000, s[1]]
22
+ end
23
+ end
24
+ respond_to do |format|
25
+ format.json { render :json => @stats }
26
+ end
27
+ end
28
+
29
+ def pages
30
+ @pages_stats = Visit::Page.aggregate_count_by_url(:limit => 6)
31
+ respond_to do |format|
32
+ format.html { render :partial => "concen/traffics/pages" }
33
+ end
34
+ end
35
+
36
+ def referrals
37
+ @referrals_stats = Visit::Referral.aggregate_count_by_domain(:limit => 6)
38
+ respond_to do |format|
39
+ format.html { render :partial => "concen/traffics/referrals" }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,118 @@
1
+ module Concen
2
+ class UsersController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ before_filter :authenticate_concen_user, :except => [:new, :edit, :update, :create, :new_reset_password, :reset_password]
6
+
7
+ def index
8
+ @page_title = "Users"
9
+ @users = User.all
10
+ end
11
+
12
+ def new
13
+ if User.all.any?
14
+ redirect_to root_path
15
+ else
16
+ @user = User.new
17
+ end
18
+ end
19
+
20
+ def create
21
+ if !User.all.any? || (current_concen_user && current_concen_user.full_control)
22
+ @user = User.new(params[:concen_user])
23
+ @user.full_control = true
24
+ if @user.save
25
+ redirect_to(concen_users_path, :notice => "User was successfully created.")
26
+ else
27
+ render :new
28
+ end
29
+ end
30
+ end
31
+
32
+ def edit
33
+ if params[:password_reset_token]
34
+ @user = User.where(:password_reset_token => params[:password_reset_token]).first
35
+ elsif params[:invitation_token]
36
+ @user = User.where(:invitation_token => params[:invitation_token]).first
37
+ else
38
+ @page_title = "Settings"
39
+ @user = current_concen_user
40
+ end
41
+ redirect_to concen_signin_path unless @user
42
+ end
43
+
44
+ def update
45
+ if params[:concen_user][:password_reset_token]
46
+ @user = User.where(:password_reset_token => params[:concen_user][:password_reset_token]).first
47
+ authenticated = true if @user.password_reset_sent_at > 2.hours.ago
48
+ elsif params[:concen_user][:invitation_token]
49
+ @user = User.where(:invitation_token => params[:concen_user][:invitation_token]).first
50
+ authenticated = true if @user.invitation_sent_at > 24.hours.ago
51
+ else
52
+ @user = current_concen_user
53
+ authenticated = true if @user.authenticate(params[:concen_user].delete(:current_password))
54
+ end
55
+ if @user && authenticated
56
+ if @user.update_attributes(params[:concen_user])
57
+ redirect_to edit_concen_user_path @user
58
+ else
59
+ render :edit
60
+ end
61
+ else
62
+ flash.now.alert = "Invalid password."
63
+ render :edit
64
+ end
65
+ end
66
+
67
+ def destroy
68
+ if current_concen_user.full_control
69
+ @user = User.find(params[:id])
70
+ @user.destroy
71
+ redirect_to concen_users_path
72
+ else
73
+ flash[:notice] = "Only user with full control can delete a user."
74
+ redirect_to concen_users_path
75
+ end
76
+ end
77
+
78
+ def toggle_attribute
79
+ respond_to do |format|
80
+ if current_concen_user.full_control
81
+ @user = User.find(params[:id])
82
+ @user.write_attribute(params[:attribute].to_sym, !@user.read_attribute(params[:attribute].to_sym))
83
+ @user.save
84
+ format.json { render :json => {:success => true} }
85
+ else
86
+ format.json { render :json => {:success => false, :message => "Only user with full control can toggle attribute."} }
87
+ end
88
+ end
89
+ end
90
+
91
+ def new_invite
92
+ if current_concen_user.full_control
93
+ @user = User.new
94
+ else
95
+ redirect_to(concen_users_path, :notice => "Only user with full control can invite.")
96
+ end
97
+ end
98
+
99
+ def invite
100
+ if current_concen_user.full_control
101
+ @user = User.send_invitation params[:concen_user][:email]
102
+ redirect_to concen_users_path, :notice => "Invitation has been sent."
103
+ else
104
+ redirect_to concen_users_path, :notice => "Only user with full control can invite."
105
+ end
106
+ end
107
+
108
+ def new_reset_password
109
+ @user = User.new
110
+ end
111
+
112
+ def reset_password
113
+ @user = User.where(:email => params[:concen_user][:email]).first
114
+ @user.send_password_reset
115
+ redirect_to concen_signin_path, :notice => "Password reset instruction has been sent."
116
+ end
117
+ end
118
+ end