Initial import

master
Alinson S. Xavier 18 years ago
commit 5e4951fa47

203
README

@ -0,0 +1,203 @@
== Welcome to Rails
Rails is a web-application and persistence framework that includes everything
needed to create database-backed web-applications according to the
Model-View-Control pattern of separation. This pattern splits the view (also
called the presentation) into "dumb" templates that are primarily responsible
for inserting pre-built data in between HTML tags. The model contains the
"smart" domain objects (such as Account, Product, Person, Post) that holds all
the business logic and knows how to persist themselves to a database. The
controller handles the incoming requests (such as Save New Account, Update
Product, Show Post) by manipulating the model and directing data to the view.
In Rails, the model is handled by what's called an object-relational mapping
layer entitled Active Record. This layer allows you to present the data from
database rows as objects and embellish these data objects with business logic
methods. You can read more about Active Record in
link:files/vendor/rails/activerecord/README.html.
The controller and view are handled by the Action Pack, which handles both
layers by its two parts: Action View and Action Controller. These two layers
are bundled in a single package due to their heavy interdependence. This is
unlike the relationship between the Active Record and Action Pack that is much
more separate. Each of these packages can be used independently outside of
Rails. You can read more about Action Pack in
link:files/vendor/rails/actionpack/README.html.
== Getting Started
1. At the command prompt, start a new Rails application using the <tt>rails</tt> command
and your application name. Ex: rails myapp
(If you've downloaded Rails in a complete tgz or zip, this step is already done)
2. Change directory into myapp and start the web server: <tt>script/server</tt> (run with --help for options)
3. Go to http://localhost:3000/ and get "Welcome aboard: Youre riding the Rails!"
4. Follow the guidelines to start developing your application
== Web Servers
By default, Rails will try to use Mongrel and lighttpd if they are installed, otherwise
Rails will use WEBrick, the webserver that ships with Ruby. When you run script/server,
Rails will check if Mongrel exists, then lighttpd and finally fall back to WEBrick. This ensures
that you can always get up and running quickly.
Mongrel is a Ruby-based webserver with a C component (which requires compilation) that is
suitable for development and deployment of Rails applications. If you have Ruby Gems installed,
getting up and running with mongrel is as easy as: <tt>gem install mongrel</tt>.
More info at: http://mongrel.rubyforge.org
If Mongrel is not installed, Rails will look for lighttpd. It's considerably faster than
Mongrel and WEBrick and also suited for production use, but requires additional
installation and currently only works well on OS X/Unix (Windows users are encouraged
to start with Mongrel). We recommend version 1.4.11 and higher. You can download it from
http://www.lighttpd.net.
And finally, if neither Mongrel or lighttpd are installed, Rails will use the built-in Ruby
web server, WEBrick. WEBrick is a small Ruby web server suitable for development, but not
for production.
But of course its also possible to run Rails on any platform that supports FCGI.
Apache, LiteSpeed, IIS are just a few. For more information on FCGI,
please visit: http://wiki.rubyonrails.com/rails/pages/FastCGI
== Debugging Rails
Sometimes your application goes wrong. Fortunately there are a lot of tools that
will help you debug it and get it back on the rails.
First area to check is the application log files. Have "tail -f" commands running
on the server.log and development.log. Rails will automatically display debugging
and runtime information to these files. Debugging info will also be shown in the
browser on requests from 127.0.0.1.
You can also log your own messages directly into the log file from your code using
the Ruby logger class from inside your controllers. Example:
class WeblogController < ActionController::Base
def destroy
@weblog = Weblog.find(params[:id])
@weblog.destroy
logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
end
end
The result will be a message in your log file along the lines of:
Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1
More information on how to use the logger is at http://www.ruby-doc.org/core/
Also, Ruby documentation can be found at http://www.ruby-lang.org/ including:
* The Learning Ruby (Pickaxe) Book: http://www.ruby-doc.org/docs/ProgrammingRuby/
* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
These two online (and free) books will bring you up to speed on the Ruby language
and also on programming in general.
== Debugger
Debugger support is available through the debugger command when you start your Mongrel or
Webrick server with --debugger. This means that you can break out of execution at any point
in the code, investigate and change the model, AND then resume execution! Example:
class WeblogController < ActionController::Base
def index
@posts = Post.find(:all)
debugger
end
end
So the controller will accept the action, run the first line, then present you
with a IRB prompt in the server window. Here you can do things like:
>> @posts.inspect
=> "[#<Post:0x14a6be8 @attributes={\"title\"=>nil, \"body\"=>nil, \"id\"=>\"1\"}>,
#<Post:0x14a6620 @attributes={\"title\"=>\"Rails you know!\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]"
>> @posts.first.title = "hello from a debugger"
=> "hello from a debugger"
...and even better is that you can examine how your runtime objects actually work:
>> f = @posts.first
=> #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
>> f.
Display all 152 possibilities? (y or n)
Finally, when you're ready to resume execution, you enter "cont"
== Console
You can interact with the domain model by starting the console through <tt>script/console</tt>.
Here you'll have all parts of the application configured, just like it is when the
application is running. You can inspect domain models, change values, and save to the
database. Starting the script without arguments will launch it in the development environment.
Passing an argument will specify a different environment, like <tt>script/console production</tt>.
To reload your controllers and models after launching the console run <tt>reload!</tt>
== Description of Contents
app
Holds all the code that's specific to this particular application.
app/controllers
Holds controllers that should be named like weblogs_controller.rb for
automated URL mapping. All controllers should descend from ApplicationController
which itself descends from ActionController::Base.
app/models
Holds models that should be named like post.rb.
Most models will descend from ActiveRecord::Base.
app/views
Holds the template files for the view that should be named like
weblogs/index.erb for the WeblogsController#index action. All views use eRuby
syntax.
app/views/layouts
Holds the template files for layouts to be used with views. This models the common
header/footer method of wrapping views. In your views, define a layout using the
<tt>layout :default</tt> and create a file named default.erb. Inside default.erb,
call <% yield %> to render the view using this layout.
app/helpers
Holds view helpers that should be named like weblogs_helper.rb. These are generated
for you automatically when using script/generate for controllers. Helpers can be used to
wrap functionality for your views into methods.
config
Configuration files for the Rails environment, the routing map, the database, and other dependencies.
db
Contains the database schema in schema.rb. db/migrate contains all
the sequence of Migrations for your schema.
doc
This directory is where your application documentation will be stored when generated
using <tt>rake doc:app</tt>
lib
Application specific libraries. Basically, any kind of custom code that doesn't
belong under controllers, models, or helpers. This directory is in the load path.
public
The directory available for the web server. Contains subdirectories for images, stylesheets,
and javascripts. Also contains the dispatchers and the default HTML files. This should be
set as the DOCUMENT_ROOT of your web server.
script
Helper scripts for automation and generation.
test
Unit and functional tests along with fixtures. When using the script/generate scripts, template
test files will be generated for you and placed in this directory.
vendor
External libraries that the application depends on. Also includes the plugins subdirectory.
This directory is in the load path.

@ -0,0 +1,10 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'
require 'tasks/rails'

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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'

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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')

@ -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'

@ -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"

@ -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

@ -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))

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

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

@ -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'

@ -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)

@ -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"

@ -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

@ -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))

@ -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'

@ -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

@ -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"

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

@ -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'

@ -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

@ -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'

@ -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'

@ -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'

@ -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'

@ -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'

@ -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'

@ -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)

@ -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)

@ -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)

@ -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)) + ")"

@ -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?

@ -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'))

@ -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'

@ -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

@ -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

@ -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"

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

@ -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
-------------

@ -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] %>;
}

@ -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>

@ -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>

@ -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>

@ -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>

@ -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
}

@ -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>

@ -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>

@ -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"

@ -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

@ -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

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

@ -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>

@ -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"}

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

@ -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

@ -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'

@ -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?

@ -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'

@ -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;

@ -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 -%>

@ -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>

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

@ -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)

@ -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>

@ -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>

@ -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' })

@ -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>)"

@ -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)

@ -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"}

@ -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"}

@ -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();

Some files were not shown because too many files have changed in this diff Show More