diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee
index 9e5d594c861d6867308d9c47b571795fe5f51efd..746fa3cea871322fe7f5b42d15197107391bab39 100644
--- a/app/assets/javascripts/api.js.coffee
+++ b/app/assets/javascripts/api.js.coffee
@@ -2,6 +2,8 @@
   groups_path: "/api/:version/groups.json"
   group_path: "/api/:version/groups/:id.json"
   namespaces_path: "/api/:version/namespaces.json"
+  group_projects_path: "/api/:version/groups/:id/projects.json"
+  projects_path: "/api/:version/projects.json"
 
   group: (group_id, callback) ->
     url = Api.buildUrl(Api.group_path)
@@ -44,6 +46,35 @@
     ).done (namespaces) ->
       callback(namespaces)
 
+  # Return projects list. Filtered by query
+  projects: (query, callback) ->
+    url = Api.buildUrl(Api.projects_path)
+
+    $.ajax(
+      url: url
+      data:
+        private_token: gon.api_token
+        search: query
+        per_page: 20
+      dataType: "json"
+    ).done (projects) ->
+      callback(projects)
+
+  # Return group projects list. Filtered by query
+  groupProjects: (group_id, query, callback) ->
+    url = Api.buildUrl(Api.group_projects_path)
+    url = url.replace(':id', group_id)
+
+    $.ajax(
+      url: url
+      data:
+        private_token: gon.api_token
+        search: query
+        per_page: 20
+      dataType: "json"
+    ).done (projects) ->
+      callback(projects)
+
   buildUrl: (url) ->
     url = gon.relative_url_root + url if gon.relative_url_root?
     return url.replace(':version', gon.api_version)
diff --git a/app/assets/javascripts/project_select.js.coffee b/app/assets/javascripts/project_select.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..0ae274f33632dc71ca5862ec68c18971b94d9525
--- /dev/null
+++ b/app/assets/javascripts/project_select.js.coffee
@@ -0,0 +1,39 @@
+class @ProjectSelect
+  constructor: ->
+    $('.ajax-project-select').each (i, select) ->
+      @groupId = $(select).data('group-id')
+      @includeGroups = $(select).data('include-groups')
+
+      placeholder = "Search for project"
+      placeholder += " or group" if @includeGroups
+
+      $(select).select2
+        placeholder: placeholder
+        minimumInputLength: 0
+        query: (query) =>
+          finalCallback = (projects) ->
+            data = { results: projects }
+            query.callback(data)
+
+          if @includeGroups
+            projectsCallback = (projects) ->
+              groupsCallback = (groups) ->
+                data = groups.concat(projects)
+                finalCallback(data)
+
+              Api.groups query.term, false, groupsCallback
+          else
+            projectsCallback = finalCallback
+
+          if @groupId
+            Api.groupProjects @groupId, query.term, projectsCallback
+          else
+            Api.projects query.term, projectsCallback
+
+        id: (project) ->
+          project.web_url
+
+        text: (project) ->
+          project.name_with_namespace || project.name
+
+        dropdownCssClass: "ajax-project-dropdown"
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index d2f491daf789133ff1694d1bd79a74088accbc59..7eabd9c99f7b7f53201f58e180dc5ef118688d67 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -437,3 +437,16 @@ table {
 .alert, .progress {
   margin-bottom: $gl-padding;
 }
+
+.new-project-item-select-holder {
+  display: inline-block;
+  position: relative;
+
+  .new-project-item-select {
+    position: absolute;
+    top: 0;
+    right: 0;
+    width: 250px !important;
+    visibility: hidden;
+  }
+}
diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb
index 7e175d0de8a7cfa7b3c3f195c78f983abbc93dcf..05386d790ca887ba4c465b5f0ebcd846d7245c35 100644
--- a/app/helpers/selects_helper.rb
+++ b/app/helpers/selects_helper.rb
@@ -48,6 +48,19 @@ module SelectsHelper
     select2_tag(id, opts)
   end
 
+  def project_select_tag(id, opts = {})
+    opts[:class] ||= ''
+    opts[:class] << ' ajax-project-select'
+
+    unless opts.delete(:scope) == :all
+      if @group
+        opts['data-group-id'] = @group.id
+      end
+    end
+
+    hidden_field_tag(id, opts[:selected], opts)
+  end
+
   def select2_tag(id, opts = {})
     css_class = ''
     css_class << 'multiselect ' if opts[:multiple]
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index cd602e897b7f0809034389d3bf34ef4af9b32f94..2d3da01178a0a6adf4b353e85333e30f3b8858e1 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -4,14 +4,20 @@
   - if current_user
     = auto_discovery_link_tag(:atom, issues_dashboard_url(format: :atom, private_token: current_user.private_token), title: "#{current_user.name} issues")
 
+.project-issuable-filter
+  .controls
+    .pull-left
+      - if current_user
+        .hidden-xs.pull-left
+          = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: 'btn' do
+            %i.fa.fa-rss
 
-.append-bottom-20
-  .pull-right
-    - if current_user
-      .hidden-xs.pull-left.prepend-top-20
-        = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: '' do
-          %i.fa.fa-rss
+    = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue"
 
   = render 'shared/issuable/filter', type: :issues
 
-= render 'shared/issues'
+.gray-content-block.second-block
+  List all issues from all projects you have access to.
+
+.prepend-top-default
+  = render 'shared/issues'
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index d1f332fa0d3ad3fd4b32ec032ff199ab58595a1c..c5a5ec21f78aa35e3b0f2501cd88cfae96ac2e97 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -1,6 +1,14 @@
 - page_title "Merge Requests"
 - header_title  "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id)
 
-.append-bottom-20
+.project-issuable-filter
+  .controls
+    = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request"
+
   = render 'shared/issuable/filter', type: :merge_requests
-= render 'shared/merge_requests'
+
+.gray-content-block.second-block
+  List all merge requests from all projects you have access to.
+
+.prepend-top-default
+  = render 'shared/merge_requests'
diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml
index 635251e2374e82ceed3bc9b4a31b80489a9fe4b8..bec1692a4dedda7647d8ed053a1c1d04914fb227 100644
--- a/app/views/dashboard/milestones/index.html.haml
+++ b/app/views/dashboard/milestones/index.html.haml
@@ -1,12 +1,14 @@
 - page_title "Milestones"
-- header_title  "Milestones", dashboard_milestones_path
+- header_title "Milestones", dashboard_milestones_path
 
+.project-issuable-filter
+  .controls
+    = render 'shared/new_project_item_select', path: 'milestones/new', label: "New Milestone", include_groups: true
 
-= render 'shared/milestones_filter'
+  = render 'shared/milestones_filter'
 
 .gray-content-block
-  .oneline
-    List all milestones from all projects you have access to.
+  List all milestones from all projects you have access to.
 
 .milestones
   %ul.content-list
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index 08d97e418a334083bb0ca55f9424103d035759e0..90ade1e1680b07b60b9063e75ab2afd17d9f8620 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -4,21 +4,24 @@
   - if current_user
     = auto_discovery_link_tag(:atom, issues_group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} issues")
 
+.project-issuable-filter
+  .controls
+    .pull-left
+      - if current_user
+        .hidden-xs.pull-left
+          = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token), class: 'btn' do
+            %i.fa.fa-rss
 
+    = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue"
+
+  = render 'shared/issuable/filter', type: :issues
 
-= render 'shared/issuable/filter', type: :issues
 .gray-content-block.second-block
-  .pull-right
-    - if current_user
-      .hidden-xs.pull-left
-        = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token) do
-          %i.fa.fa-rss
-  %div
-    Only issues from
-    %strong #{@group.name}
-    group are listed here.
-    - if current_user
-      To see all issues you should visit #{link_to 'dashboard', issues_dashboard_path} page.
+  Only issues from
+  %strong #{@group.name}
+  group are listed here.
+  - if current_user
+    To see all issues you should visit #{link_to 'dashboard', issues_dashboard_path} page.
 
 .prepend-top-default
   = render 'shared/issues'
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index 425ad8331bffb6228a5f4e8f2d8970e499aae712..f662f5a8c17e2fd72c9350297604321babe93fd4 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -1,13 +1,18 @@
 - page_title "Merge Requests"
 - header_title group_title(@group, "Merge Requests", merge_requests_group_path(@group))
 
-= render 'shared/issuable/filter', type: :merge_requests
+.project-issuable-filter
+  .controls
+    = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request"
+
+  = render 'shared/issuable/filter', type: :merge_requests
+
 .gray-content-block.second-block
-  %div
-    Only merge requests from
-    %strong #{@group.name}
-    group are listed here.
-    - if current_user
-      To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page.
+  Only merge requests from
+  %strong #{@group.name}
+  group are listed here.
+  - if current_user
+    To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page.
+
 .prepend-top-default
   = render 'shared/merge_requests'
diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml
index 84ec77c61888e082a057a9e6e74230bf8520e416..b221d3a89a4a5654b46f6ad50b4555da30f2a1e7 100644
--- a/app/views/groups/milestones/index.html.haml
+++ b/app/views/groups/milestones/index.html.haml
@@ -1,18 +1,22 @@
 - page_title "Milestones"
 - header_title group_title(@group, "Milestones", group_milestones_path(@group))
 
-= render 'shared/milestones_filter'
+.project-issuable-filter
+  .controls
+    - if can?(current_user, :admin_milestones, @group)
+      .pull-right
+        %span.pull-right.hidden-xs
+          = link_to new_group_milestone_path(@group), class: "btn btn-new" do
+            = icon('plus')
+            New Milestone
+
+  = render 'shared/milestones_filter'
+
 .gray-content-block
-  - if can?(current_user, :admin_milestones, @group)
-    .pull-right
-      %span.pull-right.hidden-xs
-        = link_to new_group_milestone_path(@group), class: "btn btn-new" do
-          New Milestone
+  Only milestones from
+  %strong #{@group.name}
+  group are listed here.
 
-  .oneline
-    Only milestones from
-    %strong #{@group.name}
-    group are listed here.
 .milestones
   %ul.content-list
     - if @milestones.blank?
diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml
index a207385bd4351984a40d0073b66c6cec30c6377b..114b06457a52aead1faea05a1e3c89e506527ae0 100644
--- a/app/views/projects/milestones/index.html.haml
+++ b/app/views/projects/milestones/index.html.haml
@@ -1,15 +1,18 @@
 - page_title "Milestones"
 = render "header_title"
-= render 'shared/milestones_filter'
 
-.gray-content-block
-  .pull-right
-    - if can? current_user, :admin_milestone, @project
+
+.project-issuable-filter
+  .controls
+    - if can?(current_user, :admin_milestone, @project)
       = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "pull-right btn btn-new", title: "New Milestone" do
         %i.fa.fa-plus
         New Milestone
-  .oneline
-    Milestone allows you to group issues and set due date for it
+
+  = render 'shared/milestones_filter'
+
+.gray-content-block
+  Milestone allows you to group issues and set due date for it
 
 .milestones
   %ul.content-list
diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..c4431d66927eb999b7fd5958e6e69d118b450f57
--- /dev/null
+++ b/app/views/shared/_new_project_item_select.html.haml
@@ -0,0 +1,20 @@
+- if @projects.any?
+  .prepend-left-10.new-project-item-select-holder
+    = project_select_tag :project_path, class: "new-project-item-select", data: { include_groups: local_assigns[:include_groups] }
+    %a.btn.btn-new.new-project-item-select-button
+      = icon('plus')
+      = local_assigns[:label]
+      %b.caret
+
+  :javascript
+    $('.new-project-item-select-button').on('click', function() {
+      $('.new-project-item-select').select2('open');
+    });
+
+    var relativePath = '#{local_assigns[:path]}';
+
+    $('.new-project-item-select').on('click', function() {
+      window.location = $(this).val() + '/' + relativePath;
+    });
+
+    new ProjectSelect()
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 0b9f6406d8dd71a7c7c3b8a181666c50326117b2..808675d8605006c142a25eb188d66190c6bb73da 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -1,6 +1,6 @@
 # Groups
 
-## List project groups
+## List groups
 
 Get a list of groups. (As user: my groups, as admin: all groups)
 
@@ -21,6 +21,70 @@ GET /groups
 
 You can search for groups by name or path, see below.
 
+
+## List a group's projects
+
+Get a list of projects in this group.
+
+```
+GET /groups/:id/projects
+```
+
+Parameters:
+
+- `archived` (optional) - if passed, limit by archived status
+- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
+- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
+- `search` (optional) - Return list of authorized projects according to a search criteria
+- `ci_enabled_first` - Return projects ordered by ci_enabled flag. Projects with enabled GitLab CI go first
+
+```json
+[
+  {
+    "id": 4,
+    "description": null,
+    "default_branch": "master",
+    "public": false,
+    "visibility_level": 0,
+    "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git",
+    "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
+    "web_url": "http://example.com/diaspora/diaspora-client",
+    "tag_list": [
+      "example",
+      "disapora client"
+    ],
+    "owner": {
+      "id": 3,
+      "name": "Diaspora",
+      "created_at": "2013-09-30T13: 46: 02Z"
+    },
+    "name": "Diaspora Client",
+    "name_with_namespace": "Diaspora / Diaspora Client",
+    "path": "diaspora-client",
+    "path_with_namespace": "diaspora/diaspora-client",
+    "issues_enabled": true,
+    "merge_requests_enabled": true,
+    "builds_enabled": true,
+    "wiki_enabled": true,
+    "snippets_enabled": false,
+    "created_at": "2013-09-30T13: 46: 02Z",
+    "last_activity_at": "2013-09-30T13: 46: 02Z",
+    "creator_id": 3,
+    "namespace": {
+      "created_at": "2013-09-30T13: 46: 02Z",
+      "description": "",
+      "id": 3,
+      "name": "Diaspora",
+      "owner_id": 1,
+      "path": "diaspora",
+      "updated_at": "2013-09-30T13: 46: 02Z"
+    },
+    "archived": false,
+    "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png"
+  }
+]
+```
+
 ## Details of a group
 
 Get all details of a group.
@@ -186,7 +250,7 @@ To get more (up to 100), pass the following as an argument to the API call:
 /groups?per_page=100
 ```
 
-And to switch pages add: 
+And to switch pages add:
 ```
 /groups?per_page=100&page=2
-```
\ No newline at end of file
+```
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 024aeec2e14bde0d9eb41b052af7d18f5117e59c..1a14d870a4a396e51ea76c0792112913f1248498 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -65,6 +65,18 @@ module API
         DestroyGroupService.new(group, current_user).execute
       end
 
+      # Get a list of projects in this group
+      #
+      # Example Request:
+      #   GET /groups/:id/projects
+      get ":id/projects" do
+        group = find_group(params[:id])
+        projects = group.projects
+        projects = filter_projects(projects)
+        projects = paginate projects
+        present projects, with: Entities::Project
+      end
+
       # Transfer a project to the Group namespace
       #
       # Parameters:
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 13cced81875c59f7680a92082e72c9c89542a56d..4cfa49d15666d06deeee90d6ba0181acde3978c5 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -10,6 +10,8 @@ describe API::API, api: true  do
   let(:avatar_file_path) { File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif') }
   let!(:group1) { create(:group, avatar: File.open(avatar_file_path)) }
   let!(:group2) { create(:group) }
+  let!(:project1) { create(:project, namespace: group1) }
+  let!(:project2) { create(:project, namespace: group2) }
 
   before do
     group1.add_owner(user1)
@@ -67,7 +69,7 @@ describe API::API, api: true  do
       it "should return any existing group" do
         get api("/groups/#{group2.id}", admin)
         expect(response.status).to eq(200)
-        json_response['name'] == group2.name
+        expect(json_response['name']).to eq(group2.name)
       end
 
       it "should not return a non existing group" do
@@ -80,7 +82,7 @@ describe API::API, api: true  do
       it 'should return any existing group' do
         get api("/groups/#{group1.path}", admin)
         expect(response.status).to eq(200)
-        json_response['name'] == group2.name
+        expect(json_response['name']).to eq(group1.name)
       end
 
       it 'should not return a non existing group' do
@@ -95,6 +97,59 @@ describe API::API, api: true  do
     end
   end
 
+  describe "GET /groups/:id/projects" do
+    context "when authenticated as user" do
+      it "should return the group's projects" do
+        get api("/groups/#{group1.id}/projects", user1)
+        expect(response.status).to eq(200)
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['name']).to eq(project1.name)
+      end
+
+      it "should not return a non existing group" do
+        get api("/groups/1328/projects", user1)
+        expect(response.status).to eq(404)
+      end
+
+      it "should not return a group not attached to user1" do
+        get api("/groups/#{group2.id}/projects", user1)
+        expect(response.status).to eq(403)
+      end
+    end
+
+    context "when authenticated as admin" do
+      it "should return any existing group" do
+        get api("/groups/#{group2.id}/projects", admin)
+        expect(response.status).to eq(200)
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['name']).to eq(project2.name)
+      end
+
+      it "should not return a non existing group" do
+        get api("/groups/1328/projects", admin)
+        expect(response.status).to eq(404)
+      end
+    end
+
+    context 'when using group path in URL' do
+      it 'should return any existing group' do
+        get api("/groups/#{group1.path}/projects", admin)
+        expect(response.status).to eq(200)
+        expect(json_response.first['name']).to eq(project1.name)
+      end
+
+      it 'should not return a non existing group' do
+        get api('/groups/unknown/projects', admin)
+        expect(response.status).to eq(404)
+      end
+
+      it 'should not return a group not attached to user1' do
+        get api("/groups/#{group2.path}/projects", user1)
+        expect(response.status).to eq(403)
+      end
+    end
+  end
+
   describe "POST /groups" do
     context "when authenticated as user without group permissions" do
       it "should not create group" do