Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq into backup-archive-permissions
This commit is contained in:
commit
0be6debb0b
240 changed files with 2594 additions and 1161 deletions
37
CHANGELOG
37
CHANGELOG
|
@ -1,24 +1,39 @@
|
|||
Please view this file on the master branch, on stable branches it's out of date.
|
||||
|
||||
v 7.14.0 (unreleased)
|
||||
- Fix full screen mode for snippet comments (Daniel Gerhardt)
|
||||
- Fix 404 error in files view after deleting the last file in a repository (Stan Hu)
|
||||
- Fix label read access for unauthenticated users (Daniel Gerhardt)
|
||||
- Fix access to disabled features for unauthenticated users (Daniel Gerhardt)
|
||||
- Fix OAuth provider bug where GitLab would not go return to the redirect_uri after sign-in (Stan Hu)
|
||||
- Fix file upload dialog for comment editing (Daniel Gerhardt)
|
||||
- Set OmniAuth full_host parameter to ensure redirect URIs are correct (Stan Hu)
|
||||
- Expire Rails cache entries after two weeks to prevent endless Redis growth
|
||||
- Add support for destroying project milestones (Stan Hu)
|
||||
- Add fetch command to the MR page.
|
||||
|
||||
v 7.13.0 (unreleased)
|
||||
- Remove repository graph log to fix slow cache updates after push event (Stan Hu)
|
||||
- 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)
|
||||
- Remove link leading to a 404 error in Deploy Keys page (Stan Hu)
|
||||
- Add support for unlocking users in admin settings (Stan Hu)
|
||||
- Add Irker service configuration options (Stan Hu)
|
||||
- Fix order of issues imported form GitHub (Hiroyuki Sato)
|
||||
- Fix order of issues imported from GitHub (Hiroyuki Sato)
|
||||
- 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
|
||||
- Add `two_factor_enabled` field to admin user API (Stan Hu)
|
||||
- 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)
|
||||
- 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)
|
||||
- Extract the longest-matching ref from a commit path when multiple matches occur (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)
|
||||
- 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
|
||||
- Rename "Design" profile settings page to "Preferences".
|
||||
- Allow users to customize their default Dashboard page.
|
||||
|
@ -38,11 +53,21 @@ v 7.13.0 (unreleased)
|
|||
- Query Optimization in MySQL.
|
||||
- Allow users to be blocked and unblocked via the API
|
||||
- Allow custom backup archive permissions
|
||||
- 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
|
||||
- Store commits count in database (will populate with valid values only after first push)
|
||||
- Rebuild cache after push to repository in background job
|
||||
|
||||
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
|
||||
- Fix error when deleting a user who has projects (Stan Hu)
|
||||
|
@ -52,6 +77,8 @@ v 7.12.1
|
|||
- Fix closed merge request scope at milestone page (Dmitriy Zaporozhets)
|
||||
- Revert merge request states renaming
|
||||
- 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
|
||||
- Fix Error 500 when one user attempts to access a personal, internal snippet (Stan Hu)
|
||||
|
@ -110,6 +137,7 @@ v 7.12.0
|
|||
- Improve group removing logic
|
||||
- Trigger create-hooks on backup restore task
|
||||
- Add option to automatically link omniauth and LDAP identities
|
||||
- Allow special character in users bio. I.e.: I <3 GitLab
|
||||
|
||||
v 7.11.4
|
||||
- Fix missing bullets when creating lists
|
||||
|
@ -128,9 +156,6 @@ v 7.11.1
|
|||
v 7.11.0
|
||||
- Fall back to Plaintext when Syntaxhighlighting doesn't work. Fixes some buggy lexers (Hannes Rosenögger)
|
||||
- Get editing comments to work in Chrome 43 again.
|
||||
- Allow special character in users bio. I.e.: I <3 GitLab
|
||||
|
||||
v 7.11.0
|
||||
- Fix broken view when viewing history of a file that includes a path that used to be another file (Stan Hu)
|
||||
- Don't show duplicate deploy keys
|
||||
- Fix commit time being displayed in the wrong timezone in some cases (Hannes Rosenögger)
|
||||
|
|
26
Gemfile
26
Gemfile
|
@ -46,7 +46,7 @@ gem "gitlab_git", '~> 7.2.5'
|
|||
gem 'gitlab-grack', '~> 2.0.2', require: 'grack'
|
||||
|
||||
# LDAP Auth
|
||||
# GitLab fork with several improvements to original library. For full list of changes
|
||||
# GitLab fork with several improvements to original library. For full list of changes
|
||||
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
|
||||
gem 'gitlab_omniauth-ldap', '1.2.1', require: "omniauth-ldap"
|
||||
|
||||
|
@ -54,9 +54,9 @@ gem 'gitlab_omniauth-ldap', '1.2.1', require: "omniauth-ldap"
|
|||
gem 'gollum-lib', '~> 4.0.2'
|
||||
|
||||
# Language detection
|
||||
# GitLab fork of linguist does not require pygments/python dependency.
|
||||
# New version of original gem also dropped pygments support but it has strict
|
||||
# dependency to unstable rugged version. We have internal issue for replacing
|
||||
# GitLab fork of linguist does not require pygments/python dependency.
|
||||
# New version of original gem also dropped pygments support but it has strict
|
||||
# dependency to unstable rugged version. We have internal issue for replacing
|
||||
# fork with original gem when we meet on same rugged version - https://dev.gitlab.org/gitlab/gitlabhq/issues/2052.
|
||||
gem "gitlab-linguist", "~> 3.0.1", require: "linguist"
|
||||
|
||||
|
@ -203,7 +203,7 @@ gem 'jquery-ui-rails'
|
|||
gem 'nprogress-rails'
|
||||
gem 'raphael-rails', '~> 2.1.2'
|
||||
gem 'request_store'
|
||||
gem 'select2-rails'
|
||||
gem 'select2-rails', '~> 3.5.9'
|
||||
gem 'virtus'
|
||||
|
||||
group :development do
|
||||
|
@ -227,30 +227,24 @@ end
|
|||
|
||||
group :development, :test do
|
||||
gem 'awesome_print'
|
||||
gem 'byebug'
|
||||
gem 'byebug', platform: :mri
|
||||
gem 'fuubar', '~> 2.0.0'
|
||||
gem 'pry-rails'
|
||||
|
||||
gem 'coveralls', require: false
|
||||
gem 'coveralls', '~> 0.8.2', require: false
|
||||
gem 'database_cleaner', '~> 1.4.0'
|
||||
gem 'factory_girl_rails'
|
||||
gem 'rspec-rails', '~> 3.3.0'
|
||||
gem 'rubocop', '0.28.0', require: false
|
||||
gem 'rspec-rails', '~> 3.3.0'
|
||||
gem 'rubocop', '0.28.0', require: false
|
||||
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)
|
||||
gem 'minitest', '~> 5.3.0'
|
||||
|
||||
# Generate Fake data
|
||||
gem 'ffaker', '~> 2.0.0'
|
||||
|
||||
gem 'capybara', '~> 2.3.0'
|
||||
gem 'capybara', '~> 2.4.0'
|
||||
gem 'capybara-screenshot', '~> 1.0.0'
|
||||
gem 'poltergeist', '~> 1.6.0'
|
||||
|
||||
|
|
15
Gemfile.lock
15
Gemfile.lock
|
@ -82,7 +82,7 @@ GEM
|
|||
columnize (~> 0.8)
|
||||
debugger-linecache (~> 1.2)
|
||||
cal-heatmap-rails (0.0.1)
|
||||
capybara (2.3.0)
|
||||
capybara (2.4.4)
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
|
@ -598,7 +598,7 @@ GEM
|
|||
seed-fu (2.3.5)
|
||||
activerecord (>= 3.1, < 4.3)
|
||||
activesupport (>= 3.1, < 4.3)
|
||||
select2-rails (3.5.2)
|
||||
select2-rails (3.5.9.3)
|
||||
thor (~> 0.14)
|
||||
settingslogic (2.0.9)
|
||||
sexp_processor (4.4.5)
|
||||
|
@ -703,7 +703,7 @@ GEM
|
|||
underscore-rails (1.4.4)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.6)
|
||||
unf_ext (0.0.7.1)
|
||||
unicorn (4.6.3)
|
||||
kgio (~> 2.6)
|
||||
rack
|
||||
|
@ -753,13 +753,13 @@ DEPENDENCIES
|
|||
browser (~> 0.8.0)
|
||||
byebug
|
||||
cal-heatmap-rails (~> 0.0.1)
|
||||
capybara (~> 2.3.0)
|
||||
capybara (~> 2.4.0)
|
||||
capybara-screenshot (~> 1.0.0)
|
||||
carrierwave
|
||||
charlock_holmes
|
||||
coffee-rails
|
||||
colored
|
||||
coveralls
|
||||
coveralls (~> 0.8.2)
|
||||
creole (~> 0.3.6)
|
||||
d3_rails (~> 3.5.5)
|
||||
database_cleaner (~> 1.4.0)
|
||||
|
@ -833,7 +833,6 @@ DEPENDENCIES
|
|||
redis-rails
|
||||
request_store
|
||||
rerun (~> 0.10.0)
|
||||
rest-client (~> 1.8.0)
|
||||
rqrcode-rails3
|
||||
rspec-rails (~> 3.3.0)
|
||||
rubocop (= 0.28.0)
|
||||
|
@ -842,7 +841,7 @@ DEPENDENCIES
|
|||
sass-rails (~> 4.0.5)
|
||||
sdoc
|
||||
seed-fu
|
||||
select2-rails
|
||||
select2-rails (~> 3.5.9)
|
||||
settingslogic
|
||||
shoulda-matchers (~> 2.8.0)
|
||||
sidekiq (~> 3.3)
|
||||
|
@ -878,4 +877,4 @@ DEPENDENCIES
|
|||
wikicloth (= 0.8.1)
|
||||
|
||||
BUNDLED WITH
|
||||
1.10.4
|
||||
1.10.5
|
||||
|
|
76
README.md
76
README.md
|
@ -1,9 +1,14 @@
|
|||
# GitLab
|
||||
|
||||
[![build status](https://ci.gitlab.com/projects/1/status.png?ref=master)](https://ci.gitlab.com/projects/1?ref=master)
|
||||
[![Build Status](https://semaphoreapp.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/243338/badge.png)](https://semaphoreapp.com/gitlabhq/gitlabhq)
|
||||
[![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq)
|
||||
[![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master)
|
||||
|
||||
## Canonical source
|
||||
|
||||
The source of GitLab Community Edition is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/) and there are mirrors to make [contributing](CONTRIBUTING.md) as easy as possible.
|
||||
|
||||
# ![logo](https://about.gitlab.com/images/gitlab_logo.png) GitLab
|
||||
|
||||
## Open source software to collaborate on code
|
||||
|
||||
To see how GitLab looks please see the [features page on our website](https://about.gitlab.com/features/).
|
||||
|
@ -17,21 +22,12 @@ To see how GitLab looks please see the [features page on our website](https://ab
|
|||
|
||||
## Editions
|
||||
|
||||
There are two editions of GitLab.
|
||||
*GitLab [Community Edition](https://about.gitlab.com/features/) (CE)* is available without any costs under an MIT license.
|
||||
There are two editions of GitLab:
|
||||
|
||||
*GitLab Enterprise Edition (EE)* includes [extra features](https://about.gitlab.com/features/#compare) that are most useful for organizations with more than 100 users.
|
||||
To use EE and get official support please [become a subscriber](https://about.gitlab.com/pricing/).
|
||||
- GitLab Community Edition (CE) is available freely under the MIT Expat license.
|
||||
- GitLab Enterprise Edition (EE) includes [extra features](https://about.gitlab.com/features/#compare) that are more useful for organizations with more than 100 users. To use EE and get official support please [become a subscriber](https://about.gitlab.com/pricing/).
|
||||
|
||||
## 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://semaphoreapp.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/243338/badge.png)](https://semaphoreapp.com/gitlabhq/gitlabhq)
|
||||
|
||||
- [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq)
|
||||
|
||||
- [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master)
|
||||
Included with the GitLab Omnibus Packages is [GitLab CI](https://about.gitlab.com/gitlab-ci/) that can easily build, test and deploy code.
|
||||
|
||||
## Website
|
||||
|
||||
|
@ -46,7 +42,31 @@ On [about.gitlab.com](https://about.gitlab.com/) you can find more information a
|
|||
|
||||
## Requirements
|
||||
|
||||
GitLab requires the following software:
|
||||
Please see the [requirements documentation](doc/install/requirements.md) for system requirements and more information about the supported operating systems.
|
||||
|
||||
## Installation
|
||||
|
||||
The recommended way to install GitLab is with the [Omnibus packages](https://about.gitlab.com/downloads/) on our package server.
|
||||
Compared to an installation from source, this is faster and less error prone.
|
||||
Just select your operating system, download the respective package (Debian or RPM) and install it using the system's package manager.
|
||||
|
||||
There are various other options to install GitLab, please refer to the [installation page on the GitLab website](https://about.gitlab.com/installation/) for more information.
|
||||
|
||||
You can access a new installation with the login **`root`** and password **`5iveL!fe`**, after login you are required to set a unique password.
|
||||
|
||||
## Install a development environment
|
||||
|
||||
To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
|
||||
If you do not use the GitLab Development Kit you need to install and setup all the dependencies yourself, this is a lot of work and error prone.
|
||||
One small thing you also have to do when installing it yourself is to copy the example development unicorn configuration file:
|
||||
|
||||
cp config/unicorn.rb.example.development config/unicorn.rb
|
||||
|
||||
Instructions on how to start GitLab and how to run the tests can be found in the [development section of the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit#development).
|
||||
|
||||
## Software stack
|
||||
|
||||
GitLab is a Ruby on Rails application that runs on the following software:
|
||||
|
||||
- Ubuntu/Debian/CentOS/RHEL
|
||||
- Ruby (MRI) 2.0 or 2.1
|
||||
|
@ -54,15 +74,7 @@ GitLab requires the following software:
|
|||
- Redis 2.0+
|
||||
- MySQL or PostgreSQL
|
||||
|
||||
Please see the [requirements documentation](doc/install/requirements.md) for system requirements and more information about the supported operating systems.
|
||||
|
||||
## Installation
|
||||
|
||||
The recommended way to install GitLab is using the provided [Omnibus packages](https://about.gitlab.com/downloads/). Compared to an installation from source, this is faster and less error prone. Just select your operating system, download the respective package (Debian or RPM) and install it using the system's package manager.
|
||||
|
||||
There are various other options to install GitLab, please refer to the [installation page on the GitLab website](https://about.gitlab.com/installation/) for more information.
|
||||
|
||||
You can access a new installation with the login **`root`** and password **`password`**, after login you are required to set a unique password.
|
||||
For more information please see the [architecture documentation](http://doc.gitlab.com/ce/development/architecture.html).
|
||||
|
||||
## Third-party applications
|
||||
|
||||
|
@ -74,17 +86,7 @@ Since 2011 a minor or major version of GitLab is released on the 22nd of every m
|
|||
|
||||
## 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.
|
||||
|
||||
## Install a development environment
|
||||
|
||||
To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
|
||||
If you do not use the GitLab Development Kit you need to install and setup all the dependencies yourself, this is a lot of work and error prone.
|
||||
One small thing you also have to do when installing it yourself is to copy the example development unicorn configuration file:
|
||||
|
||||
cp config/unicorn.rb.example.development config/unicorn.rb
|
||||
|
||||
Instructions on how to start GitLab and how to run the tests can be found in the [development section of the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit#development).
|
||||
For upgrading information please see our [update page](https://about.gitlab.com/update/).
|
||||
|
||||
## Documentation
|
||||
|
||||
|
@ -101,4 +103,4 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on
|
|||
## Is it awesome?
|
||||
|
||||
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.
|
BIN
app/assets/images/msapplication-tile.png
Normal file
BIN
app/assets/images/msapplication-tile.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6 KiB |
BIN
app/assets/images/touch-icon-ipad-retina.png
Normal file
BIN
app/assets/images/touch-icon-ipad-retina.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.9 KiB |
BIN
app/assets/images/touch-icon-ipad.png
Normal file
BIN
app/assets/images/touch-icon-ipad.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
BIN
app/assets/images/touch-icon-iphone-retina.png
Normal file
BIN
app/assets/images/touch-icon-iphone-retina.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
BIN
app/assets/images/touch-icon-iphone.png
Normal file
BIN
app/assets/images/touch-icon-iphone.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
|
@ -40,6 +40,7 @@
|
|||
#= require shortcuts_issuable
|
||||
#= require shortcuts_network
|
||||
#= require cal-heatmap
|
||||
#= require jquery.nicescroll.min
|
||||
#= require_tree .
|
||||
|
||||
window.slugify = (text) ->
|
||||
|
@ -104,6 +105,8 @@ if location.hash
|
|||
window.addEventListener "hashchange", shiftWindow
|
||||
|
||||
$ ->
|
||||
$(".nicescroll").niceScroll(cursoropacitymax: '0.4', cursorcolor: '#FFF', cursorborder: "1px solid #FFF")
|
||||
|
||||
# Click a .js-select-on-focus field, select the contents
|
||||
$(".js-select-on-focus").on "focusin", ->
|
||||
# Prevent a mouseup event from deselecting the input
|
||||
|
|
|
@ -62,8 +62,9 @@ class Dispatcher
|
|||
shortcut_handler = new ShortcutsNavigation()
|
||||
when 'projects:commits:show'
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
when 'projects:activity'
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
when 'projects:show'
|
||||
new Activities()
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
when 'groups:show'
|
||||
new Activities()
|
||||
|
@ -127,7 +128,10 @@ class Dispatcher
|
|||
shortcut_handler = new ShortcutsNavigation()
|
||||
new ZenMode()
|
||||
new DropzoneInput($('.wiki-form'))
|
||||
when 'snippets', 'labels', 'graphs'
|
||||
when 'snippets'
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
new ZenMode() if path[2] == 'show'
|
||||
when 'labels', 'graphs'
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
when 'project_members', 'deploy_keys', 'hooks', 'services', 'protected_branches'
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
|
|
|
@ -25,10 +25,10 @@ class @DropzoneInput
|
|||
form_dropzone = $(form).find('.div-dropzone')
|
||||
form_dropzone.parent().addClass "div-dropzone-wrapper"
|
||||
form_dropzone.append divHover
|
||||
$(".div-dropzone-hover").append iconPaperclip
|
||||
form_dropzone.find(".div-dropzone-hover").append iconPaperclip
|
||||
form_dropzone.append divSpinner
|
||||
$(".div-dropzone-spinner").append iconSpinner
|
||||
$(".div-dropzone-spinner").css
|
||||
form_dropzone.find(".div-dropzone-spinner").append iconSpinner
|
||||
form_dropzone.find(".div-dropzone-spinner").css
|
||||
"opacity": 0
|
||||
"display": "none"
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ class @LineHighlighter
|
|||
|
||||
@clearHighlight()
|
||||
|
||||
lineNumber = $(event.target).data('line-number')
|
||||
lineNumber = $(event.target).closest('a').data('line-number')
|
||||
current = @hashToRange(@_hash)
|
||||
|
||||
unless current[0] && event.shiftKey
|
||||
|
|
|
@ -15,9 +15,7 @@ class @MergeRequest
|
|||
this.$('.show-all-commits').on 'click', =>
|
||||
this.showAllCommits()
|
||||
|
||||
# `MergeRequests#new` has no tab-persisting or lazy-loading behavior
|
||||
unless @opts.action == 'new'
|
||||
new MergeRequestTabs(@opts)
|
||||
@initTabs()
|
||||
|
||||
# Prevent duplicate event bindings
|
||||
@disableTaskList()
|
||||
|
@ -29,6 +27,14 @@ class @MergeRequest
|
|||
$: (selector) ->
|
||||
this.$el.find(selector)
|
||||
|
||||
initTabs: ->
|
||||
if @opts.action != 'new'
|
||||
# `MergeRequests#new` has no tab-persisting or lazy-loading behavior
|
||||
new MergeRequestTabs(@opts)
|
||||
else
|
||||
# Show the first tab (Commits)
|
||||
$('.merge-request-tabs a[data-toggle="tab"]:first').tab('show')
|
||||
|
||||
showAllCommits: ->
|
||||
this.$('.first-commits').remove()
|
||||
this.$('.all-commits').removeClass 'hide'
|
||||
|
|
|
@ -298,7 +298,7 @@ class @Notes
|
|||
note.find(".note-header").hide()
|
||||
base_form = note.find(".note-edit-form")
|
||||
form = base_form.clone().insertAfter(base_form)
|
||||
form.addClass('current-note-edit-form')
|
||||
form.addClass('current-note-edit-form gfm-form')
|
||||
form.find('.div-dropzone').remove()
|
||||
|
||||
# Show the attachment delete link
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
@loading.show()
|
||||
$.ajax
|
||||
type: "GET"
|
||||
url: location.href
|
||||
url: $(".content_list").data('href') || location.href
|
||||
data: "limit=" + @limit + "&offset=" + @offset
|
||||
complete: =>
|
||||
@loading.hide()
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
class @ProjectShow
|
||||
constructor: ->
|
||||
$('.project-home-panel .star').on 'ajax:success', (e, data, status, xhr) ->
|
||||
$(@).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"
|
||||
# I kept class for future
|
||||
|
|
|
@ -4,6 +4,7 @@ class @ShortcutsNavigation extends Shortcuts
|
|||
constructor: ->
|
||||
super()
|
||||
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 c', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-commits'))
|
||||
Mousetrap.bind('g n', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-network'))
|
||||
|
|
|
@ -109,7 +109,7 @@
|
|||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
blockquote {
|
||||
color: #888;
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
|
|
|
@ -44,20 +44,18 @@
|
|||
.project-home-panel {
|
||||
padding-left: 0 !important;
|
||||
|
||||
.project-home-row {
|
||||
.project-home-desc {
|
||||
margin-right: 0 !important;
|
||||
float: none !important;
|
||||
}
|
||||
|
||||
.project-repo-buttons {
|
||||
position: static;
|
||||
margin-top: 15px;
|
||||
width: 100%;
|
||||
float: none;
|
||||
text-align: left;
|
||||
}
|
||||
.project-avatar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.project-repo-buttons,
|
||||
.git-clone-holder {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.project-stats {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.container .title {
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
.sidebar-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
transition-duration: .3s;
|
||||
|
@ -21,8 +24,9 @@
|
|||
}
|
||||
|
||||
.nav-sidebar {
|
||||
margin-top: 29 + $header-height;
|
||||
margin-bottom: 50px;
|
||||
transition-duration: .3s;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
overflow: hidden;
|
||||
|
||||
|
@ -39,12 +43,12 @@
|
|||
}
|
||||
|
||||
a {
|
||||
padding: 8px 15px;
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
color: $gray;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
padding: 8px 15px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
padding-left: 16px;
|
||||
|
||||
&:hover {
|
||||
|
@ -88,14 +92,17 @@
|
|||
width: $sidebar_width;
|
||||
|
||||
.nav-sidebar {
|
||||
margin-top: 29px;
|
||||
position: fixed;
|
||||
top: $header-height;
|
||||
width: $sidebar_width;
|
||||
}
|
||||
|
||||
.nav-sidebar li a{
|
||||
width: 230px;
|
||||
|
||||
&.back-link {
|
||||
i {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,15 +115,9 @@
|
|||
width: $sidebar_collapsed_width;
|
||||
|
||||
.nav-sidebar {
|
||||
margin-top: 29px;
|
||||
position: fixed;
|
||||
top: $header-height;
|
||||
width: $sidebar_collapsed_width;
|
||||
|
||||
li a {
|
||||
font-size: 14px;
|
||||
padding: 8px 15px;
|
||||
text-align: left;
|
||||
padding-left: 16px;
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +176,7 @@
|
|||
}
|
||||
|
||||
.sidebar-user {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: $sidebar_width;
|
||||
padding: 10px;
|
||||
|
|
|
@ -17,6 +17,14 @@ pre {
|
|||
background: #333;
|
||||
color: $background-color;
|
||||
}
|
||||
|
||||
&.plain-readme {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.monospace {
|
||||
|
|
|
@ -72,13 +72,28 @@ ul.notes {
|
|||
.note {
|
||||
display: block;
|
||||
position:relative;
|
||||
|
||||
.note-body {
|
||||
overflow: auto;
|
||||
|
||||
.note-text {
|
||||
overflow: auto;
|
||||
word-wrap: break-word;
|
||||
@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
|
||||
ul.task-list:first-child {
|
||||
padding-left: 10px;
|
||||
|
@ -94,6 +109,7 @@ ul.notes {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.note-header {
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
|
|
@ -15,48 +15,31 @@
|
|||
}
|
||||
|
||||
.project-home-panel {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 15px;
|
||||
position: relative;
|
||||
padding-left: 65px;
|
||||
min-height: 50px;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.project-identicon-holder {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -14px;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.avatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
.avatar, .identicon {
|
||||
margin: 0 auto;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.identicon {
|
||||
font-size: 26px;
|
||||
line-height: 50px;
|
||||
@include border-radius(50%);
|
||||
}
|
||||
}
|
||||
|
||||
.project-home-row {
|
||||
@extend .clearfix;
|
||||
margin-bottom: 15px;
|
||||
|
||||
&.project-home-row-top {
|
||||
margin-bottom: 15px;
|
||||
.lead {
|
||||
p {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.project-home-desc {
|
||||
color: $gray;
|
||||
float: left;
|
||||
font-size: 16px;
|
||||
line-height: 1.3;
|
||||
margin-right: 250px;
|
||||
|
||||
// Render Markdown-generated HTML inline for this block
|
||||
p {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
.git-clone-holder {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.visibility-level-label {
|
||||
|
@ -67,22 +50,22 @@
|
|||
}
|
||||
|
||||
.project-repo-buttons {
|
||||
margin-top: -3px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 265px;
|
||||
text-align: right;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 25px;
|
||||
|
||||
.btn {
|
||||
@extend .btn-info;
|
||||
|
||||
margin-left: 10px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
padding: 8px 12px;
|
||||
|
||||
.count {
|
||||
padding-left: 10px;
|
||||
border-left: 1px solid #ccc;
|
||||
padding-left: 7px;
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
margin-left: 7px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -307,3 +290,15 @@ table.table.protected-branches-list tr.no-border {
|
|||
float: left;
|
||||
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 @@
|
|||
|
||||
.sidebar-wrapper {
|
||||
background: $color-darker;
|
||||
border-right: 1px solid $color-darker;
|
||||
|
||||
.sidebar-user {
|
||||
background: $color-darker;
|
||||
color: $color-light;
|
||||
|
||||
&:hover {
|
||||
|
|
|
@ -23,7 +23,8 @@ class Admin::ProjectsController < Admin::ApplicationController
|
|||
end
|
||||
|
||||
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
|
||||
redirect_to admin_namespace_project_path(@project.namespace, @project)
|
||||
|
|
|
@ -55,6 +55,12 @@ class Admin::UsersController < Admin::ApplicationController
|
|||
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
|
||||
opts = {
|
||||
force_random_password: true,
|
||||
|
|
|
@ -183,7 +183,10 @@ class ApplicationController < ActionController::Base
|
|||
headers['X-XSS-Protection'] = '1; mode=block'
|
||||
headers['X-UA-Compatible'] = 'IE=edge'
|
||||
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
|
||||
|
||||
def add_gon_variables
|
||||
|
@ -265,6 +268,7 @@ class ApplicationController < ActionController::Base
|
|||
params[:scope] = 'all' if params[:scope].blank?
|
||||
params[:state] = 'opened' if params[:state].blank?
|
||||
|
||||
@sort = params[:sort]
|
||||
@filter_params = params.dup
|
||||
|
||||
if @project
|
||||
|
|
|
@ -1,22 +1,35 @@
|
|||
class AutocompleteController < ApplicationController
|
||||
skip_before_action :authenticate_user!, only: [:users]
|
||||
|
||||
def users
|
||||
@users =
|
||||
if params[:project_id].present?
|
||||
project = Project.find(params[:project_id])
|
||||
begin
|
||||
@users =
|
||||
if params[:project_id].present?
|
||||
project = Project.find(params[:project_id])
|
||||
|
||||
if can?(current_user, :read_project, project)
|
||||
project.team.users
|
||||
end
|
||||
elsif params[:group_id]
|
||||
group = Group.find(params[:group_id])
|
||||
if can?(current_user, :read_project, project)
|
||||
project.team.users
|
||||
end
|
||||
elsif params[:group_id]
|
||||
group = Group.find(params[:group_id])
|
||||
|
||||
if can?(current_user, :read_group, group)
|
||||
group.users
|
||||
if can?(current_user, :read_group, group)
|
||||
group.users
|
||||
end
|
||||
elsif current_user
|
||||
User.all
|
||||
end
|
||||
else
|
||||
User.all
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
if current_user
|
||||
return render json: {}, status: 404
|
||||
end
|
||||
end
|
||||
|
||||
if @users.nil? && current_user.nil?
|
||||
authenticate_user!
|
||||
end
|
||||
|
||||
@users ||= User.none
|
||||
@users = @users.search(params[:search]) if params[:search].present?
|
||||
@users = @users.active
|
||||
@users = @users.page(params[:page]).per(PER_PAGE)
|
||||
|
|
|
@ -32,6 +32,7 @@ class Profiles::PreferencesController < Profiles::ApplicationController
|
|||
params.require(:user).permit(
|
||||
:color_scheme_id,
|
||||
:dashboard,
|
||||
:project_view,
|
||||
:theme_id
|
||||
)
|
||||
end
|
||||
|
|
|
@ -29,13 +29,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
current_user.update_attributes({
|
||||
two_factor_enabled: false,
|
||||
encrypted_otp_secret: nil,
|
||||
encrypted_otp_secret_iv: nil,
|
||||
encrypted_otp_secret_salt: nil,
|
||||
otp_backup_codes: nil
|
||||
})
|
||||
current_user.disable_two_factor!
|
||||
|
||||
redirect_to profile_account_path
|
||||
end
|
||||
|
|
|
@ -32,7 +32,7 @@ class Projects::BranchesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
DeleteBranchService.new(project, current_user).execute(params[:id])
|
||||
status = DeleteBranchService.new(project, current_user).execute(params[:id])
|
||||
@branch_name = params[:id]
|
||||
|
||||
respond_to do |format|
|
||||
|
@ -40,7 +40,7 @@ class Projects::BranchesController < Projects::ApplicationController
|
|||
redirect_to namespace_project_branches_path(@project.namespace,
|
||||
@project)
|
||||
end
|
||||
format.js
|
||||
format.js { render status: status[:return_code] }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
class Projects::GraphsController < Projects::ApplicationController
|
||||
include ExtractsPath
|
||||
|
||||
# Authorize
|
||||
before_action :require_non_empty_project
|
||||
before_action :assign_ref_vars
|
||||
before_action :authorize_download_code!
|
||||
|
||||
def show
|
||||
|
@ -13,7 +16,7 @@ class Projects::GraphsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
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_per_week_days = @commits_graph.commits_per_week_days
|
||||
@commits_per_time = @commits_graph.commits_per_time
|
||||
|
@ -23,7 +26,7 @@ class Projects::GraphsController < Projects::ApplicationController
|
|||
private
|
||||
|
||||
def fetch_graph
|
||||
@commits = @project.repository.commits(nil, nil, 6000, 0, true)
|
||||
@commits = @project.repository.commits(@ref, nil, 6000, 0, true)
|
||||
@log = []
|
||||
|
||||
@commits.each do |commit|
|
||||
|
|
|
@ -64,7 +64,12 @@ class Projects::MilestonesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
return access_denied! unless can?(current_user, :admin_milestone, @milestone)
|
||||
return access_denied! unless can?(current_user, :admin_milestone, @project)
|
||||
|
||||
update_params = { milestone: nil }
|
||||
@milestone.issues.each do |issue|
|
||||
Issues::UpdateService.new(@project, current_user, update_params).execute(issue)
|
||||
end
|
||||
|
||||
@milestone.destroy
|
||||
|
||||
|
|
|
@ -8,17 +8,21 @@ class Projects::RefsController < Projects::ApplicationController
|
|||
def switch
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
new_path = if params[:destination] == "tree"
|
||||
namespace_project_tree_path(@project.namespace, @project,
|
||||
(@id))
|
||||
elsif params[:destination] == "blob"
|
||||
namespace_project_blob_path(@project.namespace, @project,
|
||||
(@id))
|
||||
elsif params[:destination] == "graph"
|
||||
namespace_project_network_path(@project.namespace, @project, @id, @options)
|
||||
else
|
||||
namespace_project_commits_path(@project.namespace, @project, @id)
|
||||
end
|
||||
new_path =
|
||||
case params[:destination]
|
||||
when "tree"
|
||||
namespace_project_tree_path(@project.namespace, @project, @id)
|
||||
when "blob"
|
||||
namespace_project_blob_path(@project.namespace, @project, @id)
|
||||
when "graph"
|
||||
namespace_project_network_path(@project.namespace, @project, @id, @options)
|
||||
when "graphs"
|
||||
namespace_project_graph_path(@project.namespace, @project, @id)
|
||||
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
|
||||
end
|
||||
|
|
|
@ -7,13 +7,15 @@ class Projects::TreeController < Projects::ApplicationController
|
|||
before_action :authorize_download_code!
|
||||
|
||||
def show
|
||||
return not_found! unless @repository.commit(@ref)
|
||||
|
||||
if tree.entries.empty?
|
||||
if @repository.blob_at(@commit.id, @path)
|
||||
redirect_to(
|
||||
namespace_project_blob_path(@project.namespace, @project,
|
||||
File.join(@ref, @path))
|
||||
) and return
|
||||
else
|
||||
elsif @path.present?
|
||||
return not_found!
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
class ProjectsController < ApplicationController
|
||||
prepend_before_filter :render_go_import, only: [:show]
|
||||
skip_before_action :authenticate_user!, only: [:show]
|
||||
skip_before_action :authenticate_user!, only: [:show, :activity]
|
||||
before_action :project, except: [:new, :create]
|
||||
before_action :repository, except: [:new, :create]
|
||||
|
||||
# Authorize
|
||||
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
|
||||
|
||||
|
@ -52,10 +52,21 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def transfer
|
||||
transfer_params = params.permit(:new_namespace_id)
|
||||
::Projects::TransferService.new(project, current_user, transfer_params).execute
|
||||
if @project.errors[:namespace_id].present?
|
||||
flash[:alert] = @project.errors[:namespace_id].first
|
||||
namespace = Namespace.find_by(id: params[:new_namespace_id])
|
||||
::Projects::TransferService.new(project, current_user).execute(namespace)
|
||||
|
||||
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
|
||||
|
||||
|
@ -65,15 +76,12 @@ class ProjectsController < ApplicationController
|
|||
return
|
||||
end
|
||||
|
||||
@show_star = !(current_user && current_user.starred?(@project))
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
if @project.repository_exists?
|
||||
if @project.empty_repo?
|
||||
render 'projects/empty'
|
||||
else
|
||||
@last_push = current_user.recent_push(@project.id) if current_user
|
||||
render :show
|
||||
end
|
||||
else
|
||||
|
@ -81,11 +89,6 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
format.json do
|
||||
load_events
|
||||
pager_json('events/_events', @events.count)
|
||||
end
|
||||
|
||||
format.atom do
|
||||
load_events
|
||||
render layout: false
|
||||
|
@ -147,11 +150,14 @@ class ProjectsController < ApplicationController
|
|||
def toggle_star
|
||||
current_user.toggle_star(@project)
|
||||
@project.reload
|
||||
render json: { star_count: @project.star_count }
|
||||
|
||||
render json: {
|
||||
html: view_to_html_string("projects/buttons/_star")
|
||||
}
|
||||
end
|
||||
|
||||
def markdown_preview
|
||||
text = params[:text]
|
||||
text = params[:text]
|
||||
|
||||
ext = Gitlab::ReferenceExtractor.new(@project, current_user)
|
||||
ext.analyze(text)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# state: 'open' or 'closed' or 'all'
|
||||
# group_id: integer
|
||||
# project_id: integer
|
||||
# milestone_id: integer
|
||||
# milestone_title: string
|
||||
# assignee_id: integer
|
||||
# search: string
|
||||
# label_name: string
|
||||
|
@ -76,7 +76,7 @@ class IssuableFinder
|
|||
return @milestones if defined?(@milestones)
|
||||
|
||||
@milestones =
|
||||
if milestones? && params[:milestone_title] != NONE
|
||||
if milestones? && params[:milestone_title] != Milestone::None.title
|
||||
Milestone.where(title: params[:milestone_title])
|
||||
else
|
||||
nil
|
||||
|
|
|
@ -213,6 +213,10 @@ module ApplicationHelper
|
|||
Haml::Helpers.preserve(markdown(file_content))
|
||||
elsif asciidoc?(file_name)
|
||||
asciidoc(file_content)
|
||||
elsif plain?(file_name)
|
||||
content_tag :pre, class: 'plain-readme' do
|
||||
file_content
|
||||
end
|
||||
else
|
||||
GitHub::Markup.render(file_name, file_content).
|
||||
force_encoding(file_content.encoding).html_safe
|
||||
|
@ -221,6 +225,10 @@ module ApplicationHelper
|
|||
simple_format(file_content)
|
||||
end
|
||||
|
||||
def plain?(filename)
|
||||
Gitlab::MarkupHelper.plain?(filename)
|
||||
end
|
||||
|
||||
def markup?(filename)
|
||||
Gitlab::MarkupHelper.markup?(filename)
|
||||
end
|
||||
|
|
|
@ -28,7 +28,7 @@ module ApplicationSettingsHelper
|
|||
def restricted_level_checkboxes(help_block_id)
|
||||
Gitlab::VisibilityLevel.options.map do |name, level|
|
||||
checked = restricted_visibility_levels(true).include?(level)
|
||||
css_class = 'btn btn-primary'
|
||||
css_class = 'btn'
|
||||
css_class += ' active' if checked
|
||||
checkbox_name = 'application_setting[restricted_visibility_levels][]'
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ module GitlabMarkdownHelper
|
|||
|
||||
# Returns a random markdown tip for use as a textarea placeholder
|
||||
def random_markdown_tip
|
||||
"Tip: #{MARKDOWN_TIPS.sample}"
|
||||
MARKDOWN_TIPS.sample
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -17,6 +17,10 @@ module GitlabRoutingHelper
|
|||
namespace_project_path(project.namespace, project, *args)
|
||||
end
|
||||
|
||||
def activity_project_path(project, *args)
|
||||
activity_namespace_project_path(project.namespace, project, *args)
|
||||
end
|
||||
|
||||
def edit_project_path(project, *args)
|
||||
edit_namespace_project_path(project.namespace, project, *args)
|
||||
end
|
||||
|
|
|
@ -29,6 +29,8 @@ module MilestonesHelper
|
|||
end.active
|
||||
|
||||
grouped_milestones = Milestones::GroupService.new(milestones).execute
|
||||
grouped_milestones.unshift(Milestone::None)
|
||||
|
||||
options_from_collection_for_select(grouped_milestones, 'title', 'title', params[:milestone_title])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -42,6 +42,13 @@ module PreferencesHelper
|
|||
end
|
||||
end
|
||||
|
||||
def project_view_choices
|
||||
[
|
||||
['Readme (default)', :readme],
|
||||
['Activity view', :activity]
|
||||
]
|
||||
end
|
||||
|
||||
def user_application_theme
|
||||
theme = Gitlab::Themes.by_id(current_user.try(:theme_id))
|
||||
theme.css_class
|
||||
|
@ -50,4 +57,9 @@ module PreferencesHelper
|
|||
def user_color_scheme_class
|
||||
COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user)
|
||||
end
|
||||
|
||||
def prefer_readme?
|
||||
!current_user ||
|
||||
current_user.project_view == 'readme'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -84,53 +84,6 @@ module ProjectsHelper
|
|||
@project.milestones.active.order("due_date, title ASC")
|
||||
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)
|
||||
if deploy_key.projects.include?(@project)
|
||||
@project
|
||||
|
@ -139,6 +92,16 @@ module ProjectsHelper
|
|||
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
|
||||
|
||||
def get_project_nav_tabs(project, current_user)
|
||||
|
@ -168,8 +131,12 @@ module ProjectsHelper
|
|||
nav_tabs << :snippets
|
||||
end
|
||||
|
||||
if can?(current_user, :read_label, project)
|
||||
nav_tabs << :labels
|
||||
end
|
||||
|
||||
if can?(current_user, :read_milestone, project)
|
||||
nav_tabs << [:milestones, :labels]
|
||||
nav_tabs << :milestones
|
||||
end
|
||||
|
||||
nav_tabs.flatten
|
||||
|
@ -285,16 +252,6 @@ module ProjectsHelper
|
|||
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)
|
||||
level = project.team.max_member_access(user)
|
||||
|
||||
|
@ -306,4 +263,35 @@ module ProjectsHelper
|
|||
def leave_project_message(project)
|
||||
"Are you sure you want to leave \"#{project.name}\" project?"
|
||||
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
|
||||
|
||||
def round_commit_count(project)
|
||||
count = project.commit_count
|
||||
|
||||
if count > 10000
|
||||
'10000+'
|
||||
elsif count > 5000
|
||||
'5000+'
|
||||
elsif count > 1000
|
||||
'1000+'
|
||||
else
|
||||
count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -86,4 +86,10 @@ module VisibilityLevelHelper
|
|||
def default_snippet_visibility
|
||||
current_application_settings.default_snippet_visibility
|
||||
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
|
||||
|
|
|
@ -31,10 +31,11 @@ class Ability
|
|||
end
|
||||
|
||||
if project && project.public?
|
||||
[
|
||||
rules = [
|
||||
:read_project,
|
||||
:read_wiki,
|
||||
:read_issue,
|
||||
:read_label,
|
||||
:read_milestone,
|
||||
:read_project_snippet,
|
||||
:read_project_member,
|
||||
|
@ -42,6 +43,8 @@ class Ability
|
|||
:read_note,
|
||||
:download_code
|
||||
]
|
||||
|
||||
rules - project_disabled_features_rules(project)
|
||||
else
|
||||
group = if subject.kind_of?(Group)
|
||||
subject
|
||||
|
@ -102,28 +105,7 @@ class Ability
|
|||
rules -= project_archived_rules
|
||||
end
|
||||
|
||||
unless project.issues_enabled
|
||||
rules -= named_abilities('issue')
|
||||
end
|
||||
|
||||
unless project.merge_requests_enabled
|
||||
rules -= named_abilities('merge_request')
|
||||
end
|
||||
|
||||
unless project.issues_enabled or project.merge_requests_enabled
|
||||
rules -= named_abilities('label')
|
||||
rules -= named_abilities('milestone')
|
||||
end
|
||||
|
||||
unless project.snippets_enabled
|
||||
rules -= named_abilities('project_snippet')
|
||||
end
|
||||
|
||||
unless project.wiki_enabled
|
||||
rules -= named_abilities('wiki')
|
||||
end
|
||||
|
||||
rules
|
||||
rules - project_disabled_features_rules(project)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -205,6 +187,33 @@ class Ability
|
|||
]
|
||||
end
|
||||
|
||||
def project_disabled_features_rules(project)
|
||||
rules = []
|
||||
|
||||
unless project.issues_enabled
|
||||
rules += named_abilities('issue')
|
||||
end
|
||||
|
||||
unless project.merge_requests_enabled
|
||||
rules += named_abilities('merge_request')
|
||||
end
|
||||
|
||||
unless project.issues_enabled or project.merge_requests_enabled
|
||||
rules += named_abilities('label')
|
||||
rules += named_abilities('milestone')
|
||||
end
|
||||
|
||||
unless project.snippets_enabled
|
||||
rules += named_abilities('project_snippet')
|
||||
end
|
||||
|
||||
unless project.wiki_enabled
|
||||
rules += named_abilities('wiki')
|
||||
end
|
||||
|
||||
rules
|
||||
end
|
||||
|
||||
def group_abilities(user, group)
|
||||
rules = []
|
||||
|
||||
|
|
|
@ -79,22 +79,36 @@ module Mentionable
|
|||
end
|
||||
end
|
||||
|
||||
# If the mentionable_text field is about to change, locate any *added* references and create cross references for
|
||||
# them. Invoke from an observer's #before_save implementation.
|
||||
def notice_added_references(p = project, a = author)
|
||||
ch = changed_attributes
|
||||
original, mentionable_changed = "", false
|
||||
self.class.mentionable_attrs.each do |attr|
|
||||
if ch[attr]
|
||||
original << ch[attr]
|
||||
mentionable_changed = true
|
||||
end
|
||||
end
|
||||
# When a mentionable field is changed, creates cross-reference notes that
|
||||
# don't already exist
|
||||
def create_new_cross_references!(p = project, a = author)
|
||||
changes = detect_mentionable_changes
|
||||
|
||||
# Only proceed if the saved changes actually include a chance to an attr_mentionable field.
|
||||
return unless mentionable_changed
|
||||
return if changes.empty?
|
||||
|
||||
preexisting = references(p, self.author, original)
|
||||
original_text = changes.collect { |_, vals| vals.first }.join(' ')
|
||||
|
||||
preexisting = references(p, self.author, original_text)
|
||||
create_cross_references!(p, a, preexisting)
|
||||
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
|
||||
|
|
|
@ -24,6 +24,7 @@ class Key < ActiveRecord::Base
|
|||
|
||||
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, format: { without: /\n|\r/, message: 'should be a single line' }
|
||||
validates :fingerprint, uniqueness: true, presence: { message: 'cannot be generated' }
|
||||
|
||||
delegate :name, :email, to: :user, prefix: true
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
#
|
||||
|
||||
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 Sortable
|
||||
|
||||
|
|
|
@ -356,7 +356,7 @@ class Note < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def set_references
|
||||
notice_added_references(project, author)
|
||||
create_new_cross_references!(project, author)
|
||||
end
|
||||
|
||||
def editable?
|
||||
|
|
|
@ -683,6 +683,10 @@ class Project < ActiveRecord::Base
|
|||
update_attribute(:repository_size, repository.size)
|
||||
end
|
||||
|
||||
def update_commit_count
|
||||
update_attribute(:commit_count, repository.commit_count)
|
||||
end
|
||||
|
||||
def forks_count
|
||||
ForkedProjectLink.where(forked_from_project_id: self.id).count
|
||||
end
|
||||
|
|
|
@ -22,8 +22,12 @@ class GitlabCiService < CiService
|
|||
API_PREFIX = "api/v1"
|
||||
|
||||
prop_accessor :project_url, :token
|
||||
validates :project_url, presence: true, if: :activated?
|
||||
validates :token, presence: true, if: :activated?
|
||||
validates :project_url,
|
||||
presence: true,
|
||||
format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }, if: :activated?
|
||||
validates :token,
|
||||
presence: true,
|
||||
format: { with: /\A([A-Za-z0-9]+)\z/ }, if: :activated?
|
||||
|
||||
after_save :compose_service_hook, if: :activated?
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ class IrkerService < Service
|
|||
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',
|
||||
{ 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',
|
||||
|
|
|
@ -94,18 +94,6 @@ class Repository
|
|||
gitlab_shell.rm_tag(path_with_namespace, tag_name)
|
||||
end
|
||||
|
||||
def round_commit_count
|
||||
if commit_count > 10000
|
||||
'10000+'
|
||||
elsif commit_count > 5000
|
||||
'5000+'
|
||||
elsif commit_count > 1000
|
||||
'1000+'
|
||||
else
|
||||
commit_count
|
||||
end
|
||||
end
|
||||
|
||||
def branch_names
|
||||
cache.fetch(:branch_names) { raw_repository.branch_names }
|
||||
end
|
||||
|
@ -130,28 +118,29 @@ class Repository
|
|||
cache.fetch(:size) { raw_repository.size }
|
||||
end
|
||||
|
||||
def cache_keys
|
||||
%i(size branch_names tag_names commit_count
|
||||
readme version contribution_guide changelog license)
|
||||
end
|
||||
|
||||
def build_cache
|
||||
cache_keys.each do |key|
|
||||
unless cache.exist?(key)
|
||||
send(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def expire_cache
|
||||
%i(size branch_names tag_names commit_count graph_log
|
||||
readme version contribution_guide changelog license).each do |key|
|
||||
cache_keys.each do |key|
|
||||
cache.expire(key)
|
||||
end
|
||||
end
|
||||
|
||||
def graph_log
|
||||
cache.fetch(:graph_log) do
|
||||
commits = raw_repository.log(limit: 6000, skip_merges: true,
|
||||
ref: root_ref)
|
||||
|
||||
commits.map do |rugged_commit|
|
||||
commit = Gitlab::Git::Commit.new(rugged_commit)
|
||||
|
||||
{
|
||||
author_name: commit.author_name,
|
||||
author_email: commit.author_email,
|
||||
additions: commit.stats.additions,
|
||||
deletions: commit.stats.deletions,
|
||||
}
|
||||
end
|
||||
def rebuild_cache
|
||||
cache_keys.each do |key|
|
||||
cache.expire(key)
|
||||
send(key)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -431,6 +420,39 @@ class Repository
|
|||
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
|
||||
|
||||
result.each_line.each_with_index do |line, index|
|
||||
if line =~ /^.*:.*:\d+:/
|
||||
ref, filename, startline = line.split(':')
|
||||
startline = startline.to_i - index
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
data = ""
|
||||
|
||||
result.each_line do |line|
|
||||
data << line.sub(ref, '').sub(filename, '').sub(/^:-\d+-/, '').sub(/^::\d+:/, '')
|
||||
end
|
||||
|
||||
OpenStruct.new(
|
||||
filename: filename,
|
||||
ref: ref,
|
||||
startline: startline,
|
||||
data: data
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def cache
|
||||
|
|
|
@ -177,6 +177,10 @@ class User < ActiveRecord::Base
|
|||
# Note: When adding an option, it MUST go on the end of the array.
|
||||
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
|
||||
|
||||
delegate :path, to: :namespace, allow_nil: true, prefix: true
|
||||
|
@ -322,6 +326,16 @@ class User < ActiveRecord::Base
|
|||
@reset_token
|
||||
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
|
||||
namespace_name = self.username
|
||||
existing_namespace = Namespace.by_path(namespace_name)
|
||||
|
|
|
@ -21,7 +21,6 @@ class GitPushService
|
|||
|
||||
project.ensure_satellite_exists
|
||||
project.repository.expire_cache
|
||||
project.update_repository_size
|
||||
|
||||
if push_remove_branch?(ref, newrev)
|
||||
@push_commits = []
|
||||
|
@ -61,6 +60,7 @@ class GitPushService
|
|||
EventCreateService.new.push(project, user, @push_data)
|
||||
project.execute_hooks(@push_data.dup, :push_hooks)
|
||||
project.execute_services(@push_data.dup, :push_hooks)
|
||||
ProjectCacheWorker.perform_async(project.id)
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
@ -2,15 +2,15 @@ class GitTagPushService
|
|||
attr_accessor :project, :user, :push_data
|
||||
|
||||
def execute(project, user, oldrev, newrev, ref)
|
||||
@project, @user = project, user
|
||||
project.repository.expire_cache
|
||||
|
||||
@project, @user = project, user
|
||||
@push_data = build_push_data(oldrev, newrev, ref)
|
||||
|
||||
EventCreateService.new.push(project, user, @push_data)
|
||||
project.execute_hooks(@push_data.dup, :tag_push_hooks)
|
||||
project.execute_services(@push_data.dup, :tag_push_hooks)
|
||||
|
||||
project.repository.expire_cache
|
||||
ProjectCacheWorker.perform_async(project.id)
|
||||
|
||||
true
|
||||
end
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
module Issues
|
||||
class UpdateService < Issues::BaseService
|
||||
def execute(issue)
|
||||
state = params[:state_event]
|
||||
|
||||
case state
|
||||
case params.delete(:state_event)
|
||||
when 'reopen'
|
||||
Issues::ReopenService.new(project, current_user, {}).execute(issue)
|
||||
when 'close'
|
||||
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
|
||||
|
||||
params[:assignee_id] = "" if params[:assignee_id] == IssuableFinder::NONE
|
||||
|
@ -20,8 +14,7 @@ module Issues
|
|||
filter_params
|
||||
old_labels = issue.labels.to_a
|
||||
|
||||
if params.present? && issue.update_attributes(params.except(:state_event,
|
||||
:task_num))
|
||||
if params.present? && issue.update_attributes(params)
|
||||
issue.reset_events_cache
|
||||
|
||||
if issue.labels != old_labels
|
||||
|
@ -42,7 +35,7 @@ module Issues
|
|||
create_title_change_note(issue, issue.previous_changes['title'].first)
|
||||
end
|
||||
|
||||
issue.notice_added_references(issue.project, current_user)
|
||||
issue.create_new_cross_references!(issue.project, current_user)
|
||||
execute_hooks(issue, 'update')
|
||||
end
|
||||
|
||||
|
|
|
@ -11,17 +11,11 @@ module MergeRequests
|
|||
params.except!(:target_project_id)
|
||||
params.except!(:source_branch)
|
||||
|
||||
state = params[:state_event]
|
||||
|
||||
case state
|
||||
case params.delete(:state_event)
|
||||
when 'reopen'
|
||||
MergeRequests::ReopenService.new(project, current_user, {}).execute(merge_request)
|
||||
when 'close'
|
||||
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
|
||||
|
||||
params[:assignee_id] = "" if params[:assignee_id] == IssuableFinder::NONE
|
||||
|
@ -30,9 +24,7 @@ module MergeRequests
|
|||
filter_params
|
||||
old_labels = merge_request.labels.to_a
|
||||
|
||||
if params.present? && merge_request.update_attributes(
|
||||
params.except(:state_event, :task_num)
|
||||
)
|
||||
if params.present? && merge_request.update_attributes(params)
|
||||
merge_request.reset_events_cache
|
||||
|
||||
if merge_request.labels != old_labels
|
||||
|
@ -67,7 +59,7 @@ module MergeRequests
|
|||
merge_request.mark_as_unchecked
|
||||
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')
|
||||
end
|
||||
|
||||
|
|
|
@ -11,19 +11,16 @@ module Projects
|
|||
include Gitlab::ShellAdapter
|
||||
class TransferError < StandardError; end
|
||||
|
||||
def execute
|
||||
namespace_id = params[:new_namespace_id]
|
||||
namespace = Namespace.find_by(id: namespace_id)
|
||||
|
||||
if allowed_transfer?(current_user, project, namespace)
|
||||
transfer(project, namespace)
|
||||
def execute(new_namespace)
|
||||
if allowed_transfer?(current_user, project, new_namespace)
|
||||
transfer(project, new_namespace)
|
||||
else
|
||||
project.errors.add(:namespace, 'is invalid')
|
||||
project.errors.add(:new_namespace, 'is invalid')
|
||||
false
|
||||
end
|
||||
rescue Projects::TransferService::TransferError => ex
|
||||
project.reload
|
||||
project.errors.add(:namespace_id, ex.message)
|
||||
project.errors.add(:new_namespace, ex.message)
|
||||
false
|
||||
end
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
%strong{class: @user.two_factor_enabled? ? 'cgreen' : 'cred'}
|
||||
- if @user.two_factor_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
|
||||
Disabled
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
- if event.created_project?
|
||||
= cache [event, current_user] do
|
||||
= image_tag avatar_icon(event.author_email, 24), class: "avatar s24", alt:''
|
||||
= render "events/event/created_project", event: event
|
||||
- else
|
||||
= cache event do
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
.repo-info
|
||||
- unless project.empty_repo?
|
||||
= link_to pluralize(project.repository.round_commit_count, 'commit'), namespace_project_commits_path(project.namespace, project, project.default_branch)
|
||||
= link_to pluralize(round_commit_count(project), 'commit'), namespace_project_commits_path(project.namespace, project, project.default_branch)
|
||||
·
|
||||
= link_to pluralize(project.repository.branch_names.count, 'branch'), namespace_project_branches_path(project.namespace, project)
|
||||
·
|
||||
|
|
|
@ -79,6 +79,12 @@
|
|||
%td.shortcut
|
||||
.key g
|
||||
.key p
|
||||
%td
|
||||
Go to the project's home page
|
||||
%tr
|
||||
%td.shortcut
|
||||
.key g
|
||||
.key e
|
||||
%td
|
||||
Go to the project's activity feed
|
||||
%tr
|
||||
|
|
|
@ -7,14 +7,29 @@
|
|||
%title= page_title
|
||||
|
||||
= 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"
|
||||
|
||||
= csrf_meta_tags
|
||||
|
||||
= include_gon
|
||||
|
||||
%meta{name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1'}
|
||||
%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
|
||||
|
||||
= render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id')
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.page-with-sidebar{ class: nav_sidebar_class }
|
||||
= render "layouts/broadcast"
|
||||
.sidebar-wrapper
|
||||
.sidebar-wrapper.nicescroll
|
||||
- if defined?(sidebar) && sidebar
|
||||
= render "layouts/nav/#{sidebar}"
|
||||
- elsif current_user
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
%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
|
||||
= link_to group_path(@group), title: 'Home', data: {placement: 'right'} do
|
||||
= icon('dashboard fw')
|
||||
%span
|
||||
Activity
|
||||
Group
|
||||
- if current_user
|
||||
= nav_link(controller: [:group, :milestones]) do
|
||||
= link_to group_milestones_path(@group), title: 'Milestones', data: {placement: 'right'} do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
%ul.nav.nav-sidebar
|
||||
= 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')
|
||||
%span
|
||||
Back to group
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
%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
|
||||
= link_to profile_path, title: 'Profile', data: {placement: 'right'} do
|
||||
= icon('user fw')
|
||||
|
|
|
@ -1,9 +1,29 @@
|
|||
%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
|
||||
= link_to project_path(@project), title: 'Project', class: 'shortcuts-project', data: {placement: 'right'} do
|
||||
= icon('dashboard fw')
|
||||
= icon('home fw')
|
||||
%span
|
||||
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
|
||||
= 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
%ul.nav.nav-sidebar
|
||||
= 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')
|
||||
%span
|
||||
Back to project
|
||||
|
|
|
@ -66,4 +66,4 @@
|
|||
%td= token.scopes
|
||||
%td= render 'doorkeeper/authorized_applications/delete_form', token: token
|
||||
- else
|
||||
%p.light You dont have any authorized applications
|
||||
%p.light You don't have any authorized applications
|
||||
|
|
|
@ -38,5 +38,13 @@
|
|||
= link_to('(?)', help_page_path('profile', 'preferences') + '#default-dashboard', target: '_blank')
|
||||
.col-sm-10
|
||||
= 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
|
||||
= f.submit 'Save', class: 'btn btn-save'
|
||||
|
|
15
app/views/projects/_activity.html.haml
Normal file
15
app/views/projects/_activity.html.haml
Normal file
|
@ -0,0 +1,15 @@
|
|||
= 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()
|
|
@ -1,106 +0,0 @@
|
|||
.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
|
|
@ -1,37 +1,28 @@
|
|||
- empty_repo = @project.empty_repo?
|
||||
.project-home-panel.clearfix{:class => ("empty-project" if empty_repo)}
|
||||
.project-identicon-holder
|
||||
= project_icon(@project, alt: '', class: 'avatar project-avatar')
|
||||
.project-home-row.project-home-row-top
|
||||
.project-home-desc
|
||||
- if @project.description.present?
|
||||
= markdown(@project.description, pipeline: :description)
|
||||
- if can?(current_user, :admin_project, @project)
|
||||
–
|
||||
= link_to 'Edit', edit_namespace_project_path
|
||||
- elsif !empty_repo && @repository.readme
|
||||
- readme = @repository.readme
|
||||
–
|
||||
= link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)) do
|
||||
= readme.name
|
||||
.project-repo-buttons
|
||||
.inline.star.js-toggler-container{class: @show_star ? 'on' : ''}
|
||||
- if current_user
|
||||
= link_to_toggle_star('Star this project.', false)
|
||||
= link_to_toggle_star('Unstar this project.', true)
|
||||
- else
|
||||
= link_to new_user_session_path, class: 'btn star-btn has_tooltip', title: 'You must sign in to star a project' do
|
||||
%span
|
||||
= icon('star')
|
||||
Star
|
||||
%span.count
|
||||
= @project.star_count
|
||||
- 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
|
||||
= project_icon(@project, alt: '', class: 'project-avatar avatar s90')
|
||||
.project-home-desc.lead
|
||||
- if @project.description.present?
|
||||
= markdown(@project.description, pipeline: :description)
|
||||
|
||||
|
||||
.project-repo-buttons
|
||||
= render 'projects/buttons/star'
|
||||
|
||||
- unless empty_repo
|
||||
= render 'projects/buttons/fork'
|
||||
|
||||
- if forked_from_project = @project.forked_from_project
|
||||
= link_to project_path(forked_from_project), class: 'btn' do
|
||||
= icon("code-fork fw")
|
||||
Forked from
|
||||
= forked_from_project.namespace.try(:name)
|
||||
|
||||
- if can? current_user, :download_code, @project
|
||||
= link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), class: 'btn', rel: 'nofollow' do
|
||||
%i.fa.fa-download
|
||||
|
||||
= render 'projects/buttons/dropdown'
|
||||
|
||||
= render "shared/clone_panel"
|
||||
|
|
14
app/views/projects/_last_push.html.haml
Normal file
14
app/views/projects/_last_push.html.haml
Normal file
|
@ -0,0 +1,14 @@
|
|||
- 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
|
24
app/views/projects/_readme.html.haml
Normal file
24
app/views/projects/_readme.html.haml
Normal file
|
@ -0,0 +1,24 @@
|
|||
- if readme = @repository.readme
|
||||
%article.readme-holder#README
|
||||
.clearfix
|
||||
.pull-right
|
||||
|
||||
- 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.
|
|
@ -1,36 +0,0 @@
|
|||
%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 @@
|
|||
%input#zen-toggle-comment.zen-toggle-comment{ tabindex: '-1', type: 'checkbox' }
|
||||
.zen-backdrop
|
||||
- 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
|
||||
%i.fa.fa-expand
|
||||
Edit in fullscreen
|
||||
|
|
1
app/views/projects/activity.html.haml
Normal file
1
app/views/projects/activity.html.haml
Normal file
|
@ -0,0 +1 @@
|
|||
= render 'projects/activity'
|
|
@ -1,4 +1,7 @@
|
|||
- page_title @blob.path, @ref
|
||||
|
||||
= render 'projects/last_push'
|
||||
|
||||
%div.tree-ref-holder
|
||||
= render 'shared/ref_switcher', destination: 'blob', path: @path
|
||||
|
||||
|
|
31
app/views/projects/buttons/_dropdown.html.haml
Normal file
31
app/views/projects/buttons/_dropdown.html.haml
Normal file
|
@ -0,0 +1,31 @@
|
|||
- 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
|
||||
|
||||
|
13
app/views/projects/buttons/_fork.html.haml
Normal file
13
app/views/projects/buttons/_fork.html.haml
Normal file
|
@ -0,0 +1,13 @@
|
|||
- 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
|
22
app/views/projects/buttons/_star.html.haml
Normal file
22
app/views/projects/buttons/_star.html.haml
Normal file
|
@ -0,0 +1,22 @@
|
|||
- 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
|
|
@ -1,6 +1,6 @@
|
|||
.alert.alert-warning
|
||||
%h4
|
||||
Too many changes.
|
||||
Too many changes to show.
|
||||
.pull-right
|
||||
- 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"
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
.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
|
||||
= f.label :tag_list, "Tags", class: 'control-label'
|
||||
|
@ -176,7 +176,7 @@
|
|||
.form-group
|
||||
= label_tag :new_namespace_id, nil, class: 'control-label' do
|
||||
%span Namespace
|
||||
.col-sm-10
|
||||
.col-sm-9
|
||||
.form-group
|
||||
= select_tag :new_namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace', class: 'select2' }
|
||||
%ul
|
||||
|
|
|
@ -4,30 +4,30 @@
|
|||
|
||||
= render "home_panel"
|
||||
|
||||
.center.well
|
||||
%h3
|
||||
.center.light-well
|
||||
%h3.page-title
|
||||
The repository for this project is empty
|
||||
%h4
|
||||
You can
|
||||
= link_to namespace_project_new_blob_path(@project.namespace, @project, 'master'), class: 'btn btn-new btn-lg' do
|
||||
add a file
|
||||
or do a push via the command line.
|
||||
%p
|
||||
If you already have files you can push them using command line instructions below.
|
||||
%br
|
||||
Otherwise you can start with
|
||||
= link_to "adding README", new_readme_path, class: 'underlined-link'
|
||||
file to this project.
|
||||
|
||||
.well
|
||||
= render "shared/clone_panel"
|
||||
%h4
|
||||
%strong Command line instructions
|
||||
.prepend-top-20
|
||||
%h3.page-title
|
||||
Command line instructions
|
||||
%div.git-empty
|
||||
%fieldset
|
||||
%legend Git global setup
|
||||
%pre.dark
|
||||
%h5 Git global setup
|
||||
%pre.light-well
|
||||
:preserve
|
||||
git config --global user.name "#{git_user_name}"
|
||||
git config --global user.email "#{git_user_email}"
|
||||
|
||||
%fieldset
|
||||
%legend Create a new repository
|
||||
%pre.dark
|
||||
%h5 Create a new repository
|
||||
%pre.light-well
|
||||
:preserve
|
||||
git clone #{ content_tag(:span, default_url_to_repo, class: 'clone')}
|
||||
cd #{@project.path}
|
||||
|
@ -37,8 +37,8 @@
|
|||
git push -u origin master
|
||||
|
||||
%fieldset
|
||||
%legend Existing folder or Git repository
|
||||
%pre.dark
|
||||
%h5 Existing folder or Git repository
|
||||
%pre.light-well
|
||||
:preserve
|
||||
cd existing_folder
|
||||
git init
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
- page_title "Commit statistics"
|
||||
.tree-ref-holder
|
||||
= render 'shared/ref_switcher', destination: 'graphs_commits'
|
||||
= render 'head'
|
||||
|
||||
%p.lead
|
||||
Commit statistics for
|
||||
%strong #{@repository.root_ref}
|
||||
%strong #{@ref}
|
||||
#{@commits_graph.start_date.strftime('%b %d')} - #{@commits_graph.end_date.strftime('%b %d')}
|
||||
|
||||
.row
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
- page_title "Contributor statistics"
|
||||
.tree-ref-holder
|
||||
= render 'shared/ref_switcher', destination: 'graphs'
|
||||
= render 'head'
|
||||
|
||||
.loading-graph
|
||||
.center
|
||||
%h3.page-title
|
||||
|
@ -11,7 +14,7 @@
|
|||
.header.clearfix
|
||||
%h3#date_header.page-title
|
||||
%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"}
|
||||
.graphs
|
||||
#contributors-master
|
||||
|
@ -35,4 +38,3 @@
|
|||
$(".stat-graph").fadeIn();
|
||||
$(".loading-graph").hide();
|
||||
dataType: "json"
|
||||
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
= pluralize label.open_issues_count, 'open issue'
|
||||
|
||||
- if can? current_user, :admin_label, @project
|
||||
= link_to 'Edit', edit_namespace_project_label_path(@project.namespace, @project, label), class: 'btn'
|
||||
= 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 '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-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"}
|
||||
|
|
|
@ -31,6 +31,16 @@
|
|||
%li= link_to "Email Patches", merge_request_path(@merge_request, format: :patch)
|
||||
%li= link_to "Plain Diff", merge_request_path(@merge_request, format: :diff)
|
||||
|
||||
- if @merge_request.open? and @merge_request.source_branch_exists?
|
||||
.append-bottom-20
|
||||
.slead
|
||||
%span
|
||||
Fetch the branch with
|
||||
%strong.label-branch<
|
||||
git fetch
|
||||
\ #{@merge_request.source_project.http_url_to_repo}
|
||||
\ #{@merge_request.source_branch}
|
||||
|
||||
= render "projects/merge_requests/show/how_to_merge"
|
||||
= render "projects/merge_requests/widget/show.html.haml"
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
:plain
|
||||
$(".mr_source_commit").html("#{commit_to_html(@commit, @source_project, false)}");
|
||||
$('.js-timeago').timeago()
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
:plain
|
||||
$(".mr_target_commit").html("#{commit_to_html(@commit, @target_project, false)}");
|
||||
$('.js-timeago').timeago()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
- page_title "Merge Requests"
|
||||
= render 'projects/last_push'
|
||||
.append-bottom-10
|
||||
.pull-right
|
||||
= render 'shared/issuable/search_form', path: namespace_project_merge_requests_path(@project.namespace, @project)
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
%i.fa.fa-pencil-square-o
|
||||
Edit
|
||||
= link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-sm btn-close"
|
||||
= link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-sm btn-remove" do
|
||||
%i.fa.fa-trash-o
|
||||
Remove
|
||||
|
||||
%h4
|
||||
= link_to_gfm truncate(milestone.title, length: 100), namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
|
||||
- if milestone.expired? and not milestone.closed?
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
= link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped"
|
||||
- else
|
||||
= link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped"
|
||||
= link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-remove" do
|
||||
%i.fa.fa-trash-o
|
||||
Remove
|
||||
|
||||
%hr
|
||||
- if @milestone.issues.any? && @milestone.can_be_closed?
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
%li
|
||||
The import will time out after 4 minutes. For big repositories, use a clone/push combination.
|
||||
%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
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
= render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-task-list-field'
|
||||
|
||||
.comment-hints.clearfix
|
||||
.pull-left Comments are parsed with #{link_to 'GitLab Flavored Markdown', help_page_path('markdown', 'markdown'),{ target: '_blank', tabindex: -1 }}
|
||||
.pull-right Attach files by dragging & dropping or #{link_to 'selecting them', '#', class: 'markdown-selector', tabindex: -1 }.
|
||||
.pull-left #{link_to 'Markdown ', help_page_path('markdown', 'markdown'),{ target: '_blank', tabindex: -1 }}
|
||||
.pull-right #{link_to 'Attach a file', '#', class: 'markdown-selector', tabindex: -1 }
|
||||
|
||||
.note-form-actions
|
||||
.buttons
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue