- <%= link_to profile_path, :class => "pic" do %>
- <%= image_tag gravatar_icon(current_user.email) %>
- <% end %>
- <%= link_to profile_path, :class => "username" do %>
- <%= current_user.name %>
- <% end %>
- <%= link_to 'Logout', destroy_user_session_path, :class => "logout", :method => :delete %>
+
+
+ <%= link_to profile_path, :class => "pic" do %>
+ <%= image_tag gravatar_icon(current_user.email) %>
+ <% end %>
+
+
+
+
+ <%= link_to profile_path, :class => "username" do %>
+ <%#= current_user.name %>
+ Your profile
+ <% end %>
+ <%= link_to "Fluid layout", url_for( :view_style => 'fluid' ) if cookies[:view_style] == "collapsed"%>
+ <%= link_to "Fixed layout", url_for( :view_style => 'collapsed' ) unless cookies[:view_style] == "collapsed"%>
+ <%= link_to 'Logout', destroy_user_session_path, :class => "logout", :method => :delete %>
-
- <%= text_field_tag "search", nil, :placeholder => "Search", :class => "search-input" %>
-
+
+
+
+ <%= text_field_tag "search", nil, :placeholder => "Search", :class => "search-input" %>
+
+
-
-
<% if current_user %>
<%= javascript_tag do %>
$(function() {
diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml
index d3de20da..e02dbe04 100644
--- a/app/views/layouts/admin.html.haml
+++ b/app/views/layouts/admin.html.haml
@@ -6,11 +6,10 @@
= stylesheet_link_tag "application"
= javascript_include_tag "application"
= csrf_meta_tags
- %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/
= javascript_tag do
REQ_URI = "#{request.env["REQUEST_URI"]}";
REQ_REFFER = "#{request.env["HTTP_REFERER"]}";
- %body{ :class => content_for?(:body_class) ? yield(:body_class) : 'project-page', :id => yield(:boyd_id)}
+ %body{ :class => body_class('project-page'), :id => yield(:boyd_id)}
#container
= render :partial => "layouts/flash"
= render :partial => "layouts/head_panel"
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 8cc63253..9022ecb1 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -2,22 +2,16 @@
%html
%head
%title
- GitLab #{" - #{@project.name}" if @project && !@project.new_record?}
- -#= stylesheet_link_tag 'blueprint/screen', :media => "screen, projection"
- -#= stylesheet_link_tag 'blueprint/print', :media => "print"
- -#= stylesheet_link_tag 'blueprint/plugins/buttons/screen', :media => "screen, projection"
- -#= stylesheet_link_tag 'blueprint/plugins/link-icons/screen', :media => "screen, projection"
+ GitLab
= stylesheet_link_tag "application"
= javascript_include_tag "application"
= csrf_meta_tags
- %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/
= javascript_tag do
REQ_URI = "#{request.env["REQUEST_URI"]}";
REQ_REFFER = "#{request.env["HTTP_REFERER"]}";
- %body{ :class => yield(:body_class), :id => yield(:boyd_id)}
+ %body{ :class => body_class, :id => yield(:boyd_id)}
#container
= render :partial => "layouts/flash"
= render :partial => "layouts/head_panel"
- %div{ :id => "main", :role => "main", :class => "container_4" }
- = render :partial => "layouts/page_title"
- = yield
+ = render :partial => "layouts/page_title"
+ = yield
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 968fe58d..32964663 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -6,7 +6,6 @@
= stylesheet_link_tag "application"
= javascript_include_tag "application"
= csrf_meta_tags
- %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/
= javascript_tag do
REQ_URI = "#{request.env["REQUEST_URI"]}";
REQ_REFFER = "#{request.env["HTTP_REFERER"]}";
diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml
index 007e03cf..2fd30dcd 100644
--- a/app/views/layouts/profile.html.haml
+++ b/app/views/layouts/profile.html.haml
@@ -6,11 +6,10 @@
= stylesheet_link_tag "application"
= javascript_include_tag "application"
= csrf_meta_tags
- %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/
= javascript_tag do
REQ_URI = "#{request.env["REQUEST_URI"]}";
REQ_REFFER = "#{request.env["HTTP_REFERER"]}";
- %body{ :class => content_for?(:body_class) ? yield(:body_class) : 'project-page', :id => yield(:boyd_id)}
+ %body{ :class => body_class('project-page'), :id => yield(:boyd_id)}
#container
= render :partial => "layouts/flash"
= render :partial => "layouts/head_panel"
diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml
index b4b51631..984ff4d0 100644
--- a/app/views/layouts/project.html.haml
+++ b/app/views/layouts/project.html.haml
@@ -6,40 +6,39 @@
= stylesheet_link_tag "application"
= javascript_include_tag "application"
= csrf_meta_tags
- %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/
= javascript_tag do
REQ_URI = "#{request.env["REQUEST_URI"]}";
REQ_REFFER = "#{request.env["HTTP_REFERER"]}";
- %body{ :class => content_for?(:body_class) ? yield(:body_class) : 'project-page', :id => yield(:boyd_id)}
+ %body{ :class => body_class('project-page'), :id => yield(:boyd_id)}
#container
= render :partial => "layouts/flash"
= render :partial => "layouts/head_panel"
.project-container
.project-sidebar
.fixed
- %input.git-url.text{:id => "", :name => "", :readonly => "", :type => "text", :value => @project.url_to_repo}
- %aside
- = link_to "History", project_path(@project), :class => current_page?(:controller => "projects", :action => "show", :id => @project) ? "current" : nil
- = link_to "Tree", tree_project_path(@project), :class => current_page?(:controller => "projects", :action => "tree", :id => @project) ? "current" : nil
- = link_to "Commits", project_commits_path(@project), :class => current_page?(:controller => "commits", :action => "index", :project_id => @project) ? "current" : nil
- = link_to team_project_path(@project), :class => (current_page?(:controller => "projects", :action => "team", :id => @project) || controller.controller_name == "team_members") ? "current" : nil do
- Team
- - if @project.users_projects.count > 0
- %span{ :class => "number" }= @project.users_projects.count
- = link_to project_issues_path(@project), :class => (controller.controller_name == "issues") ? "current" : nil do
- Issues
- - if @project.issues.opened.count > 0
- %span{ :class => "number" }= @project.issues.opened.count
- = link_to wall_project_path(@project), :class => current_page?(:controller => "projects", :action => "wall", :id => @project) ? "current" : nil do
- Wall
- - if @project.common_notes.count > 0
- %span{ :class => "number" }= @project.common_notes.count
- = link_to project_snippets_path(@project), :class => (controller.controller_name == "snippets") ? "current" : nil do
- Snippets
- - if @project.snippets.count > 0
- %span{ :class => "number" }= @project.snippets.non_expired.count
- - if @commit
- = link_to truncate(commit_name(@project,@commit), :length => 15), project_commit_path(@project, :id => @commit.id), :class => current_page?(:controller => "commits", :action => "show", :project_id => @project, :id => @commit.id) ? "current" : nil
+ %input.git-url.text{:id => "", :name => "", :readonly => "", :type => "text", :value => @project.url_to_repo, :class => "one_click_select"}
+ %aside
+ = link_to "History", project_path(@project), :class => current_page?(:controller => "projects", :action => "show", :id => @project) ? "current" : nil
+ = link_to "Tree", tree_project_path(@project), :class => current_page?(:controller => "projects", :action => "tree", :id => @project) ? "current" : nil
+ = link_to "Commits", project_commits_path(@project), :class => current_page?(:controller => "commits", :action => "index", :project_id => @project) ? "current" : nil
+ = link_to team_project_path(@project), :class => (current_page?(:controller => "projects", :action => "team", :id => @project) || controller.controller_name == "team_members") ? "current" : nil do
+ Team
+ - if @project.users_projects.count > 0
+ %span{ :class => "number" }= @project.users_projects.count
+ = link_to project_issues_path(@project), :class => (controller.controller_name == "issues") ? "current" : nil do
+ Issues
+ - if @project.issues.opened.count > 0
+ %span{ :class => "number" }= @project.issues.opened.count
+ = link_to wall_project_path(@project), :class => current_page?(:controller => "projects", :action => "wall", :id => @project) ? "current" : nil do
+ Wall
+ - if @project.common_notes.count > 0
+ %span{ :class => "number" }= @project.common_notes.count
+ = link_to project_snippets_path(@project), :class => (controller.controller_name == "snippets") ? "current" : nil do
+ Snippets
+ - if @project.snippets.count > 0
+ %span{ :class => "number" }= @project.snippets.non_expired.count
+ - if @commit
+ = link_to truncate(commit_name(@project,@commit), :length => 15), project_commit_path(@project, :id => @commit.id), :class => current_page?(:controller => "commits", :action => "show", :project_id => @project, :id => @commit.id) ? "current" : nil
.project-content
= yield
diff --git a/app/views/notes/_load.js.haml b/app/views/notes/_load.js.haml
new file mode 100644
index 00000000..c7ec9ed3
--- /dev/null
+++ b/app/views/notes/_load.js.haml
@@ -0,0 +1,17 @@
+- unless @notes.blank?
+
+ - if params[:last_id] && params[:first_id]
+ :plain
+ NoteList.replace(#{@notes.last.id}, #{@notes.first.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}");
+
+
+ - elsif params[:last_id]
+ :plain
+ NoteList.prepend(#{@notes.first.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}");
+
+ - elsif params[:first_id]
+ :plain
+ NoteList.append(#{@notes.last.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}");
+
+ - else
+ :plain
diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml
index e7cc2360..4a5c3aab 100644
--- a/app/views/notes/_notes.html.haml
+++ b/app/views/notes/_notes.html.haml
@@ -1,12 +1,8 @@
-- if controller.action_name == "wall"
- %ul#notes-list= render "notes/notes_list"
-
-- else
- %ul#notes-list= render "notes/notes_list"
- %br
- %br
- - if can? current_user, :write_note, @project
- = render "notes/form"
+- if can? current_user, :write_note, @project
+ = render "notes/form"
+.clear
+%hr
+%ul#notes-list= render "notes/notes_list"
:javascript
$('.delete-note').live('ajax:success', function() {
@@ -20,8 +16,11 @@
$("#submit_note").removeAttr("disabled");
})
-- if ["issues", "projects"].include?(controller.controller_name)
- :javascript
- $(function(){
- var int =self.setInterval("updatePage()", 20000);
+ $(function(){
+ $("#note_note").live("click", function(){
+ $(this).css("height", "100px");
+ $('.attach_holder').show();
});
+
+ NoteList.init("wall", #{@notes.last.try(:id) || 0}, #{@notes.first.try(:id) || 0});
+ });
diff --git a/app/views/notes/_show.html.haml b/app/views/notes/_show.html.haml
index 187d0a3c..27cb3874 100644
--- a/app/views/notes/_show.html.haml
+++ b/app/views/notes/_show.html.haml
@@ -1,17 +1,17 @@
-%li{:id => dom_id(note)}
- %div.note_author
- = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;"
- %div.note_content.left
- = markdown(note.note)
- - if note.attachment.url
- Attachment:
- = link_to note.attachment_identifier, note.attachment.url, :target => "_blank"
- %br
- %span.author= note.author.name
- %cite.ago
+%li{:id => dom_id(note), :class => "note"}
+ = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;"
+ %div.note-author
+ %strong= note.author_name
+ %cite.cgray
= time_ago_in_words(note.updated_at)
ago
- %br
- - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
- = link_to 'Remove', [@project, note], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-note right negative"
+ - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
+ = link_to "Remove", [@project, note], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "cred delete-note right"
+
+ %div.note-title
+ = markdown(note.note)
+ - if note.attachment.url
+ .right
+ %span.file
+ = link_to note.attachment_identifier, note.attachment.url, :target => "_blank"
.clear
diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml
index a04130e8..cf804493 100644
--- a/app/views/notes/create.js.haml
+++ b/app/views/notes/create.js.haml
@@ -1,8 +1,8 @@
- if @note.valid?
:plain
$("#new_note .errors").remove();
- updatePage();
$('#note_note').val("");
+ NoteList.prepend(#{@note.id}, "#{escape_javascript(render :partial => "notes/show", :locals => {:note => @note})}");
- else
:plain
$("#new_note").replaceWith("#{escape_javascript(render('form'))}");
diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml
index 164f1d45..2ddfda48 100644
--- a/app/views/projects/_form.html.haml
+++ b/app/views/projects/_form.html.haml
@@ -25,6 +25,11 @@
.left= f.label :code
%cite.right http://yourserver/
%td= f.text_field :code, :placeholder => "example"
+
+ %tr
+ %td= f.label :tag_list
+ %td= f.text_area :tag_list, :placeholder => "project tags", :style => "height:50px", :id => :tag_field
+
.field
= f.label :description
%br/
@@ -41,8 +46,25 @@
%h3.prepend-top Creating project & repository. Please wait for few minutes
- else
%h3.prepend-top Updating project & repository. Please wait for few minutes
+
:javascript
$('.new_project, .edit_project').bind('ajax:before', function() {
$(this).find(".form_content").hide();
$('.ajax_loader').show();
});
+
+:javascript
+ $(function(){
+ var tag_field = $('#tag_field').tagify();
+
+ tag_field.tagify('inputField').autocomplete({
+ source: '/tags.json'
+ });
+
+
+ $('form').submit( function() {
+ var tag_field = $('#tag_field')
+ tag_field.val( tag_field.tagify('serialize') );
+ return true;
+ });
+ })
diff --git a/app/views/projects/_list.html.haml b/app/views/projects/_list.html.haml
index 65f0b7fd..7976b11f 100644
--- a/app/views/projects/_list.html.haml
+++ b/app/views/projects/_list.html.haml
@@ -10,7 +10,12 @@
- @projects.each do |project|
%tr{ :class => "project", :url => project_path(project) }
- %td= project.name
+ %td
+ = project.name
+ .small-tags
+ - project.tag_list.each do |tag|
+ = link_to tag, "/tags/#{tag}"
+
%td= truncate project.url_to_repo
%td= project.code
%td= check_box_tag "read", 1, project.readers.include?(current_user), :disabled => :disabled
diff --git a/app/views/projects/_refs.html.haml b/app/views/projects/_refs.html.haml
new file mode 100644
index 00000000..60b17c7f
--- /dev/null
+++ b/app/views/projects/_refs.html.haml
@@ -0,0 +1,8 @@
+= form_tag destination, :method => :get, :class => "project-refs-form" do
+ = select_tag "ref", grouped_options_refs, :onchange => "this.form.submit();", :class => "project-refs-select"
+
+
+:javascript
+ $(function(){
+ $('.project-refs-select').chosen();
+ })
diff --git a/app/views/projects/_tile.html.haml b/app/views/projects/_tile.html.haml
index 7c0b8679..cc891f63 100644
--- a/app/views/projects/_tile.html.haml
+++ b/app/views/projects/_tile.html.haml
@@ -12,6 +12,11 @@
%span Last Activity:
- last_note = project.notes.last
= last_note ? last_note.created_at.stamp("24 Aug, 2011") : "Never"
+
+ %p.small-tags
+ - project.tag_list.each do |tag|
+ = link_to tag, "/tags/#{tag}"
+
.buttons
%a.browse-code.button.yellow{:href => tree_project_path(project)} Browse code
%a.commits.button.green{:href => project_commits_path(project)} Commits
diff --git a/app/views/projects/_tree.html.haml b/app/views/projects/_tree.html.haml
index 2aca18e4..8fdf72f0 100644
--- a/app/views/projects/_tree.html.haml
+++ b/app/views/projects/_tree.html.haml
@@ -1,12 +1,3 @@
-.left
- = form_tag tree_project_path(@project), :method => :get do
- = select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "", :prompt => "Branches"
-.left
- = form_tag tree_project_path(@project), :method => :get do
- = select_tag "tag", options_for_select(@project.tags, @tag), :onchange => "this.form.submit();", :class => "", :prompt => "Tags"
-.clear
-
-%br
-#%a.right.button{:href => "#"} Download
-#-if can? current_user, :admin_project, @project
@@ -14,14 +5,9 @@
#tree-breadcrumbs
%h2.icon
%span
- = link_to tree_project_path(@project, :path => nil, :commit_id => @commit.try(:id)), :remote => true, :class => 'project-name' do
- %i.arrow>
- = @project.name
-
%d
- %a{:href => "#"}
- = @ref
-
+ = link_to tree_project_path(@project, :path => nil, :commit_id => @commit.try(:id)), :remote => true do
+ = @project.name
- if params[:path]
- part_path = ""
- params[:path].split("\/").each do |part|
@@ -30,7 +16,8 @@
- part_path = part
\/
= link_to truncate(part, :length => 40), tree_file_project_path(@project, :path => part_path, :commit_id => @commit.try(:id), :branch => @branch, :tag => @tag), :remote => :true
-
+
+ .right= render :partial => "projects/refs", :locals => { :destination => tree_project_path(@project) }
.clear
#tree-content-holder
diff --git a/app/views/projects/_tree_item.html.haml b/app/views/projects/_tree_item.html.haml
index 53c05d5a..273d0272 100644
--- a/app/views/projects/_tree_item.html.haml
+++ b/app/views/projects/_tree_item.html.haml
@@ -11,5 +11,8 @@
%td
= time_ago_in_words(content_commit.committed_date)
ago
- %td
- = link_to truncate(content_commit.safe_message, :length => 40), project_commit_path(@project, content_commit)
+ %td.commit
+ = link_to truncate(content_commit.safe_message, :length => fixed_mode? ? 40 : 80), project_commit_path(@project, content_commit), :class => "tree-commit-link"
+ - tm = @project.team_member_by_name_or_email(content_commit.author_email, content_commit.author_name)
+ - if tm
+ = link_to "[#{tm.user_name}]", project_team_member_path(@project, tm)
diff --git a/app/views/projects/index.html.haml b/app/views/projects/index.html.haml
index a35ead82..ba860571 100644
--- a/app/views/projects/index.html.haml
+++ b/app/views/projects/index.html.haml
@@ -1,18 +1,20 @@
- content_for(:body_class, "projects-page")
- content_for(:page_title) do
- .grid_4
- - if current_user.can_create_project?
- %a.grey-button.right{:href => new_project_path} Create new project
- %h2.icon
- %span
- Projects
+ .container_4
+ .grid_4
+ - if current_user.can_create_project?
+ %a.grey-button.right{:href => new_project_path} Create new project
+ %h2.icon
+ %span
+ Projects
-- unless @projects.empty?
- %div{:class => "tile", :style => view_mode_style("tile")}
- = render "tile"
- %div{:class => "list", :style => view_mode_style("list")}
- = render "list"
-- else
- %center.prepend-top
- %h2
- %cite Nothing here
+ %div.clear
+ - unless @projects.empty?
+ %div{:class => "tile", :style => view_mode_style("tile")}
+ = render "tile"
+ %div{:class => "list", :style => view_mode_style("list")}
+ = render "list"
+ - else
+ %center.prepend-top
+ %h2
+ %cite Nothing here
diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml
index 63c9613a..4f0ec41e 100644
--- a/app/views/projects/wall.html.haml
+++ b/app/views/projects/wall.html.haml
@@ -1,29 +1,6 @@
%div.wall_page
- - if can? current_user, :write_note, @project
- = render "notes/form"
- .right
- = form_tag wall_project_path(@project), :method => :get do
- .span-2
- = radio_button_tag :view, "recent", (params[:view] || "recent") == "recent", :onclick => "this.form.submit()", :id => "recent_view"
- = label_tag "recent_view","Recent"
- .span-2
- = radio_button_tag :view, "day", params[:view] == "day", :onclick => "this.form.submit()", :id => "day_view"
- = label_tag "day_view","Today"
- .span-2
- = radio_button_tag :view, "week", params[:view] == "week", :onclick => "this.form.submit()", :id => "week_view"
- = label_tag "week_view","Week"
- .span-2
- = radio_button_tag :view, "all", params[:view] == "all", :onclick => "this.form.submit()", :id => "all_view"
- = label_tag "all_view","All"
- .clear
- %br
- %hr
-= render "notes/notes"
+ = render "notes/notes"
+
+.loading{ :style => "display:none;"}
+ %center= image_tag "ajax-loader.gif"
-:javascript
- $(function(){
- $("#note_note").live("click", function(){
- $(this).css("height", "100px");
- $('.attach_holder').show();
- });
- });
diff --git a/app/views/projects/wall.js.haml b/app/views/projects/wall.js.haml
index ae2ff32c..ee31c0b8 100644
--- a/app/views/projects/wall.js.haml
+++ b/app/views/projects/wall.js.haml
@@ -1,2 +1 @@
-:plain
- $("#notes-list").html("#{escape_javascript(render(:partial => 'notes/notes_list'))}");
+= render "notes/load"
diff --git a/app/views/tags/index.html.haml b/app/views/tags/index.html.haml
new file mode 100644
index 00000000..c83d62c7
--- /dev/null
+++ b/app/views/tags/index.html.haml
@@ -0,0 +1,11 @@
+- content_for(:body_class, "projects-page")
+- content_for(:page_title) do
+ .grid_4
+ %h2
+ Tags
+
+
+ .tags-list
+ - @tags.all.each do |tag|
+ = link_to "#{tag.name}(#{tag.count})", "/tags/#{tag.name}"
+
diff --git a/config/routes.rb b/config/routes.rb
index d45c32bd..d4e27965 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,9 @@
Gitlab::Application.routes.draw do
+
+ get 'tags'=> 'tags#index'
+ get 'tags/:tag' => 'projects#index'
+
+
namespace :admin do
resources :users
resources :projects
@@ -20,6 +25,7 @@ Gitlab::Application.routes.draw do
resources :projects, :only => [:new, :create, :index]
resources :keys
+
devise_for :users
resources :projects, :except => [:new, :create, :index], :path => "/" do
diff --git a/db/migrate/20111101222453_acts_as_taggable_on_migration.rb b/db/migrate/20111101222453_acts_as_taggable_on_migration.rb
new file mode 100644
index 00000000..16610615
--- /dev/null
+++ b/db/migrate/20111101222453_acts_as_taggable_on_migration.rb
@@ -0,0 +1,28 @@
+class ActsAsTaggableOnMigration < ActiveRecord::Migration
+ def self.up
+ create_table :tags do |t|
+ t.string :name
+ end
+
+ create_table :taggings do |t|
+ t.references :tag
+
+ # You should make sure that the column created is
+ # long enough to store the required class names.
+ t.references :taggable, :polymorphic => true
+ t.references :tagger, :polymorphic => true
+
+ t.string :context
+
+ t.datetime :created_at
+ end
+
+ add_index :taggings, :tag_id
+ add_index :taggings, [:taggable_id, :taggable_type, :context]
+ end
+
+ def self.down
+ drop_table :taggings
+ drop_table :tags
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 13c4db0c..3d430f4c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20111027152724) do
+ActiveRecord::Schema.define(:version => 20111101222453) do
create_table "issues", :force => true do |t|
t.string "title"
@@ -68,6 +68,23 @@ ActiveRecord::Schema.define(:version => 20111027152724) do
t.datetime "expires_at"
end
+ create_table "taggings", :force => true do |t|
+ t.integer "tag_id"
+ t.integer "taggable_id"
+ t.string "taggable_type"
+ t.integer "tagger_id"
+ t.string "tagger_type"
+ t.string "context"
+ t.datetime "created_at"
+ end
+
+ add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
+ add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context"
+
+ create_table "tags", :force => true do |t|
+ t.string "name"
+ end
+
create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false
diff --git a/spec/requests/commits_notes_spec.rb b/spec/requests/commits_notes_spec.rb
index c424f4fc..69a492e9 100644
--- a/spec/requests/commits_notes_spec.rb
+++ b/spec/requests/commits_notes_spec.rb
@@ -12,7 +12,6 @@ describe "Issues" do
describe "add new note", :js => true do
before do
visit project_commit_path(project, commit)
- click_link "Comments" # notes tab
fill_in "note_note", :with => "I commented this commit"
click_button "Add note"
end
diff --git a/spec/requests/tags_spec.rb b/spec/requests/tags_spec.rb
new file mode 100644
index 00000000..94a034da
--- /dev/null
+++ b/spec/requests/tags_spec.rb
@@ -0,0 +1,31 @@
+require 'spec_helper'
+
+describe "Tags" do
+ before { login_as :user }
+
+ # describe "GET 'tags/index'" do
+ # it "should be successful" do
+ # get 'tags/index'
+ # response.should be_success
+ # end
+ # end
+
+
+ describe "GET '/tags.json'" do
+ before do
+ @project = Factory :project
+ @project.add_access(@user, :read)
+ @project.tag_list = 'demo1'
+ @project.save
+ visit '/tags.json'
+ end
+
+
+ it "should contains tags" do
+ page.should have_content('demo1')
+ end
+end
+
+
+
+end
diff --git a/vendor/assets/javascripts/jquery.tagify.js b/vendor/assets/javascripts/jquery.tagify.js
new file mode 100644
index 00000000..f22d4c71
--- /dev/null
+++ b/vendor/assets/javascripts/jquery.tagify.js
@@ -0,0 +1,143 @@
+/* Author: Alicia Liu */
+
+(function ($) {
+
+ $.widget("ui.tagify", {
+ options: {
+ delimiters: [13, 188], // what user can type to complete a tag in char codes: [enter], [comma]
+ outputDelimiter: ',', // delimiter for tags in original input field
+ cssClass: 'tagify-container', // CSS class to style the tagify div and tags, see stylesheet
+ addTagPrompt: 'add tags' // placeholder text
+ },
+
+ _create: function() {
+ var self = this,
+ el = self.element,
+ opts = self.options;
+
+ this.tags = [];
+
+ // hide text field and replace with a div that contains it's own input field for entering tags
+ this.tagInput = $("
")
+ .attr( 'placeholder', opts.addTagPrompt )
+ .keypress( function(e) {
+ var $this = $(this),
+ pressed = e.which;
+
+ for ( i in opts.delimiters ) {
+
+ if (pressed == opts.delimiters[i]) {
+ self.add( $this.val() );
+ e.preventDefault();
+ return false;
+ }
+ }
+ })
+ // for some reason, in Safari, backspace is only recognized on keyup
+ .keyup( function(e) {
+ var $this = $(this),
+ pressed = e.which;
+
+ // if backspace is hit with no input, remove the last tag
+ if (pressed == 8) { // backspace
+ if ( $this.val() == "" ) {
+ self.remove();
+ return false;
+ }
+ return;
+ }
+ });
+
+ this.tagDiv = $("
")
+ .addClass( opts.cssClass )
+ .click( function() {
+ $(this).children('input').focus();
+ })
+ .append( this.tagInput )
+ .insertAfter( el.hide() );
+
+ // if the field isn't empty, parse the field for tags, and prepopulate existing tags
+ var initVal = $.trim( el.val() );
+
+ if ( initVal ) {
+ var initTags = initVal.split( opts.outputDelimiter );
+ $.each( initTags, function(i, tag) {
+ self.add( tag );
+ });
+ }
+ },
+
+ _setOption: function( key, value ) {
+ options.key = value;
+ },
+
+ // add a tag, public function
+ add: function(text) {
+ var self = this;
+ text = text || self.tagInput.val();
+ if (text) {
+ var tagIndex = self.tags.length;
+
+ var removeButton = $("
x")
+ .click( function() {
+ self.remove( tagIndex );
+ return false;
+ });
+ var newTag = $("
")
+ .text( text )
+ .append( removeButton );
+
+ self.tagInput.before( newTag );
+ self.tags.push( text );
+ self.tagInput.val('');
+ }
+ },
+
+ // remove a tag by index, public function
+ // if index is blank, remove the last tag
+ remove: function( tagIndex ) {
+ var self = this;
+ if ( tagIndex == null || tagIndex === (self.tags.length - 1) ) {
+ this.tagDiv.children("span").last().remove();
+ self.tags.pop();
+ }
+ if ( typeof(tagIndex) == 'number' ) {
+ // otherwise just hide this tag, and we don't mess up the index
+ this.tagDiv.children( "span:eq(" + tagIndex + ")" ).hide();
+ // we rely on the serialize function to remove null values
+ delete( self.tags[tagIndex] );
+ }
+ },
+
+ // serialize the tags with the given delimiter, and write it back into the tagified field
+ serialize: function() {
+ var self = this;
+ var delim = self.options.outputDelimiter;
+ var tagsStr = self.tags.join( delim );
+
+ // our tags might have deleted entries, remove them here
+ var dupes = new RegExp(delim + delim + '+', 'g'); // regex: /,,+/g
+ var ends = new RegExp('^' + delim + '|' + delim + '$', 'g'); // regex: /^,|,$/g
+ var outputStr = tagsStr.replace( dupes, delim ).replace(ends, '');
+
+ self.element.val(outputStr);
+ return outputStr;
+ },
+
+ inputField: function() {
+ return this.tagInput;
+ },
+
+ containerDiv: function() {
+ return this.tagDiv;
+ },
+
+ // remove the div, and show original input
+ destroy: function() {
+ $.Widget.prototype.destroy.apply(this);
+ this.tagDiv.remove();
+ this.element.show();
+ }
+ });
+
+})(jQuery);
\ No newline at end of file
diff --git a/vendor/assets/stylesheets/jquery-ui/jquery.tagify.css b/vendor/assets/stylesheets/jquery-ui/jquery.tagify.css
new file mode 100644
index 00000000..d6c178f7
--- /dev/null
+++ b/vendor/assets/stylesheets/jquery-ui/jquery.tagify.css
@@ -0,0 +1,34 @@
+/* Tagify styles
+Author: Alicia Liu test
+*/
+
+.tagify-container {
+}
+
+.tagify-container > span {
+ display: inline-block;
+ padding: 8px 11px 8px 11px;
+ margin: 1px 5px 0px 0px;
+ border-radius: 4px;
+ border: 1px solid #d0e1ff;
+ background-color: #d0e1ff;
+ color: #0f326d;
+ font-weight: bold;
+ font-size: 14px;
+}
+
+.tagify-container > span > a {
+ padding-left: 5px !important;
+ color: #83a5e1;
+ text-decoration: none;
+ font-weight: bold;
+}
+
+.tagify-container > input {
+ border: 0 none;
+ width: 100px !important;
+}
+
+.tagify-container > input:focus {
+ outline: none;
+}
\ No newline at end of file