Commit c84b14d2 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq into ce-to-ee

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>

Conflicts:
	app/controllers/autocomplete_controller.rb
	app/controllers/omniauth_callbacks_controller.rb
	app/controllers/projects/services_controller.rb
	app/helpers/projects_helper.rb
	app/services/audit_event_service.rb
	db/schema.rb
	doc/api/users.md
	doc/update/6.x-or-7.x-to-7.13.md
	features/project/project.feature
parents 5c3bdaf1 070d6a24
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 7.13.0 (unreleased) v 7.13.0 (unreleased)
- Only enable HSTS header for HTTPS and port 443 (Stan Hu)
- Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu)
- Fix redirection to home page URL for unauthorized users (Daniel Gerhardt)
- Add branch switching support for graphs (Daniel Gerhardt)
- Fix external issue tracker hook/test for HTTPS URLs (Daniel Gerhardt) - Fix external issue tracker hook/test for HTTPS URLs (Daniel Gerhardt)
- Remove link leading to a 404 error in Deploy Keys page (Stan Hu) - Remove link leading to a 404 error in Deploy Keys page (Stan Hu)
- Add support for unlocking users in admin settings (Stan Hu) - Add support for unlocking users in admin settings (Stan Hu)
- Fix order of issues imported form GitHub (Hiroyuki Sato) - Add Irker service configuration options (Stan Hu)
- Fix order of issues imported from GitHub (Hiroyuki Sato)
- Bump rugments to 1.0.0beta8 to fix C prototype function highlighting (Jonathon Reinhart) - Bump rugments to 1.0.0beta8 to fix C prototype function highlighting (Jonathon Reinhart)
- Fix Merge Request webhook to properly fire "merge" action when accepted from the web UI - Fix Merge Request webhook to properly fire "merge" action when accepted from the web UI
- Add `two_factor_enabled` field to admin user API (Stan Hu) - Add `two_factor_enabled` field to admin user API (Stan Hu)
- Fix invalid timestamps in RSS feeds (Rowan Wookey) - Fix invalid timestamps in RSS feeds (Rowan Wookey)
- Fix error when deleting a user who has projects (Stan Hu)
- Fix downloading of patches on public merge requests when user logged out (Stan Hu) - Fix downloading of patches on public merge requests when user logged out (Stan Hu)
- The password for the default administrator (root) account has been changed from "5iveL!fe" to "password". - The password for the default administrator (root) account has been changed from "5iveL!fe" to "password".
- Fix Error 500 when relative submodule resolves to a namespace that has a different name from its path (Stan Hu) - Fix Error 500 when relative submodule resolves to a namespace that has a different name from its path (Stan Hu)
...@@ -17,6 +21,7 @@ v 7.13.0 (unreleased) ...@@ -17,6 +21,7 @@ v 7.13.0 (unreleased)
- Update maintenance documentation to explain no need to recompile asssets for omnibus installations (Stan Hu) - Update maintenance documentation to explain no need to recompile asssets for omnibus installations (Stan Hu)
- Support commenting on diffs in side-by-side mode (Stan Hu) - Support commenting on diffs in side-by-side mode (Stan Hu)
- Fix JavaScript error when clicking on the comment button on a diff line that has a comment already (Stan Hu) - Fix JavaScript error when clicking on the comment button on a diff line that has a comment already (Stan Hu)
- Return 40x error codes if branch could not be deleted in UI (Stan Hu)
- Remove project visibility icons from dashboard projects list - Remove project visibility icons from dashboard projects list
- Rename "Design" profile settings page to "Preferences". - Rename "Design" profile settings page to "Preferences".
- Allow users to customize their default Dashboard page. - Allow users to customize their default Dashboard page.
...@@ -34,6 +39,20 @@ v 7.13.0 (unreleased) ...@@ -34,6 +39,20 @@ v 7.13.0 (unreleased)
- Faster automerge check and merge itself when source and target branches are in same repository - Faster automerge check and merge itself when source and target branches are in same repository
- Correctly show anonymous authorized applications under Profile > Applications. - Correctly show anonymous authorized applications under Profile > Applications.
- Query Optimization in MySQL. - Query Optimization in MySQL.
- Allow users to be blocked and unblocked via the API
- Use native Postgres database cleaning during backup restore
- Redesign project page. Show README as default instead of activity. Move project activity to separate page
- Make left menu more hierarchical and less contextual by adding back item at top
- A fork can’t have a visibility level that is greater than the original project.
- Faster code search in repository and wiki. Fixes search page timeout for big repositories
- Allow administrators to disable 2FA for a specific user
- Add error message for SSH key linebreaks
v 7.12.2
- Correctly show anonymous authorized applications under Profile > Applications.
- Faster automerge check and merge itself when source and target branches are in same repository
- Audit log for user authentication
- Fix transferring of project to another group using the API.
v 7.12.1 v 7.12.1
- Fix error when deleting a user who has projects (Stan Hu) - Fix error when deleting a user who has projects (Stan Hu)
...@@ -43,6 +62,8 @@ v 7.12.1 ...@@ -43,6 +62,8 @@ v 7.12.1
- Fix closed merge request scope at milestone page (Dmitriy Zaporozhets) - Fix closed merge request scope at milestone page (Dmitriy Zaporozhets)
- Revert merge request states renaming - Revert merge request states renaming
- Fix hooks for web based events with external issue references (Daniel Gerhardt) - Fix hooks for web based events with external issue references (Daniel Gerhardt)
- Improve performance for issue and merge request pages
- Compress database dumps to reduce backup size
v 7.12.0 v 7.12.0
- Fix Error 500 when one user attempts to access a personal, internal snippet (Stan Hu) - Fix Error 500 when one user attempts to access a personal, internal snippet (Stan Hu)
......
...@@ -67,7 +67,7 @@ To start with GitLab download the [GitLab Development Kit](https://gitlab.com/gi ...@@ -67,7 +67,7 @@ To start with GitLab download the [GitLab Development Kit](https://gitlab.com/gi
If you can, please submit a merge request with the fix or improvements including tests. If you don't know how to fix the issue but can write a test that exposes the issue we will accept that as well. In general bug fixes that include a regression test are merged quickly while new features without proper tests are least likely to receive timely feedback. The workflow to make a merge request is as follows: If you can, please submit a merge request with the fix or improvements including tests. If you don't know how to fix the issue but can write a test that exposes the issue we will accept that as well. In general bug fixes that include a regression test are merged quickly while new features without proper tests are least likely to receive timely feedback. The workflow to make a merge request is as follows:
1. Fork the project on GitLab Cloud 1. Fork the project into your personal space on GitLab.com
1. Create a feature branch 1. Create a feature branch
1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code 1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code
1. Add your changes to the [CHANGELOG](CHANGELOG) 1. Add your changes to the [CHANGELOG](CHANGELOG)
......
...@@ -204,7 +204,7 @@ gem 'jquery-ui-rails' ...@@ -204,7 +204,7 @@ gem 'jquery-ui-rails'
gem 'nprogress-rails' gem 'nprogress-rails'
gem 'raphael-rails', '~> 2.1.2' gem 'raphael-rails', '~> 2.1.2'
gem 'request_store' gem 'request_store'
gem 'select2-rails' gem 'select2-rails', '~> 3.5.9'
gem 'virtus' gem 'virtus'
gem "gitlab-license", "~> 0.0.2" gem "gitlab-license", "~> 0.0.2"
...@@ -234,26 +234,20 @@ group :development, :test do ...@@ -234,26 +234,20 @@ group :development, :test do
gem 'fuubar', '~> 2.0.0' gem 'fuubar', '~> 2.0.0'
gem 'pry-rails' gem 'pry-rails'
gem 'coveralls', require: false gem 'coveralls', '~> 0.8.2', require: false
gem 'database_cleaner', '~> 1.4.0' gem 'database_cleaner', '~> 1.4.0'
gem 'factory_girl_rails' gem 'factory_girl_rails'
gem 'rspec-rails', '~> 3.3.0' gem 'rspec-rails', '~> 3.3.0'
gem 'rubocop', '0.28.0', require: false gem 'rubocop', '0.28.0', require: false
gem 'spinach-rails' gem 'spinach-rails'
# rest-client is a coveralls dependency and not used directly in GitLab, but
# we specify a version here to pick up some security fixes.
# See https://github.com/rest-client/rest-client/issues/369
# and http://www.osvdb.org/show/osvdb/117461
gem 'rest-client', '~> 1.8.0'
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826) # Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
gem 'minitest', '~> 5.3.0' gem 'minitest', '~> 5.3.0'
# Generate Fake data # Generate Fake data
gem 'ffaker', '~> 2.0.0' gem 'ffaker', '~> 2.0.0'
gem 'capybara', '~> 2.3.0' gem 'capybara', '~> 2.4.0'
gem 'capybara-screenshot', '~> 1.0.0' gem 'capybara-screenshot', '~> 1.0.0'
gem 'poltergeist', '~> 1.6.0' gem 'poltergeist', '~> 1.6.0'
......
...@@ -82,7 +82,7 @@ GEM ...@@ -82,7 +82,7 @@ GEM
columnize (~> 0.8) columnize (~> 0.8)
debugger-linecache (~> 1.2) debugger-linecache (~> 1.2)
cal-heatmap-rails (0.0.1) cal-heatmap-rails (0.0.1)
capybara (2.3.0) capybara (2.4.4)
mime-types (>= 1.16) mime-types (>= 1.16)
nokogiri (>= 1.3.3) nokogiri (>= 1.3.3)
rack (>= 1.0.0) rack (>= 1.0.0)
...@@ -599,7 +599,7 @@ GEM ...@@ -599,7 +599,7 @@ GEM
seed-fu (2.3.5) seed-fu (2.3.5)
activerecord (>= 3.1, < 4.3) activerecord (>= 3.1, < 4.3)
activesupport (>= 3.1, < 4.3) activesupport (>= 3.1, < 4.3)
select2-rails (3.5.2) select2-rails (3.5.9.3)
thor (~> 0.14) thor (~> 0.14)
settingslogic (2.0.9) settingslogic (2.0.9)
sexp_processor (4.4.5) sexp_processor (4.4.5)
...@@ -704,7 +704,7 @@ GEM ...@@ -704,7 +704,7 @@ GEM
underscore-rails (1.4.4) underscore-rails (1.4.4)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.6) unf_ext (0.0.7.1)
unicorn (4.6.3) unicorn (4.6.3)
kgio (~> 2.6) kgio (~> 2.6)
rack rack
...@@ -754,13 +754,13 @@ DEPENDENCIES ...@@ -754,13 +754,13 @@ DEPENDENCIES
browser (~> 0.8.0) browser (~> 0.8.0)
byebug byebug
cal-heatmap-rails (~> 0.0.1) cal-heatmap-rails (~> 0.0.1)
capybara (~> 2.3.0) capybara (~> 2.4.0)
capybara-screenshot (~> 1.0.0) capybara-screenshot (~> 1.0.0)
carrierwave carrierwave
charlock_holmes charlock_holmes
coffee-rails coffee-rails
colored colored
coveralls coveralls (~> 0.8.2)
creole (~> 0.3.6) creole (~> 0.3.6)
d3_rails (~> 3.5.5) d3_rails (~> 3.5.5)
database_cleaner (~> 1.4.0) database_cleaner (~> 1.4.0)
...@@ -836,7 +836,6 @@ DEPENDENCIES ...@@ -836,7 +836,6 @@ DEPENDENCIES
redis-rails redis-rails
request_store request_store
rerun (~> 0.10.0) rerun (~> 0.10.0)
rest-client (~> 1.8.0)
rqrcode-rails3 rqrcode-rails3
rspec-rails (~> 3.3.0) rspec-rails (~> 3.3.0)
rubocop (= 0.28.0) rubocop (= 0.28.0)
...@@ -845,7 +844,7 @@ DEPENDENCIES ...@@ -845,7 +844,7 @@ DEPENDENCIES
sass-rails (~> 4.0.5) sass-rails (~> 4.0.5)
sdoc sdoc
seed-fu seed-fu
select2-rails select2-rails (~> 3.5.9)
settingslogic settingslogic
shoulda-matchers (~> 2.8.0) shoulda-matchers (~> 2.8.0)
sidekiq (~> 3.3) sidekiq (~> 3.3)
...@@ -881,4 +880,4 @@ DEPENDENCIES ...@@ -881,4 +880,4 @@ DEPENDENCIES
wikicloth (= 0.8.1) wikicloth (= 0.8.1)
BUNDLED WITH BUNDLED WITH
1.10.4 1.10.5
...@@ -49,7 +49,7 @@ To use EE and get official support please [become a subscriber](https://about.gi ...@@ -49,7 +49,7 @@ To use EE and get official support please [become a subscriber](https://about.gi
## Code status ## Code status
- [![build status](https://ci.gitlab.org/projects/1/status.png?ref=master)](https://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch) - [![build status](https://ci.gitlab.com/projects/1/status.png?ref=master)](https://ci.gitlab.com/projects/1?ref=master) on ci.gitlab.com (master branch)
- [![Build Status](https://semaphoreapp.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/243338/badge.png)](https://semaphoreapp.com/gitlabhq/gitlabhq) - [![Build Status](https://semaphoreapp.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/243338/badge.png)](https://semaphoreapp.com/gitlabhq/gitlabhq)
...@@ -98,7 +98,7 @@ Since 2011 a minor or major version of GitLab is released on the 22nd of every m ...@@ -98,7 +98,7 @@ Since 2011 a minor or major version of GitLab is released on the 22nd of every m
## Upgrading ## Upgrading
For updating the Omnibus installation please see the [update documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md). For installations from source there is an [upgrader script](doc/update/upgrader.md) and there are [upgrade guides](doc/update) detailing all necessary commands to migrate to the next version. For upgrading information please see our [update page](https://about.gitlab.com/update/).
## Install a development environment ## Install a development environment
...@@ -125,4 +125,4 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on ...@@ -125,4 +125,4 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on
## Is it awesome? ## Is it awesome?
Thanks for [asking this question](https://twitter.com/supersloth/status/489462789384056832) Joshua. Thanks for [asking this question](https://twitter.com/supersloth/status/489462789384056832) Joshua.
[These people](https://twitter.com/gitlab/favorites) seem to like it. [These people](https://twitter.com/gitlab/favorites) seem to like it.
\ No newline at end of file
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#= require jquery.scrollTo #= require jquery.scrollTo
#= require jquery.blockUI #= require jquery.blockUI
#= require jquery.turbolinks #= require jquery.turbolinks
#= require jquery.sticky-kit.min
#= require turbolinks #= require turbolinks
#= require autosave #= require autosave
#= require bootstrap #= require bootstrap
...@@ -41,6 +40,7 @@ ...@@ -41,6 +40,7 @@
#= require shortcuts_issuable #= require shortcuts_issuable
#= require shortcuts_network #= require shortcuts_network
#= require cal-heatmap #= require cal-heatmap
#= require jquery.nicescroll.min
#= require_tree . #= require_tree .
window.slugify = (text) -> window.slugify = (text) ->
...@@ -107,6 +107,8 @@ window.addEventListener "hashchange", shiftWindow ...@@ -107,6 +107,8 @@ window.addEventListener "hashchange", shiftWindow
$.timeago.settings.allowFuture = true $.timeago.settings.allowFuture = true
$ -> $ ->
$(".nicescroll").niceScroll(cursoropacitymax: '0.4', cursorcolor: '#FFF', cursorborder: "1px solid #FFF")
# Click a .js-select-on-focus field, select the contents # Click a .js-select-on-focus field, select the contents
$(".js-select-on-focus").on "focusin", -> $(".js-select-on-focus").on "focusin", ->
# Prevent a mouseup event from deselecting the input # Prevent a mouseup event from deselecting the input
......
...@@ -62,8 +62,9 @@ class Dispatcher ...@@ -62,8 +62,9 @@ class Dispatcher
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
when 'projects:commits:show' when 'projects:commits:show'
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
when 'projects:activity'
shortcut_handler = new ShortcutsNavigation()
when 'projects:show' when 'projects:show'
new Activities()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
when 'groups:show' when 'groups:show'
new Activities() new Activities()
......
...@@ -25,10 +25,10 @@ class @DropzoneInput ...@@ -25,10 +25,10 @@ class @DropzoneInput
form_dropzone = $(form).find('.div-dropzone') form_dropzone = $(form).find('.div-dropzone')
form_dropzone.parent().addClass "div-dropzone-wrapper" form_dropzone.parent().addClass "div-dropzone-wrapper"
form_dropzone.append divHover form_dropzone.append divHover
$(".div-dropzone-hover").append iconPaperclip form_dropzone.find(".div-dropzone-hover").append iconPaperclip
form_dropzone.append divSpinner form_dropzone.append divSpinner
$(".div-dropzone-spinner").append iconSpinner form_dropzone.find(".div-dropzone-spinner").append iconSpinner
$(".div-dropzone-spinner").css form_dropzone.find(".div-dropzone-spinner").css
"opacity": 0 "opacity": 0
"display": "none" "display": "none"
......
...@@ -69,7 +69,6 @@ class @MergeRequestTabs ...@@ -69,7 +69,6 @@ class @MergeRequestTabs
@loadCommits($target.attr('href')) @loadCommits($target.attr('href'))
else if action == 'diffs' else if action == 'diffs'
@loadDiff($target.attr('href')) @loadDiff($target.attr('href'))
@stickyDiffHeaders()
@setCurrentAction(action) @setCurrentAction(action)
...@@ -137,15 +136,11 @@ class @MergeRequestTabs ...@@ -137,15 +136,11 @@ class @MergeRequestTabs
url: "#{source}.json" url: "#{source}.json"
success: (data) => success: (data) =>
document.getElementById('diffs').innerHTML = data.html document.getElementById('diffs').innerHTML = data.html
@stickyDiffHeaders()
@diffsLoaded = true @diffsLoaded = true
toggleLoading: -> toggleLoading: ->
$('.mr-loading-status .loading').toggle() $('.mr-loading-status .loading').toggle()
stickyDiffHeaders: ->
$('.diff-header').trigger('sticky_kit:recalc')
_get: (options) -> _get: (options) ->
defaults = { defaults = {
beforeSend: @toggleLoading beforeSend: @toggleLoading
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
@loading.show() @loading.show()
$.ajax $.ajax
type: "GET" type: "GET"
url: location.href url: $(".content_list").data('href') || location.href
data: "limit=" + @limit + "&offset=" + @offset data: "limit=" + @limit + "&offset=" + @offset
complete: => complete: =>
@loading.hide() @loading.hide()
......
class @ProjectShow class @ProjectShow
constructor: -> constructor: ->
$('.project-home-panel .star').on 'ajax:success', (e, data, status, xhr) -> # I kept class for future
$(@).toggleClass('on').find('.count').html(data.star_count)
.on 'ajax:error', (e, xhr, status, error) ->
new Flash('Star toggle failed. Try again later.', 'alert')
$("a[data-toggle='tab']").on "shown.bs.tab", (e) ->
$.cookie "default_view", $(e.target).attr("href"), { expires: 30, path: '/' }
defaultView = $.cookie("default_view")
if defaultView
$("a[href=" + defaultView + "]").tab "show"
else
$("a[data-toggle='tab']:first").tab "show"
...@@ -4,6 +4,7 @@ class @ShortcutsNavigation extends Shortcuts ...@@ -4,6 +4,7 @@ class @ShortcutsNavigation extends Shortcuts
constructor: -> constructor: ->
super() super()
Mousetrap.bind('g p', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-project')) Mousetrap.bind('g p', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-project'))
Mousetrap.bind('g e', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-project-activity'))
Mousetrap.bind('g f', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-tree')) Mousetrap.bind('g f', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-tree'))
Mousetrap.bind('g c', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-commits')) Mousetrap.bind('g c', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-commits'))
Mousetrap.bind('g n', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-network')) Mousetrap.bind('g n', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-network'))
......
...@@ -109,7 +109,7 @@ ...@@ -109,7 +109,7 @@
font-size: 1.2em; font-size: 1.2em;
} }
blockquote p { blockquote {
color: #888; color: #888;
font-size: 15px; font-size: 15px;
line-height: 1.5; line-height: 1.5;
......
...@@ -44,20 +44,18 @@ ...@@ -44,20 +44,18 @@
.project-home-panel { .project-home-panel {
padding-left: 0 !important; padding-left: 0 !important;
.project-home-row { .project-avatar {
.project-home-desc { display: block;
margin-right: 0 !important;
float: none !important;
}
.project-repo-buttons {
position: static;
margin-top: 15px;
width: 100%;
float: none;
text-align: left;
}
} }
.project-repo-buttons,
.git-clone-holder {
display: none;
}
}
.project-stats {
display: none;
} }
.container .title { .container .title {
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
.sidebar-wrapper { .sidebar-wrapper {
position: fixed; position: fixed;
top: 0; top: 0;
bottom: 0;
overflow-y: auto;
overflow-x: hidden;
left: 0; left: 0;
height: 100%; height: 100%;
transition-duration: .3s; transition-duration: .3s;
...@@ -21,8 +24,9 @@ ...@@ -21,8 +24,9 @@
} }
.nav-sidebar { .nav-sidebar {
margin-top: 29 + $header-height;
margin-bottom: 50px;
transition-duration: .3s; transition-duration: .3s;
margin: 0;
list-style: none; list-style: none;
overflow: hidden; overflow: hidden;
...@@ -39,12 +43,12 @@ ...@@ -39,12 +43,12 @@
} }
a { a {
padding: 8px 15px;
font-size: 13px;
line-height: 18px;
color: $gray; color: $gray;
display: block; display: block;
text-decoration: none; text-decoration: none;
padding: 8px 15px;
font-size: 14px;
line-height: 20px;
padding-left: 16px; padding-left: 16px;
&:hover { &:hover {
...@@ -88,14 +92,17 @@ ...@@ -88,14 +92,17 @@
width: $sidebar_width; width: $sidebar_width;
.nav-sidebar { .nav-sidebar {
margin-top: 29px;
position: fixed;
top: $header-height;
width: $sidebar_width; width: $sidebar_width;
} }
.nav-sidebar li a{ .nav-sidebar li a{
width: 230px; width: 230px;
&.back-link {
i {
visibility: hidden;
}
}
} }
} }
} }
...@@ -108,15 +115,9 @@ ...@@ -108,15 +115,9 @@
width: $sidebar_collapsed_width; width: $sidebar_collapsed_width;
.nav-sidebar { .nav-sidebar {
margin-top: 29px;
position: fixed;
top: $header-height;
width: $sidebar_collapsed_width; width: $sidebar_collapsed_width;
li a { li a {
font-size: 14px;
padding: 8px 15px;
text-align: left;
padding-left: 16px; padding-left: 16px;
} }
} }
...@@ -175,7 +176,7 @@ ...@@ -175,7 +176,7 @@
} }
.sidebar-user { .sidebar-user {
position: absolute; position: fixed;
bottom: 0; bottom: 0;
width: $sidebar_width; width: $sidebar_width;
padding: 10px; padding: 10px;
......
...@@ -17,6 +17,14 @@ pre { ...@@ -17,6 +17,14 @@ pre {
background: #333; background: #333;
color: $background-color; color: $background-color;
} }
&.plain-readme {
background: none;
border: none;
padding: 0;
margin: 0;
font-size: 14px;
}
} }
.monospace { .monospace {
......
...@@ -72,13 +72,28 @@ ul.notes { ...@@ -72,13 +72,28 @@ ul.notes {
.note { .note {
display: block; display: block;
position:relative; position:relative;
.note-body { .note-body {
overflow: auto; overflow: auto;
.note-text { .note-text {
overflow: auto; overflow: auto;
word-wrap: break-word; word-wrap: break-word;
@include md-typography; @include md-typography;
// Reset ul style types since we're nested inside a ul already
& > ul {
list-style-type: disc;
ul {
list-style-type: circle;
ul {
list-style-type: square;
}
}
}
// Reduce left padding of first task list ul element // Reduce left padding of first task list ul element
ul.task-list:first-child { ul.task-list:first-child {
padding-left: 10px; padding-left: 10px;
...@@ -94,6 +109,7 @@ ul.notes { ...@@ -94,6 +109,7 @@ ul.notes {
} }
} }
} }
.note-header { .note-header {
padding-bottom: 3px; padding-bottom: 3px;
} }
......
...@@ -15,48 +15,31 @@ ...@@ -15,48 +15,31 @@
} }
.project-home-panel { .project-home-panel {
margin-top: 10px; text-align: center;
margin-bottom: 15px; margin-bottom: 20px;
position: relative;
padding-left: 65px;
min-height: 50px;
.project-identicon-holder { .project-identicon-holder {
position: absolute; margin-bottom: 15px;
left: 0;
top: -14px;
.avatar { .avatar, .identicon {
width: 50px; margin: 0 auto;
height: 50px; float: none;
} }
.identicon { .identicon {
font-size: 26px; @include border-radius(50%);
line-height: 50px;
} }
} }
.project-home-row { .lead {
@extend .clearfix; p {
margin-bottom: 15px; display: inline;
&.project-home-row-top {
margin-bottom: 15px;
} }
}
.project-home-desc { .git-clone-holder {
color: $gray; max-width: 600px;
float: left; margin: 0 auto;
font-size: 16px;
line-height: 1.3;
margin-right: 250px;
// Render Markdown-generated HTML inline for this block
p {
display: inline;
}
}
} }
.visibility-level-label { .visibility-level-label {
...@@ -67,22 +50,22 @@ ...@@ -67,22 +50,22 @@
} }
.project-repo-buttons { .project-repo-buttons {
margin-top: -3px; margin-top: 25px;
position: absolute; margin-bottom: 25px;
right: 0;
width: 265px;
text-align: right;
.btn { .btn {
@extend .btn-info;
margin-left: 10px;
font-weight: bold; font-weight: bold;
font-size: 14px; font-size: 14px;
line-height: 16px; line-height: 16px;
padding: 8px 12px;
.count { .count {
padding-left: 10px; padding-left: 7px;
border-left: 1px solid #ccc;
display: inline-block; display: inline-block;
margin-left: 10px; margin-left: 7px;
} }
} }
} }
...@@ -307,3 +290,15 @@ table.table.protected-branches-list tr.no-border { ...@@ -307,3 +290,15 @@ table.table.protected-branches-list tr.no-border {
float: left; float: left;
margin-right: 10px; margin-right: 10px;
} }
.project-stats {
text-align: center;
ul.nav-pills { display:inline-block; }
li { display:inline; }
a { float:left; }
}
pre.light-well {
border-color: #f1f1f1;
}
...@@ -35,9 +35,9 @@ ...@@ -35,9 +35,9 @@
.sidebar-wrapper { .sidebar-wrapper {
background: $color-darker; background: $color-darker;
border-right: 1px solid $color-darker;
.sidebar-user { .sidebar-user {
background: $color-darker;
color: $color-light; color: $color-light;
&:hover { &:hover {
......
...@@ -23,7 +23,8 @@ class Admin::ProjectsController < Admin::ApplicationController ...@@ -23,7 +23,8 @@ class Admin::ProjectsController < Admin::ApplicationController
end end
def transfer def transfer
::Projects::TransferService.new(@project, current_user, params.dup).execute namespace = Namespace.find_by(id: params[:new_namespace_id])
::Projects::TransferService.new(@project, current_user, params.dup).execute(namespace)
@project.reload @project.reload
redirect_to admin_namespace_project_path(@project.namespace, @project) redirect_to admin_namespace_project_path(@project.namespace, @project)
......
...@@ -55,6 +55,12 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -55,6 +55,12 @@ class Admin::UsersController < Admin::ApplicationController
end end
end end
def disable_two_factor
user.disable_two_factor!
redirect_to admin_user_path(user),
notice: 'Two-factor Authentication has been disabled for this user'
end
def create def create
opts = { opts = {
force_random_password: true, force_random_password: true,
......
...@@ -56,7 +56,7 @@ class ApplicationController < ActionController::Base ...@@ -56,7 +56,7 @@ class ApplicationController < ActionController::Base
def authenticate_user!(*args) def authenticate_user!(*args)
# If user is not signed-in and tries to access root_path - redirect him to landing page # If user is not signed-in and tries to access root_path - redirect him to landing page
if current_application_settings.home_page_url.present? if current_application_settings.home_page_url.present?
if current_user.nil? && controller_name == 'dashboard' && action_name == 'show' if current_user.nil? && root_path == request.path
redirect_to current_application_settings.home_page_url and return redirect_to current_application_settings.home_page_url and return
end end
end end
...@@ -183,7 +183,10 @@ class ApplicationController < ActionController::Base ...@@ -183,7 +183,10 @@ class ApplicationController < ActionController::Base
headers['X-XSS-Protection'] = '1; mode=block' headers['X-XSS-Protection'] = '1; mode=block'
headers['X-UA-Compatible'] = 'IE=edge' headers['X-UA-Compatible'] = 'IE=edge'
headers['X-Content-Type-Options'] = 'nosniff' headers['X-Content-Type-Options'] = 'nosniff'
headers['Strict-Transport-Security'] = 'max-age=31536000' if Gitlab.config.gitlab.https # Enabling HSTS for non-standard ports would send clients to the wrong port
if Gitlab.config.gitlab.https and Gitlab.config.gitlab.port == 443
headers['Strict-Transport-Security'] = 'max-age=31536000'
end
end end
def add_gon_variables def add_gon_variables
...@@ -271,6 +274,7 @@ class ApplicationController < ActionController::Base ...@@ -271,6 +274,7 @@ class ApplicationController < ActionController::Base
params[:scope] = 'all' if params[:scope].blank? params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank? params[:state] = 'opened' if params[:state].blank?
@sort = params[:sort]
@filter_params = params.dup @filter_params = params.dup
if @project if @project
......
class AutocompleteController < ApplicationController class AutocompleteController < ApplicationController
skip_before_action :authenticate_user!, only: [:users]
def users def users
@users = begin
if params[:project_id].present? @users =
project = Project.find(params[:project_id]) if params[:project_id].present?
project = Project.find(params[:project_id])
if can?(current_user, :read_project, project) if can?(current_user, :read_project, project)
project.team.users project.team.users
end end
elsif params[:group_id] elsif params[:group_id]
group = Group.find(params[:group_id]) group = Group.find(params[:group_id])
if can?(current_user, :read_group, group) if can?(current_user, :read_group, group)
group.users group.users
end
elsif current_user
User.all
end end
else rescue ActiveRecord::RecordNotFound
User.all if current_user
return render json: {}, status: 404
end end
end
if @users.nil? && current_user.nil?
authenticate_user!
end
@users ||= User.none
@users = @users.non_ldap if params[:skip_ldap] == 'true' @users = @users.non_ldap if params[:skip_ldap] == 'true'
@users = @users.search(params[:search]) if params[:search].present? @users = @users.search(params[:search]) if params[:search].present?
@users = @users.active @users = @users.active
......
...@@ -32,6 +32,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -32,6 +32,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
if @user.otp_required_for_login? if @user.otp_required_for_login?
prompt_for_two_factor(gl_user) prompt_for_two_factor(gl_user)
else else
log_audit_event(gl_user, with: :ldap)
sign_in_and_redirect(gl_user) sign_in_and_redirect(gl_user)
end end
else else
...@@ -52,6 +53,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -52,6 +53,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
if current_user if current_user
# Add new authentication method # Add new authentication method
current_user.identities.find_or_create_by(extern_uid: oauth['uid'], provider: oauth['provider']) current_user.identities.find_or_create_by(extern_uid: oauth['uid'], provider: oauth['provider'])
log_audit_event(current_user, with: oauth['provider'])
redirect_to profile_account_path, notice: 'Authentication method updated' redirect_to profile_account_path, notice: 'Authentication method updated'
else else
@user = Gitlab::OAuth::User.new(oauth) @user = Gitlab::OAuth::User.new(oauth)
...@@ -59,6 +61,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -59,6 +61,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
# Only allow properly saved users to login. # Only allow properly saved users to login.
if @user.persisted? && @user.valid? if @user.persisted? && @user.valid?
log_audit_event(@user.gl_user, with: oauth['provider'])
sign_in_and_redirect(@user.gl_user) sign_in_and_redirect(@user.gl_user)
else else
error_message = error_message =
...@@ -88,4 +91,9 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -88,4 +91,9 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def oauth def oauth
@oauth ||= request.env['omniauth.auth'] @oauth ||= request.env['omniauth.auth']
end end
def log_audit_event(user, options = {})
AuditEventService.new(user, user, options).
for_authentication.security_event
end
end end
...@@ -32,6 +32,7 @@ class Profiles::PreferencesController < Profiles::ApplicationController ...@@ -32,6 +32,7 @@ class Profiles::PreferencesController < Profiles::ApplicationController
params.require(:user).permit( params.require(:user).permit(
:color_scheme_id, :color_scheme_id,
:dashboard, :dashboard,
:project_view,
:theme_id :theme_id
) )
end end
......
...@@ -29,13 +29,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController ...@@ -29,13 +29,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
end end
def destroy def destroy
current_user.update_attributes({ current_user.disable_two_factor!
two_factor_enabled: false,
encrypted_otp_secret: nil,
encrypted_otp_secret_iv: nil,
encrypted_otp_secret_salt: nil,
otp_backup_codes: nil
})
redirect_to profile_account_path redirect_to profile_account_path
end end
......
...@@ -38,8 +38,11 @@ class ProfilesController < Profiles::ApplicationController ...@@ -38,8 +38,11 @@ class ProfilesController < Profiles::ApplicationController
redirect_to profile_account_path redirect_to profile_account_path
end end
def history def audit_log
@events = current_user.recent_events.page(params[:page]).per(PER_PAGE) @events = AuditEvent.where(entity_type: "User", entity_id: current_user.id).
order("created_at DESC").
page(params[:page]).
per(PER_PAGE)
end end
def update_username def update_username
......
...@@ -32,7 +32,7 @@ class Projects::BranchesController < Projects::ApplicationController ...@@ -32,7 +32,7 @@ class Projects::BranchesController < Projects::ApplicationController
end end
def destroy def destroy
DeleteBranchService.new(project, current_user).execute(params[:id]) status = DeleteBranchService.new(project, current_user).execute(params[:id])
@branch_name = params[:id] @branch_name = params[:id]
respond_to do |format| respond_to do |format|
...@@ -40,7 +40,7 @@ class Projects::BranchesController < Projects::ApplicationController ...@@ -40,7 +40,7 @@ class Projects::BranchesController < Projects::ApplicationController
redirect_to namespace_project_branches_path(@project.namespace, redirect_to namespace_project_branches_path(@project.namespace,
@project) @project)
end end
format.js format.js { render status: status[:return_code] }
end end
end end
end end
class Projects::GraphsController < Projects::ApplicationController class Projects::GraphsController < Projects::ApplicationController
include ExtractsPath
# Authorize # Authorize
before_action :require_non_empty_project before_action :require_non_empty_project
before_action :assign_ref_vars
before_action :authorize_download_code! before_action :authorize_download_code!
def show def show
...@@ -13,7 +16,7 @@ class Projects::GraphsController < Projects::ApplicationController ...@@ -13,7 +16,7 @@ class Projects::GraphsController < Projects::ApplicationController
end end
def commits def commits
@commits = @project.repository.commits(nil, nil, 2000, 0, true) @commits = @project.repository.commits(@ref, nil, 2000, 0, true)
@commits_graph = Gitlab::Graphs::Commits.new(@commits) @commits_graph = Gitlab::Graphs::Commits.new(@commits)
@commits_per_week_days = @commits_graph.commits_per_week_days @commits_per_week_days = @commits_graph.commits_per_week_days
@commits_per_time = @commits_graph.commits_per_time @commits_per_time = @commits_graph.commits_per_time
...@@ -23,7 +26,7 @@ class Projects::GraphsController < Projects::ApplicationController ...@@ -23,7 +26,7 @@ class Projects::GraphsController < Projects::ApplicationController
private private
def fetch_graph def fetch_graph
@commits = @project.repository.commits(nil, nil, 6000, 0, true) @commits = @project.repository.commits(@ref, nil, 6000, 0, true)
@log = [] @log = []
@commits.each do |commit| @commits.each do |commit|
......
...@@ -8,17 +8,21 @@ class Projects::RefsController < Projects::ApplicationController ...@@ -8,17 +8,21 @@ class Projects::RefsController < Projects::ApplicationController
def switch def switch
respond_to do |format| respond_to do |format|
format.html do format.html do
new_path = if params[:destination] == "tree" new_path =
namespace_project_tree_path(@project.namespace, @project, case params[:destination]
(@id)) when "tree"
elsif params[:destination] == "blob" namespace_project_tree_path(@project.namespace, @project, @id)
namespace_project_blob_path(@project.namespace, @project, when "blob"
(@id)) namespace_project_blob_path(@project.namespace, @project, @id)
elsif params[:destination] == "graph" when "graph"
namespace_project_network_path(@project.namespace, @project, @id, @options) namespace_project_network_path(@project.namespace, @project, @id, @options)
else when "graphs"
namespace_project_commits_path(@project.namespace, @project, @id) namespace_project_graph_path(@project.namespace, @project, @id)
end when "graphs_commits"
commits_namespace_project_graph_path(@project.namespace, @project, @id)
else
namespace_project_commits_path(@project.namespace, @project, @id)
end
redirect_to new_path redirect_to new_path
end end
......
...@@ -7,7 +7,9 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -7,7 +7,9 @@ class Projects::ServicesController < Projects::ApplicationController
:colorize_messages, :channels, :colorize_messages, :channels,
:push_events, :issues_events, :merge_requests_events, :tag_push_events, :push_events, :issues_events, :merge_requests_events, :tag_push_events,
:note_events, :send_from_committer_email, :disable_diffs, :external_wiki_url, :note_events, :send_from_committer_email, :disable_diffs, :external_wiki_url,
:jira_issue_transition_id, :notify, :color] :jira_issue_transition_id,
:notify, :color,
:server_host, :server_port, :default_irc_uri]
# Authorize # Authorize
before_action :authorize_admin_project! before_action :authorize_admin_project!
......
...@@ -6,7 +6,7 @@ class ProjectsController < ApplicationController ...@@ -6,7 +6,7 @@ class ProjectsController < ApplicationController
# Authorize # Authorize
before_action :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive] before_action :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive]
before_action :event_filter, only: :show before_action :event_filter, only: [:show, :activity]
layout :determine_layout layout :determine_layout
...@@ -52,10 +52,21 @@ class ProjectsController < ApplicationController ...@@ -52,10 +52,21 @@ class ProjectsController < ApplicationController
end end
def transfer def transfer
transfer_params = params.permit(:new_namespace_id) namespace = Namespace.find_by(id: params[:new_namespace_id])
::Projects::TransferService.new(project, current_user, transfer_params).execute ::Projects::TransferService.new(project, current_user).execute(namespace)
if @project.errors[:namespace_id].present?
flash[:alert] = @project.errors[:namespace_id].first if @project.errors[:new_namespace].present?
flash[:alert] = @project.errors[:new_namespace].first
end
end
def activity
respond_to do |format|
format.html
format.json do
load_events
pager_json('events/_events', @events.count)
end
end end
end end
...@@ -65,15 +76,12 @@ class ProjectsController < ApplicationController ...@@ -65,15 +76,12 @@ class ProjectsController < ApplicationController
return return
end end
@show_star = !(current_user && current_user.starred?(@project))
respond_to do |format| respond_to do |format|
format.html do format.html do
if @project.repository_exists? if @project.repository_exists?
if @project.empty_repo? if @project.empty_repo?
render 'projects/empty' render 'projects/empty'
else else
@last_push = current_user.recent_push(@project.id) if current_user
render :show render :show
end end
else else
...@@ -81,11 +89,6 @@ class ProjectsController < ApplicationController ...@@ -81,11 +89,6 @@ class ProjectsController < ApplicationController
end end
end end
format.json do
load_events
pager_json('events/_events', @events.count)
end
format.atom do format.atom do
load_events load_events
render layout: false render layout: false
...@@ -147,7 +150,10 @@ class ProjectsController < ApplicationController ...@@ -147,7 +150,10 @@ class ProjectsController < ApplicationController
def toggle_star def toggle_star
current_user.toggle_star(@project) current_user.toggle_star(@project)
@project.reload @project.reload
render json: { star_count: @project.star_count }
render json: {
html: view_to_html_string("projects/buttons/_star")
}
end end
def markdown_preview def markdown_preview
......
...@@ -37,6 +37,8 @@ class SessionsController < Devise::SessionsController ...@@ -37,6 +37,8 @@ class SessionsController < Devise::SessionsController
resource.update_attributes(reset_password_token: nil, resource.update_attributes(reset_password_token: nil,
reset_password_sent_at: nil) reset_password_sent_at: nil)
end end
authenticated_with = user_params[:otp_attempt] ? "two-factor" : "standard"
log_audit_event(current_user, with: authenticated_with)
end end
end end
...@@ -95,4 +97,9 @@ class SessionsController < Devise::SessionsController ...@@ -95,4 +97,9 @@ class SessionsController < Devise::SessionsController
user.valid_otp?(user_params[:otp_attempt]) || user.valid_otp?(user_params[:otp_attempt]) ||
user.invalidate_otp_backup_code!(user_params[:otp_attempt]) user.invalidate_otp_backup_code!(user_params[:otp_attempt])
end end
def log_audit_event(user, options = {})
AuditEventService.new(user, user, options).
for_authentication.security_event
end
end end
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
# state: 'open' or 'closed' or 'all' # state: 'open' or 'closed' or 'all'
# group_id: integer # group_id: integer
# project_id: integer # project_id: integer
# milestone_id: integer # milestone_title: string
# assignee_id: integer # assignee_id: integer
# search: string # search: string
# label_name: string # label_name: string
...@@ -76,7 +76,7 @@ class IssuableFinder ...@@ -76,7 +76,7 @@ class IssuableFinder
return @milestones if defined?(@milestones) return @milestones if defined?(@milestones)
@milestones = @milestones =
if milestones? && params[:milestone_title] != NONE if milestones? && params[:milestone_title] != Milestone::None.title
Milestone.where(title: params[:milestone_title]) Milestone.where(title: params[:milestone_title])
else else
nil nil
......
...@@ -213,6 +213,10 @@ module ApplicationHelper ...@@ -213,6 +213,10 @@ module ApplicationHelper
Haml::Helpers.preserve(markdown(file_content)) Haml::Helpers.preserve(markdown(file_content))
elsif asciidoc?(file_name) elsif asciidoc?(file_name)
asciidoc(file_content) asciidoc(file_content)
elsif plain?(file_name)
content_tag :pre, class: 'plain-readme' do
file_content
end
else else
GitHub::Markup.render(file_name, file_content). GitHub::Markup.render(file_name, file_content).
force_encoding(file_content.encoding).html_safe force_encoding(file_content.encoding).html_safe
...@@ -221,6 +225,10 @@ module ApplicationHelper ...@@ -221,6 +225,10 @@ module ApplicationHelper
simple_format(file_content) simple_format(file_content)
end end
def plain?(filename)
Gitlab::MarkupHelper.plain?(filename)
end
def markup?(filename) def markup?(filename)
Gitlab::MarkupHelper.markup?(filename) Gitlab::MarkupHelper.markup?(filename)
end end
......
...@@ -32,7 +32,7 @@ module ApplicationSettingsHelper ...@@ -32,7 +32,7 @@ module ApplicationSettingsHelper
def restricted_level_checkboxes(help_block_id) def restricted_level_checkboxes(help_block_id)
Gitlab::VisibilityLevel.options.map do |name, level| Gitlab::VisibilityLevel.options.map do |name, level|
checked = restricted_visibility_levels(true).include?(level) checked = restricted_visibility_levels(true).include?(level)
css_class = 'btn btn-primary' css_class = 'btn'
css_class += ' active' if checked css_class += ' active' if checked
checkbox_name = 'application_setting[restricted_visibility_levels][]' checkbox_name = 'application_setting[restricted_visibility_levels][]'
......
...@@ -118,7 +118,7 @@ module GitlabMarkdownHelper ...@@ -118,7 +118,7 @@ module GitlabMarkdownHelper
# Returns a random markdown tip for use as a textarea placeholder # Returns a random markdown tip for use as a textarea placeholder
def random_markdown_tip def random_markdown_tip
"Tip: #{MARKDOWN_TIPS.sample}" MARKDOWN_TIPS.sample
end end
private private
......
...@@ -17,6 +17,10 @@ module GitlabRoutingHelper ...@@ -17,6 +17,10 @@ module GitlabRoutingHelper
namespace_project_path(project.namespace, project, *args) namespace_project_path(project.namespace, project, *args)
end end
def activity_project_path(project, *args)
activity_namespace_project_path(project.namespace, project, *args)
end
def edit_project_path(project, *args) def edit_project_path(project, *args)
edit_namespace_project_path(project.namespace, project, *args) edit_namespace_project_path(project.namespace, project, *args)
end end
......
...@@ -29,6 +29,8 @@ module MilestonesHelper ...@@ -29,6 +29,8 @@ module MilestonesHelper
end.active end.active
grouped_milestones = Milestones::GroupService.new(milestones).execute grouped_milestones = Milestones::GroupService.new(milestones).execute
grouped_milestones.unshift(Milestone::None)
options_from_collection_for_select(grouped_milestones, 'title', 'title', params[:milestone_title]) options_from_collection_for_select(grouped_milestones, 'title', 'title', params[:milestone_title])
end end
end end
...@@ -42,6 +42,13 @@ module PreferencesHelper ...@@ -42,6 +42,13 @@ module PreferencesHelper
end end
end end
def project_view_choices
[
['Readme (default)', :readme],
['Activity view', :activity]
]
end
def user_application_theme def user_application_theme
theme = Gitlab::Themes.by_id(current_user.try(:theme_id)) theme = Gitlab::Themes.by_id(current_user.try(:theme_id))
theme.css_class theme.css_class
...@@ -50,4 +57,9 @@ module PreferencesHelper ...@@ -50,4 +57,9 @@ module PreferencesHelper
def user_color_scheme_class def user_color_scheme_class
COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user) COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user)
end end
def prefer_readme?
!current_user ||
current_user.project_view == 'readme'
end
end end
...@@ -84,53 +84,6 @@ module ProjectsHelper ...@@ -84,53 +84,6 @@ module ProjectsHelper
@project.milestones.active.order("due_date, title ASC") @project.milestones.active.order("due_date, title ASC")
end end
def link_to_toggle_star(title, starred)
cls = 'star-btn btn btn-sm btn-default'
toggle_text =
if starred
' Unstar'
else
' Star'
end
toggle_html = content_tag('span', class: 'toggle') do
icon('star') + toggle_text
end
count_html = content_tag('span', class: 'count') do
@project.star_count.to_s
end
link_opts = {
title: title,
class: cls,
method: :post,
remote: true,
data: { type: 'json' }
}
path = toggle_star_namespace_project_path(@project.namespace, @project)
content_tag 'span', class: starred ? 'turn-on' : 'turn-off' do
link_to(path, link_opts) do
toggle_html + ' ' + count_html
end
end
end
def link_to_toggle_fork
html = content_tag('span') do
icon('code-fork') + ' Fork'
end
count_html = content_tag(:span, class: 'count') do
@project.forks_count.to_s
end
html + count_html
end
def project_for_deploy_key(deploy_key) def project_for_deploy_key(deploy_key)
if deploy_key.projects.include?(@project) if deploy_key.projects.include?(@project)
@project @project
...@@ -139,6 +92,16 @@ module ProjectsHelper ...@@ -139,6 +92,16 @@ module ProjectsHelper
end end
end end
def can_change_visibility_level?(project, current_user)
return false unless can?(current_user, :change_visibility_level, project)
if project.forked?
project.forked_from_project.visibility_level > Gitlab::VisibilityLevel::PRIVATE
else
true
end
end
private private
def get_project_nav_tabs(project, current_user) def get_project_nav_tabs(project, current_user)
...@@ -285,14 +248,6 @@ module ProjectsHelper ...@@ -285,14 +248,6 @@ module ProjectsHelper
end end
end end
def github_import_enabled?
enabled_oauth_providers.include?(:github)
end
def gitlab_import_enabled?
enabled_oauth_providers.include?(:gitlab)
end
def membership_locked? def membership_locked?
if @project.group && @project.group.membership_lock if @project.group && @project.group.membership_lock
true true
...@@ -301,16 +256,6 @@ module ProjectsHelper ...@@ -301,16 +256,6 @@ module ProjectsHelper
end end
end end
def service_field_value(type, value)
return value unless type == 'password'
if value.present?
"***********"
else
nil
end
end
def user_max_access_in_project(user, project) def user_max_access_in_project(user, project)
level = project.team.max_member_access(user) level = project.team.max_member_access(user)
...@@ -322,4 +267,21 @@ module ProjectsHelper ...@@ -322,4 +267,21 @@ module ProjectsHelper
def leave_project_message(project) def leave_project_message(project)
"Are you sure you want to leave \"#{project.name}\" project?" "Are you sure you want to leave \"#{project.name}\" project?"
end end
def new_readme_path
ref = @repository.root_ref if @repository
ref ||= 'master'
namespace_project_new_blob_path(@project.namespace, @project, tree_join(ref), file_name: 'README.md')
end
def last_push_event
if current_user
current_user.recent_push(@project.id)
end
end
def readme_cache_key
[@project.id, @project.commit.sha, "readme"].join('-')
end
end end
...@@ -86,4 +86,10 @@ module VisibilityLevelHelper ...@@ -86,4 +86,10 @@ module VisibilityLevelHelper
def default_snippet_visibility def default_snippet_visibility
current_application_settings.default_snippet_visibility current_application_settings.default_snippet_visibility
end end
def skip_level?(form_model, level)
form_model.is_a?(Project) &&
form_model.forked? &&
!Gitlab::VisibilityLevel.allowed_fork_levels(form_model.forked_from_project.visibility_level).include?(level)
end
end end
...@@ -79,22 +79,36 @@ module Mentionable ...@@ -79,22 +79,36 @@ module Mentionable
end end
end end
# If the mentionable_text field is about to change, locate any *added* references and create cross references for # When a mentionable field is changed, creates cross-reference notes that
# them. Invoke from an observer's #before_save implementation. # don't already exist
def notice_added_references(p = project, a = author) def create_new_cross_references!(p = project, a = author)
ch = changed_attributes changes = detect_mentionable_changes
original, mentionable_changed = "", false
self.class.mentionable_attrs.each do |attr| return if changes.empty?
if ch[attr]
original << ch[attr]
mentionable_changed = true
end
end
# Only proceed if the saved changes actually include a chance to an attr_mentionable field. original_text = changes.collect { |_, vals| vals.first }.join(' ')
return unless mentionable_changed
preexisting = references(p, self.author, original) preexisting = references(p, self.author, original_text)
create_cross_references!(p, a, preexisting) create_cross_references!(p, a, preexisting)
end end
private
# Returns a Hash of changed mentionable fields
#
# Preference is given to the `changes` Hash, but falls back to
# `previous_changes` if it's empty (i.e., the changes have already been
# persisted).
#
# See ActiveModel::Dirty.
#
# Returns a Hash.
def detect_mentionable_changes
source = (changes.present? ? changes : previous_changes).dup
mentionable = self.class.mentionable_attrs
# Only include changed fields that are mentionable
source.select { |key, val| mentionable.include?(key) }
end
end end
...@@ -24,6 +24,7 @@ class Key < ActiveRecord::Base ...@@ -24,6 +24,7 @@ class Key < ActiveRecord::Base
validates :title, presence: true, length: { within: 0..255 } validates :title, presence: true, length: { within: 0..255 }
validates :key, presence: true, length: { within: 0..5000 }, format: { with: /\A(ssh|ecdsa)-.*\Z/ }, uniqueness: true validates :key, presence: true, length: { within: 0..5000 }, format: { with: /\A(ssh|ecdsa)-.*\Z/ }, uniqueness: true
validates :key, format: { without: /\n|\r/, message: 'should be a single line' }
validates :fingerprint, uniqueness: true, presence: { message: 'cannot be generated' } validates :fingerprint, uniqueness: true, presence: { message: 'cannot be generated' }
scope :ldap, -> { where(type: 'LDAPKey') } scope :ldap, -> { where(type: 'LDAPKey') }
......
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
# #
class Milestone < ActiveRecord::Base class Milestone < ActiveRecord::Base
# Represents a "No Milestone" state used for filtering Issues and Merge
# Requests that have no milestone assigned.
None = Struct.new(:title).new('No Milestone')
include InternalId include InternalId
include Sortable include Sortable
......
...@@ -356,7 +356,7 @@ class Note < ActiveRecord::Base ...@@ -356,7 +356,7 @@ class Note < ActiveRecord::Base
end end
def set_references def set_references
notice_added_references(project, author) create_new_cross_references!(project, author)
end end
def editable? def editable?
......
...@@ -21,26 +21,11 @@ ...@@ -21,26 +21,11 @@
require 'uri' require 'uri'
class IrkerService < Service class IrkerService < Service
prop_accessor :server_host, :server_port, :default_irc_uri
prop_accessor :colorize_messages, :recipients, :channels prop_accessor :colorize_messages, :recipients, :channels
validates :recipients, presence: true, if: :activated? validates :recipients, presence: true, if: :activated?
validate :check_recipients_count, if: :activated?
before_validation :get_channels before_validation :get_channels
after_initialize :initialize_settings
# Writer for RSpec tests
attr_writer :settings
def initialize_settings
# See the documentation (doc/project_services/irker.md) for possible values
# here
@settings ||= {
server_ip: 'localhost',
server_port: 6659,
max_channels: 3,
default_irc_uri: nil
}
end
def title def title
'Irker (IRC gateway)' 'Irker (IRC gateway)'
...@@ -51,20 +36,6 @@ class IrkerService < Service ...@@ -51,20 +36,6 @@ class IrkerService < Service
'gateway.' 'gateway.'
end end
def help
msg = 'Recipients have to be specified with a full URI: '\
'irc[s]://irc.network.net[:port]/#channel. Special cases: if you want '\
'the channel to be a nickname instead, append ",isnick" to the channel '\
'name; if the channel is protected by a secret password, append '\
'"?key=secretpassword" to the URI.'
unless @settings[:default_irc].nil?
msg += ' Note that a default IRC URI is provided by this service\'s '\
"administrator: #{default_irc}. You can thus just give a channel name."
end
msg
end
def to_param def to_param
'irker' 'irker'
end end
...@@ -77,30 +48,45 @@ class IrkerService < Service ...@@ -77,30 +48,45 @@ class IrkerService < Service
return unless supported_events.include?(data[:object_kind]) return unless supported_events.include?(data[:object_kind])
IrkerWorker.perform_async(project_id, channels, IrkerWorker.perform_async(project_id, channels,
colorize_messages, data, @settings) colorize_messages, data, settings)
end
def settings
{ server_host: server_host.present? ? server_host : 'localhost',
server_port: server_port.present? ? server_port : 6659
}
end end
def fields def fields
[ [
{ type: 'text', name: 'server_host', placeholder: 'localhost',
help: 'Irker daemon hostname (defaults to localhost)' },
{ type: 'text', name: 'server_port', placeholder: 6659,
help: 'Irker daemon port (defaults to 6659)' },
{ type: 'text', name: 'default_irc_uri', title: 'Default IRC URI',
help: 'A default IRC URI to prepend before each recipient (optional)',
placeholder: 'irc://irc.network.net:6697/' },
{ type: 'textarea', name: 'recipients', { type: 'textarea', name: 'recipients',
placeholder: 'Recipients/channels separated by whitespaces' }, placeholder: 'Recipients/channels separated by whitespaces',
help: 'Recipients have to be specified with a full URI: '\
'irc[s]://irc.network.net[:port]/#channel. Special cases: if '\
'you want the channel to be a nickname instead, append ",isnick" to ' \
'the channel name; if the channel is protected by a secret password, ' \
' append "?key=secretpassword" to the URI. Note that if you specify a ' \
' default IRC URI to prepend before each recipient, you can just give ' \
' a channel name.' },
{ type: 'checkbox', name: 'colorize_messages' }, { type: 'checkbox', name: 'colorize_messages' },
] ]
end end
private def help
' NOTE: Irker does NOT have built-in authentication, which makes it' \
def check_recipients_count ' vulnerable to spamming IRC channels if it is hosted outside of a ' \
return true if recipients.nil? || recipients.empty? ' firewall. Please make sure you run the daemon within a secured network ' \
' to prevent abuse. For more details, read: http://www.catb.org/~esr/irker/security.html.'
if recipients.split(/\s+/).count > max_chans
errors.add(:recipients, "are limited to #{max_chans}")
end
end end
def max_chans private
@settings[:max_channels]
end
def get_channels def get_channels
return true unless :activated? return true unless :activated?
...@@ -114,40 +100,35 @@ class IrkerService < Service ...@@ -114,40 +100,35 @@ class IrkerService < Service
def map_recipients def map_recipients
self.channels = recipients.split(/\s+/).map do |recipient| self.channels = recipients.split(/\s+/).map do |recipient|
format_channel default_irc_uri, recipient format_channel(recipient)
end end
channels.reject! &:nil? channels.reject! &:nil?
end end
def default_irc_uri def format_channel(recipient)
default_irc = @settings[:default_irc_uri] uri = nil
if !(default_irc.nil? || default_irc[-1] == '/')
default_irc += '/'
end
default_irc
end
def format_channel(default_irc, recipient)
cnt = 0
url = nil
# Try to parse the chan as a full URI # Try to parse the chan as a full URI
begin begin
uri = URI.parse(recipient) uri = consider_uri(URI.parse(recipient))
raise URI::InvalidURIError if uri.scheme.nil? && cnt == 0
rescue URI::InvalidURIError rescue URI::InvalidURIError
unless default_irc.nil? end
cnt += 1
recipient = "#{default_irc}#{recipient}" unless uri.present? and default_irc_uri.nil?
retry if cnt == 1 begin
new_recipient = URI.join(default_irc_uri, '/', recipient).to_s
uri = consider_uri(URI.parse(new_recipient))
rescue
Rails.logger.error("Unable to create a valid URL from #{default_irc_uri} and #{recipient}")
end end
else
url = consider_uri uri
end end
url
uri
end end
def consider_uri(uri) def consider_uri(uri)
return nil if uri.scheme.nil?
# Authorize both irc://domain.com/#chan and irc://domain.com/chan # Authorize both irc://domain.com/#chan and irc://domain.com/chan
if uri.is_a?(URI) && uri.scheme[/^ircs?\z/] && !uri.path.nil? if uri.is_a?(URI) && uri.scheme[/^ircs?\z/] && !uri.path.nil?
# Do not authorize irc://domain.com/ # Do not authorize irc://domain.com/
......
...@@ -431,6 +431,40 @@ class Repository ...@@ -431,6 +431,40 @@ class Repository
end end
end end
def search_files(query, ref)
offset = 2
args = %W(git grep -i -n --before-context #{offset} --after-context #{offset} #{query} #{ref || root_ref})
Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/)
end
def parse_search_result(result)
ref = nil
filename = nil
startline = 0
lines = result.lines
lines.each_with_index do |line, index|
if line =~ /^.*:.*:\d+:/
ref, filename, startline = line.split(':')
startline = startline.to_i - index
break
end
end
data = lines.map do |line|
line.sub(ref, '').sub(filename, '').sub(/^:-\d+-/, '').sub(/^::\d+:/, '')
end
data = data.join("")
OpenStruct.new(
filename: filename,
ref: ref,
startline: startline,
data: data
)
end
private private
def cache def cache
......
...@@ -178,6 +178,10 @@ class User < ActiveRecord::Base ...@@ -178,6 +178,10 @@ class User < ActiveRecord::Base
# Note: When adding an option, it MUST go on the end of the array. # Note: When adding an option, it MUST go on the end of the array.
enum dashboard: [:projects, :stars] enum dashboard: [:projects, :stars]
# User's Project preference
# Note: When adding an option, it MUST go on the end of the array.
enum project_view: [:readme, :activity]
alias_attribute :private_token, :authentication_token alias_attribute :private_token, :authentication_token
delegate :path, to: :namespace, allow_nil: true, prefix: true delegate :path, to: :namespace, allow_nil: true, prefix: true
...@@ -350,6 +354,16 @@ class User < ActiveRecord::Base ...@@ -350,6 +354,16 @@ class User < ActiveRecord::Base
@reset_token @reset_token
end end
def disable_two_factor!
update_attributes(
two_factor_enabled: false,
encrypted_otp_secret: nil,
encrypted_otp_secret_iv: nil,
encrypted_otp_secret_salt: nil,
otp_backup_codes: nil
)
end
def namespace_uniq def namespace_uniq
namespace_name = self.username namespace_name = self.username
existing_namespace = Namespace.by_path(namespace_name) existing_namespace = Namespace.by_path(namespace_name)
......
...@@ -60,6 +60,15 @@ class AuditEventService ...@@ -60,6 +60,15 @@ class AuditEventService
target_details: key_title, target_details: key_title,
} }
end end
end
def for_authentication
@details = {
with: @details[:with],
target_id: @author.id,
target_type: "User",
target_details: @author.name,
}
self self
end end
......
module Issues module Issues
class UpdateService < Issues::BaseService class UpdateService < Issues::BaseService
def execute(issue) def execute(issue)
state = params[:state_event] case params.delete(:state_event)
case state
when 'reopen' when 'reopen'
Issues::ReopenService.new(project, current_user, {}).execute(issue) Issues::ReopenService.new(project, current_user, {}).execute(issue)
when 'close' when 'close'
Issues::CloseService.new(project, current_user, {}).execute(issue) Issues::CloseService.new(project, current_user, {}).execute(issue)
when 'task_check'
issue.update_nth_task(params[:task_num].to_i, true)
when 'task_uncheck'
issue.update_nth_task(params[:task_num].to_i, false)
end end
params[:assignee_id] = "" if params[:assignee_id] == IssuableFinder::NONE params[:assignee_id] = "" if params[:assignee_id] == IssuableFinder::NONE
...@@ -20,8 +14,7 @@ module Issues ...@@ -20,8 +14,7 @@ module Issues
filter_params filter_params
old_labels = issue.labels.to_a old_labels = issue.labels.to_a
if params.present? && issue.update_attributes(params.except(:state_event, if params.present? && issue.update_attributes(params)
:task_num))
issue.reset_events_cache issue.reset_events_cache
if issue.labels != old_labels if issue.labels != old_labels
...@@ -42,7 +35,7 @@ module Issues ...@@ -42,7 +35,7 @@ module Issues
create_title_change_note(issue, issue.previous_changes['title'].first) create_title_change_note(issue, issue.previous_changes['title'].first)
end end
issue.notice_added_references(issue.project, current_user) issue.create_new_cross_references!(issue.project, current_user)
execute_hooks(issue, 'update') execute_hooks(issue, 'update')
end end
......
...@@ -11,17 +11,11 @@ module MergeRequests ...@@ -11,17 +11,11 @@ module MergeRequests
params.except!(:target_project_id) params.except!(:target_project_id)
params.except!(:source_branch) params.except!(:source_branch)
state = params[:state_event] case params.delete(:state_event)
case state
when 'reopen' when 'reopen'
MergeRequests::ReopenService.new(project, current_user, {}).execute(merge_request) MergeRequests::ReopenService.new(project, current_user, {}).execute(merge_request)
when 'close' when 'close'
MergeRequests::CloseService.new(project, current_user, {}).execute(merge_request) MergeRequests::CloseService.new(project, current_user, {}).execute(merge_request)
when 'task_check'
merge_request.update_nth_task(params[:task_num].to_i, true)
when 'task_uncheck'
merge_request.update_nth_task(params[:task_num].to_i, false)
end end
params[:assignee_id] = "" if params[:assignee_id] == IssuableFinder::NONE params[:assignee_id] = "" if params[:assignee_id] == IssuableFinder::NONE
...@@ -30,9 +24,7 @@ module MergeRequests ...@@ -30,9 +24,7 @@ module MergeRequests
filter_params filter_params
old_labels = merge_request.labels.to_a old_labels = merge_request.labels.to_a
if params.present? && merge_request.update_attributes( if params.present? && merge_request.update_attributes(params)
params.except(:state_event, :task_num)
)
merge_request.reset_events_cache merge_request.reset_events_cache
if merge_request.labels != old_labels if merge_request.labels != old_labels
...@@ -67,7 +59,7 @@ module MergeRequests ...@@ -67,7 +59,7 @@ module MergeRequests
merge_request.mark_as_unchecked merge_request.mark_as_unchecked
end end
merge_request.notice_added_references(merge_request.project, current_user) merge_request.create_new_cross_references!(merge_request.project, current_user)
execute_hooks(merge_request, 'update') execute_hooks(merge_request, 'update')
end end
......
...@@ -11,19 +11,16 @@ module Projects ...@@ -11,19 +11,16 @@ module Projects
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
class TransferError < StandardError; end class TransferError < StandardError; end
def execute def execute(new_namespace)
namespace_id = params[:new_namespace_id] if allowed_transfer?(current_user, project, new_namespace)
namespace = Namespace.find_by(id: namespace_id) transfer(project, new_namespace)
if allowed_transfer?(current_user, project, namespace)
transfer(project, namespace)
else else
project.errors.add(:namespace, 'is invalid') project.errors.add(:new_namespace, 'is invalid')
false false
end end
rescue Projects::TransferService::TransferError => ex rescue Projects::TransferService::TransferError => ex
project.reload project.reload
project.errors.add(:namespace_id, ex.message) project.errors.add(:new_namespace, ex.message)
false false
end end
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
%strong{class: @user.two_factor_enabled? ? 'cgreen' : 'cred'} %strong{class: @user.two_factor_enabled? ? 'cgreen' : 'cred'}
- if @user.two_factor_enabled? - if @user.two_factor_enabled?
Enabled Enabled
= link_to 'Disable', disable_two_factor_admin_user_path(@user), data: {confirm: 'Are you sure?'}, method: :patch, class: 'btn btn-xs btn-remove pull-right', title: 'Disable Two-factor Authentication'
- else - else
Disabled Disabled
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
- if event.created_project? - if event.created_project?
= cache [event, current_user] do = cache [event, current_user] do
= image_tag avatar_icon(event.author_email, 24), class: "avatar s24", alt:''
= render "events/event/created_project", event: event = render "events/event/created_project", event: event
- else - else
= cache event do = cache event do
......
...@@ -79,6 +79,12 @@ ...@@ -79,6 +79,12 @@
%td.shortcut %td.shortcut
.key g .key g
.key p .key p
%td
Go to the project's home page
%tr
%td.shortcut
.key g
.key e
%td %td
Go to the project's activity feed Go to the project's activity feed
%tr %tr
......
...@@ -7,14 +7,29 @@ ...@@ -7,14 +7,29 @@
%title= page_title %title= page_title
= favicon_link_tag 'favicon.ico' = favicon_link_tag 'favicon.ico'
= stylesheet_link_tag "application", :media => "all"
= stylesheet_link_tag "print", :media => "print" = stylesheet_link_tag "application", media: "all"
= stylesheet_link_tag "print", media: "print"
= javascript_include_tag "application" = javascript_include_tag "application"
= csrf_meta_tags = csrf_meta_tags
= include_gon = include_gon
%meta{name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1'} %meta{name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1'}
%meta{name: 'theme-color', content: '#474D57'} %meta{name: 'theme-color', content: '#474D57'}
-# Apple Safari/iOS home screen icons
= favicon_link_tag 'touch-icon-iphone.png', rel: 'apple-touch-icon'
= favicon_link_tag 'touch-icon-ipad.png', rel: 'apple-touch-icon', sizes: '76x76'
= favicon_link_tag 'touch-icon-iphone-retina.png', rel: 'apple-touch-icon', sizes: '120x120'
= favicon_link_tag 'touch-icon-ipad-retina.png', rel: 'apple-touch-icon', sizes: '152x152'
-# Windows 8 pinned site tile
%meta{name: 'msapplication-TileImage', content: image_url('msapplication-tile.png')}
%meta{name: 'msapplication-TileColor', content: '#30353E'}
= yield :meta_tags = yield :meta_tags
= render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id') = render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id')
......
.page-with-sidebar{ class: nav_sidebar_class } .page-with-sidebar{ class: nav_sidebar_class }
= render "layouts/broadcast" = render "layouts/broadcast"
.sidebar-wrapper .sidebar-wrapper.nicescroll
- if defined?(sidebar) && sidebar - if defined?(sidebar) && sidebar
= render "layouts/nav/#{sidebar}" = render "layouts/nav/#{sidebar}"
- elsif current_user - elsif current_user
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link do
= link_to root_path, title: 'Back to dashboard', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw')
%span
Back to Dashboard
%li.separate-item
= nav_link(path: 'groups#show', html_options: {class: 'home'}) do = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
= link_to group_path(@group), title: 'Home', data: {placement: 'right'} do = link_to group_path(@group), title: 'Home', data: {placement: 'right'} do
= icon('dashboard fw') = icon('dashboard fw')
%span %span
Activity Group
- if current_user - if current_user
= nav_link(controller: [:group, :milestones]) do = nav_link(controller: [:group, :milestones]) do
= link_to group_milestones_path(@group), title: 'Milestones', data: {placement: 'right'} do = link_to group_milestones_path(@group), title: 'Milestones', data: {placement: 'right'} do
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link do = nav_link do
= link_to group_path(@group), title: 'Back to group', data: {placement: 'right'} do = link_to group_path(@group), title: 'Back to group', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw') = icon('caret-square-o-left fw')
%span %span
Back to group Back to group
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link do
= link_to root_path, title: 'Back to dashboard', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw')
%span
Back to Dashboard
%li.separate-item
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path, title: 'Profile', data: {placement: 'right'} do = link_to profile_path, title: 'Profile', data: {placement: 'right'} do
= icon('user fw') = icon('user fw')
...@@ -44,8 +52,8 @@ ...@@ -44,8 +52,8 @@
= icon('image fw') = icon('image fw')
%span %span
Preferences Preferences
= nav_link(path: 'profiles#history') do = nav_link(path: 'profiles#audit_log') do
= link_to history_profile_path, title: 'History', data: {placement: 'right'} do = link_to audit_log_profile_path, title: 'Audit Log', data: {placement: 'right'} do
= icon('history fw') = icon('history fw')
%span %span
History Audit Log
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
- if @project.group
= nav_link do
= link_to group_path(@project.group), title: 'Back to group', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw')
%span
Back to Group
- else
= nav_link do
= link_to root_path, title: 'Back to dashboard', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw')
%span
Back to Dashboard
%li.separate-item
= nav_link(path: 'projects#show', html_options: {class: 'home'}) do = nav_link(path: 'projects#show', html_options: {class: 'home'}) do
= link_to project_path(@project), title: 'Project', class: 'shortcuts-project', data: {placement: 'right'} do = link_to project_path(@project), title: 'Project', class: 'shortcuts-project', data: {placement: 'right'} do
= icon('dashboard fw') = icon('home fw')
%span %span
Project Project
= nav_link(path: 'projects#activity') do
= link_to activity_project_path(@project), title: 'Project Activity', class: 'shortcuts-project-activity', data: {placement: 'right'} do
= icon('dashboard fw')
%span
Activity
- if project_nav_tab? :files - if project_nav_tab? :files
= nav_link(controller: %w(tree blob blame edit_tree new_tree)) do = nav_link(controller: %w(tree blob blame edit_tree new_tree)) do
= link_to namespace_project_tree_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Files', class: 'shortcuts-tree', data: {placement: 'right'} do = link_to namespace_project_tree_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Files', class: 'shortcuts-tree', data: {placement: 'right'} do
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link do = nav_link do
= link_to project_path(@project), title: 'Back to project', data: {placement: 'right'} do = link_to project_path(@project), title: 'Back to project', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw') = icon('caret-square-o-left fw')
%span %span
Back to project Back to project
......
%table.table#audits
%thead
%tr
%th Action
%th When
%tbody
- events.each do |event|
%tr
%td
%span
Signed in with
%b= event.details[:with]
authentication
%td #{time_ago_in_words event.created_at} ago
= paginate events, theme: "gitlab"
...@@ -66,4 +66,4 @@ ...@@ -66,4 +66,4 @@
%td= token.scopes %td= token.scopes
%td= render 'doorkeeper/authorized_applications/delete_form', token: token %td= render 'doorkeeper/authorized_applications/delete_form', token: token
- else - else
%p.light You dont have any authorized applications %p.light You don't have any authorized applications
- page_title "Audit Log"
%h3.page-title Audit Log
%p.light History of authentications
= render 'event_table', events: @events
\ No newline at end of file
- page_title "History"
%h3.page-title
Your Account History
%p.light
All events created by your account are listed below.
%hr
.profile_history
= render @events
%hr
= paginate @events, theme: "gitlab"
...@@ -38,5 +38,13 @@ ...@@ -38,5 +38,13 @@
= link_to('(?)', help_page_path('profile', 'preferences') + '#default-dashboard', target: '_blank') = link_to('(?)', help_page_path('profile', 'preferences') + '#default-dashboard', target: '_blank')
.col-sm-10 .col-sm-10
= f.select :dashboard, dashboard_choices, {}, class: 'form-control' = f.select :dashboard, dashboard_choices, {}, class: 'form-control'
.form-group
= f.label :project_view, class: 'control-label' do
Project view
= link_to('(?)', help_page_path('profile', 'preferences') + '#default-project-view', target: '_blank')
.col-sm-10
= f.select :project_view, project_view_choices, {}, class: 'form-control'
.help-block
Choose what content you want to see when visit project page
.panel-footer .panel-footer
= f.submit 'Save', class: 'btn btn-save' = f.submit 'Save', class: 'btn btn-save'
= render 'projects/last_push'
.hidden-xs
- if current_user
%ul.nav.nav-pills.event_filter.pull-right
%li
= link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), title: "Feed", class: 'rss-btn' do
%i.fa.fa-rss
= render 'shared/event_filter'
%hr
.content_list{:"data-href" => activity_project_path(@project)}
= spinner
:coffeescript
new Activities()
.clearfix
- unless @project.empty_repo?
.panel.panel-default
.panel-heading
= visibility_level_icon(@project.visibility_level)
= "#{visibility_level_label(@project.visibility_level).capitalize} project"
.panel-body
- if @repository.changelog || @repository.license || @repository.contribution_guide
%ul.nav.nav-pills
- if @repository.changelog
%li.hidden-xs
= link_to changelog_url(@project) do
Changelog
- if @repository.license
%li
= link_to license_url(@project) do
License
- if @repository.contribution_guide
%li
= link_to contribution_guide_url(@project) do
Contribution guide
.actions
- if can? current_user, :create_issue, @project
= link_to url_for_new_issue(@project, only_path: true), title: "New Issue", class: 'btn btn-sm append-right-10' do
New Issue
- if can? current_user, :create_merge_request, @project
= link_to new_namespace_project_merge_request_path(@project.namespace, @project), class: "btn btn-sm", title: "New Merge Request" do
New Merge Request
- if forked_from_project = @project.forked_from_project
.panel-footer
= icon("code-fork fw")
Forked from
.pull-right
= link_to forked_from_project.namespace.try(:name), project_path(forked_from_project)
- @project.ci_services.each do |ci_service|
- if ci_service.active? && ci_service.respond_to?(:builds_path)
.panel-footer
= icon("check fw")
= ci_service.title
.pull-right
- if ci_service.respond_to?(:status_img_path)
= link_to ci_service.builds_path, :'data-no-turbolink' => 'data-no-turbolink' do
= image_tag ci_service.status_img_path, alt: "build status", class: 'ci-status-image'
- else
= link_to 'view builds', ci_service.builds_path, :'data-no-turbolink' => 'data-no-turbolink'
- unless @project.empty_repo?
.panel.panel-default
.panel-heading
= icon("folder-o fw")
Repository
.panel-body
%ul.nav.nav-pills
%li
= link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref) do
= pluralize(number_with_delimiter(@repository.commit_count), 'commit')
%li
= link_to namespace_project_branches_path(@project.namespace, @project) do
= pluralize(number_with_delimiter(@repository.branch_names.count), 'branch')
%li
= link_to namespace_project_tags_path(@project.namespace, @project) do
= pluralize(number_with_delimiter(@repository.tag_names.count), 'tag')
.actions
= link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: @ref || @repository.root_ref), class: 'btn btn-sm append-right-10' do
%i.fa.fa-exchange
Compare code
- if can?(current_user, :download_code, @project)
= render 'projects/repositories/download_archive', split_button: true, btn_class: 'btn-group-sm'
- if version = @repository.version
.panel-footer
= icon("clock-o fw")
Version
.pull-right
= link_to version_url(@project) do
= @repository.blob_by_oid(version.id).data
= render "shared/clone_panel"
- if @project.archived?
%br
.alert.alert-warning
%h4
= icon("exclamation-triangle fw")
Archived project!
%p Repository is read-only
- if current_user
- access = user_max_access_in_project(current_user, @project)
- if access
.light-well.light.prepend-top-20
%small
You have #{access} access to this project.
- if @project.project_member_by_id(current_user)
%br
= link_to leave_namespace_project_project_members_path(@project.namespace, @project),
data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do
Leave this project
- empty_repo = @project.empty_repo? - empty_repo = @project.empty_repo?
.project-home-panel.clearfix{:class => ("empty-project" if empty_repo)} .project-home-panel.clearfix{:class => ("empty-project" if empty_repo)}
.project-identicon-holder .project-identicon-holder
= project_icon(@project, alt: '', class: 'avatar project-avatar') = project_icon(@project, alt: '', class: 'project-avatar avatar s90')
.project-home-row.project-home-row-top .project-home-desc.lead
.project-home-desc - if @project.description.present?
- if @project.description.present? = markdown(@project.description, pipeline: :description)
= markdown(@project.description, pipeline: :description)
- if can?(current_user, :admin_project, @project)
&ndash; .project-repo-buttons
= link_to 'Edit', edit_namespace_project_path = render 'projects/buttons/star'
- elsif !empty_repo && @repository.readme
- readme = @repository.readme - unless empty_repo
&ndash; = render 'projects/buttons/fork'
= link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)) do
= readme.name - if forked_from_project = @project.forked_from_project
.project-repo-buttons = link_to project_path(forked_from_project), class: 'btn' do
.inline.star.js-toggler-container{class: @show_star ? 'on' : ''} = icon("code-fork fw")
- if current_user Forked from
= link_to_toggle_star('Star this project.', false) = forked_from_project.namespace.try(:name)
= link_to_toggle_star('Unstar this project.', true)
- else - if can? current_user, :download_code, @project
= link_to new_user_session_path, class: 'btn star-btn has_tooltip', title: 'You must sign in to star a project' do = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), class: 'btn', rel: 'nofollow' do
%span %i.fa.fa-download
= icon('star')
Star = render 'projects/buttons/dropdown'
%span.count
= @project.star_count = render "shared/clone_panel"
- unless empty_repo
- if current_user && can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
.inline.fork-buttons.prepend-left-10
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-sm btn-default' do
= link_to_toggle_fork
- else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-sm btn-default' do
= link_to_toggle_fork
- if event = last_push_event
- if show_last_push_widget?(event)
.hidden-xs.center
.slead
%span You pushed to
= link_to namespace_project_commits_path(event.project.namespace, event.project, event.ref_name) do
%strong= event.ref_name
branch
#{time_ago_with_tooltip(event.created_at)}
%div
= link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-info btn-sm" do
Create Merge Request
%hr
- if readme = @repository.readme
%article.readme-holder#README
.clearfix
.pull-right
&nbsp;
- if can?(current_user, :push_code, @project)
= link_to namespace_project_edit_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)), class: 'light' do
%i.fa.fa-pencil
.wiki
= cache(readme_cache_key) do
= render_readme(readme)
- else
%h3.page-title
This project does not have README yet
- if can?(current_user, :push_code, @project)
%p.slead
A
%code README
file contains information about other files in a repository and is commonly
distributed with computer software, forming part of its documentation.
%br
We recommend you to
= link_to "add README", new_readme_path, class: 'underlined-link'
file to the repository and GitLab will render it here instead of this message.
%ul.nav.nav-tabs
%li.active
= link_to '#tab-activity', 'data-toggle' => 'tab' do
= icon("tachometer")
Activity
- if @repository.readme
%li
= link_to '#tab-readme', 'data-toggle' => 'tab' do
= icon("file-text-o")
Readme
.tab-content
.tab-pane.active#tab-activity
.hidden-xs
= render "events/event_last_push", event: @last_push
- if current_user
%ul.nav.nav-pills.event_filter.pull-right
%li
= link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), title: "Feed", class: 'rss-btn' do
%i.fa.fa-rss
= render 'shared/event_filter'
%hr
.content_list
= spinner
- if readme = @repository.readme
.tab-pane#tab-readme
%article.readme-holder#README
.clearfix
%small.pull-right
= link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)), class: 'light' do
%i.fa.fa-file
= readme.name
.wiki
= render_readme(readme)
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
%input#zen-toggle-comment.zen-toggle-comment{ tabindex: '-1', type: 'checkbox' } %input#zen-toggle-comment.zen-toggle-comment{ tabindex: '-1', type: 'checkbox' }
.zen-backdrop .zen-backdrop
- classes << ' js-gfm-input markdown-area' - classes << ' js-gfm-input markdown-area'
= f.text_area attr, class: classes, placeholder: random_markdown_tip = f.text_area attr, class: classes, placeholder: ''
= link_to nil, class: 'zen-enter-link', tabindex: '-1' do = link_to nil, class: 'zen-enter-link', tabindex: '-1' do
%i.fa.fa-expand %i.fa.fa-expand
Edit in fullscreen Edit in fullscreen
......
= render 'projects/activity'
- page_title @blob.path, @ref - page_title @blob.path, @ref
= render 'projects/last_push'
%div.tree-ref-holder %div.tree-ref-holder
= render 'shared/ref_switcher', destination: 'blob', path: @path = render 'shared/ref_switcher', destination: 'blob', path: @path
......
- if current_user
%span.dropdown
%a.dropdown-toggle.btn.btn-new{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-plus
%ul.dropdown-menu
- if @project.issues_enabled && can?(current_user, :create_issue, @project)
%li
= link_to url_for_new_issue, title: "New Issue" do
New issue
- if @project.merge_requests_enabled && can?(current_user, :create_merge_request, @project)
%li
= link_to new_namespace_project_merge_request_path(@project.namespace, @project), title: "New Merge Request" do
New merge request
- if @project.snippets_enabled && can?(current_user, :create_snippet, @project)
%li
= link_to new_namespace_project_snippet_path(@project.namespace, @project), title: "New Snippet" do
New snippet
- if can?(current_user, :admin_project_member, @project)
%li
= link_to namespace_project_project_members_path(@project.namespace, @project), title: "New project member" do
New project member
- if can? current_user, :push_code, @project
%li.divider
%li
= link_to new_namespace_project_branch_path(@project.namespace, @project) do
New git branch
%li
= link_to new_namespace_project_tag_path(@project.namespace, @project) do
New git tag
- if current_user && can?(current_user, :fork_project, @project)
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn' do
= icon('code-fork')
Fork
%span.count
= @project.forks_count
- else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn' do
= icon('code-fork')
Fork
%span.count
= @project.forks_count
- if current_user
= link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star', method: :post, remote: true do
= icon('star')
- if current_user.starred?(@project)
Unstar
- else
Star
%span.count
= @project.star_count
:coffeescript
$('.project-home-panel .toggle-star').on 'ajax:success', (e, data, status, xhr) ->
$(@).replaceWith(data.html)
.on 'ajax:error', (e, xhr, status, error) ->
new Flash('Star toggle failed. Try again later.', 'alert')
- else
= link_to new_user_session_path, class: 'btn has_tooltip star-btn', title: 'You must sign in to star a project' do
= icon('star')
Star
%span.count
= @project.star_count
...@@ -20,6 +20,3 @@ ...@@ -20,6 +20,3 @@
Failed to collect changes Failed to collect changes
%p %p
Maybe diff is really big and operation failed with timeout. Try to get diff locally Maybe diff is really big and operation failed with timeout. Try to get diff locally
:coffeescript
$('.files .diff-header').stick_in_parent(offset_top: $('.navbar').height())
.alert.alert-warning .alert.alert-warning
%h4 %h4
Too many changes. Too many changes to show.
.pull-right .pull-right
- unless diff_hard_limit_enabled? - unless diff_hard_limit_enabled?
= link_to "Reload with full diff", url_for(params.merge(force_show_diff: true)), class: "btn btn-sm btn-warning" = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true)), class: "btn btn-sm btn-warning"
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
.col-sm-10= f.select(:default_branch, @repository.branch_names, {}, {class: 'select2 select-wide'}) .col-sm-10= f.select(:default_branch, @repository.branch_names, {}, {class: 'select2 select-wide'})
= render 'shared/visibility_level', f: f, visibility_level: @project.visibility_level, can_change_visibility_level: can?(current_user, :change_visibility_level, @project), form_model: @project = render 'shared/visibility_level', f: f, visibility_level: @project.visibility_level, can_change_visibility_level: can_change_visibility_level?(@project, current_user), form_model: @project
.form-group .form-group
= f.label :tag_list, "Tags", class: 'control-label' = f.label :tag_list, "Tags", class: 'control-label'
...@@ -178,7 +178,7 @@ ...@@ -178,7 +178,7 @@
.form-group .form-group
= label_tag :new_namespace_id, nil, class: 'control-label' do = label_tag :new_namespace_id, nil, class: 'control-label' do
%span Namespace %span Namespace
.col-sm-10 .col-sm-9
.form-group .form-group
= select_tag :new_namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace', class: 'select2' } = select_tag :new_namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace', class: 'select2' }
%ul %ul
......
...@@ -4,30 +4,30 @@ ...@@ -4,30 +4,30 @@
= render "home_panel" = render "home_panel"
.center.well .center.light-well
%h3 %h3.page-title
The repository for this project is empty The repository for this project is empty
%h4 %p
You can If you already have files you can push them using command line instructions below.
= link_to namespace_project_new_blob_path(@project.namespace, @project, 'master'), class: 'btn btn-new btn-lg' do %br
add a file Otherwise you can start with
&nbsp;or do a push via the command line. = link_to "adding README", new_readme_path, class: 'underlined-link'
file to this project.
.well .prepend-top-20
= render "shared/clone_panel" %h3.page-title
%h4 Command line instructions
%strong Command line instructions
%div.git-empty %div.git-empty
%fieldset %fieldset
%legend Git global setup %h5 Git global setup
%pre.dark %pre.light-well
:preserve :preserve
git config --global user.name "#{git_user_name}" git config --global user.name "#{git_user_name}"
git config --global user.email "#{git_user_email}" git config --global user.email "#{git_user_email}"
%fieldset %fieldset
%legend Create a new repository %h5 Create a new repository
%pre.dark %pre.light-well
:preserve :preserve
git clone #{ content_tag(:span, default_url_to_repo, class: 'clone')} git clone #{ content_tag(:span, default_url_to_repo, class: 'clone')}
cd #{@project.path} cd #{@project.path}
...@@ -37,8 +37,8 @@ ...@@ -37,8 +37,8 @@
git push -u origin master git push -u origin master
%fieldset %fieldset
%legend Existing folder or Git repository %h5 Existing folder or Git repository
%pre.dark %pre.light-well
:preserve :preserve
cd existing_folder cd existing_folder
git init git init
......
- page_title "Commit statistics" - page_title "Commit statistics"
.tree-ref-holder
= render 'shared/ref_switcher', destination: 'graphs_commits'
= render 'head' = render 'head'
%p.lead %p.lead
Commit statistics for Commit statistics for
%strong #{@repository.root_ref} %strong #{@ref}
#{@commits_graph.start_date.strftime('%b %d')} - #{@commits_graph.end_date.strftime('%b %d')} #{@commits_graph.start_date.strftime('%b %d')} - #{@commits_graph.end_date.strftime('%b %d')}
.row .row
......
- page_title "Contributor statistics" - page_title "Contributor statistics"
.tree-ref-holder
= render 'shared/ref_switcher', destination: 'graphs'
= render 'head' = render 'head'
.loading-graph .loading-graph
.center .center
%h3.page-title %h3.page-title
...@@ -11,7 +14,7 @@ ...@@ -11,7 +14,7 @@
.header.clearfix .header.clearfix
%h3#date_header.page-title %h3#date_header.page-title
%p.light %p.light
Commits to #{@project.default_branch}, excluding merge commits. Limited by 6,000 commits Commits to #{@ref}, excluding merge commits. Limited by 6,000 commits
%input#brush_change{:type => "hidden"} %input#brush_change{:type => "hidden"}
.graphs .graphs
#contributors-master #contributors-master
...@@ -35,4 +38,3 @@ ...@@ -35,4 +38,3 @@
$(".stat-graph").fadeIn(); $(".stat-graph").fadeIn();
$(".loading-graph").hide(); $(".loading-graph").hide();
dataType: "json" dataType: "json"
...@@ -6,5 +6,5 @@ ...@@ -6,5 +6,5 @@
= pluralize label.open_issues_count, 'open issue' = pluralize label.open_issues_count, 'open issue'
- if can? current_user, :admin_label, @project - if can? current_user, :admin_label, @project
= link_to 'Edit', edit_namespace_project_label_path(@project.namespace, @project, label), class: 'btn' = link_to 'Edit', edit_namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-sm'
= link_to 'Remove', namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"} = link_to 'Remove', namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"}
- page_title "Merge Requests" - page_title "Merge Requests"
= render 'projects/last_push'
.append-bottom-10 .append-bottom-10
.pull-right .pull-right
= render 'shared/issuable/search_form', path: namespace_project_merge_requests_path(@project.namespace, @project) = render 'shared/issuable/search_form', path: namespace_project_merge_requests_path(@project.namespace, @project)
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
%li %li
The import will time out after 4 minutes. For big repositories, use a clone/push combination. The import will time out after 4 minutes. For big repositories, use a clone/push combination.
%li %li
To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}. To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"}.
%hr.prepend-botton-10 %hr.prepend-botton-10
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
= render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-task-list-field' = render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-task-list-field'
.comment-hints.clearfix .comment-hints.clearfix
.pull-left Comments are parsed with #{link_to 'GitLab Flavored Markdown', help_page_path('markdown', 'markdown'),{ target: '_blank', tabindex: -1 }} .pull-left #{link_to 'Markdown ', help_page_path('markdown', 'markdown'),{ target: '_blank', tabindex: -1 }}
.pull-right Attach files by dragging &amp; dropping or #{link_to 'selecting them', '#', class: 'markdown-selector', tabindex: -1 }. .pull-right #{link_to 'Attach a file', '#', class: 'markdown-selector', tabindex: -1 }
.note-form-actions .note-form-actions
.buttons .buttons
......
...@@ -12,8 +12,14 @@ ...@@ -12,8 +12,14 @@
classes: 'note_text js-note-text' classes: 'note_text js-note-text'
.comment-hints.clearfix .comment-hints.clearfix
.pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }} .pull-left
.pull-right Attach files by dragging &amp; dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }. = link_to "Markdown ", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }
tip:
= random_markdown_tip
.pull-right
= link_to '#', class: 'markdown-selector', tabindex: -1 do
Attach a file
= icon('paperclip')
.error-alert .error-alert
.note-form-actions .note-form-actions
......
...@@ -6,11 +6,54 @@ ...@@ -6,11 +6,54 @@
= render 'shared/no_ssh' = render 'shared/no_ssh'
= render 'shared/no_password' = render 'shared/no_password'
= render 'projects/last_push'
= render "home_panel" = render "home_panel"
= render 'shared/show_aside'
.row .project-stats
%section.col-md-8 %ul.nav.nav-pills
= render 'section' %li
%aside.col-md-4.project-side = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref) do
= render 'aside' = pluralize(number_with_delimiter(@repository.commit_count), 'commit')
%li
= link_to namespace_project_branches_path(@project.namespace, @project) do
= pluralize(number_with_delimiter(@repository.branch_names.count), 'branch')
%li
= link_to namespace_project_tags_path(@project.namespace, @project) do
= pluralize(number_with_delimiter(@repository.tag_names.count), 'tag')
- if @repository.changelog
%li
= link_to changelog_url(@project) do
Changelog
- if @repository.license
%li
= link_to license_url(@project) do
License
- if @repository.contribution_guide
%li
= link_to contribution_guide_url(@project) do
Contribution guide
- if @project.archived?
.text-warning.center.prepend-top-20
%p
= icon("exclamation-triangle fw")
Archived project! Repository is read-only
%hr
%section
- if prefer_readme?
= render 'projects/readme'
- else
= render 'projects/activity'
- if current_user
- access = user_max_access_in_project(current_user, @project)
- if access
%hr
%p.light
You have #{access} access to this project.
- if @project.project_member_by_id(current_user)
= link_to leave_namespace_project_project_members_path(@project.namespace, @project),
data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project', class: 'cred' do
Leave this project
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
= content_for :meta_tags do = content_for :meta_tags do
- if current_user - if current_user
= auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits") = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits")
= render 'projects/last_push'
.tree-ref-holder .tree-ref-holder
= render 'shared/ref_switcher', destination: 'tree', path: @path = render 'shared/ref_switcher', destination: 'tree', path: @path
......
- blob = @project.repository.parse_search_result(blob)
.blob-result .blob-result
.file-holder .file-holder
.file-title .file-title
......
- wiki_blob = @project.repository.parse_search_result(wiki_blob)
.blob-result .blob-result
.file-holder .file-holder
.file-title .file-title
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment