Initial import

This commit is contained in:
2008-03-02 16:04:34 -03:00
commit 5e4951fa47
798 changed files with 59730 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
require 'yaml'
class ApplicationController < ActionController::Base
include AuthenticationSystem
before_filter :startup
around_filter :set_timezone
# Força o login para algumas áreas do sistema
before_filter :require_login, :only => [ :edit, :new, :create, :update, :delete, :destroy, :download ]
protected
def rescue_action(exception)
# Acesso negado
if exception.is_a?(AccessDenied)
respond_to do |format|
format.html { render :file => "#{RAILS_ROOT}/public/401.html", :status => 401 }
format.xml { head 401 }
end
# Erro de validacao
elsif exception.is_a?(ActiveRecord::RecordInvalid)
respond_to do |format|
format.html { render :action => (exception.record.new_record? ? 'new' : 'edit') }
format.xml { render :xml => exception.record.errors, :status => :unprocessable_entity }
end
# Registro nao encontrado
elsif (RAILS_ENV == 'production') and exception.is_a?(ActiveRecord::RecordNotFound)
respond_to do |format|
format.html { render :file => "#{RAILS_ROOT}/public/404.html", :status => 404 }
format.xml { head 404 }
end
# Outras excecoes
else
super
end
end
def set_timezone
#TzTime.zone = session[:user].tz
TzTime.zone = TZInfo::Timezone.get("America/Fortaleza")
yield
TzTime.reset!
end
def startup
if session[:user_id]
@current_user = User.find(session[:user_id])
else
login_by_token
end
@color = App.default_color
@color = @current_user.pref_color if @current_user
@color = params[:color].to_i if params[:color]
end
end

View File

@@ -0,0 +1,105 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class AttachmentsController < ApplicationController
#verify :method => :post, :only => [ :destroy, :create, :update ],
# :redirect_to => { :controller => 'courses', :action => :show }
before_filter :find_attachment, :except => [ :undelete ]
after_filter :cache_sweep, :only => [ :create, :update, :destroy ]
def show
end
def new
end
def create
@attachment.course_id = @course.id
@attachment.description = params[:attachment][:description]
unless params[:attachment][:file].kind_of?(String)
@attachment.file = params[:attachment][:file]
@attachment.file_name = params[:attachment][:file].original_filename
@attachment.content_type = params[:attachment][:file].content_type
end
# Verifica se o arquivo ja esta associado a outro anexo
#file_path = "#{RAILS_ROOT}/public/upload/#{@course.id}/#{@attachment.file_name}"
#@attachment.errors.add("file", "already exists") if File.exists?(file_path)
if @attachment.save
AttachmentCreateLogEntry.create!(:target_id => @attachment.id, :user => @current_user, :course => @course)
flash[:notice] = 'Attachment created'[]
redirect_to :action => 'show', :id => @attachment.id
else
render :action => 'new'
end
end
def edit
end
def update
@attachment.description = params[:attachment][:description]
unless params[:attachment][:file].kind_of?(String)
@attachment.file = params[:attachment][:file]
@attachment.file_name = params[:attachment][:file].original_filename
@attachment.content_type = params[:attachment][:file].content_type
end
if @attachment.save
AttachmentEditLogEntry.create!(:target_id => @attachment.id, :user => @current_user, :course => @course)
@attachment.last_modified = Time.now.utc
flash[:notice] = 'Attachment updated'[]
redirect_to :action => 'show', :id => @attachment.id
else
render :action => 'edit'
end
end
def destroy
@attachment.destroy
flash[:notice] = 'Attachment removed'[]
flash[:undo] = undelete_course_attachment_url(@course, @attachment)
AttachmentDeleteLogEntry.create!(:target_id => @attachment.id, :user => @current_user, :course => @course)
redirect_to :controller => 'courses', :action => 'show', :id => @course
end
def download
send_file("#{RAILS_ROOT}/public/upload/#{@course.id}/#{@attachment.id}",
:filename => @attachment.file_name,
:type => @attachment.content_type,
:disposition => 'attachment',
:streaming => 'true')
end
def undelete
@attachment = Attachment.find_with_deleted(params[:id])
@attachment.update_attribute(:deleted_at, nil)
flash[:notice] = 'Attachment restored'[]
AttachmentRestoreLogEntry.create!(:target_id => @attachment.id, :user => @current_user, :course => @course)
redirect_to course_attachment_url(@attachment.course, @attachment)
end
protected
def find_attachment
params[:course_id] = Course.find_by_short_name(params[:course_id]).id if !params[:course_id].is_numeric? and !Course.find_by_short_name(params[:course_id]).nil?
@course = Course.find(params[:course_id])
@attachment = params[:id] ? @course.attachments.find(params[:id]) : Attachment.new
end
def cache_sweep
expire_fragment(:controller => 'courses', :action => 'show')
end
end

View File

@@ -0,0 +1,112 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class CoursesController < ApplicationController
before_filter :find_course, :except => [ :index ]
before_filter :require_admin, :only => [ :new, :create, :edit, :update, :destroy ]
before_filter :require_login, :only => [ :enroll, :unenroll ]
after_filter :cache_sweep, :only => [ :create, :update, :destroy ]
def index
@courses = Course.find(:all,
:order => 'period asc, full_name asc',
:conditions => (logged_in? and !@current_user.courses.empty? ? [ 'id not in (?)', @current_user.courses] : ''))
respond_to do |format|
format.html
format.xml { render :xml => @courses }
end
end
def show
respond_to do |format|
format.html
format.xml { render :xml => @course }
end
end
def new
end
def create
@course.save!
flash[:notice] = 'Course created'[]
respond_to do |format|
format.html { redirect_to course_path(@course) }
format.xml { head :created, :location => formatted_course_url(@course, :xml) }
end
end
def edit
end
def update
@course.attributes = params[:course]
@course.save!
flash[:notice] = 'Course updated'[]
respond_to do |format|
format.html { redirect_to course_path(@course) }
format.xml { head :ok }
end
end
def destroy
@course.destroy
flash[:notice] = 'Course removed'[]
respond_to do |format|
format.html { redirect_to courses_path }
format.xml { head :ok }
end
end
def enroll
@current_user.courses << @course
flash[:highlight] = @course.id
respond_to do |format|
format.html { redirect_to courses_path }
format.xml { head :ok }
end
end
def unenroll
@current_user.courses.delete(@course)
flash[:highlight] = @course.id
respond_to do |format|
format.html { redirect_to courses_path }
format.xml { head :ok }
end
end
protected
def find_course
params[:id] = Course.find_by_short_name(params[:id]).id if params[:id] and !params[:id].is_numeric? and !Course.find_by_short_name(params[:id]).nil?
@course = params[:id] ? Course.find(params[:id]) : Course.new(params[:course])
end
def require_admin
raise AccessDenied.new unless admin?
end
def cache_sweep
expire_fragment(:action => 'show', :part => 'right')
expire_fragment(:action => 'show', :part => 'left')
expire_fragment(:action => 'show')
expire_fragment(:action => 'index')
end
end

View File

@@ -0,0 +1,118 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class EventsController < ApplicationController
before_filter :find_event, :except => [ :mini_calendar, :undelete ]
after_filter :cache_sweep, :only => [ :create, :update, :destroy ]
def index
@events = @course.events
respond_to do |format|
format.html
format.xml { render :xml => @events }
format.ics { response.content_type = Mime::ICS; render :text => Event.to_ical([@course]) }
end
end
def show
respond_to do |format|
format.html
format.xml { render :xml => @event }
end
end
def new
end
def create
@event.course_id = @course.id
@event.created_by = session[:user_id]
@event.save!
flash[:notice] = 'Event created'[]
EventCreateLogEntry.create!(:target_id => @event.id, :user => @current_user, :course => @course)
respond_to do |format|
format.html { redirect_to course_event_path(@course, @event) }
format.xml { head :created, :location => formatted_course_event_url(@course, @event, :xml) }
end
end
def edit
end
def update
@event.attributes = params[:event]
@event.save!
flash[:notice] = 'Event updated'[]
EventEditLogEntry.create!(:target_id => @event.id, :user => @current_user, :course => @course)
respond_to do |format|
format.html { redirect_to course_event_path(@course, @event) }
format.xml { head :created, :location => formatted_course_event_url(@course, @event, :xml) }
end
end
def destroy
@event.destroy
flash[:notice] = 'Event removed'[]
flash[:undo] = undelete_course_event_url(@course, @event)
EventDeleteLogEntry.create!(:target_id => @event.id, :user => @current_user, :course => @course)
respond_to do |format|
format.html { redirect_to course_events_path(@course) }
format.xml { head :ok }
end
end
# Exibe o widget do calendario
def mini_calendar
@course = Course.find(params[:id])
@year = params[:year].to_i
@month = params[:month].to_i
@ajax = true
@events = @course.events
render :template => 'widgets/calendario', :layout => false
end
def undelete
@event = Event.find_with_deleted(params[:id])
@event.update_attribute(:deleted_at, nil)
flash[:notice] = "Event restored"[]
EventRestoreLogEntry.create!(:target_id => @event.id, :user => @current_user, :course => @course)
respond_to do |format|
format.html { redirect_to course_event_url(@event.course, @event) }
end
end
protected
def find_event
params[:course_id] = Course.find_by_short_name(params[:course_id]).id if !params[:course_id].is_numeric? and !Course.find_by_short_name(params[:course_id]).nil?
@course = Course.find(params[:course_id])
@event = params[:id] ? @course.events.find(params[:id]) : Event.new(params[:event])
end
def cache_sweep
expire_fragment(:controller => 'courses', :action => 'show', :part => 'right')
expire_fragment(:action => 'index')
end
end

View File

@@ -0,0 +1,39 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class LogController < ApplicationController
before_filter :find_course
def index
@log_entries = @course.log_entries.find(:all, :limit => 50) #.paginate(:page => params[:page], :per_page => 30)
respond_to do |format|
format.html
end
end
def undo
@log_entry = LogEntry.find(params[:id])
@log_entry.undo!(@current_user)
respond_to do |format|
format.html { redirect_to course_log_url }
end
end
protected
def find_course
params[:course_id] = Course.find_by_short_name(params[:course_id]).id if !params[:course_id].is_numeric? and !Course.find_by_short_name(params[:course_id]).nil?
@course = Course.find(params[:course_id])
end
end

View File

@@ -0,0 +1,111 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class NewsController < ApplicationController
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
#verify :method => :post, :only => [ :destroy, :create, :update ],
# :redirect_to => { :action => :list }
before_filter :find_new, :except => [ :undelete ]
after_filter :cache_sweep, :only => [ :create, :update, :destroy ]
def index
@news = @course.news
respond_to do |format|
format.html
format.xml { render :xml => @news }
format.rss { response.content_type = Mime::RSS }
end
end
def show
respond_to do |format|
format.html
format.xml { render :xml => @news }
end
end
def new
end
def create
@news.receiver_id = @course.id
@news.sender_id = session[:user_id]
@news.timestamp = Time.now.utc
@news.save!
flash[:notice] = 'News created'[]
NewsCreateLogEntry.create!(:target_id => @news.id, :user => @current_user, :course => @course)
respond_to do |format|
format.html { redirect_to course_news_path(@course, @news) }
format.xml { head :created, :location => formatted_course_news_url(@course, @news, :xml) }
end
end
def edit
end
def update
@news.attributes = params[:news]
@news.save!
flash[:notice] = 'News updated'[]
NewsEditLogEntry.create!(:target_id => @news.id, :user => @current_user, :course => @course)
respond_to do |format|
format.html { redirect_to course_news_path(@course, @news) }
format.xml { head :created, :location => formatted_course_news_url(@course, @news, :xml) }
end
end
def destroy
@news.destroy
flash[:notice] = 'News removed'[]
flash[:undo] = undelete_course_news_url(@course, @news)
NewsDeleteLogEntry.create!(:target_id => @news.id, :user => @current_user, :course => @course)
respond_to do |format|
format.html { redirect_to course_news_index_path(@course) }
format.xml { head :ok }
end
end
def undelete
@news = News.find_with_deleted(params[:id])
@news.update_attribute(:deleted_at, nil)
flash[:notice] = "News restored"[]
NewsRestoreLogEntry.create!(:target_id => @news.id, :user => @current_user, :course => @course)
respond_to do |format|
format.html { redirect_to course_news_url(@news.course, @news) }
end
end
protected
def find_new
params[:course_id] = Course.find_by_short_name(params[:course_id]).id if !params[:course_id].is_numeric? and !Course.find_by_short_name(params[:course_id]).nil?
@course = Course.find(params[:course_id])
@news = params[:id] ? @course.news.find(params[:id]) : News.new(params[:news])
end
def cache_sweep
expire_fragment(:controller => 'courses', :action => 'show', :part => 'right')
expire_fragment(:action => 'index')
end
end

View File

@@ -0,0 +1,25 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class StylesheetsController < ApplicationController
layout nil
caches_page :wiki
before_filter :set_headers
private
def set_headers
response.content_type = Mime::CSS
end
end

View File

@@ -0,0 +1,143 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class UsersController < ApplicationController
before_filter :find_user, :only => [ :show, :edit, :update, :destroy, :signup ]
before_filter :require_login, :only => [ :settings ]
before_filter :require_admin, :only => [ :edit, :update, :destroy ]
def index
@users = User.find(:all, :order => 'name')
respond_to do |format|
format.html
format.xml { render :xml => @users }
end
end
def show
respond_to do |format|
format.html
format.xml { render :xml => @user }
end
end
def edit
end
def update
raise AccessDenied.new unless (params[:user][:login] == @user.login)
raise AccessDenied.new unless (params[:user][:admin].nil? or @current_user.admin?)
@user.admin = !params[:user][:admin].nil?
@user.attributes = params[:user]
@user.save!
flash[:notice] = 'User account updated'[]
respond_to do |format|
format.html { redirect_to user_path(@user) }
format.xml { head :ok }
end
end
def destroy
@user.destroy
flash[:notice] = 'User account removed'[]
respond_to do |format|
format.html { redirect_to users_path }
format.xml { head :ok }
end
end
def signup
if request.post?
begin
@user.last_seen = Time.now.utc
@user.save!
setup_session(@user)
flash[:message] = 'User account created'[]
redirect_to user_path(@user)
rescue ActiveRecord::RecordInvalid
flash[:warning] = 'Não foi possível cadastrar a conta.'
end
end
end
def settings
@user = @current_user
if request.post?
@user.attributes = params[:user]
@user.save!
@color = @user.pref_color
flash[:message] = 'Settings updated'[]
redirect_to '/'
end
end
def login
if request.post?
@user = User.find_by_login_and_pass(params[:user][:login], params[:user][:password])
if !@user.nil?
setup_session(@user, (params[:remember_me] == "1"))
@user.update_attribute(:last_seen, Time.now.utc)
flash[:message] = 'Welcome back, {u}'[:login_success, @user.login]
redirect_to_stored
else
flash[:warning] = 'Login failed'
end
end
end
def logout
destroy_session
flash[:message] = 'You have logged out'[:logout_success]
redirect_to '/'
end
def dashboard
@news = []
@events = []
unless @current_user.courses.empty?
@news = News.find(:all, :conditions => [ 'receiver_id in (?)', @current_user.courses ],
:order => 'timestamp desc')
@events = Event.find(:all, :conditions => [ 'course_id in (?) and (date > ?) and (date < ?)',
@current_user.courses, 1.day.ago, 14.days.from_now ], :order => 'date, time')
end
end
# def forgot_password
# if request.post?
# u = User.find_by_email(params[:user][:email])
# if u and u.send_new_password
# flash[:message] = "Uma nova senha foi enviada para o seu email."
# redirect_to :action=>'login'
# else
# flash[:warning] = "Não foi possível gerar uma nova senha."
# end
# end
# end
#Funções do Fórum
protected
def find_user
params[:id] = User.find_by_login(params[:id]).id if params[:id] and !params[:id].is_numeric?
@user = params[:id] ? User.find(params[:id]) : User.new(params[:user])
end
def require_admin
raise AccessDenied.new unless admin? or @current_user == @user
end
end

View File

@@ -0,0 +1,164 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class WikiController < ApplicationController
verify :params => :text, :only => :preview, :redirect_to => { :action => :show }
verify :params => [:from, :to], :only => :diff, :redirect_to => { :action => :versions }
after_filter :cache_sweep, :only => [ :create, :update, :destroy ]
before_filter :find_wiki, :except => [ :preview, :undelete ]
before_filter :require_login, :only => [ :new, :create, :edit, :update, :destroy,
:move_up, :move_down, :undelete ]
def index
@wiki_pages = @course.wiki_pages
respond_to do |format|
format.html { redirect_to course_url(@course) }
format.xml { render :xml => @wiki_pages }
end
end
def new
end
def create
@wiki_page.version = 1
@wiki_page.user_id = session[:user_id]
@wiki_page.course_id = @course.id
@wiki_page.description = "Nova página"
@wiki_page.save!
flash[:notice] = "Wiki page created"[]
WikiCreateLogEntry.create!(:target_id => @wiki_page.id, :user => @current_user, :course => @course)
respond_to do |format|
format.html { redirect_to course_wiki_path(@course, @wiki_page) }
format.xml { head :created, :location => formatted_course_wiki_url(@course, @wiki_page, :xml) }
end
end
def show
@wiki_page.revert_to(params[:version]) if params[:version]
respond_to do |format|
format.html
format.xml { render :xml => @wiki_page }
format.text { render :text => "# #{@wiki_page.title}\n\n#{@wiki_page.content}" }
end
end
def edit
@wiki_page.revert_to(params[:version]) if params[:version]
@wiki_page.description = params[:description] || ""
end
def update
@wiki_page.attributes = params[:wiki_page]
@wiki_page.user_id = session[:user_id]
@wiki_page.course_id = @course.id
dirty = @wiki_page.dirty?
@wiki_page.save!
WikiEditLogEntry.create!(:target_id => @wiki_page.id, :user => @current_user, :course => @course, :version => @wiki_page.version) if dirty
flash[:notice] = "Wiki page updated"[]
respond_to do |format|
format.html { redirect_to course_wiki_path(@course, @wiki_page) }
format.xml { head :created, :location => formatted_course_wiki_url(@course, @wiki_page, :xml) }
end
end
def destroy
@wiki_page.destroy
flash[:notice] = "Wiki page removed"[]
flash[:undo] = url_for(:course_id => @course, :id => @wiki_page.id, :action => 'undelete')
WikiDeleteLogEntry.create!(:target_id => @wiki_page.id, :user => @current_user, :course => @course)
respond_to do |format|
format.html { redirect_to course_url(@course) }
format.xml { head :ok }
end
end
def versions
@history_to = params[:to] || @wiki_page.versions.count
@history_from = params[:from] || @wiki_page.versions.count - 1
@offset = params[:offset] || 0
respond_to do |format|
format.html
format.xml
end
end
def preview
@text = params[:text]
render :text => BlueCloth.new(@text).to_html
end
def diff
@to = WikiPage.find_version(params[:id], params[:to])
@from = WikiPage.find_version(params[:id], params[:from])
@diff = WikiPage.diff(@from, @to)
end
def move_up
@wiki_page.move_higher
@wiki_page.save
flash[:highlight] = @wiki_page.id
respond_to do |format|
format.html { redirect_to course_url(@course) }
end
end
def move_down
@wiki_page.move_lower
@wiki_page.save
flash[:highlight] = @wiki_page.id
respond_to do |format|
format.html { redirect_to course_url(@course) }
end
end
def undelete
@wiki_page = WikiPage.find_with_deleted(params[:id])
@wiki_page.update_attribute(:deleted_at, nil)
flash[:notice] = "Wiki page restored"[]
WikiRestoreLogEntry.create!(:target_id => @wiki_page.id, :user => @current_user, :course => @wiki_page.course)
respond_to do |format|
format.html { redirect_to course_wiki_url(@wiki_page.course, @wiki_page) }
end
end
protected
def find_wiki
params[:course_id] = Course.find_by_short_name(params[:course_id]).id if !params[:course_id].is_numeric? and !Course.find_by_short_name(params[:course_id]).nil?
@course = Course.find(params[:course_id])
params[:id] = @course.wiki_pages.find_by_title(params[:id]).id if params[:id] and !params[:id].is_numeric? and !@course.wiki_pages.find_by_title(params[:id]).nil?
@wiki_page = params[:id] ? @course.wiki_pages.find(params[:id]) : WikiPage.new(params[:wiki_page])
end
def cache_sweep
expire_fragment(:controller => 'courses', :action => 'show')
expire_fragment(:action => 'show')
end
end

View File

@@ -0,0 +1,65 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
require 'digest/md5'
module ApplicationHelper
# Converte para o timezone local
def tz(time_at)
TzTime.zone.utc_to_local(time_at.utc)
end
FLASH_NAMES = [:notice, :warning, :message]
def flash_div
output = ""
for name in FLASH_NAMES
if flash[name]
output << "<div id='validation' class='validation #{name}' style='display: none'>#{flash[name]}"
output << ". " + link_to("Undo"[] + "?", flash[:undo], :method => 'post') if flash[:undo]
output << "</div>"
end
end
return output
end
def logged_in?
session[:user_id]
end
def current_user
User.find(session[:user_id]) if logged_in?
end
def admin?
logged_in? and current_user.admin?
end
def wiki(text)
BlueCloth.new(text).to_html
end
def highlight(name)
return {:class => 'highlight'} if (flash[:highlight] == name)
end
def gravatar_url_for(email, size=80)
"http://www.gravatar.com/avatar.php?gravatar_id=#{Digest::MD5.hexdigest(email)}&size=#{size}&default=#{App.default_avatar}"
end
def action_icon(action_name, description, options = {}, html_options = {})
html_options.merge!({:class => 'icon', :alt => description, :title => description})
link_to(image_tag("action/#{action_name}.gif"), options, html_options)
end
end

View File

@@ -0,0 +1,15 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
module AttachmentsHelper
end

View File

@@ -0,0 +1,39 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
module CoursesHelper
def mime_class(str)
str.strip!
case str
when "application/octet-stream"
return "mime_binary"
when
"application/pdf",
"application/postscript",
"application/msword"
return "mime_document"
when "application/pdf"
return "mime_document"
when
"application/zip",
"application/x-gzip",
"application/x-gtar"
return "mime_zip"
else "mime_plain_text"
end
end
end

View File

@@ -0,0 +1,15 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
module EventsHelper
end

View File

@@ -0,0 +1,2 @@
module LogHelper
end

View File

@@ -0,0 +1,15 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
module NewsHelper
end

View File

@@ -0,0 +1,47 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
module StylesheetsHelper
def browser_is? name
name = name.to_s.strip
return true if browser_name == name
return true if name == 'mozilla' && browser_name == 'gecko'
return true if name == 'ie' && browser_name.index('ie')
return true if name == 'webkit' && browser_name == 'safari'
end
def browser_name
@browser_name ||= begin
ua = request.env['HTTP_USER_AGENT'].downcase
if ua.index('msie') && !ua.index('opera') && !ua.index('webtv')
'ie'+ua[ua.index('msie')+5].chr
elsif ua.index('gecko/')
'gecko'
elsif ua.index('opera')
'opera'
elsif ua.index('konqueror')
'konqueror'
elsif ua.index('applewebkit/')
'safari'
elsif ua.index('mozilla/')
'gecko'
end
end
end
def ie?
return browser_is?('ie')
end
end

View File

@@ -0,0 +1,15 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
module UserHelper
end

View File

@@ -0,0 +1,48 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
module WikiHelper
def format_diff(text)
last = 0
result = ""
text << "\n"
style = { '+' => 'add', '-' => 'del', ' ' => 'line' }
text.each do |line|
# Ignora o cabecalho
next if line.match(/^---/)
next if line.match(/^\+\+\+/)
# Divisao entre pedacos
if line[0].chr == '@'
result << "<tr><td class='diff_space diff_border_#{style[last.chr]}' ></td></tr>"
last = 0
else
# Verifica se mudou de contexto (add para del, linha normal para add, etc)
if line[0] != last
last = line[0] if last == 0 or line[0].chr == '+' or line[0].chr == '-'
result << "<tr><td class='diff_border_#{style[last.chr]} "
last = line[0]
else
result << "<tr><td class='"
end
result << "diff_#{style[line[0].chr]}'>" +
" #{line[1..-1]}&nbsp;</td></td>"
end
end
return "<table class='diff'>#{result}</table>"
end
end

66
app/models/attachment.rb Normal file
View File

@@ -0,0 +1,66 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
require 'fileutils.rb'
class Attachment < ActiveRecord::Base
belongs_to :course
generate_validations
acts_as_paranoid
# Atributo virtual file
def file=(new_file)
@tmp_file = new_file
self.size = new_file.size
end
# Limpa o nome do arquivo
protected
def sanitize(filename)
filename = File.basename(filename)
filename.gsub(/[^\w\.\-]/, '_')
end
# Verifica se o arquivo é válido
def validate
if @tmp_file
errors.add("file") if @tmp_file.size == 0
errors.add("file", "is too large"[]) if @tmp_file.size > App.max_upload_file_size
else
# Caso o objeto possua id, significa que ele já está no banco de dados.
# Um arquivo em branco, entao, não é inválido: significa que a pessoa só quer
# modificar a descrição, ou algo assim..
errors.add("file", "is needed"[]) if not self.id
end
end
# Salva o arquivo fisicamente no HD
def after_save
@file_path = "#{RAILS_ROOT}/public/upload/#{course.id}/#{self.id}"
FileUtils.mkdir_p(File.dirname(@file_path))
if @tmp_file
logger.debug("Saving #{self.id}")
File.open(@file_path, "wb") do |f|
f.write(@tmp_file.read)
end
end
end
# Deleta o arquivo
#def after_destroy
# @file_path = "#{RAILS_ROOT}/public/upload/#{course.id}/#{self.id}"
# File.delete(@file_path) if File.exists?(@file_path)
#end
end

56
app/models/course.rb Normal file
View File

@@ -0,0 +1,56 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class Course < ActiveRecord::Base
has_many :attachments, :order => "file_name"
has_many :wiki_pages, :order => "position"
has_many :shoutbox_messages,
:class_name => 'CourseShoutboxMessage',
:foreign_key => "receiver_id",
:order => 'id desc'
has_many :news,
:class_name => 'News',
:foreign_key => "receiver_id",
:order => 'id desc'
has_many :events, :order => "date asc, time asc"
has_many :log_entries, :order => "created_at desc"
generate_validations
validates_uniqueness_of :short_name
validates_format_of :short_name, :with => /^[^0-9]/
def after_create
App.inital_wiki_pages.each do |page_title|
wiki_page = WikiPage.new(:title => page_title, :version => 1, :content => App.initial_wiki_page_content)
self.wiki_pages << wiki_page
end
end
def after_destroy
associations = [:attachments, :wiki_pages, :shoutbox_messages, :news, :events]
associations.each do |assoc|
send("#{assoc}").each do |record|
record.destroy
end
end
end
def to_param
self.short_name
end
end

33
app/models/event.rb Normal file
View File

@@ -0,0 +1,33 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class Event < ActiveRecord::Base
acts_as_paranoid
generate_validations
def Event.to_ical(courses)
cal = Icalendar::Calendar.new
courses.each do |course|
course.events.each do |user_event|
event = Icalendar::Event.new
event.start = user_event.date
event.end = user_event.date
event.summary = "#{course.short_name}: #{user_event.title}"
event.description = user_event.description
cal.add(event)
end
end
return cal.to_ical
end
end

24
app/models/log_entry.rb Normal file
View File

@@ -0,0 +1,24 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class LogEntry < ActiveRecord::Base
belongs_to :user
belongs_to :course
def reversible?() false end
end
require 'log_entry/attachment_log_entry.rb'
require 'log_entry/event_log_entry.rb'
require 'log_entry/news_log_entry.rb'
require 'log_entry/wiki_log_entry.rb'

View File

@@ -0,0 +1,35 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class AttachmentLogEntry < LogEntry
def attachment
Attachment.find_with_deleted(target_id)
end
end
class AttachmentDeleteLogEntry < AttachmentLogEntry
def reversible?()
a = Attachment.find_with_deleted(target_id)
a.deleted_at != nil
end
def undo!(current_user)
a = Attachment.find_with_deleted(target_id)
a.update_attribute(:deleted_at, nil)
AttachmentRestoreLogEntry.create!(:target_id => a.id, :user_id => current_user.id,
:course => a.course)
end
end
class AttachmentEditLogEntry < AttachmentLogEntry; end
class AttachmentCreateLogEntry < AttachmentLogEntry; end
class AttachmentRestoreLogEntry < AttachmentLogEntry; end

View File

@@ -0,0 +1,35 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class EventLogEntry < LogEntry
def event
Event.find_with_deleted(target_id)
end
end
class EventDeleteLogEntry < EventLogEntry
def reversible?()
e = Event.find_with_deleted(target_id)
e.deleted_at != nil
end
def undo!(current_user)
e = Event.find_with_deleted(target_id)
e.update_attribute(:deleted_at, nil)
EventRestoreLogEntry.create!(:target_id => e.id, :user_id => current_user.id,
:course => e.course)
end
end
class EventEditLogEntry < EventLogEntry; end
class EventCreateLogEntry < EventLogEntry; end
class EventRestoreLogEntry < EventLogEntry; end

View File

@@ -0,0 +1,35 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class NewsLogEntry < LogEntry
def news
News.find_with_deleted(target_id)
end
end
class NewsDeleteLogEntry < NewsLogEntry
def reversible?()
n = News.find_with_deleted(target_id)
n.deleted_at != nil
end
def undo!(current_user)
n = News.find_with_deleted(target_id)
n.update_attribute(:deleted_at, nil)
NewsRestoreLogEntry.create!(:target_id => n.id, :user_id => current_user.id,
:course => n.course)
end
end
class NewsEditLogEntry < NewsLogEntry; end
class NewsCreateLogEntry < NewsLogEntry; end
class NewsRestoreLogEntry < NewsLogEntry; end

View File

@@ -0,0 +1,43 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class WikiLogEntry < LogEntry
def wiki_page
w = WikiPage.find_with_deleted(target_id)
w.revert_to(version)
return w
end
end
class WikiEditLogEntry < WikiLogEntry
validates_presence_of :version
end
class WikiDeleteLogEntry < WikiLogEntry
def reversible?()
w = WikiPage.find_with_deleted(target_id)
w.deleted_at != nil
end
def undo!(current_user)
w = WikiPage.find_with_deleted(target_id)
w.update_attribute(:deleted_at, nil)
w.position = w.course.wiki_pages.maximum(:position) + 1
w.save!
WikiRestoreLogEntry.create!(:target_id => w.id, :user_id => current_user.id,
:course => w.course)
end
end
class WikiCreateLogEntry < WikiLogEntry; end
class WikiRestoreLogEntry < WikiLogEntry; end

39
app/models/message.rb Normal file
View File

@@ -0,0 +1,39 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class Message < ActiveRecord::Base
acts_as_paranoid
belongs_to :user, :foreign_key => "sender_id"
end
class PrivateMessage < Message
end
class News < Message
validates_presence_of :title
belongs_to :course, :foreign_key => "receiver_id"
end
class ShoutboxMessage < Message
end
class CourseShoutboxMessage < ShoutboxMessage
end
class UserShoutboxMessage < ShoutboxMessage
end

View File

@@ -0,0 +1,25 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
class Notifications < ActionMailer::Base
def forgot_password(to, login, pass, sent_at = Time.now)
@subject = "Your password is ..."
@body['login']=login
@body['pass']=pass
@recipients = to
@from = 'support@yourdomain.com'
@sent_on = sent_at
@headers = {}
end
end

108
app/models/user.rb Normal file
View File

@@ -0,0 +1,108 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
require 'digest/sha1'
class User < ActiveRecord::Base
has_and_belongs_to_many :courses, :order => 'full_name'
validates_length_of :login, :within => 3..40
validates_length_of :name, :within => 3..40
validates_length_of :display_name, :within => 3..40
validates_presence_of :login, :email, :display_name
validates_uniqueness_of :login, :email, :display_name
validates_format_of :display_name, :with => /^[^0-9]/
validates_format_of :email,
:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
attr_protected :id, :salt
attr_accessor :password, :password_confirmation
has_many :shoutbox_messages,
:class_name => 'UserShoutboxMessage',
:foreign_key => "receiver_id",
:order => 'id desc'
def User.find_by_login_and_pass(login, pass)
user = find(:first, :conditions => [ "login = ?", login ])
return (!user.nil? and User.encrypt(pass, user.salt) == user.hashed_password) ? user : nil
end
def to_xml(options = {})
options[:indent] ||= 2
xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
xml.instruct! unless options[:skip_instruct]
xml.user do
xml.id self.id
xml.name self.name
xml.created_at self.created_at
xml.last_seen self.last_seen
xml.description self.description
end
end
# Gera uma nova senha, e a envia por email.
def send_new_password
new_pass = User.random_string(10)
@password = @password_confirmation = new_pass
save
Notifications.deliver_forgot_password(self.email, self.login, new_pass)
end
def reset_login_key
self.login_key = Digest::SHA1.hexdigest(Time.now.to_s + password.to_s + rand(123456789).to_s).to_s
end
def reset_login_key!
reset_login_key
save!
self.login_key
end
def to_param
self.login
end
protected
def validate
if new_record?
errors.add_on_blank :password
errors.add_on_blank :password_confirmation
end
if !@password.blank?
errors.add(:password_confirmation) if @password_confirmation.blank? or @password != @password_confirmation
errors.add(:password, 'é muito curta') if !(5..40).include?(@password.length)
end
end
def before_save
self.salt = User.random_string(10) if !self.salt?
self.hashed_password = User.encrypt(@password, self.salt) if !@password.blank?
end
def self.encrypt(pass, salt)
Digest::SHA1.hexdigest(pass + salt)
end
def self.random_string(len)
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
newpass = ""
1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
return newpass
end
end

59
app/models/wiki_page.rb Normal file
View File

@@ -0,0 +1,59 @@
# Engenharia de Software 2007.1
# Copyright (C) 2007, Adriano, Alinson, Andre, Rafael e Bustamante
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
require 'acts_as_versioned'
require 'tempfile'
class WikiPage < ActiveRecord::Base
belongs_to :course
belongs_to :user
generate_validations
validates_uniqueness_of :title, :scope => :course_id
validates_format_of :title, :with => /^[^0-9]/
acts_as_paranoid
acts_as_list :scope => 'course_id = #{course_id}'
acts_as_versioned :if_changed => [ :content, :description, :title ]
self.non_versioned_fields << 'position'
def to_html(text = self.content)
return BlueCloth.new(text).to_html
end
def to_param
self.title
end
def WikiPage.diff(from, to)
# Cria um arquivo com o conteudo da versao antiga
original_content_file = Tempfile.new("old")
original_content_file << from.content << "\n"
original_content_file.flush
# Cria um arquivo com o conteudo da versao nova
new_content_file = Tempfile.new("new")
new_content_file << to.content << "\n"
new_content_file.flush
# Calcula as diferencas
diff = `diff -u #{original_content_file.path()} #{new_content_file.path()}`
# Fecha os arquivos temporarios
new_content_file.close!
original_content_file.close!
return diff
end
end

View File

@@ -0,0 +1,10 @@
= error_messages_for 'attachment'
%dl
%dt
%label{:for => 'attachment_file'} Arquivo
%dd= file_field 'attachment', 'file'
%dt
%label{:for => "attachment_description"} Descrição
%dd= preserve(text_area 'attachment', 'description')

View File

@@ -0,0 +1,7 @@
%h4.title= h(@course.full_name)
%h1.title Modificar arquivo
%p
- form_for :attachment, @attachment, :url => course_attachment_url, :html => { :method => 'put', :multipart => 'true' } do
= render :partial => 'form'
= submit_tag 'Editar'

View File

@@ -0,0 +1,7 @@
%h4.title= h(@course.full_name)
%h1.title Adicionar arquivo
%p
- form_for :attachment, @attachment, :url => course_attachments_url, :html => { :method => 'post', :multipart => 'true' } do
= render :partial => 'form'
= submit_tag "Criar"

View File

@@ -0,0 +1,20 @@
.cmd
= action_icon 'edit', 'Editar', edit_course_attachment_url
= action_icon 'trash', 'Excluir', course_attachment_url, :confirm => 'Tem certeza que deseja excluir o arquivo?', :method => :delete
%h4.title= h(@attachment.course.full_name)
%h1.title Repositório
%p
%dl
%dt Arquivo
%dd= link_to h(@attachment.file_name), download_course_attachment_url
%dt Descrição
%dd= h(@attachment.description)
%dt Tipo de Arquivo
%dd= h(@attachment.content_type)
%dt Tamanho
%dd= number_to_human_size @attachment.size

View File

@@ -0,0 +1,22 @@
= error_messages_for 'course'
%dl
%dt
%label{:for => "course_full_name"} Nome completo
%dd= text_field 'course', 'full_name'
%dt
%label{:for => "course_short_name"} Nome abreviado
%dd= text_field 'course', 'short_name'
%dt
%label{:for => "course_code"} Código
%dd= text_field 'course', 'code'
%dt
%label{:for => "course_period"} Semestre
%dd= text_field 'course', 'period'
%dt
%label{:for => "course_description"} Descrição
%dd= preserve(text_area('course', 'description', :cols => 60, :rows => 10))

View File

@@ -0,0 +1,3 @@
- cache(:controller => 'courses', :action => 'show', :id => @course, :part => 'left') do
= render 'widgets/menu_disciplina'
= render 'widgets/menu_user'

View File

@@ -0,0 +1,3 @@
- cache(:controller => 'courses', :action => 'show', :id => @course, :part => 'right') do
= render 'widgets/calendario'
= render 'widgets/news'

View File

@@ -0,0 +1,7 @@
%h4.title= App.title
%h1.title Editar disciplina
%p
- form_tag course_path(@course.id), :method => :put do
= render :partial => 'form'
= submit_tag 'Editar'

View File

@@ -0,0 +1,29 @@
.cmd
= action_icon('add', 'Cadastrar nova disciplina', new_course_url) if admin?
- cache do
%h4.title= App.title
%h1.title Disciplinas
.box
%ul
- if logged_in?
- unless @current_user.courses.empty?
%h3 Disciplinas matriculadas
- for course in @current_user.courses
%li{highlight(course.id)}
.right
= action_icon('subtract', 'Desmatricular-se', unenroll_course_url(course))
= link_to h(course.full_name), course_url(course)
- old_period = 0
- for course in @courses
- if course.period != old_period
%h3= (course.period == 99 ? "Optativas" : "Semestre #{course.period}")
- old_period = course.period
%li{highlight(course.id)}
.right
= action_icon('add', 'Matricular-se', enroll_course_url(course))
= link_to h(course.full_name), course_url(course)

View File

@@ -0,0 +1,6 @@
%h4.title= App.title
%h1.title Adicionar disciplina
- form_tag course_url(@course.id), :method => :post do
= render :partial => 'form'
= submit_tag "Cadastrar"

View File

@@ -0,0 +1,40 @@
.cmd
- if admin?
= action_icon 'edit', 'Editar disciplina', edit_course_url
/= action_icon 'trash', 'Excluir disciplina', course_url, :confirm => 'Tem certeza que deseja excluir?', :method => :delete
- cache do
%h4.title Disciplina
%h1.title= h(@course.full_name)
%p= wiki @course.description
.box
.cmd
= action_icon 'add', 'Adicionar página wiki', new_course_wiki_url(@course)
%h3 Páginas Wiki
%ul.wiki
- @course.wiki_pages.each do |wiki|
%li{highlight(wiki.id)}
.cmd{:style => 'margin-bottom: -27px; margin-top: -9px;'}
=action_icon 'arrow2_n', 'Mover para cima', move_up_course_wiki_url(@course, wiki) unless wiki.first?
=action_icon 'arrow2_s', 'Mover para baixo', move_down_course_wiki_url(@course, wiki) unless wiki.last?
- if wiki.last?
%span{:style => 'margin-right: 14px'} &nbsp;
=link_to h(wiki.title), course_wiki_url(@course, wiki)
- if @course.wiki_pages.empty?
%li.no_itens Nenhuma página wiki
.box
.cmd= action_icon 'add', 'Adicionar anexo', new_course_attachment_url(@course)
%h3 Repositório de Arquivos
.repositorio
%ul.wiki
- @course.attachments.each do |att|
%li{:class => mime_class(att.content_type)}
= link_to h(att.file_name), course_attachment_url(@course, att)
- if @course.attachments.empty?
%li.no_itens Nenhum arquivo

View File

@@ -0,0 +1,19 @@
= error_messages_for 'event'
%dl
%dt
%label{:for => "event_title"} Título
%dd= text_field 'event', 'title'
%dt
%label{:for => "event_date"} Data
%dd= date_select 'event', 'date', :order => [:day, :month, :year]
%dt
%label{:for => "event_time"} Horário
%dd= time_select 'event', 'time'
%dt
%label{:for => "event_description"} Descrição
%dd= preserve(text_area('event', 'description', :rows => 6))

View File

@@ -0,0 +1,7 @@
%h4.title= h(@course.full_name)
%h1.title Editar evento
%p
- form_tag course_event_url(@course, @event), :method => :put do
= render :partial => 'form'
= submit_tag 'Editar'

View File

@@ -0,0 +1,39 @@
- cache do
- last_event = nil
.cmd
= action_icon 'add', 'Adicionar evento', new_course_event_url
%h4.title= h(@course.full_name)
%h1.title Calendário
.box.div_calendario
- @events.each do |event|
- if last_event != event.date
= "</ul></div>" if last_event
.date= event.date.strftime("%d de %B")
= "<div><ul>"
%li[event]
.time= event.time.strftime("%H:%M")
= link_to h(event.title), course_event_url(@course, event)
%div.description{:style => (event.id == params[:id].to_i ? '' : 'display: none')}
%div.cmd{:style => "height: 27px; margin-top: -27px;"}
= action_icon 'edit', 'Editar', edit_course_event_url(@course, event)
= action_icon 'trash', 'Excluir', course_event_url(@course, event), :confirm => 'Tem certeza que deseja excluir?', :method => :delete
= h(event.description)
= "Sem descrição" if event.description.empty?
- last_event = event.date
= "</ul></div>" if !@events.empty?
- if @events.empty?
.box
%ul
%li.grey Nenhum evento
%br

View File

@@ -0,0 +1,7 @@
%h4.title= @course.full_name
%h1.title Adicionar evento
%p
- form_tag course_event_url(@course, @event), :method => :post do
= render :partial => 'form'
= submit_tag "Adicionar"

View File

@@ -0,0 +1,2 @@
- @events = @course.events
= render 'events/index'

View File

@@ -0,0 +1,15 @@
- @title = "#{App.title} - #{h(@course.full_name)}"
- @location = capture do
= link_to(App.title, "/") + "&rsaquo;"
= link_to("Disciplinas", courses_url) + "&rsaquo;"
= link_to(h(@course.full_name), course_url(@course)) + "&rsaquo;"
= link_to("Arquivos", course_url(@course))
- if @attachment.id
= "&rsaquo;" + link_to(truncate(h(@attachment.file_name)), course_attachment_url)
- @title = @title + " - #{truncate(h(@attachment.file_name))}"
- @left_panel = render 'courses/_left_panel'
- @right_panel = render 'courses/_right_panel'
- @content = yield
= render 'layouts/base'

View File

@@ -0,0 +1,47 @@

!!! XML
!!!
%html
%head
%title= @title || App.title
%meta{'name' => 'robots', :content => 'noindex,nofollow'}
%meta{'http-equiv' => 'Content-Type', 'content' => 'text/html; charset=UTF-8'}
%link{'href' => "/stylesheets/wiki.css", 'rel' => 'Stylesheet', 'type' => %'text/css'}
%link#css_color{'href' => "/stylesheets/themes/color.#@color.css", 'rel' => 'Stylesheet', 'type' => %'text/css'}
= javascript_include_merged :base
%body{'onload' => 'javascript: startup()'}
#wrapper
#header
%h1= "<strong>Wiki</strong> UFC"
#header_menu
%ul
- if logged_in?
%li.grey= "Logged in as {u}"[:logged_in_as, h(@current_user.display_name)]
%li.last= link_to 'Logout', logout_path
- else
%li= link_to 'Cadastrar', signup_path
%li.last= link_to 'Login', login_path
#strip
#location
= flash_div
= @location
#site
%div
- if @right_panel.nil?
.float_panel_left= @left_panel
#innerwrapper_2column
.content= @content
- else
.float_panel_left= @left_panel
.float_panel_right= @right_panel
#innerwrapper_3column
.content= @content
%br{'style' => 'clear:both'}
#footer

View File

@@ -0,0 +1,20 @@
- @title = "#{App.title}"
- @location = capture do
= link_to(App.title, "/") + "&rsaquo;";
= link_to("Disciplinas", courses_url)
- if @course and @course.id
= "&rsaquo; " + link_to(h(@course.full_name), course_url)
- @title = @title + " - #{h(@course.full_name)}"
- else
- @title = @title + " - Disciplinas"
- if @course and @course.id
- @left_panel = render 'courses/_left_panel'
- @right_panel = render 'courses/_right_panel'
- else
- @left_panel = render('widgets/menu_navigation') + render('widgets/menu_user')
- end
- @content = yield
= render 'layouts/base'

View File

@@ -0,0 +1,12 @@
- @title = "#{App.title} - #{h(@course.full_name)} - Calendário"
- @location = capture do
= link_to(App.title, "/") + "&rsaquo;"
= link_to("Disciplinas", courses_url) + "&rsaquo;"
= link_to(h(@course.full_name), course_url(@course)) + "&rsaquo;"
= link_to("Calendário", course_events_url)
- @left_panel = render 'courses/_left_panel'
- @right_panel = render 'courses/_right_panel'
- @content = yield
= render 'layouts/base'

View File

@@ -0,0 +1,11 @@
- @title = "#{App.title} - #{h(@course.full_name)} - Mudanças recentes"
- @location = capture do
= link_to(App.title, "/") + "&rsaquo;"
= link_to("Disciplinas", courses_url) + "&rsaquo;"
= link_to(h(@course.full_name), course_url(@course)) + "&rsaquo;"
= link_to("Log", course_log_url(@course))
- @left_panel = render 'courses/_left_panel'
- @content = yield
= render 'layouts/base'

View File

@@ -0,0 +1,12 @@
- @title = "#{App.title} - #{h(@course.full_name)} - Notícias"
- @location = capture do
= link_to(App.title, "/") + "&rsaquo;"
= link_to("Disciplinas", courses_url) + "&rsaquo;"
= link_to(h(@course.full_name), course_url(@course)) + "&rsaquo;"
= link_to("Noticias", course_news_index_url(@course))
- @left_panel = render 'courses/_left_panel'
- @right_panel = render 'courses/_right_panel'
- @content = yield
= render 'layouts/base'

View File

@@ -0,0 +1,12 @@
- @title = App.title
- @location = capture do
= link_to(App.title, "/") + "&rsaquo;";
= link_to("Usuários", users_path)
- if @user and @user.id
= "&rsaquo; " + link_to(h(@user.name), user_url(@user))
- @title = @title + " - #{h(@user.display_name)}"
- @left_panel = render('widgets/menu_navigation') + render('widgets/menu_user')
- @content = yield
= render 'layouts/base'

View File

@@ -0,0 +1,14 @@
- @title = "#{App.title} - #{h(@course.full_name)}"
- @location = capture do
= link_to(App.title, "/") + "&rsaquo;"
= link_to("Disciplinas", courses_url) + "&rsaquo;"
= link_to(h(@course.full_name), course_url(@course)) + "&rsaquo;"
= link_to("Wiki", course_url(@course))
- if @wiki_page.title
= "&rsaquo;" + link_to(h(@wiki_page.title), course_wiki_url(@course, @wiki_page))
- @title = @title + " - #{h(@wiki_page.title)}"
- @left_panel = render 'courses/_left_panel'
- @content = yield
= render 'layouts/base'

View File

@@ -0,0 +1,6 @@
= "Anexo " + link_to(h(entry.attachment.file_name), course_attachment_url(@course, entry.attachment))
= "criado " if entry.kind_of?(AttachmentCreateLogEntry)
= "editado " if entry.kind_of?(AttachmentEditLogEntry)
= "excluído " if entry.kind_of?(AttachmentDeleteLogEntry)
= "restaurado " if entry.kind_of?(AttachmentRestoreLogEntry)

View File

@@ -0,0 +1,6 @@
= "Evento " + link_to(h(entry.event.title), course_event_url(@course, entry.event))
= "criado " if entry.kind_of?(EventCreateLogEntry)
= "editado " if entry.kind_of?(EventEditLogEntry)
= "excluído " if entry.kind_of?(EventDeleteLogEntry)
= "restaurado " if entry.kind_of?(EventRestoreLogEntry)

View File

@@ -0,0 +1,6 @@
= "Notícia " + link_to(h(entry.news.title), course_news_url(@course, entry.news))
= "criada " if entry.kind_of?(NewsCreateLogEntry)
= "editada " if entry.kind_of?(NewsEditLogEntry)
= "excluída " if entry.kind_of?(NewsDeleteLogEntry)
= "restaurada " if entry.kind_of?(NewsRestoreLogEntry)

View File

@@ -0,0 +1,13 @@
= "Página " + link_to(h(entry.wiki_page.versions.last.title), course_wiki_url(@course, entry.wiki_page.id, :version => entry.wiki_page.version))
= "criada " if entry.kind_of?(WikiCreateLogEntry)
= "editada " if entry.kind_of?(WikiEditLogEntry)
= "excluída " if entry.kind_of?(WikiDeleteLogEntry)
= "restaurada " if entry.kind_of?(WikiRestoreLogEntry)
- if entry.kind_of?(WikiEditLogEntry)
- if entry.wiki_page.description and !entry.wiki_page.description.empty?
= "(<i>#{h(entry.wiki_page.description)}</i>)"
= "(" + link_to("diff", diff_course_wiki_url(@course, entry.wiki_page.id, :from => entry.wiki_page.version - 1, :to => entry.wiki_page.version)) + ")"
= "(" + link_to("edit", edit_course_wiki_url(@course, entry.wiki_page.id, :description => "Revertendo para versão #{entry.wiki_page.version}", :version => entry.wiki_page.version)) + ")"
= "(" + link_to("undo", edit_course_wiki_url(@course, entry.wiki_page.id, :description => "Revertendo para versão #{entry.wiki_page.version-1}", :version => entry.wiki_page.version - 1)) + ")"

View File

@@ -0,0 +1,18 @@
%h4.title= h(@course.full_name)
%h1.title Mudanças recentes
%table.log
%tr
%th Data
%th Usuário
%th Descrição
- @log_entries.each do |entry|
%tr
%td= entry.created_at.strftime("%d/%m/%y&nbsp;%H:%M:%S")
%td= link_to truncate(h(entry.user.display_name), 20), user_path(entry.user)
%td
= render(:partial => 'log/attachment_log_entry', :locals => { :entry => entry }) if entry.kind_of?(AttachmentLogEntry)
= render(:partial => 'log/event_log_entry', :locals => { :entry => entry }) if entry.kind_of?(EventLogEntry)
= render(:partial => 'log/news_log_entry', :locals => { :entry => entry }) if entry.kind_of?(NewsLogEntry)
= render(:partial => 'log/wiki_log_entry', :locals => { :entry => entry }) if entry.kind_of?(WikiLogEntry)
= "(" + link_to("undo", undo_course_log_url(@course, entry)) + ")" if entry.reversible?

View File

@@ -0,0 +1,10 @@
= error_messages_for 'news'
%dl
%dt
%label{:for => "news_title"} Título
%dd= text_field 'news', 'title'
%dt
%label{:for => "news_body"} Descrição
%dd= preserve(text_area('news', 'body'))

View File

@@ -0,0 +1,7 @@
%h4.title= h(@course.full_name)
%h1.title Editar noticia
%p
- form_tag course_news_url(@course, @news), :method => :put do
= render :partial => 'form'
= submit_tag 'Editar'

View File

@@ -0,0 +1,28 @@
- cache do
.cmd
= action_icon 'add', 'Adicionar', new_course_news_url
%h4.title= h(@course.full_name)
%h1.title Notícias
= auto_discovery_link_tag :rss, formatted_course_news_index_url(@course, :rss)
.news
- @course.news.each do |n|
.line{:class => 'new', :id => "news_#{n.id}"}
.cmd{:style => (n.id == params[:id].to_i ? '' : 'display: none')}
= action_icon 'edit', 'Editar', edit_course_news_url(@course, n)
= action_icon 'trash', 'Excluir', course_news_url(@course, n), :confirm => 'Tem certeza que deseja excluir?', :method => :delete
.left= n.timestamp.strftime("%d de %B")
%h4
= link_to h(n.title), course_news_url(@course, n)
%p{:style => (n.id == params[:id].to_i ? '' : 'display: none')}
= h(n.body)
- if @course.news.empty?
.box
%ul
%li.grey Nenhuma notícia

View File

@@ -0,0 +1,18 @@
xml.instruct! :xml, :version=>"1.0"
xml.rss(:version=>"2.0") do
xml.channel do
xml.title("#{App.title} - #{@course.full_name} - " + "News"[].titleize)
xml.link(course_news_index_url(@course))
xml.language(App.language)
xml.description("{course} news"[:news_about, @course.full_name])
for news_item in @news
xml.item do
xml.title(news_item.title)
xml.description(news_item.body)
xml.pubDate(news_item.timestamp.rfc2822)
xml.link(course_news_url(@course, news_item))
xml.guid(course_news_url(@course, news_item))
end
end
end
end

View File

@@ -0,0 +1,6 @@
%h4.title= @course.full_name
%h1.title Adicionar evento
- form_tag course_news_url(@course, @news), :method => :post do
= render :partial => 'form'
= submit_tag "Enviar"

View File

@@ -0,0 +1 @@
= render 'news/index'

View File

@@ -0,0 +1,9 @@
_____________
Seu nome de usuário é <%= h(@login) %>. E seu novo password é <%= h(@pass) %>.
Faça o seu Login e mude para algo mais fácil de ser memorizado.
Wiki Ufc
-------------

View File

@@ -0,0 +1,38 @@
<% color = App.color_schemes[@color] || App.color_schemes[App.default_color] %>
a {
color: <%= color[1] %>;
}
a:hover {
border-bottom: 1px dotted <%= color[1] %>;
}
h1, h2, h3, h4, h5, th {
color: <%= color[2] %>;
}
#header {
background-color: <%= color[0] %>;
}
#header_menu {
background-color: <%= color[0] %>;
}
#header_menu ul li {
border-right: 1px solid <%= color[0] %>;
}
#strip {
background-color: <%= color[0] %>;
}
#footer {
background-color: <%= color[3] %>;
border-top: 5px solid <%= color[3] %>;
}
.icon img:hover {
background-color: <%= color[1] %>;
}

View File

@@ -0,0 +1,18 @@
<h4 class="title"><%= App.title %></h4>
<h3 class="title">Alterar senha</h3>
<p>
<%= error_messages_for 'user' %><br/>
<% form_tag :action => 'change_password' do %>
<label for="user_password">Nova senha</label><br/>
<%= password_field "user", "password", :size => 20, :value=>"" %><br/>
<label for="user_password_confirmation">Confirme nova senha</label><br/>
<%= password_field "user", "password_confirmation", :size => 20, :value=>"" %><br/>
<br/>
<%= submit_tag "Enviar" %>
<% end %>
</o>

View File

@@ -0,0 +1,54 @@
<h4 class="title"><%= App.title %></h4>
<h1 class="title">Editar Preferências</h1>
<p>
<%= error_messages_for 'user' %><br/>
<% form_tag :action => 'update', :id => @user do %>
<label for="user_name">Nome</label><br/>
<%= text_field "user", "name", :size => 20 %><br/>
<label for="user_email">Email</label><br/>
<%= text_field "user", "email", :size => 20 %><br/><br/>
<label for="user_password">Senha</label><br/>
<%= password_field "user", "password", {:value => "", :size => 20, :id => 'password'} %><br/>
<label for="user_password_confirmation">Confirmação de Senha</label><br/>
<%= password_field "user", "password_confirmation", {:value => "", :size => 20} %><br/>
<div id="passmeter">&nbsp;</div><br/>
<label for="user_pref_color">Cor de Preferência:</label><br />
<%= select_tag("user[pref_color]", options_for_select( {
"Preto" => 0,
"Verde (Claro)" => 1,
"Azul (Claro)" => 2,
"Lilás" => 3,
"Vermelho/Cinza" => 4,
"Verde-limão" => 5,
"Azul (Padrão)" => 6,
"Vermelho" => 7,
"Azul/Laranja" => 8,
"Verde/Vermelho" => 9,
"Pink" => 10,
"Roxo" => 11,
"Vinho" => 12,
}.sort)) %><br/><br/>
<label for="user_courses">Disciplinas matriculadas:</label><br/>
<% Course.find(:all).each do |course| %>
<%= check_box_tag("user[course_ids][]", course.id, @user.courses.include?(course)) %>
<%= h(course.full_name) %><br/>
<% end %>
<br/><br/>
<%= submit_tag "Editar" %>
<% end %><br/><br/>
</p>

View File

@@ -0,0 +1,15 @@
<h4 class="title"><%= App.title %></h4>
<h1 class="title">Recuperar senha</h1>
<p>
<%= error_messages_for 'user' %><br/>
<% form_tag :action=>'forgot_password' do %>
Email<br/>
<%= text_field "user","email" %><br/><br/>
<%= submit_tag 'Enviar nova senha' %>
<% end %>
</p>

View File

@@ -0,0 +1,21 @@
<h4 class="title"><%= App.title %></h4>
<h1 class="title">Login</h1>
<p>
<%= error_messages_for 'user' %><br/>
<% form_tag :action=> "login" do %>
<label for="user_login">Login:</label><br/>
<%= text_field "user", "login", :size => 20 %><br/>
<label for="user_password">Senha:</label><br/>
<%= password_field "user", "password", :size => 20 %><br/>
<%= submit_tag "Login" %><br /><br />
<%= link_to 'Criar conta', :action => 'signup' %> |
<%= link_to 'Recuperar senha', :action => 'forgot_password' %>
<% end %>
</p>

View File

@@ -0,0 +1,13 @@
xml.instruct! :xml, :version=>"1.0"
xml.instruct! :rss, :version=>"2.0"
xml.channel{
for course in @courses
for event in course.events
xml.item do
xml.title("[" + course.short_name + "] " + event.title)
xml.pubDate(Time.parse(event.date.to_s).rfc822)
xml.description(event.description)
end
end
end
}

View File

@@ -0,0 +1,84 @@
<% last_event = nil %>
<div class="cmd">
<%= link_to 'preferências', :action => 'edit'%>
</div>
<h4 class="title">Página Pessoal</h4>
<h1 class="title">Bem vindo, <%= h(@user.name) %></h1>
<!-- Noticias -->
<div class="box news">
<h3>Notícias</h3>
<% @news_messages.each do |n| %>
<div class="line">
<h4 class="left"><%= n.timestamp.strftime("%d de %B") %></h4>
<h4><%= link_to h(n.course.full_name) , course_news_url(n.course, n) %> &rsaquo;
<a href="#" id="new_<%=n.id%>"><%= h(n.title) %></a></h4>
<p id="new_desc_<%= n.id %>" style="display:none">
<%= h(n.body) %>
</p>
</div>
<% end %>
</div>
<script type="text/javascript">
<% @news_messages.each do |n| %>
events['#new_<%= n.id %>:click'] = function(el, e) {
Effect.toggle($('new_desc_<%= n.id %>'), 'blind');
Event.stop(e);
};
<% end %>
</script>
<!-- Calendario -->
<div class="box div_calendario">
<div class="cmd">
<%= link_to 'rss', :action => 'rss', :login => h(@user.login)%>
<%= link_to 'icalendar', :controller => 'events', :action => 'icalendar'%>
</div>
<h3>Calendário</h3>
<% @events.each do |event| %>
<% if last_event != event.date %>
<% if last_event %></ul></div><% end %>
<div class="date"><%= event.date.strftime("%d de %B") %></div>
<div><ul>
<% end %>
<li>
<div class="time"><%= event.time.strftime("%H:%M") %></div>
<%= link_to h(event.course.full_name), course_event_url(event.course, event) %> &rsaquo;
<a href="#" id="event_<%= event.id %>"><%= h(event.title) %></a>
<div id="desc_<%= event.id %>" class="description" style="display:none">
<%= h(event.description) %>
<%= "Sem descrição" if event.description.length == 0 %>
</div>
</li>
<% last_event = event.date %>
<% end %>
<%= "</ul></div>" if !@events.empty? %>
</div>
<script type="text/javascript">
<% @events.each do |event| %>
events['#event_<%= event.id %>:click'] = function(el, e) {
Effect.toggle($('desc_<%= event.id %>'), 'blind');
Event.stop(e);
};
<% end %>
</script>
<!-- Disciplinas Matriculadas -->
<div class="box">
<h3>Disciplinas Matriculadas</h3>
<ul class="wiki">
<% @user.courses.each do |course| %>
<li><%= link_to h(course.full_name), course_url(course) %></li>
<% end %>
</ul>
</div>
<h4><%#= link_to 'Descadastrar usuário', :action => 'destroy'%></h4>

View File

@@ -0,0 +1,58 @@
<h4 class="title"><%= App.title %></h4>
<h1 class="title">Criar conta</h1>
<p>
<% form_tag :action=> "signup" do %>
<%= error_messages_for 'user' %><br/>
<label for="user_name">Nome</label><br/>
<%= text_field "user", "name", :size => 20 %><br/>
<label for="user_email">Email</label><br/>
<%= text_field "user", "email", :size => 20 %><br/><br/>
<label for="user_login">Login</label><br/>
<%= text_field "user", "login", :size => 20 %><br/>
<label for="user_password">Senha</label><br/>
<%= password_field "user", "password", {:value => "", :size => 20, :id => 'password'} %><br/>
<label for="user_password_confirmation">Confirmação de Senha</label><br/>
<%= password_field "user", "password_confirmation", {:value => "", :size => 20} %><br/>
<div id="passmeter">&nbsp;</div><br />
<label for="user_pref_color">Cor de Preferência:</label>&nbsp;&nbsp;&nbsp;
<%= select_tag("user[pref_color]", options_for_select( {
"Preto" => 0,
"Verde (Claro)" => 1,
"Azul (Claro)" => 2,
"Lilás" => 3,
"Vermelho/Cinza" => 4,
"Verde-limão" => 5,
"Azul (Padrão)" => 6,
"Vermelho" => 7,
"Azul/Laranja" => 8,
"Verde/Vermelho" => 9,
"Pink" => 10,
"Roxo" => 11,
"Vinho" => 12,
}.sort)) %><br/><br/><br/>
<label for="user_courses">Disciplinas matriculadas:</label><br/>
<% @courses.each do |course| %>
<%= check_box_tag("user[course_ids][]", course.id, @user.courses.include?(course)) %>
<%= h(course.full_name) %><br/>
<% end %>
<% if @courses.empty? %>
Nenhuma disciplina cadastrada<br/>
<% end %>
<br/><br/>
<%= submit_tag "Enviar" %>
<% end %>
</p>

View File

@@ -0,0 +1,18 @@
= error_messages_for 'user'
%dl
%dt
%label{:for => 'user_display_name'} Nome de Exibição
%dd= text_field('user', 'display_name')
%dt
%label{:for => 'user_name'} Nome completo
%dd= text_field('user', 'name')
%dt
%label{:for => 'user_description'} Descrição
%dd= text_area('user', 'description', { :rows => 10 })
- if admin?
%dt= check_box_tag('user[admin]', 1, @user.admin?) + " Administrador"

View File

@@ -0,0 +1,37 @@
= javascript_include_tag 'color'
= error_messages_for 'user'
%dl
- if defined?(signup) and signup
%dt
%label{:for => 'user_login'} Login
%dd= text_field('user', 'login')
%dt
%label{:for => 'user_name'} Nome completo
%dd= text_field('user', 'name')
%dt
%label{:for => 'user_display_name'} Nome de exibição
%dd= text_field('user', 'display_name')
%dt
%laber{:for => 'user_email'} Email
%dd= text_field('user', 'email')
%dt
%label{:for => 'user_password'} Senha
%dd= password_field('user', 'password', {:value => '', :id => 'password'})
%dt
%label{:for => 'user_password_confirmation'} Confirmação de Senha
%dd= password_field('user', 'password_confirmation', {:value => ''})
#passmeter &nbsp;
%dt
%label{:for => 'user_color_pref'} Esquema de cores
= render :partial => 'widgets/color', :collection => App.color_schemes
%br.clear

View File

@@ -0,0 +1,35 @@
= javascript_include_tag 'color'
= error_messages_for 'user'
%dl
%dt
%label{:for => 'user_login'} Login
%dd= text_field('user', 'login')
%dt
%label{:for => 'user_name'} Nome Completo
%dd= text_field('user', 'name')
%dt
%label{:for => 'user_display_name'} Nome de exibição (apelido)
%dd= text_field('user', 'display_name')
%dt
%laber{:for => 'user_email'} Email
%dd= text_field('user', 'email')
%dt
%label{:for => 'user_password'} Senha
%dd= password_field('user', 'password', {:value => '', :id => 'password'})
%dt
%label{:for => 'user_password_confirmation'} Confirmação de Senha
%dd= password_field('user', 'password_confirmation', {:value => ''})
#passmeter &nbsp;
%dt
%label{:for => 'user_color_pref'} Esquema de cores
= render :partial => 'widgets/color', :collection => App.color_schemes
%br.clear

View File

@@ -0,0 +1 @@
%li= link_to h(user.name), user_path(user)

View File

@@ -0,0 +1,49 @@
<% last_event = nil %>
<h4 class="title">Dashboard</h4>
<h1 class="title">Bem vindo, <%= h(@current_user.display_name) %></h1>
<!-- Noticias -->
<div class="news box">
<h3>Notícias recentes</h3>
<% @news.each do |n| %>
<div class="line">
<h4 class="left"><%= n.timestamp.strftime("%d de %B") %></h4>
<h4><%= link_to h(n.course.full_name) , course_url(n.course) %> &rsaquo;
<%= link_to h(n.title), course_news_url(n.course, n) %></h4>
</div>
<% end %>
</div>
<!-- Calendario -->
<div class="box div_calendario">
<h3>Próximos eventos</h3>
<% @events.each do |event| %>
<% if last_event != event.date %>
<% if last_event %></ul></div><% end %>
<div class="date"><%= event.date.strftime("%d de %B") %></div>
<div><ul>
<% end %>
<li>
<div class="time"><%= event.time.strftime("%H:%M") %></div>
<%= link_to h(event.course.full_name), course_url(event.course) %> &rsaquo;
<%= link_to h(event.title), course_event_url(event.course, event) %>
</li>
<% last_event = event.date %>
<% end %>
<%= "</ul></div>" if !@events.empty? %>
</div>
<!-- Disciplinas Matriculadas -->
<div class="box">
<h3>Disciplinas Matriculadas</h3>
<ul class="wiki">
<% @current_user.courses.each do |course| %>
<li><%= link_to h(course.full_name), course_url(course) %></li>
<% end %>
</ul>
</div>
<h4><%#= link_to 'Descadastrar usuário', :action => 'destroy'%></h4>

View File

@@ -0,0 +1,13 @@
= javascript_include_tag 'wiki'
%h4.title Usuários
%h1.title Editar perfil
%p
- form_tag user_path(@user.id), :method => 'put' do
= render :partial => 'form_profile'
= submit_tag 'Editar'
%button#show_preview{:type => "button"}
Visualizar
= image_tag "loading.gif", :class => "spinner_button", :id => "spinner_preview", :style => "display: none"
#wiki_preview{:style => "display: none"}

View File

@@ -0,0 +1,7 @@
- cache do
%h4.title= App.title
%h1.title Usuários
.box
%ul
= render :partial => @users

View File

@@ -0,0 +1,25 @@
%h4.title= App.title
%h1.title Login
%p
= error_messages_for :user
- form_tag login_path do
%dl
%dt
%label{:for => 'user_login'} Login
%dd= text_field "user", "login"
%dt
%label{:for => 'user_password'} Senha
%dd= password_field "user", "password"
%dt
= check_box_tag('remember_me', 1)
%label{:for => 'remember_me'} Lembrar de mim neste computador
= submit_tag 'Login'
%br
= link_to 'Criar nova conta', signup_path
=# link_ro 'Recuperar senha', recover_password_path

View File

@@ -0,0 +1,7 @@
%h4.title Usuários
%h1.title Editar configurações
%p
- form_tag settings_url do
= render :partial => 'form_settings'
= submit_tag 'Editar'

View File

@@ -0,0 +1,14 @@
- cache do
#users
.cmd
= action_icon('edit', 'Editar perfil', edit_user_url) if admin? or @current_user == @user
/= action_icon 'trash', 'Excluir usuário', user_url, :confirm => 'Tem certeza que deseja excluir?', :method => :delete
.card
%img.avatar{:src => gravatar_url_for(@user.email)}
%h1.title= h(@user.display_name)
%p= h(@user.name)
%p= "Membro desde {c}"[:member_since, @user.created_at.strftime("%d de %B de %Y")]
%p= "Última visita há {c}"[:last_seen, distance_of_time_in_words(Time.now, @user.last_seen)]
= wiki @user.description if !@user.description.blank?

View File

@@ -0,0 +1,7 @@
%h4.title= App.title
%h1.title Nova conta
%p
- form_tag signup_path do
= render :partial => 'form_settings', :locals => { :signup => true }
= submit_tag 'Criar'

View File

@@ -0,0 +1,4 @@
.color_theme
= radio_button('user', 'pref_color', App.color_schemes.index(color), :class => 'color_radio')
- color.each do |c|
.color_box{:style => "background-color: #{c}"} &nbsp;

View File

@@ -0,0 +1,100 @@
<% if not @ajax %>
<!-- Calendario -->
<div class="menu">
<%= image_tag "loading.gif", :id => "spinner_calendar",
:class => "spinner", :style => "display:none" %>
<div class="cmd">
<%= action_icon 'add', 'Adicionar evento', new_course_event_url(@course) %>
</div>
<h1>Calendário</h1>
<div id="calendar">
<% end -%>
<%=
@year ||= Time.now.year
@month ||= Time.now.month
@events ||= @course.events
calendar({:year => @year, :month => @month, :table_class => 'calendario',
:abbrev => (0..1) }) do |d|
cell_text = d.mday
cell_attrs = {:class => 'day'}
@events.each do |e|
if e.date == d
cell_attrs[:onclick] = "show_events('#{d.to_s}')"
cell_attrs[:class] = 'specialDay'
cell_text = link_to d.mday, "#"
end
end
[cell_text, cell_attrs]
end
%>
<% if not @ajax -%>
</div>
<div class="widget_events">
<ul>
<% @events.each do |e| -%>
<li style="display: none" class="event_item events_<%=e.date.to_s%>">
<%= link_to e.date.strftime("%d de %B"), course_event_url(@course, e) %>.
<%= h(e.title) %>. <%= h(e.description) %>
</li>
<% end -%>
</ul>
</div>
</div>
<% end -%>
<% if not @ajax -%>
<script type="text/javascript">
calendar_year = <%= @year %>;
calendar_month = <%= @month %>;
events['#calendar_next:click'] = function(element, e) {
if(++calendar_month > 12) {
calendar_month = 1;
calendar_year++;
}
<% if @course %>
url = '/widgets/calendar/<%= @course.id %>/' + calendar_year + '/' + calendar_month;
<% end %>
spinner_start('calendar');
new Ajax.Updater('calendar', url, {
onComplete: function() {
spinner_stop('calendar');
}
});
Event.stop(e);
};
events['#calendar_prev:click'] = function(element, e) {
if(--calendar_month < 1) {
calendar_month = 12;
calendar_year--;
}
<% if @course %>
url = '/widgets/calendar/<%= @course.id %>/' + calendar_year + '/' + calendar_month;
<% end %>
spinner_start('calendar');
new Ajax.Updater('calendar', url, {
onComplete: function() {
spinner_stop('calendar');
}
});
Event.stop(e);
};
function show_events(e) {
$$('.event_item').each(function(x) {
if(x.match('.events_' + e)) x.show();
else x.hide();
});
}
</script>
<% end -%>

View File

@@ -0,0 +1,10 @@
<!-- Menu Disciplina -->
<div class="menu">
<h1>Disciplina</h1>
<ul>
<li><%= link_to "Visão Geral", course_url(@course) %></li>
<li><%= link_to "Noticias", course_news_index_url(@course) %></li>
<li><%= link_to "Calendário", course_events_url(@course) %></li>
<li><%= link_to "Mudanças recentes", course_log_url(@course) %></li>
</ul>
</div>

View File

@@ -0,0 +1,5 @@
.menu
%h1= App.title
%ul
%li= link_to "Courses"[].titleize, courses_url
%li= link_to "Users"[].titleize, users_url

View File

@@ -0,0 +1,7 @@
- if session[:user_id]
.menu
%h1= "User"[].titleize
%ul
/%li= link_to "Dashboard"[].titleize, dashboard_path
%li= link_to("User profile"[].titleize, user_url(session[:user_id]))
%li= link_to("Edit settings"[].titleize, settings_url)

View File

@@ -0,0 +1,22 @@
<!-- Mural -->
<div class="menu">
<div class="cmd">
<%= action_icon 'add', 'Adicionar notícia', new_course_news_url(@course) %>
</div>
<h1>Noticias</h1>
<ul class="widget_news">
<% @course.news[0..3].each do |msg| %>
<li>
<h4><%= tz(msg.timestamp).strftime("%d/%m") %></h4>
<%= link_to msg.title, course_news_url(@course, msg) %>.
<%= truncate(msg.body, 80) %>
</li>
<% end %>
<% if @course.news.size > 4 %>
<li><%= link_to("Ver todas as notícias", course_news_index_url(@course)) %></li>
<% end %>
<% if @course.news.empty? %>
<li class="no_itens">Nenhuma notícia</li>
<% end %>
</ul>
</div>

View File

@@ -0,0 +1,44 @@
<% receiver = @user ? @user : @course %>
<!-- Shoutbox -->
<div class="menu">
<h1>Shoutbox</h1>
<div id="shoutbox">
<ul id="shoutbox_messages">
<li>Carregando...</li>
</ul>
<% if session[:user] %>
<% form_tag(
{:controller => 'message', :action => 'create'}, {:id => 'shoutbox_form' }) do %>
<div>
<%= text_area :message, :body %>
<%= hidden_field :message, :message_type, :value => (@user ? Message::USER_SHOUTBOX_MESSAGE : Message::SHOUTBOX_MESSAGE) %>
<%= hidden_field :message, :receiver_id, :value => receiver.id %>
<%= submit_tag 'Enviar', :id => 'shoutbox_send' %>
</div>
<% end %>
<% else %>
<i>Para enviar mensagens, é preciso fazer <%= link_to 'login', :controller => 'user', :action => 'login' %>.</i>
<% end %>
</div>
</div>
<script type="text/javascript">
var updater = new Ajax.PeriodicalUpdater('shoutbox_messages',
'<%= url_for :controller => 'message', :action => 'show_shoutbox' + (@user?'_user':''), :id => receiver.id %>',
{ method: 'get', frequency: 10, decay: 1.5}
);
events['#shoutbox_send:click'] = function(button, e) {
Event.stop(e);
button.disabled = true;
$('shoutbox_form').request({
method: 'post',
onSuccess: function(t) {
button.disabled = false;
updater.stop();
updater.start();
$('shoutbox_form').reset();
}
});
};
</script>

View File

@@ -0,0 +1,15 @@
= error_messages_for 'wiki_page'
%dl
%dt
%label{:for => 'wiki_page_title'} Título
%dd= text_field 'wiki_page', 'title'
%dt
%label{:for =>'wiki_page_content'} Conteúdo
%dd= preserve(text_area('wiki_page', 'content'))
- unless @wiki_page.new_record?
%dt
%label{:for => 'wiki_page_description'} Descrição das alterações
%dd= text_field('wiki_page', 'description', { :size => '80' })

View File

@@ -0,0 +1,6 @@
= action_icon('undo', "Reverter", edit_course_wiki_url(@course, @wiki_page, :description => "Revertendo para versão #{page.version}", :version => page.version)) + "&nbsp;"
= link_to page.updated_at.strftime("%d/%m/%y&nbsp;%H:%M:%S"), course_wiki_url(@course, @wiki_page, :version => page.version)
= "por #{link_to h(page.user.display_name), user_path(page.user)}" if page.respond_to?(:user) and !page.user.nil?
- if page.description and !page.description.empty?
= "(<i>#{h(page.description)}</i>)"

View File

@@ -0,0 +1,11 @@
%h4.title= h(@course.full_name)
%h1.title= h(@wiki_page.title)
%p
Comparando versões:
%ul
%li= render :partial => 'wiki/history', :locals => { :page => @to }
%li= render :partial => 'wiki/history', :locals => { :page => @from }
= link_to "Comparar outras versões", versions_course_wiki_url(@course, @wiki_page, :from => @from.version, :to => @to.version)
= format_diff h(@diff)

View File

@@ -0,0 +1,14 @@
= javascript_include_tag 'wiki'
%h4.title= h(@course.full_name)
%h1.title= "Editar #{h(@wiki_page.title)}"
%p
- form_tag course_wiki_url(@course, @wiki_page.id), :method => :put do
= render :partial => 'form'
= submit_tag 'Salvar'
%button#show_preview{:type => "button"}
Visualizar
= image_tag "loading.gif", :class => "spinner_button", :id => "spinner_preview", :style => "display: none"
#wiki_preview{:style => "display: none"}

View File

@@ -0,0 +1,13 @@
= javascript_include_tag 'wiki'
%h4.title= h(@course.full_name)
%h1.title Adicionar página wiki
%p
- form_tag course_wiki_url(@course, @wiki_page.id) do
= render :partial => 'form'
= submit_tag "Criar"
%button#show_preview{:type => "button"}
Visualizar
= image_tag "loading.gif", :class => "spinner_button", :id => "spinner_preview", :style => "display: none"
#wiki_preview{:style => "display: none"}

View File

@@ -0,0 +1,16 @@
= javascript_include_tag 'wiki'
.cmd
= action_icon 'edit', 'Editar', edit_course_wiki_url
= action_icon 'undo', 'Historico', versions_course_wiki_url
= action_icon 'trash', 'Excluir página wiki', course_wiki_url, :confirm => 'Tem certeza que deseja excluir?', :method => :delete
- cache(:action => 'show', :short_name => h(@course.short_name), :title => h(@wiki_page.title) ) do
%h4.title= h(@course.full_name)
%h1.title= h(@wiki_page.title)
#wiki_text
= @wiki_page.to_html
%script{:language => 'javascript'}
== enumerate_headers();

View File

@@ -0,0 +1,34 @@
%h4.title= h(@course.full_name)
%h1.title= "Histórico de #{h(@wiki_page.title)}"
%br
= javascript_include_tag "history"
%script{:language => 'javascript'}
== radios_to = #{h(@history_to)};
== radios_from = #{h(@history_from)};
- form_tag diff_course_wiki_url(@course, @wiki_page), :method => :get do
%button{:type => "submit"}= "Comparar as versões selecionadas"
%table.log
%tr
%th.narrow &nbsp;
%th.narrow &nbsp;
%th Data
%th Usuário
%th Descrição
- @wiki_page.versions.reverse.each do |entry|
%tr
%td.narrow
%input{:type => "radio", :name => "from", :value => entry.version, :onclick => "history_from(#{entry.version})"}
%td.narrow
%input{:type => "radio", :name => "to", :value => entry.version, :onclick => %"history_to(#{entry.version})"}
%td= link_to(entry.updated_at.strftime("%d/%m/%y&nbsp;%H:%M:%S"), course_wiki_url(@course, @wiki_page, :version => entry.version))
%td= link_to truncate(h(entry.user.display_name), 20), user_path(entry.user)
%td
= entry.description
- if (entry.version > @wiki_page.versions.minimum(:version))
= "(" + link_to("diff", diff_course_wiki_url(@course, @wiki_page, :from => entry.version - 1, :to => entry.version)) + ")"
= "(" + link_to("edit", edit_course_wiki_url(@course, @wiki_page, :description => "Revertendo para versão #{entry.version}", :version => entry.version)) + ")"
/= will_paginate @versions

View File

@@ -0,0 +1,15 @@
xml.instruct! :xml, :version=>"1.0"
xml.versions do
xml.count @wiki_page.versions.count
xml.offset @offset
@wiki_page.versions[(@offset.to_i)..(@offset.to_i+30)].reverse.each do |version|
xml.version do
xml.created_at version.created_at
xml.updated_at version.updated_at
xml.description version.description
xml.title version.title
xml.user_id version.user_id
xml.version version.version
end
end
end