From 2fd9f1cc2b2389dade7d124694a6dd2c5872fca5 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 17 Mar 2015 16:23:43 -0700 Subject: [PATCH 01/46] Version 7.9.0.rc1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e5d25bf79a9..03d55a5a014 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.9.0.pre +7.9.0.rc1 \ No newline at end of file -- GitLab From 2e2f9d3eed63597b3306e56cd18eda6410ba296c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 18 Mar 2015 06:23:29 +0000 Subject: [PATCH 02/46] Merge branch 'fix_subscription' into 'master' Fix public issue See merge request !1717 --- .../projects/issues/_issue_context.html.haml | 27 ++++++++++--------- .../merge_requests/show/_context.html.haml | 27 ++++++++++--------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/app/views/projects/issues/_issue_context.html.haml b/app/views/projects/issues/_issue_context.html.haml index cb4846a41d1..d43ce0aa293 100644 --- a/app/views/projects/issues/_issue_context.html.haml +++ b/app/views/projects/issues/_issue_context.html.haml @@ -27,19 +27,20 @@ = hidden_field_tag :issue_context = f.submit class: 'btn' - %div.prepend-top-20.clearfix - .issuable-context-title - %label - Subscription: - %button.btn.btn-block.subscribe-button - %i.fa.fa-eye - %span= @issue.subscribed?(current_user) ? "Unsubscribe" : "Subscribe" - - subscribtion_status = @issue.subscribed?(current_user) ? "subscribed" : "unsubscribed" - .subscription-status{"data-status" => subscribtion_status} - .description-block.unsubscribed{class: ( "hidden" if @issue.subscribed?(current_user) )} - You're not receiving notifications from this thread. - .description-block.subscribed{class: ( "hidden" unless @issue.subscribed?(current_user) )} - You're receiving notifications because you're subscribed to this thread. + - if current_user + %div.prepend-top-20.clearfix + .issuable-context-title + %label + Subscription: + %button.btn.btn-block.subscribe-button + %i.fa.fa-eye + %span= @issue.subscribed?(current_user) ? "Unsubscribe" : "Subscribe" + - subscribtion_status = @issue.subscribed?(current_user) ? "subscribed" : "unsubscribed" + .subscription-status{"data-status" => subscribtion_status} + .description-block.unsubscribed{class: ( "hidden" if @issue.subscribed?(current_user) )} + You're not receiving notifications from this thread. + .description-block.subscribed{class: ( "hidden" unless @issue.subscribed?(current_user) )} + You're receiving notifications because you're subscribed to this thread. :coffeescript $ -> diff --git a/app/views/projects/merge_requests/show/_context.html.haml b/app/views/projects/merge_requests/show/_context.html.haml index 753c7e0e611..14ad89a2000 100644 --- a/app/views/projects/merge_requests/show/_context.html.haml +++ b/app/views/projects/merge_requests/show/_context.html.haml @@ -29,19 +29,20 @@ = hidden_field_tag :merge_request_context = f.submit class: 'btn' - %div.prepend-top-20.clearfix - .issuable-context-title - %label - Subscription: - %button.btn.btn-block.subscribe-button - %i.fa.fa-eye - %span= @merge_request.subscribed?(current_user) ? "Unsubscribe" : "Subscribe" - - subscribtion_status = @merge_request.subscribed?(current_user) ? "subscribed" : "unsubscribed" - .subscription-status{"data-status" => subscribtion_status} - .description-block.unsubscribed{class: ( "hidden" if @merge_request.subscribed?(current_user) )} - You're not receiving notifications from this thread. - .description-block.subscribed{class: ( "hidden" unless @merge_request.subscribed?(current_user) )} - You're receiving notifications because you're subscribed to this thread. + - if current_user + %div.prepend-top-20.clearfix + .issuable-context-title + %label + Subscription: + %button.btn.btn-block.subscribe-button + %i.fa.fa-eye + %span= @merge_request.subscribed?(current_user) ? "Unsubscribe" : "Subscribe" + - subscribtion_status = @merge_request.subscribed?(current_user) ? "subscribed" : "unsubscribed" + .subscription-status{"data-status" => subscribtion_status} + .description-block.unsubscribed{class: ( "hidden" if @merge_request.subscribed?(current_user) )} + You're not receiving notifications from this thread. + .description-block.subscribed{class: ( "hidden" unless @merge_request.subscribed?(current_user) )} + You're receiving notifications because you're subscribed to this thread. :coffeescript $ -> -- GitLab From 368a391182039f7973f7cf3da7b4e29c760003df Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 18 Mar 2015 01:37:04 +0000 Subject: [PATCH 03/46] Merge branch 'css-vars' into 'master' More actively use css variabled to prevent colors duplication See merge request !1715 --- app/assets/stylesheets/generic/files.scss | 2 +- app/assets/stylesheets/generic/lists.scss | 9 ++--- .../stylesheets/generic/nav_sidebar.scss | 34 +++++++++---------- .../stylesheets/generic/typography.scss | 3 +- app/assets/stylesheets/pages/diff.scss | 2 +- app/assets/stylesheets/pages/editor.scss | 2 +- app/assets/stylesheets/pages/events.scss | 2 +- .../stylesheets/pages/merge_requests.scss | 2 +- app/assets/stylesheets/pages/tree.scss | 2 +- .../notify/project_was_moved_email.html.haml | 4 +-- 10 files changed, 31 insertions(+), 31 deletions(-) diff --git a/app/assets/stylesheets/generic/files.scss b/app/assets/stylesheets/generic/files.scss index 91220a856ac..8014dcb165b 100644 --- a/app/assets/stylesheets/generic/files.scss +++ b/app/assets/stylesheets/generic/files.scss @@ -94,7 +94,7 @@ } .author, .blame_commit { - background: #f5f5f5; + background: $background-color; vertical-align: top; } .lines { diff --git a/app/assets/stylesheets/generic/lists.scss b/app/assets/stylesheets/generic/lists.scss index 5950885c42c..85176fec0dc 100644 --- a/app/assets/stylesheets/generic/lists.scss +++ b/app/assets/stylesheets/generic/lists.scss @@ -35,7 +35,7 @@ color: #8a6d3b; } - &.smoke { background-color: #f5f5f5; } + &.smoke { background-color: $background-color; } &:hover { background: $hover; @@ -46,7 +46,7 @@ border-bottom: none; &.bottom { - background: #f5f5f5; + background: $background-color; } } @@ -74,9 +74,10 @@ } .row_title { - color: #444; + color: $text-color; + &:hover { - color: #444; + color: $text-color; text-decoration: underline; } } diff --git a/app/assets/stylesheets/generic/nav_sidebar.scss b/app/assets/stylesheets/generic/nav_sidebar.scss index c14f12284da..bb890171985 100644 --- a/app/assets/stylesheets/generic/nav_sidebar.scss +++ b/app/assets/stylesheets/generic/nav_sidebar.scss @@ -1,18 +1,18 @@ .page-with-sidebar { - background: #F5F5F5; + background: $background-color; .sidebar-wrapper { position: fixed; top: 0; left: 0; height: 100%; - border-right: 1px solid #EAEAEA; + border-right: 1px solid $border-color; } } .sidebar-wrapper { z-index: 99; - background: #F5F5F5; + background: $background-color; } .content-wrapper { @@ -39,7 +39,7 @@ .nav-sidebar li { &.active a { - color: #333; + color: $text-color; background: #FFF !important; font-weight: bold; border: 1px solid #EEE; @@ -52,32 +52,33 @@ } i { - color: #444; + color: $text-color; } } } .nav-sidebar li { + text-shadow: 0 1px 1px $border-color; + &.separate-item { - border-top: 1px solid #ddd; + border-top: 1px solid $border-color; padding-top: 10px; margin-top: 10px; } a { - color: #555; + color: #3b5a5b; display: block; text-decoration: none; padding: 8px 15px; font-size: 13px; line-height: 20px; - text-shadow: 0 1px 2px #FFF; padding-left: 20px; &:hover { text-decoration: none; - color: #333; - background: #EEE; + color: $text-color; + background: #f2f6f7; } &:active, &:focus { @@ -86,7 +87,7 @@ i { width: 20px; - color: #888; + color: $gray-dark; margin-right: 23px; } } @@ -156,18 +157,17 @@ position: fixed; top: 46px; padding: 5px 13px 5px 13px; - left: 197px; + left: 198px; font-size: 13px; - background: #EEE; + background: transparent; color: black; - border-left: 1px solid rgba(0,0,0,0.035); - border-right: 1px solid rgba(0,0,0,0.035); + border-left: 1px solid $border-color; + border-bottom: 1px solid $border-color; } .collapse-nav a:hover { text-decoration: none; - color: #333; - background: #eaeaea; + background: #f2f6f7; } @media (max-width: $screen-md-max) { diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss index 4d940ee6b29..80190424c1b 100644 --- a/app/assets/stylesheets/generic/typography.scss +++ b/app/assets/stylesheets/generic/typography.scss @@ -4,7 +4,6 @@ */ .page-title { margin-top: 0px; - color: #333; line-height: 1.5; font-weight: normal; margin-bottom: 5px; @@ -16,7 +15,7 @@ pre { &.dark { background: #333; - color: #f5f5f5; + color: $background-color; } } diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 5a9f93dc03d..83f65913ee6 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -89,7 +89,7 @@ margin: 0px; padding: 0px; border: none; - background: #F5F5F5; + background: $background-color; color: rgba(0,0,0,0.3); padding: 0px 5px; border-right: 1px solid $border-color; diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index 851f126318d..759ba6b1c22 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -37,7 +37,7 @@ } .editor-ref { - background: #f5f5f5; + background: $background-color; padding: 11px 15px; border-right: 1px solid #CCC; display: inline-block; diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss index 3e9e36e477e..480cc2c50a9 100644 --- a/app/assets/stylesheets/pages/events.scss +++ b/app/assets/stylesheets/pages/events.scss @@ -188,7 +188,7 @@ li a { font-size: 13px; padding: 5px 10px; - background: rgba(0,0,0,0.045); + background: $background-color; margin-left: 4px; } } diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index d41e34caba1..fe5667a587f 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -129,7 +129,7 @@ font-size: 15px; border-bottom: 1px solid #BBB; color: #777; - background-color: #F5F5F5; + background-color: $background-color; &.ci-success { color: $gl-success; diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index ce02cdb1652..b0e6a05fa06 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -27,7 +27,7 @@ } &.selected { td { - background: #f5f5f5; + background: $background-color; border-top: 1px solid #EEE; border-bottom: 1px solid #EEE; } diff --git a/app/views/notify/project_was_moved_email.html.haml b/app/views/notify/project_was_moved_email.html.haml index f53de2de287..d2df398ed4a 100644 --- a/app/views/notify/project_was_moved_email.html.haml +++ b/app/views/notify/project_was_moved_email.html.haml @@ -6,10 +6,10 @@ = @project.name_with_namespace %p To update the remote url in your local repository run (for ssh): -%p{ style: "background:#f5f5f5; padding:10px; border:1px solid #ddd" } +%p{ style: "background:$background-color; padding:10px; border:1px solid #ddd" } git remote set-url origin #{@project.ssh_url_to_repo} %p or for http(s): -%p{ style: "background:#f5f5f5; padding:10px; border:1px solid #ddd" } +%p{ style: "background:$background-color; padding:10px; border:1px solid #ddd" } git remote set-url origin #{@project.http_url_to_repo} %br -- GitLab From b6e7940c3db2d3e580e592cb2f9490eb4a3b0cef Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 17 Mar 2015 18:38:10 -0700 Subject: [PATCH 04/46] Fix email template css for project moved emails --- app/views/notify/project_was_moved_email.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/notify/project_was_moved_email.html.haml b/app/views/notify/project_was_moved_email.html.haml index d2df398ed4a..3cd759f1f57 100644 --- a/app/views/notify/project_was_moved_email.html.haml +++ b/app/views/notify/project_was_moved_email.html.haml @@ -6,10 +6,10 @@ = @project.name_with_namespace %p To update the remote url in your local repository run (for ssh): -%p{ style: "background:$background-color; padding:10px; border:1px solid #ddd" } +%p{ style: "background: #f5f5f5; padding:10px; border:1px solid #ddd" } git remote set-url origin #{@project.ssh_url_to_repo} %p or for http(s): -%p{ style: "background:$background-color; padding:10px; border:1px solid #ddd" } +%p{ style: "background: #f5f5f5; padding:10px; border:1px solid #ddd" } git remote set-url origin #{@project.http_url_to_repo} %br -- GitLab From e34d778f0186ef89ef1ab22401e288318f32b1d4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 17 Mar 2015 22:57:58 -0700 Subject: [PATCH 05/46] Merge branch 'refactor-css' --- app/assets/stylesheets/base/gl_variables.scss | 755 +----------------- app/assets/stylesheets/base/variables.scss | 14 +- app/assets/stylesheets/generic/forms.scss | 4 +- app/assets/stylesheets/generic/lists.scss | 4 +- .../stylesheets/generic/nav_sidebar.scss | 8 +- app/assets/stylesheets/generic/timeline.scss | 4 +- 6 files changed, 20 insertions(+), 769 deletions(-) diff --git a/app/assets/stylesheets/base/gl_variables.scss b/app/assets/stylesheets/base/gl_variables.scss index ce82ad80318..17b5622d74a 100644 --- a/app/assets/stylesheets/base/gl_variables.scss +++ b/app/assets/stylesheets/base/gl_variables.scss @@ -1,5 +1,5 @@ // Override Bootstrap variables here (defaults from bootstrap-sass v3.3.3): - +// For all variables see https://github.com/twbs/bootstrap-sass/blob/master/templates/project/_bootstrap-variables.sass // // Variables // -------------------------------------------------- @@ -15,12 +15,6 @@ // $gray: lighten($gray-base, 33.5%) // #555 // $gray-light: lighten($gray-base, 46.7%) // #777 // $gray-lighter: lighten($gray-base, 93.5%) // #eee -$gray-base: #000; -$gray-darker: lighten($gray-base, 13.5%); // #222 -$gray-dark: #7b8a8b; // #333 -$gray: #95a5a6; // #555 -$gray-light: #b4bcc2; // #999 -$gray-lighter: #ecf0f1; // #eee $brand-primary: $gl-primary; $brand-success: $gl-success; @@ -31,68 +25,17 @@ $brand-danger: $gl-danger; //== Scaffolding // -//## Settings for some of the most global styles. - -//** Background color for ``. -// $body-bg: #fff -//** Global text color on ``. -$text-color: $brand-primary; - -//** Global textual link color. +$text-color: $gl-text-color; $link-color: $gl-link-color; -//** Link hover color set via `darken()` function. -// $link-hover-color: darken($link-color, 15%) -//** Link hover decoration. -// $link-hover-decoration: underline //== Typography // //## Font, line-height, and color for body text, headings, and more. -// $font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif -// $font-family-serif: Georgia, "Times New Roman", Times, serif -//** Default monospace fonts for ``, ``, and `
`.
-// $font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace
-// $font-family-base:        $font-family-sans-serif
-
-$font-size-base:          $gl-font-size;
-// $font-size-large:         ceil(($font-size-base * 1.25)) // ~18px
-// $font-size-small:         ceil(($font-size-base * 0.85)) // ~12px
-
-// $font-size-h1:            floor(($font-size-base * 2.6)) // ~36px
-// $font-size-h2:            floor(($font-size-base * 2.15)) // ~30px
-// $font-size-h3:            ceil(($font-size-base * 1.7)) // ~24px
-// $font-size-h4:            ceil(($font-size-base * 1.25)) // ~18px
-// $font-size-h5:            $font-size-base
-// $font-size-h6:            ceil(($font-size-base * 0.85)) // ~12px
-
-//** Unit-less `line-height` for use in components like buttons.
-// $line-height-base:        1.428571429 // 20/14
-//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
-// $line-height-computed:    floor(($font-size-base * $line-height-base)) // ~20px
-
-//** By default, this inherits from the ``.
-// $headings-font-family:    inherit
-// $headings-font-weight:    500
-// $headings-line-height:    1.1
-// $headings-color:          inherit
-
-
-//== Iconography
-//
-//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
-
-//** Load fonts from this directory.
-
-// [converter] If $bootstrap-sass-asset-helper if used, provide path relative to the assets load path.
-// [converter] This is because some asset helpers, such as Sprockets, do not work with file-relative paths.
-// $icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/")
-
-//** File name for all font files.
-// $icon-font-name:          "glyphicons-halflings-regular"
-//** Element ID within SVG icon file.
-// $icon-font-svg-id:        "glyphicons_halflingsregular"
+$font-family-sans-serif: $regular_font;
+$font-family-monospace:  $monospace_font;
+$font-size-base:         $gl-font-size;
 
 
 //== Components
@@ -102,348 +45,15 @@ $font-size-base:          $gl-font-size;
 $padding-base-vertical:     6px;
 $padding-base-horizontal:   14px;
 
-// $padding-large-vertical:    10px
-// $padding-large-horizontal:  16px
-
-// $padding-small-vertical:    5px
-// $padding-small-horizontal:  10px
-
-// $padding-xs-vertical:       1px
-// $padding-xs-horizontal:     5px
-
-// $line-height-large:         1.3333333 // extra decimals for Win 8.1 Chrome
-// $line-height-small:         1.5
-
-// $border-radius-base:        4px
-// $border-radius-large:       6px
-// $border-radius-small:       3px
-
-//** Global color for active items (e.g., navs or dropdowns).
-// $component-active-color:    #fff
-//** Global background color for active items (e.g., navs or dropdowns).
-// $component-active-bg:       $brand-primary
-
-//** Width of the `border` for generating carets that indicator dropdowns.
-// $caret-width-base:          4px
-//** Carets increase slightly in size for larger components.
-// $caret-width-large:         5px
-
-
-//== Tables
-//
-//## Customizes the `.table` component with basic values, each used across all table variations.
-
-//** Padding for ``s and ``s.
-// $table-cell-padding:            8px
-//** Padding for cells in `.table-condensed`.
-// $table-condensed-cell-padding:  5px
-
-//** Default background color used for all tables.
-// $table-bg:                      transparent
-//** Background color used for `.table-striped`.
-// $table-bg-accent:               #f9f9f9
-//** Background color used for `.table-hover`.
-// $table-bg-hover:                #f5f5f5
-// $table-bg-active:               $table-bg-hover
-
-//** Border color for table and cell borders.
-// $table-border-color:            #ddd
-
-
-//== Buttons
-//
-//## For each of Bootstrap's buttons, define text, background and border color.
-
-// $btn-font-weight:                normal
-
-// $btn-default-color:              #333
-// $btn-default-bg:                 #fff
-// $btn-default-border:             #ccc
-
-// $btn-primary-color:              #fff
-// $btn-primary-bg:                 $brand-primary
-// $btn-primary-border:             darken($btn-primary-bg, 5%)
-
-// $btn-success-color:              #fff
-// $btn-success-bg:                 $brand-success
-// $btn-success-border:             darken($btn-success-bg, 5%)
-
-// $btn-info-color:                 #fff
-// $btn-info-bg:                    $brand-info
-// $btn-info-border:                darken($btn-info-bg, 5%)
-
-// $btn-warning-color:              #fff
-// $btn-warning-bg:                 $brand-warning
-// $btn-warning-border:             darken($btn-warning-bg, 5%)
-
-// $btn-danger-color:               #fff
-// $btn-danger-bg:                  $brand-danger
-// $btn-danger-border:              darken($btn-danger-bg, 5%)
-
-// $btn-link-disabled-color:        $gray-light
-
 
 //== Forms
 //
 //##
 
-//** `` background color
-// $input-bg:                       #fff
-//** `` background color
-// $input-bg-disabled:              $gray-lighter
-
-//** Text color for ``s
 $input-color:                    $text-color;
-//** `` border color
-$input-border:                   #dce4ec;
-
-// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
-//** Default `.form-control` border radius
-// This has no effect on ``s in CSS.
-// $input-border-radius:            $border-radius-base
-//** Large `.form-control` border radius
-// $input-border-radius-large:      $border-radius-large
-//** Small `.form-control` border radius
-// $input-border-radius-small:      $border-radius-small
-
-//** Border color for inputs on focus
+$input-border:                   #DDD;
 $input-border-focus:             $brand-info;
-
-//** Placeholder text color
-// $input-color-placeholder:        #999
-
-//** Default `.form-control` height
-// $input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2)
-//** Large `.form-control` height
-// $input-height-large:             (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2)
-//** Small `.form-control` height
-// $input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2)
-
 $legend-color:                   $text-color;
-// $legend-border-color:            #e5e5e5
-
-//** Background color for textual input addons
-// $input-group-addon-bg:           $gray-lighter
-//** Border color for textual input addons
-// $input-group-addon-border-color: $input-border
-
-//** Disabled cursor for form controls and buttons.
-// $cursor-disabled:                not-allowed
-
-
-//== Dropdowns
-//
-//## Dropdown menu container and contents.
-
-//** Background for the dropdown menu.
-// $dropdown-bg:                    #fff
-//** Dropdown menu `border-color`.
-// $dropdown-border:                rgba(0,0,0,.15)
-//** Dropdown menu `border-color` **for IE8**.
-// $dropdown-fallback-border:       #ccc
-//** Divider color for between dropdown items.
-// $dropdown-divider-bg:            #e5e5e5
-
-//** Dropdown link text color.
-// $dropdown-link-color:            $gray-dark
-//** Hover color for dropdown links.
-// $dropdown-link-hover-color:      darken($gray-dark, 5%)
-//** Hover background for dropdown links.
-// $dropdown-link-hover-bg:         #f5f5f5
-
-//** Active dropdown menu item text color.
-// $dropdown-link-active-color:     $component-active-color
-//** Active dropdown menu item background color.
-// $dropdown-link-active-bg:        $component-active-bg
-
-//** Disabled dropdown menu item background color.
-// $dropdown-link-disabled-color:   $gray-light
-
-//** Text color for headers within dropdown menus.
-// $dropdown-header-color:          $gray-light
-
-//** Deprecated `$dropdown-caret-color` as of v3.1.0
-// $dropdown-caret-color:           #000
-
-
-//-- Z-index master list
-//
-// Warning: Avoid customizing these values. They're used for a bird's eye view
-// of components dependent on the z-axis and are designed to all work together.
-//
-// Note: These variables are not generated into the Customizer.
-
-// $zindex-navbar:            1000
-// $zindex-dropdown:          1000
-// $zindex-popover:           1060
-// $zindex-tooltip:           1070
-// $zindex-navbar-fixed:      1030
-// $zindex-modal:             1040
-
-
-//== Media queries breakpoints
-//
-//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
-
-// Extra small screen / phone
-//** Deprecated `$screen-xs` as of v3.0.1
-// $screen-xs:                  480px
-//** Deprecated `$screen-xs-min` as of v3.2.0
-// $screen-xs-min:              $screen-xs
-//** Deprecated `$screen-phone` as of v3.0.1
-// $screen-phone:               $screen-xs-min
-
-// Small screen / tablet
-//** Deprecated `$screen-sm` as of v3.0.1
-// $screen-sm:                  768px
-// $screen-sm-min:              $screen-sm
-//** Deprecated `$screen-tablet` as of v3.0.1
-// $screen-tablet:              $screen-sm-min
-
-// Medium screen / desktop
-//** Deprecated `$screen-md` as of v3.0.1
-// $screen-md:                  992px
-// $screen-md-min:              $screen-md
-//** Deprecated `$screen-desktop` as of v3.0.1
-// $screen-desktop:             $screen-md-min
-
-// Large screen / wide desktop
-//** Deprecated `$screen-lg` as of v3.0.1
-// $screen-lg:                  1200px
-// $screen-lg-min:              $screen-lg
-//** Deprecated `$screen-lg-desktop` as of v3.0.1
-// $screen-lg-desktop:          $screen-lg-min
-
-// So media queries don't overlap when required, provide a maximum
-// $screen-xs-max:              ($screen-sm-min - 1)
-// $screen-sm-max:              ($screen-md-min - 1)
-// $screen-md-max:              ($screen-lg-min - 1)
-
-
-//== Grid system
-//
-//## Define your custom responsive grid.
-
-//** Number of columns in the grid.
-// $grid-columns:              12
-//** Padding between columns. Gets divided in half for the left and right.
-// $grid-gutter-width:         30px
-// Navbar collapse
-//** Point at which the navbar becomes uncollapsed.
-// $grid-float-breakpoint:     $screen-sm-min
-//** Point at which the navbar begins collapsing.
-// $grid-float-breakpoint-max: ($grid-float-breakpoint - 1)
-
-
-//== Container sizes
-//
-//## Define the maximum width of `.container` for different screen sizes.
-
-// Small screen / tablet
-// $container-tablet:             (720px + $grid-gutter-width)
-//** For `$screen-sm-min` and up.
-// $container-sm:                 $container-tablet
-
-// Medium screen / desktop
-// $container-desktop:            (940px + $grid-gutter-width)
-//** For `$screen-md-min` and up.
-// $container-md:                 $container-desktop
-
-// Large screen / wide desktop
-// $container-large-desktop:      (1140px + $grid-gutter-width)
-//** For `$screen-lg-min` and up.
-// $container-lg:                 $container-large-desktop
-
-
-//== Navbar
-//
-//##
-
-// Basics of a navbar
-// $navbar-height:                    50px
-// $navbar-margin-bottom:             $line-height-computed
-// $navbar-border-radius:             $border-radius-base
-// $navbar-padding-horizontal:        floor(($grid-gutter-width / 2))
-// $navbar-padding-vertical:          (($navbar-height - $line-height-computed) / 2)
-// $navbar-collapse-max-height:       340px
-
-// $navbar-default-color:             #777
-// $navbar-default-bg:                #f8f8f8
-// $navbar-default-border:            darken($navbar-default-bg, 6.5%)
-
-// Navbar links
-// $navbar-default-link-color:                #777
-// $navbar-default-link-hover-color:          #333
-// $navbar-default-link-hover-bg:             transparent
-// $navbar-default-link-active-color:         #555
-// $navbar-default-link-active-bg:            darken($navbar-default-bg, 6.5%)
-// $navbar-default-link-disabled-color:       #ccc
-// $navbar-default-link-disabled-bg:          transparent
-
-// Navbar brand label
-// $navbar-default-brand-color:               $navbar-default-link-color
-// $navbar-default-brand-hover-color:         darken($navbar-default-brand-color, 10%)
-// $navbar-default-brand-hover-bg:            transparent
-
-// Navbar toggle
-// $navbar-default-toggle-hover-bg:           #ddd
-// $navbar-default-toggle-icon-bar-bg:        #888
-// $navbar-default-toggle-border-color:       #ddd
-
-
-// Inverted navbar
-// Reset inverted navbar basics
-// $navbar-inverse-color:                      lighten($gray-light, 15%)
-// $navbar-inverse-bg:                         #222
-// $navbar-inverse-border:                     darken($navbar-inverse-bg, 10%)
-
-// Inverted navbar links
-// $navbar-inverse-link-color:                 lighten($gray-light, 15%)
-// $navbar-inverse-link-hover-color:           #fff
-// $navbar-inverse-link-hover-bg:              transparent
-// $navbar-inverse-link-active-color:          $navbar-inverse-link-hover-color
-// $navbar-inverse-link-active-bg:             darken($navbar-inverse-bg, 10%)
-// $navbar-inverse-link-disabled-color:        #444
-// $navbar-inverse-link-disabled-bg:           transparent
-
-// Inverted navbar brand label
-// $navbar-inverse-brand-color:                $navbar-inverse-link-color
-// $navbar-inverse-brand-hover-color:          #fff
-// $navbar-inverse-brand-hover-bg:             transparent
-
-// Inverted navbar toggle
-// $navbar-inverse-toggle-hover-bg:            #333
-// $navbar-inverse-toggle-icon-bar-bg:         #fff
-// $navbar-inverse-toggle-border-color:        #333
-
-
-//== Navs
-//
-//##
-
-//=== Shared nav styles
-// $nav-link-padding:                          10px 15px
-// $nav-link-hover-bg:                         $gray-lighter
-
-// $nav-disabled-link-color:                   $gray-light
-// $nav-disabled-link-hover-color:             $gray-light
-
-//== Tabs
-// $nav-tabs-border-color:                     #ddd
-
-// $nav-tabs-link-hover-border-color:          $gray-lighter
-
-// $nav-tabs-active-link-hover-bg:             $body-bg
-// $nav-tabs-active-link-hover-color:          $gray
-// $nav-tabs-active-link-hover-border-color:   #ddd
-
-// $nav-tabs-justified-link-border-color:            #ddd
-// $nav-tabs-justified-active-link-border-color:     $body-bg
-
-//== Pills
-// $nav-pills-border-radius:                   $border-radius-base
-// $nav-pills-active-link-hover-bg:            $component-active-bg
-// $nav-pills-active-link-hover-color:         $component-active-color
 
 
 //== Pagination
@@ -467,38 +77,10 @@ $pagination-disabled-bg:               lighten($brand-success, 15%);
 $pagination-disabled-border:           transparent;
 
 
-//== Pager
-//
-//##
-
-// $pager-bg:                             $pagination-bg
-// $pager-border:                         $pagination-border
-// $pager-border-radius:                  15px
-
-// $pager-hover-bg:                       $pagination-hover-bg
-
-// $pager-active-bg:                      $pagination-active-bg
-// $pager-active-color:                   $pagination-active-color
-
-// $pager-disabled-color:                 $pagination-disabled-color
-
-
-//== Jumbotron
-//
-//##
-
-// $jumbotron-padding:              30px
-// $jumbotron-color:                inherit
-// $jumbotron-bg:                   $gray-lighter
-// $jumbotron-heading-color:        inherit
-// $jumbotron-font-size:            ceil(($font-size-base * 1.5))
-
-
 //== Form states and alerts
 //
 //## Define colors for form feedback states and, by default, alerts.
 
-
 $state-success-text:             #fff;
 $state-success-bg:               $brand-success;
 $state-success-border:           $brand-success;
@@ -516,316 +98,22 @@ $state-danger-bg:                $brand-danger;
 $state-danger-border:            $brand-danger;
 
 
-//== Tooltips
-//
-//##
-
-//** Tooltip max width
-// $tooltip-max-width:           200px
-//** Tooltip text color
-// $tooltip-color:               #fff
-//** Tooltip background color
-// $tooltip-bg:                  #000
-// $tooltip-opacity:             .9
-
-//** Tooltip arrow width
-// $tooltip-arrow-width:         5px
-//** Tooltip arrow color
-// $tooltip-arrow-color:         $tooltip-bg
-
-
-//== Popovers
-//
-//##
-
-//** Popover body background color
-// $popover-bg:                          #fff
-//** Popover maximum width
-// $popover-max-width:                   276px
-//** Popover border color
-// $popover-border-color:                rgba(0,0,0,.2)
-//** Popover fallback border color
-// $popover-fallback-border-color:       #ccc
-
-//** Popover title background color
-// $popover-title-bg:                    darken($popover-bg, 3%)
-
-//** Popover arrow width
-// $popover-arrow-width:                 10px
-//** Popover arrow color
-// $popover-arrow-color:                 $popover-bg
-
-//** Popover outer arrow width
-// $popover-arrow-outer-width:           ($popover-arrow-width + 1)
-//** Popover outer arrow color
-// $popover-arrow-outer-color:           fade_in($popover-border-color, 0.05)
-//** Popover outer arrow fallback color
-// $popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%)
-
-
-//== Labels
-//
-//##
-
-//** Default label background color
-// $label-default-bg:            $gray-light
-//** Primary label background color
-// $label-primary-bg:            $brand-primary
-//** Success label background color
-// $label-success-bg:            $brand-success
-//** Info label background color
-// $label-info-bg:               $brand-info
-//** Warning label background color
-// $label-warning-bg:            $brand-warning
-//** Danger label background color
-// $label-danger-bg:             $brand-danger
-
-//** Default label text color
-// $label-color:                 #fff
-//** Default text color of a linked label
-// $label-link-hover-color:      #fff
-
-
-//== Modals
-//
-//##
-
-//** Padding applied to the modal body
-// $modal-inner-padding:         15px
-
-//** Padding applied to the modal title
-// $modal-title-padding:         15px
-//** Modal title line-height
-// $modal-title-line-height:     $line-height-base
-
-//** Background color of modal content area
-// $modal-content-bg:                             #fff
-//** Modal content border color
-// $modal-content-border-color:                   rgba(0,0,0,.2)
-//** Modal content border color **for IE8**
-// $modal-content-fallback-border-color:          #999
-
-//** Modal backdrop background color
-// $modal-backdrop-bg:           #000
-//** Modal backdrop opacity
-// $modal-backdrop-opacity:      .5
-//** Modal header border color
-// $modal-header-border-color:   #e5e5e5
-//** Modal footer border color
-// $modal-footer-border-color:   $modal-header-border-color
-
-// $modal-lg:                    900px
-// $modal-md:                    600px
-// $modal-sm:                    300px
-
-
 //== Alerts
 //
 //## Define alert colors, border radius, and padding.
 
-// $alert-padding:               15px
 $alert-border-radius:            0;
-// $alert-link-font-weight:      bold
-
-// $alert-success-bg:            $state-success-bg
-// $alert-success-text:          $state-success-text
-// $alert-success-border:        $state-success-border
-
-// $alert-info-bg:               $state-info-bg
-// $alert-info-text:             $state-info-text
-// $alert-info-border:           $state-info-border
-
-// $alert-warning-bg:            $state-warning-bg
-// $alert-warning-text:          $state-warning-text
-// $alert-warning-border:        $state-warning-border
-
-// $alert-danger-bg:             $state-danger-bg
-// $alert-danger-text:           $state-danger-text
-// $alert-danger-border:         $state-danger-border
-
-
-//== Progress bars
-//
-//##
-
-//** Background color of the whole progress component
-// $progress-bg:                 #f5f5f5
-//** Progress bar text color
-// $progress-bar-color:          #fff
-//** Variable for setting rounded corners on progress bar.
-// $progress-border-radius:      $border-radius-base
-
-//** Default progress bar color
-// $progress-bar-bg:             $brand-primary
-//** Success progress bar color
-// $progress-bar-success-bg:     $brand-success
-//** Warning progress bar color
-// $progress-bar-warning-bg:     $brand-warning
-//** Danger progress bar color
-// $progress-bar-danger-bg:      $brand-danger
-//** Info progress bar color
-// $progress-bar-info-bg:        $brand-info
-
-
-//== List group
-//
-//##
-
-//** Background color on `.list-group-item`
-// $list-group-bg:                 #fff
-//** `.list-group-item` border color
-// $list-group-border:             #ddd
-//** List group border radius
-// $list-group-border-radius:      $border-radius-base
-
-//** Background color of single list items on hover
-// $list-group-hover-bg:           #f5f5f5
-//** Text color of active list items
-// $list-group-active-color:       $component-active-color
-//** Background color of active list items
-// $list-group-active-bg:          $component-active-bg
-//** Border color of active list elements
-// $list-group-active-border:      $list-group-active-bg
-//** Text color for content within active list items
-// $list-group-active-text-color:  lighten($list-group-active-bg, 40%)
-
-//** Text color of disabled list items
-// $list-group-disabled-color:      $gray-light
-//** Background color of disabled list items
-// $list-group-disabled-bg:         $gray-lighter
-//** Text color for content within disabled list items
-// $list-group-disabled-text-color: $list-group-disabled-color
-
-// $list-group-link-color:         #555
-// $list-group-link-hover-color:   $list-group-link-color
-// $list-group-link-heading-color: #333
 
 
 //== Panels
 //
 //##
 
-// $panel-bg:                    #fff
-// $panel-body-padding:          15px
-// $panel-heading-padding:       10px 15px
-// $panel-footer-padding:        $panel-heading-padding
 $panel-border-radius:            0;
-
-//** Border color for elements within panels
-// $panel-inner-border:          #ddd
-// $panel-footer-bg:             #f5f5f5
-
 $panel-default-text:          $text-color;
 $panel-default-border:        $border-color;
 $panel-default-heading-bg:    $background-color;
 
-// $panel-primary-text:          #fff
-// $panel-primary-border:        $brand-primary
-// $panel-primary-heading-bg:    $brand-primary
-
-// $panel-success-text:          $state-success-text
-// $panel-success-border:        $state-success-border
-// $panel-success-heading-bg:    $state-success-bg
-
-// $panel-info-text:             $state-info-text
-// $panel-info-border:           $state-info-border
-// $panel-info-heading-bg:       $state-info-bg
-
-// $panel-warning-text:          $state-warning-text
-// $panel-warning-border:        $state-warning-border
-// $panel-warning-heading-bg:    $state-warning-bg
-
-// $panel-danger-text:           $state-danger-text
-// $panel-danger-border:         $state-danger-border
-// $panel-danger-heading-bg:     $state-danger-bg
-
-
-//== Thumbnails
-//
-//##
-
-//** Padding around the thumbnail image
-// $thumbnail-padding:           4px
-//** Thumbnail background color
-// $thumbnail-bg:                $body-bg
-//** Thumbnail border color
-// $thumbnail-border:            #ddd
-//** Thumbnail border radius
-// $thumbnail-border-radius:     $border-radius-base
-
-//** Custom text color for thumbnail captions
-// $thumbnail-caption-color:     $text-color
-//** Padding around the thumbnail caption
-// $thumbnail-caption-padding:   9px
-
-
-//== Wells
-//
-//##
-
-$well-bg:                     $gray-lighter;
-$well-border:                 transparent;
-
-
-//== Badges
-//
-//##
-
-// $badge-color:                 #fff
-//** Linked badge text color on hover
-// $badge-link-hover-color:      #fff
-// $badge-bg:                    $gray-light
-
-//** Badge text color in active nav link
-// $badge-active-color:          $link-color
-//** Badge background color in active nav link
-// $badge-active-bg:             #fff
-
-// $badge-font-weight:           bold
-// $badge-line-height:           1
-// $badge-border-radius:         10px
-
-
-//== Breadcrumbs
-//
-//##
-
-// $breadcrumb-padding-vertical:   8px
-// $breadcrumb-padding-horizontal: 15px
-//** Breadcrumb background color
-// $breadcrumb-bg:                 #f5f5f5
-//** Breadcrumb text color
-// $breadcrumb-color:              #ccc
-//** Text color of current page in the breadcrumb
-// $breadcrumb-active-color:       $gray-light
-//** Textual separator for between breadcrumb elements
-// $breadcrumb-separator:          "/"
-
-
-//== Carousel
-//
-//##
-
-// $carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6)
-
-// $carousel-control-color:                      #fff
-// $carousel-control-width:                      15%
-// $carousel-control-opacity:                    .5
-// $carousel-control-font-size:                  20px
-
-// $carousel-indicator-active-bg:                #fff
-// $carousel-indicator-border-color:             #fff
-
-// $carousel-caption-color:                      #fff
-
-
-//== Close
-//
-//##
-
-// $close-font-weight:           bold
-// $close-color:                 #000
-// $close-text-shadow:           0 1px 0 #fff
 
 
 //== Code
@@ -837,34 +125,3 @@ $code-bg:                     #f9f2f4;
 
 $kbd-color:                   #fff;
 $kbd-bg:                      #333;
-
-$pre-bg:                      $gray-lighter;
-$pre-color:                   $text-color;
-$pre-border-color:            #ccc;
-// $pre-scrollable-max-height:   340px
-
-
-//== Type
-//
-//##
-
-//** Horizontal offset for forms and lists.
-// $component-offset-horizontal: 180px
-//** Text muted color
-// $text-muted:                  $gray-light
-//** Abbreviations and acronyms border color
-// $abbr-border-color:           $gray-light
-//** Headings small color
-$headings-small-color:        $gray-dark;
-//** Blockquote small color
-// $blockquote-small-color:      $gray-light
-//** Blockquote font size
-// $blockquote-font-size:        ($font-size-base * 1.25)
-//** Blockquote border color
-// $blockquote-border-color:     $gray-lighter
-//** Page header border color
-// $page-header-border-color:    $gray-lighter
-//** Width of horizontal description list titles
-// $dl-horizontal-offset:        $component-offset-horizontal
-//** Horizontal line color.
-// $hr-border:                   $gray-lighter
diff --git a/app/assets/stylesheets/base/variables.scss b/app/assets/stylesheets/base/variables.scss
index 4e2c64aa132..596376c3970 100644
--- a/app/assets/stylesheets/base/variables.scss
+++ b/app/assets/stylesheets/base/variables.scss
@@ -1,5 +1,6 @@
 $style_color: #474D57;
 $hover: #FFF3EB;
+$gl-text-color: #222222;
 $gl-link-color: #446e9b;
 $nprogress-color: #c0392b;
 $gl-font-size: 14px;
@@ -8,23 +9,18 @@ $sidebar_width: 230px;
 $avatar_radius: 50%;
 $code_font_size: 13px;
 $code_line_height: 1.5;
-$border-color: #dce4ec;
-$background-color: #ECF0F1;
+$border-color: #E5E5E5;
+$background-color: #f5f5f5;
 
 /*
  * State colors:
  */
-$gl-success: #019875;
-$gl-danger: #d9534f;
 $gl-primary: #446e9b;
+$gl-success: #019875;
 $gl-info: #029ACF;
 $gl-warning: #EB9532;
+$gl-danger: #d9534f;
 
-$gl-primary:         #2C3E50;
-$gl-success:         #18BC9C;
-$gl-info:            #3498DB;
-$gl-warning:         #F39C12;
-$gl-danger:          #E74C3C;
 /*
  * Commit Diff Colors
  */
diff --git a/app/assets/stylesheets/generic/forms.scss b/app/assets/stylesheets/generic/forms.scss
index 19bc11086e9..31fe5a03f37 100644
--- a/app/assets/stylesheets/generic/forms.scss
+++ b/app/assets/stylesheets/generic/forms.scss
@@ -29,8 +29,8 @@ fieldset legend {
   padding: 17px 20px 18px;
   margin-top: 18px;
   margin-bottom: 18px;
-  background-color: #ecf0f1;
-  border-top: 1px solid #e5e5e5;
+  background-color: $background-color;
+  border-top: 1px solid $border-color;
 }
 
 @media (min-width: $screen-sm-min) {
diff --git a/app/assets/stylesheets/generic/lists.scss b/app/assets/stylesheets/generic/lists.scss
index 85176fec0dc..08bf6e943d2 100644
--- a/app/assets/stylesheets/generic/lists.scss
+++ b/app/assets/stylesheets/generic/lists.scss
@@ -61,7 +61,7 @@
     p {
       padding-top: 1px;
       margin: 0;
-      color: #222;
+      color: $gray-dark;
       img {
         position: relative;
         top: 3px;
@@ -74,7 +74,7 @@
     }
 
     .row_title {
-      color: $text-color;
+      color: $gray-dark;
 
       &:hover {
         color: $text-color;
diff --git a/app/assets/stylesheets/generic/nav_sidebar.scss b/app/assets/stylesheets/generic/nav_sidebar.scss
index bb890171985..3bcb7b81333 100644
--- a/app/assets/stylesheets/generic/nav_sidebar.scss
+++ b/app/assets/stylesheets/generic/nav_sidebar.scss
@@ -58,8 +58,6 @@
 }
 
 .nav-sidebar li {
-  text-shadow: 0 1px 1px $border-color;
-
   &.separate-item {
     border-top: 1px solid $border-color;
     padding-top: 10px;
@@ -67,7 +65,7 @@
   }
 
   a {
-    color: #3b5a5b;
+    color: $gray;
     display: block;
     text-decoration: none;
     padding: 8px 15px;
@@ -78,7 +76,7 @@
     &:hover {
       text-decoration: none;
       color: $text-color;
-      background: #f2f6f7;
+      background: $border-color;
     }
 
     &:active, &:focus {
@@ -87,7 +85,7 @@
 
     i {
       width: 20px;
-      color: $gray-dark;
+      color: $gray-light;
       margin-right: 23px;
     }
   }
diff --git a/app/assets/stylesheets/generic/timeline.scss b/app/assets/stylesheets/generic/timeline.scss
index f92a79f7a5f..97831eb7c27 100644
--- a/app/assets/stylesheets/generic/timeline.scss
+++ b/app/assets/stylesheets/generic/timeline.scss
@@ -54,7 +54,7 @@
 
       .timeline-content {
         position: relative;
-        background: #f5f5f6;
+        background: $background-color;
         padding: 10px 15px;
         margin-left: 60px;
 
@@ -70,7 +70,7 @@
           height: 0;
           border-style: solid;
           border-width: 9px 9px 9px 0;
-          border-color: transparent #f5f5f6 transparent transparent;
+          border-color: transparent $background-color transparent transparent;
           left: 0;
           top: 10px;
           margin-left: -9px;
-- 
GitLab


From d71e2318f94f53c5ab924c1b9dcf603e28770dea Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets 
Date: Tue, 17 Mar 2015 18:11:27 -0700
Subject: [PATCH 06/46] Fix scroll for last push widget

---
 app/assets/stylesheets/pages/events.scss | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 480cc2c50a9..83daea10ed5 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -154,10 +154,12 @@
   overflow: auto;
   .event-last-push-text {
     @include str-truncated(100%);
+    padding: 5px 0;
+    font-size: 13px;
     float:left;
     margin-right: -150px;
     padding-right: 150px;
-    line-height: 24px;
+    line-height: 20px;
   }
 }
 
-- 
GitLab


From 245f03cd6102e64998799f843843f593d48c0e54 Mon Sep 17 00:00:00 2001
From: Marin Jankovski 
Date: Wed, 18 Mar 2015 08:25:50 -0700
Subject: [PATCH 07/46] Fix the order of signin and signup on features page.

---
 app/views/admin/application_settings/_form.html.haml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index 781600a3766..edfcccfcf4c 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -12,13 +12,13 @@
         .checkbox
           = f.label :signup_enabled do
             = f.check_box :signup_enabled
-            Signin enabled
+            Signup enabled
     .form-group
       .col-sm-offset-2.col-sm-10
         .checkbox
           = f.label :signin_enabled do
             = f.check_box :signin_enabled
-            Signup enabled
+            Signin enabled
     .form-group
       .col-sm-offset-2.col-sm-10
         .checkbox
-- 
GitLab


From c0524574c8d2c94fd50499b754f8aaa70e2dde4c Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets 
Date: Wed, 18 Mar 2015 10:25:22 -0700
Subject: [PATCH 08/46] Bump gitlab_git to 7.1.2

---
 Gemfile      | 2 +-
 Gemfile.lock | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Gemfile b/Gemfile
index 9dd75455c87..08bcd85f53e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -39,7 +39,7 @@ gem "browser"
 
 # Extracting information from a git repository
 # Provide access to Gitlab::Git library
-gem "gitlab_git", '~> 7.1.0'
+gem "gitlab_git", '~> 7.1.2'
 
 # Ruby/Rack Git Smart-HTTP Server Handler
 gem 'gitlab-grack', '~> 2.0.0.rc2', require: 'grack'
diff --git a/Gemfile.lock b/Gemfile.lock
index d6e66707c8a..1bea70d5a0c 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -213,7 +213,7 @@ GEM
       mime-types (~> 1.19)
     gitlab_emoji (0.1.0)
       gemojione (~> 2.0)
-    gitlab_git (7.1.1)
+    gitlab_git (7.1.2)
       activesupport (~> 4.0)
       charlock_holmes (~> 0.6)
       gitlab-linguist (~> 3.0)
@@ -705,7 +705,7 @@ DEPENDENCIES
   gitlab-grack (~> 2.0.0.rc2)
   gitlab-linguist (~> 3.0.1)
   gitlab_emoji (~> 0.1)
-  gitlab_git (~> 7.1.0)
+  gitlab_git (~> 7.1.2)
   gitlab_meta (= 7.0)
   gitlab_omniauth-ldap (= 1.2.0)
   gollum-lib (~> 4.0.0)
-- 
GitLab


From 33d5a60571267ffa33fcb3e19f03f977e1a3f9c8 Mon Sep 17 00:00:00 2001
From: Vinnie Okada 
Date: Wed, 18 Mar 2015 12:38:58 -0600
Subject: [PATCH 09/46] Handle nil restricted visibility settings

Return `true` from `non_restricted_level?` when the
`restricted_visibility_levels` setting is nil.
---
 lib/gitlab/visibility_level.rb | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb
index 1851e76067c..e4306bd2a56 100644
--- a/lib/gitlab/visibility_level.rb
+++ b/lib/gitlab/visibility_level.rb
@@ -35,7 +35,11 @@ module Gitlab
       end
 
       def non_restricted_level?(level)
-        ! current_application_settings.restricted_visibility_levels.include?(level)
+        if current_application_settings.restricted_visibility_levels.nil?
+          true
+        else
+          ! current_application_settings.restricted_visibility_levels.include?(level)
+        end
       end
 
       def valid_level?(level)
-- 
GitLab


From 09657f1071571ca6a2ef7dd844e3e930dcb4a27e Mon Sep 17 00:00:00 2001
From: Marin Jankovski 
Date: Wed, 18 Mar 2015 13:55:41 -0700
Subject: [PATCH 10/46] Move application setting to separate variable.

---
 lib/gitlab/visibility_level.rb | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb
index e4306bd2a56..582fc759efd 100644
--- a/lib/gitlab/visibility_level.rb
+++ b/lib/gitlab/visibility_level.rb
@@ -35,10 +35,12 @@ module Gitlab
       end
 
       def non_restricted_level?(level)
-        if current_application_settings.restricted_visibility_levels.nil?
+        restricted_levels = current_application_settings.restricted_visibility_levels
+
+        if restricted_levels.nil?
           true
         else
-          ! current_application_settings.restricted_visibility_levels.include?(level)
+          !restricted_levels.include?(level)
         end
       end
 
-- 
GitLab


From 8b17fcb89715007e6877f676225fcce3bd909c83 Mon Sep 17 00:00:00 2001
From: Douwe Maan 
Date: Wed, 18 Mar 2015 16:37:29 +0100
Subject: [PATCH 11/46] Fix condensed range in MR push comment.

---
 app/models/note.rb                             | 8 ++++++--
 app/services/merge_requests/refresh_service.rb | 2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/app/models/note.rb b/app/models/note.rb
index 9ca3e4d7e97..649e9b4e852 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -151,7 +151,7 @@ class Note < ActiveRecord::Base
       )
     end
 
-    def create_new_commits_note(merge_request, project, author, new_commits, existing_commits = [])
+    def create_new_commits_note(merge_request, project, author, new_commits, existing_commits = [], oldrev = nil)
       total_count = new_commits.length + existing_commits.length
       commits_text = ActionController::Base.helpers.pluralize(total_count, 'commit')
       body = "Added #{commits_text}:\n\n"
@@ -161,7 +161,11 @@ class Note < ActiveRecord::Base
           if existing_commits.length == 1
             existing_commits.first.short_id
           else
-            "#{existing_commits.first.short_id}..#{existing_commits.last.short_id}"
+            if oldrev
+              "#{Commit.truncate_sha(oldrev)}...#{existing_commits.last.short_id}"
+            else
+              "#{existing_commits.first.short_id}..#{existing_commits.last.short_id}"
+            end
           end
 
         commits_text = ActionController::Base.helpers.pluralize(existing_commits.length, 'commit')
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index cab8a1e880e..7eef2c2d6a5 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -89,7 +89,7 @@ module MergeRequests
         end
 
         Note.create_new_commits_note(merge_request, merge_request.project,
-                                     @current_user, new_commits, existing_commits)
+                                     @current_user, new_commits, existing_commits, @oldrev)
       end
     end
 
-- 
GitLab


From e716e4377f65443bb0eb779f17b4206f01add3a4 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets 
Date: Wed, 18 Mar 2015 14:23:06 -0700
Subject: [PATCH 12/46] Version 7.9.0.rc2

---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index 03d55a5a014..fa86dc427f2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-7.9.0.rc1
\ No newline at end of file
+7.9.0.rc2
\ No newline at end of file
-- 
GitLab


From 1667861ed2987bc3156af33700c48609b61546c8 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets 
Date: Wed, 18 Mar 2015 17:42:53 -0700
Subject: [PATCH 13/46] Fix link to project from fork

---
 app/views/projects/show.html.haml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 74b07395650..28a8a9f3b67 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -44,7 +44,7 @@
               %i.fa.fa-code-fork.project-fork-icon
               Forked from:
               %br
-              = link_to @project.forked_from_project.name_with_namespace, namespace_project_path(@project.namespace, @project.forked_from_project)
+              = link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project)
 
           - unless @project.empty_repo?
             = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: @ref || @repository.root_ref), class: 'btn btn-block' do
-- 
GitLab


From d793de7ad7c9f9a585e5938bb153ed30c22ea985 Mon Sep 17 00:00:00 2001
From: Marin Jankovski 
Date: Wed, 18 Mar 2015 23:32:57 -0700
Subject: [PATCH 14/46] Commits in push data should always be an array.

---
 lib/gitlab/push_data_builder.rb | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/lib/gitlab/push_data_builder.rb b/lib/gitlab/push_data_builder.rb
index ea9012b8844..1e35f67ca0f 100644
--- a/lib/gitlab/push_data_builder.rb
+++ b/lib/gitlab/push_data_builder.rb
@@ -28,6 +28,12 @@ module Gitlab
         # Get latest 20 commits ASC
         commits_limited = commits.last(20)
 
+        # For performance purposes maximum 20 latest commits
+        # will be passed as post receive hook data.
+        commit_attrs = commits_limited.map do |commit|
+          commit.hook_attrs(project)
+        end
+
         type = Gitlab::Git.tag_ref?(ref) ? "tag_push" : "push"
         # Hash to be passed as post_receive_data
         data = {
@@ -49,17 +55,10 @@ module Gitlab
             git_ssh_url: project.ssh_url_to_repo,
             visibility_level: project.visibility_level
           },
-          commits: [],
+          commits: commit_attrs,
           total_commits_count: commits_count
         }
 
-        # For performance purposes maximum 20 latest commits
-        # will be passed as post receive hook data.
-        commits_limited.each do |commit|
-          data[:commits] << commit.hook_attrs(project)
-        end
-
-        data[:commits] = "" if data[:commits].count == 0
         data
       end
 
-- 
GitLab


From 1ea6b05e87bacfca0d1cbaf0c9db1833258d64c3 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets 
Date: Thu, 19 Mar 2015 15:54:53 +0000
Subject: [PATCH 15/46] Merge branch 'rake_backup' into 'master'

Backup repo with tar instead of git bundle

Fixes gitlab/gitlab-ee#246

See merge request !1723
---
 CHANGELOG                | 1 +
 lib/backup/repository.rb | 5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 27b930d23a6..16f625e2480 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -77,6 +77,7 @@ v 7.9.0 (unreleased)
   - Ability to unsubscribe/subscribe to issue or merge request
   - Delete deploy key when last connection to a project is destroyed.
   - Fix invalid Atom feeds when using emoji, horizontal rules, or images (Christian Walther)
+  - Backup of repositories with tar instead of git bundle (only now are git-annex files included in the backup)
 
 v 7.8.4
   - Fix issue_tracker_id substitution in custom issue trackers
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index e18bc804437..dfb2da9f84e 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -16,7 +16,7 @@ module Backup
         if project.empty_repo?
           $progress.puts "[SKIPPED]".cyan
         else
-          cmd = %W(git --git-dir=#{path_to_repo(project)} bundle create #{path_to_bundle(project)} --all)
+          cmd = %W(tar -cf #{path_to_bundle(project)} -C #{path_to_repo(project)} .)
           output, status = Gitlab::Popen.popen(cmd)
           if status.zero?
             $progress.puts "[DONE]".green
@@ -64,7 +64,8 @@ module Backup
         project.namespace.ensure_dir_exist if project.namespace
 
         if File.exists?(path_to_bundle(project))
-          cmd = %W(git clone --bare #{path_to_bundle(project)} #{path_to_repo(project)})
+          FileUtils.mkdir_p(path_to_repo(project))
+          cmd = %W(tar -xf #{path_to_bundle(project)} -C #{path_to_repo(project)})
         else
           cmd = %W(git init --bare #{path_to_repo(project)})
         end
-- 
GitLab


From ab83fb992b70b29d92f7605d4ed66c042b56dfee Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets 
Date: Thu, 19 Mar 2015 17:21:20 +0000
Subject: [PATCH 16/46] Merge branch 'add_canceled_ci_status' into 'master'

Add canceled CI status

Fixes https://github.com/gitlabhq/gitlab-ci/issues/564

https://dev.gitlab.org/gitlab/gitlab-ci/issues/169

![Screen_Shot_2015-03-19_at_17.10.08](https://dev.gitlab.org/gitlab/gitlabhq/uploads/87f47d9fd1b1a60e0c5402eedd1a1566/Screen_Shot_2015-03-19_at_17.10.08.png)

See merge request !1729
---
 CHANGELOG                                               | 1 +
 app/assets/javascripts/merge_request.js.coffee          | 2 +-
 app/assets/stylesheets/pages/merge_requests.scss        | 6 ++++++
 app/views/projects/merge_requests/show/_mr_ci.html.haml | 6 ++++++
 4 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG b/CHANGELOG
index 16f625e2480..543c382a8e7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -78,6 +78,7 @@ v 7.9.0 (unreleased)
   - Delete deploy key when last connection to a project is destroyed.
   - Fix invalid Atom feeds when using emoji, horizontal rules, or images (Christian Walther)
   - Backup of repositories with tar instead of git bundle (only now are git-annex files included in the backup)
+  - Add canceled status for CI
 
 v 7.8.4
   - Fix issue_tracker_id substitution in custom issue trackers
diff --git a/app/assets/javascripts/merge_request.js.coffee b/app/assets/javascripts/merge_request.js.coffee
index 1fee9dc1892..10462ac073d 100644
--- a/app/assets/javascripts/merge_request.js.coffee
+++ b/app/assets/javascripts/merge_request.js.coffee
@@ -110,7 +110,7 @@ class @MergeRequest
 
   showCiState: (state) ->
     $('.ci_widget').hide()
-    allowed_states = ["failed", "running", "pending", "success"]
+    allowed_states = ["failed", "canceled", "running", "pending", "success"]
     if state in allowed_states
       $('.ci_widget.ci-' + state).show()
     else
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index fe5667a587f..592b0b729f3 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -155,6 +155,12 @@
       background-color: #FAF1F1;
     }
 
+    &.ci-canceled {
+      color: $gl-warning;
+      border-color: $gl-danger;
+      background-color: #FAF5F1;
+    }
+
     &.ci-error {
       color: $gl-danger;
       border-color: $gl-danger;
diff --git a/app/views/projects/merge_requests/show/_mr_ci.html.haml b/app/views/projects/merge_requests/show/_mr_ci.html.haml
index 85a7103f3bc..ffa3f7b0e36 100644
--- a/app/views/projects/merge_requests/show/_mr_ci.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_ci.html.haml
@@ -23,6 +23,12 @@
     %i.fa.fa-spinner
     Checking for CI status for #{@merge_request.last_commit_short_sha}
 
+  .ci_widget.ci-canceled{style: "display:none"}
+    %i.fa.fa-times
+    %span CI build canceled
+    for #{@merge_request.last_commit_short_sha}.
+    = link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
+
   .ci_widget.ci-error{style: "display:none"}
     %i.fa.fa-times
     %span Cannot connect to the CI server. Please check your settings and try again.
-- 
GitLab


From 68dcfabfe60c76e26bcfc29a317368eab2f02aa5 Mon Sep 17 00:00:00 2001
From: Marin Jankovski 
Date: Thu, 19 Mar 2015 12:38:24 -0700
Subject: [PATCH 17/46] Version 7.9.0.rc3

---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index fa86dc427f2..86cd47608be 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-7.9.0.rc2
\ No newline at end of file
+7.9.0.rc3
\ No newline at end of file
-- 
GitLab


From ec746368f1554ccc3f1040b331b660e188cec59f Mon Sep 17 00:00:00 2001
From: Marin Jankovski 
Date: Thu, 19 Mar 2015 17:43:21 -0700
Subject: [PATCH 18/46] Remove mention of branch to commit to.

---
 app/views/projects/_commit_button.html.haml | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/app/views/projects/_commit_button.html.haml b/app/views/projects/_commit_button.html.haml
index fd8320adb8d..35f7e7bb34b 100644
--- a/app/views/projects/_commit_button.html.haml
+++ b/app/views/projects/_commit_button.html.haml
@@ -2,8 +2,5 @@
   .commit-button-annotation
     = button_tag 'Commit Changes',
                  class: 'btn commit-btn js-commit-button btn-create'
-    .message
-      to branch
-      %strong= ref
   = link_to 'Cancel', cancel_path,
             class: 'btn btn-cancel', data: {confirm: leave_edit_message}
-- 
GitLab


From 5909e5f6b2615642e92be366649ea375c399919d Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets 
Date: Thu, 19 Mar 2015 17:57:37 -0700
Subject: [PATCH 19/46] Revert "Increase timeout for Git-over-HTTP requests."

This reverts commit 516bcabbf42d60db2ac989dce4c7187b2a1e5de9.

Conflicts:
	Gemfile
---
 Gemfile                          |  3 ---
 Gemfile.lock                     |  8 --------
 config/initializers/timeout.rb   |  8 --------
 config/unicorn.rb.example        | 20 ++++++++++++++++----
 lib/gitlab/middleware/timeout.rb | 13 -------------
 public/503.html                  | 13 -------------
 6 files changed, 16 insertions(+), 49 deletions(-)
 delete mode 100644 config/initializers/timeout.rb
 delete mode 100644 lib/gitlab/middleware/timeout.rb
 delete mode 100644 public/503.html

diff --git a/Gemfile b/Gemfile
index 08bcd85f53e..f697f09b542 100644
--- a/Gemfile
+++ b/Gemfile
@@ -180,9 +180,6 @@ gem 'mousetrap-rails'
 # Detect and convert string character encoding
 gem 'charlock_holmes'
 
-# Shutting down requests that take too long
-gem "slowpoke"
-
 gem "sass-rails", '~> 4.0.2'
 gem "coffee-rails"
 gem "uglifier"
diff --git a/Gemfile.lock b/Gemfile.lock
index 1bea70d5a0c..3fd051e29b5 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -147,7 +147,6 @@ GEM
     enumerize (0.7.0)
       activesupport (>= 3.2)
     equalizer (0.0.8)
-    errbase (0.0.2)
     erubis (2.7.0)
     escape_utils (0.2.4)
     eventmachine (1.0.4)
@@ -429,7 +428,6 @@ GEM
       rack
     rack-test (0.6.3)
       rack (>= 1.0)
-    rack-timeout (0.2.0)
     rails (4.1.9)
       actionmailer (= 4.1.9)
       actionpack (= 4.1.9)
@@ -482,8 +480,6 @@ GEM
     rest-client (1.6.7)
       mime-types (>= 1.16)
     rinku (1.7.3)
-    robustly (0.0.3)
-      errbase
     rouge (1.7.4)
     rspec (2.99.0)
       rspec-core (~> 2.99.0)
@@ -566,9 +562,6 @@ GEM
       temple (~> 0.6.6)
       tilt (>= 1.3.3, < 2.1)
     slop (3.6.0)
-    slowpoke (0.0.5)
-      rack-timeout (>= 0.1.0)
-      robustly
     spinach (0.8.7)
       colorize (= 0.5.8)
       gherkin-ruby (>= 0.3.1)
@@ -776,7 +769,6 @@ DEPENDENCIES
   six
   slack-notifier (~> 1.0.0)
   slim
-  slowpoke
   spinach-rails
   spring (~> 1.3.1)
   spring-commands-rspec (= 1.0.4)
diff --git a/config/initializers/timeout.rb b/config/initializers/timeout.rb
deleted file mode 100644
index bc88595cf26..00000000000
--- a/config/initializers/timeout.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# Slowpoke extends Rack::Timeout to gracefully kill Unicorn workers so they can clean up state.
-Slowpoke.timeout = 60
-
-# The `Rack::Timeout` middleware kills requests after 60 seconds (as set above).
-# We're replacing it with our `Gitlab::Middleware::Timeout` that does the same,
-# except ignoring Git-over-HTTP requests, letting those take as long as they need.
-
-Rails.application.config.middleware.swap(Rack::Timeout, Gitlab::Middleware::Timeout)
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index 3aee718097f..86a5512e761 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -35,10 +35,22 @@ working_directory "/home/git/gitlab" # available in 0.94.0+
 listen "/home/git/gitlab/tmp/sockets/gitlab.socket", :backlog => 1024
 listen "127.0.0.1:8080", :tcp_nopush => true
 
-# Kill workers after 1 hour.
-# A shorter timeout of 60 seconds is enforced by rack-timeout for web requests.
-# Git-over-HTTP only has the below timeout since large pulls/pushes can take a long time.
-timeout 60 * 60
+# nuke workers after 30 seconds instead of 60 seconds (the default)
+#
+# NOTICE: git push over http depends on this value.
+# If you want be able to push huge amount of data to git repository over http
+# you will have to increase this value too.
+#
+# Example of output if you try to push 1GB repo to GitLab over http.
+#   -> git push http://gitlab.... master
+#
+#   error: RPC failed; result=18, HTTP code = 200
+#   fatal: The remote end hung up unexpectedly
+#   fatal: The remote end hung up unexpectedly
+#
+# For more information see http://stackoverflow.com/a/21682112/752049
+#
+timeout 60
 
 # feel free to point this anywhere accessible on the filesystem
 pid "/home/git/gitlab/tmp/pids/unicorn.pid"
diff --git a/lib/gitlab/middleware/timeout.rb b/lib/gitlab/middleware/timeout.rb
deleted file mode 100644
index 015600392b9..00000000000
--- a/lib/gitlab/middleware/timeout.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-module Gitlab
-  module Middleware
-    class Timeout < Rack::Timeout
-      GRACK_REGEX = /[-\/\w\.]+\.git\//.freeze
-
-      def call(env)
-        return @app.call(env) if env['PATH_INFO'] =~ GRACK_REGEX
-
-        super
-      end
-    end
-  end
-end
diff --git a/public/503.html b/public/503.html
deleted file mode 100644
index efdae0f512d..00000000000
--- a/public/503.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-  Page took too long to load (503)
-  
-
-
-  

503

-

Page took too long to load.

-
-

Please contact your GitLab administrator if this problem persists.

- - -- GitLab From 86fc054e14ae6e78c6ded8a42e29f9fc45825548 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 20 Mar 2015 11:28:58 -0700 Subject: [PATCH 20/46] Fix project name overflow on dashboard --- app/assets/stylesheets/pages/dashboard.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/pages/dashboard.scss b/app/assets/stylesheets/pages/dashboard.scss index 5a543a852c2..e6d279c3517 100644 --- a/app/assets/stylesheets/pages/dashboard.scss +++ b/app/assets/stylesheets/pages/dashboard.scss @@ -28,6 +28,10 @@ font-size: 14px; line-height: 24px; + .str-truncated { + max-width: 72%; + } + a { display: block; padding: 8px 15px; -- GitLab From e494adc28446319c109bb71c1ce3a43c2f1ac3c9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 20 Mar 2015 12:34:21 -0700 Subject: [PATCH 21/46] Remove upvotes js logic since it does not work as expected anyway --- app/assets/javascripts/notes.js.coffee | 2 +- app/assets/javascripts/notes_votes.js.coffee | 20 -------------------- 2 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 app/assets/javascripts/notes_votes.js.coffee diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index 90e6fd6d154..c366c98cf54 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -425,7 +425,7 @@ class @Notes @removeDiscussionNoteForm(form) updateVotes: -> - (new NotesVotes).updateVotes() + true ### Called after an attachment file has been selected. diff --git a/app/assets/javascripts/notes_votes.js.coffee b/app/assets/javascripts/notes_votes.js.coffee deleted file mode 100644 index 65c149b7886..00000000000 --- a/app/assets/javascripts/notes_votes.js.coffee +++ /dev/null @@ -1,20 +0,0 @@ -class @NotesVotes - updateVotes: -> - votes = $("#votes .votes") - notes = $("#notes-list .note .vote") - - # only update if there is a vote display - if votes.size() - upvotes = notes.filter(".upvote").size() - downvotes = notes.filter(".downvote").size() - votesCount = upvotes + downvotes - upvotesPercent = (if votesCount then (100.0 / votesCount * upvotes) else 0) - downvotesPercent = (if votesCount then (100.0 - upvotesPercent) else 0) - - # change vote bar lengths - votes.find(".bar-success").css "width", upvotesPercent + "%" - votes.find(".bar-danger").css "width", downvotesPercent + "%" - - # replace vote numbers - votes.find(".upvotes").text votes.find(".upvotes").text().replace(/\d+/, upvotes) - votes.find(".downvotes").text votes.find(".downvotes").text().replace(/\d+/, downvotes) -- GitLab From 6e4ee0df3cdf5bba2a09b77579dcc0ba24e5a521 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 20 Mar 2015 12:45:45 -0700 Subject: [PATCH 22/46] Make issue and merge request sidebar more compact * move votes block to participants * make smaller font in sidebar --- app/assets/stylesheets/pages/issuable.scss | 8 ++++- app/assets/stylesheets/pages/votes.scss | 35 ------------------- .../projects/issues/_discussion.html.haml | 12 +++---- .../projects/issues/_issue_context.html.haml | 4 +-- .../merge_requests/_discussion.html.haml | 10 +++--- app/views/votes/_votes_block.html.haml | 14 +++++--- 6 files changed, 26 insertions(+), 57 deletions(-) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index d8d12338859..a640a4e2051 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -25,7 +25,7 @@ } .issuable-context-title { - font-size: 15px; + font-size: 14px; line-height: 1.4; margin-bottom: 5px; @@ -39,3 +39,9 @@ margin-right: 4px; } } + +.issuable-affix .context { + font-size: 13px; + + .btn { font-size: 13px; } +} diff --git a/app/assets/stylesheets/pages/votes.scss b/app/assets/stylesheets/pages/votes.scss index ba0a519dca6..dc9a7d71e8b 100644 --- a/app/assets/stylesheets/pages/votes.scss +++ b/app/assets/stylesheets/pages/votes.scss @@ -1,39 +1,4 @@ -.votes { - font-size: 13px; - line-height: 15px; - .progress { - height: 4px; - margin: 0; - .bar { - float: left; - height: 100%; - } - .bar-success { - @include linear-gradient(#62C462, #51A351); - background-color: #468847; - } - .bar-danger { - @include linear-gradient(#EE5F5B, #BD362F); - background-color: #B94A48; - } - } - .upvotes { - display: inline-block; - color: #468847; - } - .downvotes { - display: inline-block; - color: #B94A48; - } -} -.votes-block { - margin: 6px; - .downvotes { - float: right; - } -} .votes-inline { display: inline-block; margin: 0 8px; } - diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml index fc3e35640dc..0d3028d50b4 100644 --- a/app/views/projects/issues/_discussion.html.haml +++ b/app/views/projects/issues/_discussion.html.haml @@ -6,11 +6,12 @@ = link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close js-note-target-close", title: "Close Issue" .row %section.col-md-9 + .votes-holder.pull-right + #votes= render 'votes/votes_block', votable: @issue .participants %span= pluralize(@issue.participants.count, 'participant') - @issue.participants.each do |participant| = link_to_member(@project, participant, name: false, size: 24) - .voting_notes#notes= render "projects/notes/notes_with_form" %aside.col-md-3 .issuable-affix @@ -20,15 +21,10 @@ %hr .context = render partial: 'issue_context', locals: { issue: @issue } - %hr - .clearfix - .votes-holder - %h6 Votes - #votes= render 'votes/votes_block', votable: @issue - if @issue.labels.any? - %hr - %h6 Labels + .issuable-context-title + %label Labels .issue-show-labels - @issue.labels.each do |label| = link_to namespace_project_issues_path(@project.namespace, @project, label_name: label.name) do diff --git a/app/views/projects/issues/_issue_context.html.haml b/app/views/projects/issues/_issue_context.html.haml index d43ce0aa293..91fe0b68371 100644 --- a/app/views/projects/issues/_issue_context.html.haml +++ b/app/views/projects/issues/_issue_context.html.haml @@ -45,5 +45,5 @@ :coffeescript $ -> new Subscription("#{toggle_subscription_namespace_project_issue_path(@issue.project.namespace, @project, @issue)}") - - \ No newline at end of file + + diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml index 79a093dc775..eb72eaabd8b 100644 --- a/app/views/projects/merge_requests/_discussion.html.haml +++ b/app/views/projects/merge_requests/_discussion.html.haml @@ -7,6 +7,8 @@ .row %section.col-md-9 + .votes-holder.pull-right + #votes= render 'votes/votes_block', votable: @merge_request = render "projects/merge_requests/show/participants" = render "projects/notes/notes_with_form" %aside.col-md-3 @@ -17,14 +19,10 @@ %hr .context = render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request } - %hr - .votes-holder - %h6 Votes - #votes= render 'votes/votes_block', votable: @merge_request - if @merge_request.labels.any? - %hr - %h6 Labels + .issuable-context-title + %label Labels .merge-request-show-labels - @merge_request.labels.each do |label| = link_to namespace_project_merge_requests_path(@project.namespace, @project, label_name: label.name) do diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml index 788d9065a7b..36ea6742064 100644 --- a/app/views/votes/_votes_block.html.haml +++ b/app/views/votes/_votes_block.html.haml @@ -1,6 +1,10 @@ .votes.votes-block - .progress - .progress-bar.progress-bar-success{style: "width: #{votable.upvotes_in_percent}%;"} - .progress-bar.progress-bar-danger{style: "width: #{votable.downvotes_in_percent}%;"} - .upvotes= "#{votable.upvotes} up" - .downvotes= "#{votable.downvotes} down" + .btn-group + - unless votable.upvotes.zero? + .btn.btn-sm.disabled.cgreen + %i.fa.fa-thumbs-up + = votable.upvotes + - unless votable.downvotes.zero? + .btn.btn-sm.disabled.cred + %i.fa.fa-thumbs-down + = votable.downvotes -- GitLab From d9d1dc99bcf57a2214616cb3d80144b2306f0b8f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 20 Mar 2015 13:37:37 -0700 Subject: [PATCH 23/46] Fix commits routing --- config/routes.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index e65ef30afb7..cfcc2d3c202 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -239,7 +239,7 @@ Gitlab::Application.routes.draw do resources :group_members, only: [:index, :create, :update, :destroy] do delete :leave, on: :collection end - + resource :avatar, only: [:destroy] resources :milestones, only: [:index, :show, :update] end @@ -321,7 +321,6 @@ Gitlab::Application.routes.draw do get :branches, on: :member end - resources :commits, only: [:show], constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } resources :compare, only: [:index, :create] scope do @@ -333,6 +332,15 @@ Gitlab::Application.routes.draw do ) end + scope do + get( + '/commits/*id', + to: 'commits#show', + constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }, + as: :commits + ) + end + resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do member do -- GitLab From 7cd053b50aa347f24ffe34fe9d0e492919022e4a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 20 Mar 2015 15:33:13 -0700 Subject: [PATCH 24/46] Improve issue sidebar position --- app/assets/javascripts/issue.js.coffee | 2 +- app/assets/javascripts/merge_request.js.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/issue.js.coffee b/app/assets/javascripts/issue.js.coffee index f2753170478..bf71c144eaf 100644 --- a/app/assets/javascripts/issue.js.coffee +++ b/app/assets/javascripts/issue.js.coffee @@ -19,6 +19,6 @@ class @Issue $('.issue-details').waitForImages -> $('.issuable-affix').affix offset: top: -> - @top = $('.issue-details').outerHeight(true) + 25 + @top = ($('.issuable-affix').offset().top - 70) bottom: -> @bottom = $('.footer').outerHeight(true) diff --git a/app/assets/javascripts/merge_request.js.coffee b/app/assets/javascripts/merge_request.js.coffee index 10462ac073d..09c202e42a5 100644 --- a/app/assets/javascripts/merge_request.js.coffee +++ b/app/assets/javascripts/merge_request.js.coffee @@ -23,7 +23,7 @@ class @MergeRequest $('.merge-request-details').waitForImages -> $('.issuable-affix').affix offset: top: -> - @top = $('.merge-request-details').outerHeight(true) + 91 + @top = ($('.issuable-affix').offset().top - 70) bottom: -> @bottom = $('.footer').outerHeight(true) -- GitLab From 452ffd46f3ffe8f1136b3f5abe5f000e7420db92 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 20 Mar 2015 15:34:29 -0700 Subject: [PATCH 25/46] Fix votes inline rendering --- app/views/votes/_votes_inline.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/votes/_votes_inline.html.haml b/app/views/votes/_votes_inline.html.haml index ee805474830..2cb3ae04e1a 100644 --- a/app/views/votes/_votes_inline.html.haml +++ b/app/views/votes/_votes_inline.html.haml @@ -1,9 +1,9 @@ .votes.votes-inline - unless votable.upvotes.zero? - .upvotes + %span.upvotes.cgreen + #{votable.upvotes} - unless votable.downvotes.zero? \/ - unless votable.downvotes.zero? - .downvotes + %span.downvotes.cred \- #{votable.downvotes} -- GitLab From d9415bf9c26e468ac40fb4c81ebee93c4265df1d Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 20 Mar 2015 15:54:11 -0700 Subject: [PATCH 26/46] Change the name of the key used for bitbucket importer. --- config/initializers/public_key.rb | 2 +- doc/integration/bitbucket.md | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/config/initializers/public_key.rb b/config/initializers/public_key.rb index 75d74e3625d..b70c665f80d 100644 --- a/config/initializers/public_key.rb +++ b/config/initializers/public_key.rb @@ -1,2 +1,2 @@ -path = File.expand_path("~/.ssh/id_rsa.pub") +path = File.expand_path("~/.ssh/bitbucket_isa.pub") Gitlab::BitbucketImport.public_key = File.read(path) if File.exist?(path) diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md index cc6389f5aaf..d82e1f8b41b 100644 --- a/doc/integration/bitbucket.md +++ b/doc/integration/bitbucket.md @@ -2,7 +2,7 @@ Import projects from Bitbucket and login to your GitLab instance with your Bitbucket account. -To enable the Bitbucket OmniAuth provider you must register your application with Bitbucket. +To enable the Bitbucket OmniAuth provider you must register your application with Bitbucket. Bitbucket will generate an application ID and secret key for you to use. 1. Sign in to Bitbucket. @@ -19,8 +19,8 @@ Bitbucket will generate an application ID and secret key for you to use. - URL: The URL to your GitLab installation. 'https://gitlab.company.com' 1. Select "Save". -1. You should now see a Key and Secret in the list of OAuth customers. - Keep this page open as you continue configuration. +1. You should now see a Key and Secret in the list of OAuth customers. + Keep this page open as you continue configuration. 1. On your GitLab server, open the configuration file. @@ -70,13 +70,13 @@ Bitbucket will generate an application ID and secret key for you to use. 1. Restart GitLab for the changes to take effect. -On the sign in page there should now be a Bitbucket icon below the regular sign in form. -Click the icon to begin the authentication process. Bitbucket will ask the user to sign in and authorize the GitLab application. +On the sign in page there should now be a Bitbucket icon below the regular sign in form. +Click the icon to begin the authentication process. Bitbucket will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in. ## Bitbucket project import -To allow projects to be imported directly into GitLab, Bitbucket requires two extra setup steps compared to GitHub and GitLab.com. +To allow projects to be imported directly into GitLab, Bitbucket requires two extra setup steps compared to GitHub and GitLab.com. Bitbucket doesn't allow OAuth applications to clone repositories over HTTPS, and instead requires GitLab to use SSH and identify itself using your GitLab server's SSH key. @@ -95,7 +95,7 @@ To allow GitLab to connect to Bitbucket over SSH, you need to add 'bitbucket.org ```sh The authenticity of host 'bitbucket.org (207.223.240.182)' can't be established. RSA key fingerprint is 97:8c:1b:f2:6f:14:6b:5c:3b:ec:aa:46:46:74:7c:40. - Are you sure you want to continue connecting (yes/no)? + Are you sure you want to continue connecting (yes/no)? ``` 1. If the fingerprint matches, type `yes` to continue connecting and have 'bitbucket.org' be added to your known hosts. @@ -104,7 +104,7 @@ To allow GitLab to connect to Bitbucket over SSH, you need to add 'bitbucket.org ### Step 2: Public key -To be able to access repositories on Bitbucket, GitLab will automatically register your public key with Bitbucket as a deploy key for the repositories to be imported. Your public key needs to be at `~/.ssh/id_rsa.pub`, which will expand to `/home/git/.ssh/id_rsa.pub` in most configurations. +To be able to access repositories on Bitbucket, GitLab will automatically register your public key with Bitbucket as a deploy key for the repositories to be imported. Your public key needs to be at `~/.ssh/bitbucket_rsa.pub`, which will expand to `/home/git/.ssh/bitbucket_rsa.pub` in most configurations. If you have that file in place, you're all set and should see the "Import projects from Bitbucket" option enabled. If you don't, do the following: @@ -114,6 +114,7 @@ If you have that file in place, you're all set and should see the "Import projec sudo -u git -H ssh-keygen ``` + When asked `Enter file in which to save the key` specify the correct path, eg. `/home/git/.ssh/bitbucket_rsa`. Make sure to use an **empty passphrase**. 2. Restart GitLab to allow it to find the new public key. -- GitLab From 3b1842f67bd0019093e7f1c01a3c8fa0de096910 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 20 Mar 2015 16:13:03 -0700 Subject: [PATCH 27/46] Fix typo. --- config/initializers/public_key.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/public_key.rb b/config/initializers/public_key.rb index b70c665f80d..e4f09a2d020 100644 --- a/config/initializers/public_key.rb +++ b/config/initializers/public_key.rb @@ -1,2 +1,2 @@ -path = File.expand_path("~/.ssh/bitbucket_isa.pub") +path = File.expand_path("~/.ssh/bitbucket_rsa.pub") Gitlab::BitbucketImport.public_key = File.read(path) if File.exist?(path) -- GitLab From 16d6f0e35b8bd3a88e3a2e2e3ae8bf98be426f85 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 20 Mar 2015 17:11:11 -0700 Subject: [PATCH 28/46] Version 7.9.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 86cd47608be..84c5308f033 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.9.0.rc3 \ No newline at end of file +7.9.0 \ No newline at end of file -- GitLab From 6b3cff19e953d39f2d7bcdcb474424a72d276fb6 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 23 Mar 2015 08:23:19 +0100 Subject: [PATCH 29/46] Merge pull request #8995 from MichaelAlt/patch-1 Faulty LDAP DN name escaping removed --- lib/gitlab/ldap/person.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/gitlab/ldap/person.rb b/lib/gitlab/ldap/person.rb index 3c426179375..b81f3e8e8f5 100644 --- a/lib/gitlab/ldap/person.rb +++ b/lib/gitlab/ldap/person.rb @@ -14,7 +14,6 @@ module Gitlab end def self.find_by_dn(dn, adapter) - dn = Net::LDAP::Filter.escape(dn) adapter.user('dn', dn) end -- GitLab From 325cedebe321a75594db4a97826e3742e309b37d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 23 Mar 2015 02:33:45 +0000 Subject: [PATCH 30/46] Merge branch 'fix-broken-new-project-import' into 'master' Fix OAuth2 issue importing a new project from GitHub and GitLab It appears that the GitLab OAuth2 client options were converted to strings instead of symbols when merged with the default options (i.e. `{}.merge(github_options)`). As a result, the OAuth2 defaults were being used. For example, the OAuth2 client options would have a key with `authorize_url` and `:authorize_url`, but the former was never used. As a result, the OAuth2 client would always use the wrong URL to talk to GitHub. Note that this bug should also have affected GitLab, but not Bitbucket: The OAuth client is careful to convert all keys to symbols. Closes #1268 See merge request !425 --- CHANGELOG | 28 +++++++++++++++++++ lib/gitlab/bitbucket_import/client.rb | 4 +-- lib/gitlab/github_import/client.rb | 2 +- lib/gitlab/gitlab_import/client.rb | 2 +- .../gitlab/bitbucket_import/client_spec.rb | 17 +++++++++++ spec/lib/gitlab/github_import/client_spec.rb | 16 +++++++++++ spec/lib/gitlab/gitlab_import/client_spec.rb | 16 +++++++++++ 7 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 spec/lib/gitlab/bitbucket_import/client_spec.rb create mode 100644 spec/lib/gitlab/github_import/client_spec.rb create mode 100644 spec/lib/gitlab/gitlab_import/client_spec.rb diff --git a/CHANGELOG b/CHANGELOG index 543c382a8e7..ea325d4892a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,33 @@ Please view this file on the master branch, on stable branches it's out of date. +v 7.10.0 (unreleased) + - Fix "Import projects from" button to show the correct instructions (Stan Hu) + - Fix dots in Wiki slugs causing errors (Stan Hu) + - Fix OAuth2 issue importing a new project from GitHub and GitLab (Stan Hu) + - Update poltergeist to version 1.6.0 to support PhantomJS 2.0 (Zeger-Jan van de Weg) + - Fix cross references when usernames, milestones, or project names contain underscores (Stan Hu) + - Disable reference creation for comments surrounded by code/preformatted blocks (Stan Hu) + - enable line wrapping per default and remove the checkbox to toggle it (Hannes Rosenögger) + - extend the commit calendar to show the actual commits made on a date (Hannes Rosenögger) + - Fix a link in the patch update guide + - Add a service to support external wikis (Hannes Rosenögger) + - List new commits for newly pushed branch in activity view. + - Add sidetiq gem dependency to match EE + - Add changelog, license and contribution guide links to project sidebar. + - Improve diff UI + - Fix alignment of navbar toggle button (Cody Mize) + - Identical look of selectboxes in UI + - Move "Import existing repository by URL" option to button. + - Improve error message when save profile has error. + - Passing the name of pushed ref to CI service (requires GitLab CI 7.9+) + - Add location field to user profile + - Fix print view for markdown files and wiki pages + - Improve GitLab performance when working with git repositories + - Add tag message and last commit to tag hook (Kamil Trzciński) + - Restrict permissions on backup files + - Improve oauth accounts UI in profile page + - Add ability to unlink connected accounts + v 7.9.0 (unreleased) - Add HipChat integration documentation (Stan Hu) - Update documentation for object_kind field in Webhook push and tag push Webhooks (Stan Hu) diff --git a/lib/gitlab/bitbucket_import/client.rb b/lib/gitlab/bitbucket_import/client.rb index 1e4906c9e31..5b1952b9675 100644 --- a/lib/gitlab/bitbucket_import/client.rb +++ b/lib/gitlab/bitbucket_import/client.rb @@ -62,7 +62,7 @@ module Gitlab end def find_deploy_key(project_identifier, key) - JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/deploy-keys").body).find do |deploy_key| + JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/deploy-keys").body).find do |deploy_key| deploy_key["key"].chomp == key.chomp end end @@ -92,7 +92,7 @@ module Gitlab end def bitbucket_options - OmniAuth::Strategies::Bitbucket.default_options[:client_options].dup + OmniAuth::Strategies::Bitbucket.default_options[:client_options].symbolize_keys end end end diff --git a/lib/gitlab/github_import/client.rb b/lib/gitlab/github_import/client.rb index 7fe076b333b..270cbcd9ccd 100644 --- a/lib/gitlab/github_import/client.rb +++ b/lib/gitlab/github_import/client.rb @@ -46,7 +46,7 @@ module Gitlab end def github_options - OmniAuth::Strategies::GitHub.default_options[:client_options].dup + OmniAuth::Strategies::GitHub.default_options[:client_options].symbolize_keys end end end diff --git a/lib/gitlab/gitlab_import/client.rb b/lib/gitlab/gitlab_import/client.rb index 2236439c6ce..f48ede9d067 100644 --- a/lib/gitlab/gitlab_import/client.rb +++ b/lib/gitlab/gitlab_import/client.rb @@ -71,7 +71,7 @@ module Gitlab end def gitlab_options - OmniAuth::Strategies::GitLab.default_options[:client_options].dup + OmniAuth::Strategies::GitLab.default_options[:client_options].symbolize_keys end end end diff --git a/spec/lib/gitlab/bitbucket_import/client_spec.rb b/spec/lib/gitlab/bitbucket_import/client_spec.rb new file mode 100644 index 00000000000..dd450e9967b --- /dev/null +++ b/spec/lib/gitlab/bitbucket_import/client_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe Gitlab::BitbucketImport::Client do + let(:token) { '123456' } + let(:secret) { 'secret' } + let(:client) { Gitlab::BitbucketImport::Client.new(token, secret) } + + before do + Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "bitbucket") + end + + it 'all OAuth client options are symbols' do + client.consumer.options.keys.each do |key| + expect(key).to be_kind_of(Symbol) + end + end +end diff --git a/spec/lib/gitlab/github_import/client_spec.rb b/spec/lib/gitlab/github_import/client_spec.rb new file mode 100644 index 00000000000..26618120316 --- /dev/null +++ b/spec/lib/gitlab/github_import/client_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::Client do + let(:token) { '123456' } + let(:client) { Gitlab::GithubImport::Client.new(token) } + + before do + Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "github") + end + + it 'all OAuth2 client options are symbols' do + client.client.options.keys.each do |key| + expect(key).to be_kind_of(Symbol) + end + end +end diff --git a/spec/lib/gitlab/gitlab_import/client_spec.rb b/spec/lib/gitlab/gitlab_import/client_spec.rb new file mode 100644 index 00000000000..c511c515474 --- /dev/null +++ b/spec/lib/gitlab/gitlab_import/client_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe Gitlab::GitlabImport::Client do + let(:token) { '123456' } + let(:client) { Gitlab::GitlabImport::Client.new(token) } + + before do + Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "gitlab") + end + + it 'all OAuth2 client options are symbols' do + client.client.options.keys.each do |key| + expect(key).to be_kind_of(Symbol) + end + end +end -- GitLab From cd26d79ca4531a95eb165191ec84ef86914665f4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 22 Mar 2015 22:20:20 +0000 Subject: [PATCH 31/46] Merge branch 'fix-import-from-modal' into 'master' Fix "Import projects from" button to show the correct instructions Closes #1267 See merge request !422 Conflicts: app/views/projects/new.html.haml --- app/views/projects/new.html.haml | 2 +- features/dashboard/new_project.feature | 13 ++++++++++++ features/steps/dashboard/new_project.rb | 27 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 features/dashboard/new_project.feature create mode 100644 features/steps/dashboard/new_project.rb diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 7fc612c0c7d..dbceec3633c 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -111,6 +111,6 @@ $ -> $('.how_to_import_link').bind 'click', (e) -> e.preventDefault() - import_modal = $(this).parent().find(".modal").show() + import_modal = $(this).next(".modal").show() $('.modal-header .close').bind 'click', -> $(".modal").hide() diff --git a/features/dashboard/new_project.feature b/features/dashboard/new_project.feature new file mode 100644 index 00000000000..431dc4ccfcb --- /dev/null +++ b/features/dashboard/new_project.feature @@ -0,0 +1,13 @@ +@dashboard +Feature: New Project +Background: + Given I sign in as a user + And I own project "Shop" + And I visit dashboard page + + @javascript + Scenario: I should see New projects page + Given I click "New project" link + Then I see "New project" page + When I click on "Import project from GitHub" + Then I see instructions on how to import from GitHub diff --git a/features/steps/dashboard/new_project.rb b/features/steps/dashboard/new_project.rb new file mode 100644 index 00000000000..5e588ceb780 --- /dev/null +++ b/features/steps/dashboard/new_project.rb @@ -0,0 +1,27 @@ +class Spinach::Features::NewProject < Spinach::FeatureSteps + include SharedAuthentication + include SharedPaths + include SharedProject + + step 'I click "New project" link' do + click_link "New project" + end + + step 'I see "New project" page' do + page.should have_content("Project path") + end + + step 'I click on "Import project from GitHub"' do + first('.how_to_import_link').click + end + + step 'I see instructions on how to import from GitHub' do + github_modal = first('.modal-body') + github_modal.should be_visible + github_modal.should have_content "To enable importing projects from GitHub" + + all('.modal-body').each do |element| + element.should_not be_visible unless element == github_modal + end + end +end -- GitLab From 1b23122f999980f6725ad617cde44b582b663fdc Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 23 Mar 2015 14:58:15 +0000 Subject: [PATCH 32/46] Merge branch 'fix-admin-service-template-config' into 'master' Include missing events and fix save functionality in admin service template settings form ### What does this MR do? This MR includes missing settings left out in the Admin -> Service Templates page and fixes the inability to save certain settings. ### Are there points in the code the reviewer needs to double check? No. ### Why was this MR needed? Because the service template form was broken and untested. ### What are the relevant issue numbers / [Feature requests](http://feedback.gitlab.com/)? #1275 Before: ![Screen_Shot_2015-03-23_at_5.53.19_AM](https://gitlab.com/stanhu/gitlab-ce/uploads/e1bff75f30a3b6ecb174d3e25c722b7e/Screen_Shot_2015-03-23_at_5.53.19_AM.png) After: ![Screen_Shot_2015-03-23_at_5.53.13_AM](https://gitlab.com/stanhu/gitlab-ce/uploads/8fada00128a3d0951b3230fefa64be92/Screen_Shot_2015-03-23_at_5.53.13_AM.png) See merge request !427 --- CHANGELOG | 1 + app/controllers/admin/services_controller.rb | 4 ++- app/views/admin/services/_form.html.haml | 13 +++++++++ features/admin/settings.feature | 7 +++++ features/steps/admin/settings.rb | 29 ++++++++++++++++++++ 5 files changed, 53 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index ea325d4892a..62fbdd25c6f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.10.0 (unreleased) + - Include missing events and fix save functionality in admin service template settings form (Stan Hu) - Fix "Import projects from" button to show the correct instructions (Stan Hu) - Fix dots in Wiki slugs causing errors (Stan Hu) - Fix OAuth2 issue importing a new project from GitHub and GitLab (Stan Hu) diff --git a/app/controllers/admin/services_controller.rb b/app/controllers/admin/services_controller.rb index 44a3f1379d8..76a938c5fe4 100644 --- a/app/controllers/admin/services_controller.rb +++ b/app/controllers/admin/services_controller.rb @@ -46,7 +46,9 @@ class Admin::ServicesController < Admin::ApplicationController :user_key, :device, :priority, :sound, :bamboo_url, :username, :password, :build_key, :server, :teamcity_url, :build_type, :description, :issues_url, :new_issue_url, :restrict_to_branch, - :send_from_committer_email, :disable_diffs + :send_from_committer_email, :disable_diffs, + :push_events, :tag_push_events, :note_events, :issues_events, + :merge_requests_events ]) end end diff --git a/app/views/admin/services/_form.html.haml b/app/views/admin/services/_form.html.haml index a953833b37c..18b7e8ba270 100644 --- a/app/views/admin/services/_form.html.haml +++ b/app/views/admin/services/_form.html.haml @@ -14,6 +14,11 @@ = preserve do = markdown @service.help + .form-group + = f.label :active, "Active", class: "control-label" + .col-sm-10 + = f.check_box :active + - if @service.supported_events.length > 1 .form-group = f.label :url, "Trigger", class: 'control-label' @@ -34,6 +39,14 @@ %strong Tag push events %p.light This url will be triggered when a new tag is pushed to the repository + - if @service.supported_events.include?("note") + %div + = f.check_box :note_events, class: 'pull-left' + .prepend-left-20 + = f.label :note_events, class: 'list-label' do + %strong Comments + %p.light + This url will be triggered when someone adds a comment - if @service.supported_events.include?("issue") %div = f.check_box :issues_events, class: 'pull-left' diff --git a/features/admin/settings.feature b/features/admin/settings.feature index 8fdf0575c2c..52e47307b23 100644 --- a/features/admin/settings.feature +++ b/features/admin/settings.feature @@ -7,3 +7,10 @@ Feature: Admin Settings Scenario: Change application settings When I modify settings and save form Then I should see application settings saved + + Scenario: Change Slack Service Template settings + When I click on "Service Templates" + And I click on "Slack" service + Then I check all events and submit form + And I should see service template settings saved + And I should see all checkboxes checked diff --git a/features/steps/admin/settings.rb b/features/steps/admin/settings.rb index c2d0d2a3fa3..87d4e969ff5 100644 --- a/features/steps/admin/settings.rb +++ b/features/steps/admin/settings.rb @@ -15,4 +15,33 @@ class Spinach::Features::AdminSettings < Spinach::FeatureSteps current_application_settings.home_page_url.should == 'https://about.gitlab.com/' page.should have_content 'Application settings saved successfully' end + + step 'I click on "Service Templates"' do + click_link 'Service Templates' + end + + step 'I click on "Slack" service' do + click_link 'Slack' + end + + step 'I check all events and submit form' do + page.check('Active') + page.check('Push events') + page.check('Tag push events') + page.check('Comments') + page.check('Issues events') + page.check('Merge Request events') + fill_in 'Webhook', with: "http://localhost" + click_on 'Save' + end + + step 'I should see service template settings saved' do + page.should have_content 'Application settings saved successfully' + end + + step 'I should see all checkboxes checked' do + all('input[type=checkbox]').each do |checkbox| + checkbox.should be_checked + end + end end -- GitLab From 8a61111410d539a1c9aa1719af85da49be107da5 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 23 Mar 2015 17:37:17 +0100 Subject: [PATCH 33/46] Merge pull request #9001 from vichak/master Fix #8966 Remove Milestones/Labels from project navbar when Issues disabled --- app/helpers/projects_helper.rb | 4 ++++ app/views/layouts/nav/_project.html.haml | 22 ++++++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 2225b110651..dd0669209cf 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -146,6 +146,10 @@ module ProjectsHelper nav_tabs << feature if project.send :"#{feature}_enabled" end + if project.issues_enabled + nav_tabs << [:milestones, :labels] + end + nav_tabs.flatten end diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index d340ab1796a..c58161c3362 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -44,11 +44,12 @@ %span Graphs - = nav_link(controller: :milestones) do - = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do - %i.fa.fa-clock-o - %span - Milestones + - if project_nav_tab? :milestones + = nav_link(controller: :milestones) do + = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do + %i.fa.fa-clock-o + %span + Milestones - if project_nav_tab? :issues = nav_link(controller: :issues) do @@ -67,11 +68,12 @@ Merge Requests %span.count.merge_counter= @project.merge_requests.opened.count - = nav_link(controller: :labels) do - = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do - %i.fa.fa-tags - %span - Labels + - if project_nav_tab? :labels + = nav_link(controller: :labels) do + = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do + %i.fa.fa-tags + %span + Labels - if project_nav_tab? :wiki = nav_link(controller: :wikis) do -- GitLab From b6f1f5e3b4c4dd0ab87c04cb658545942684cdb8 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 23 Mar 2015 21:21:23 +0100 Subject: [PATCH 34/46] Revert "Update gemnasium-gitlab-service gem" This reverts commit af522ede14cad4605bc7f0137ddf6950974eccce. --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3fd051e29b5..c38daf648de 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -188,7 +188,7 @@ GEM dotenv (>= 0.7) thor (>= 0.13.6) formatador (0.2.4) - gemnasium-gitlab-service (0.2.5) + gemnasium-gitlab-service (0.2.4) rugged (~> 0.21) gemojione (2.0.0) json -- GitLab From b6a5a46163c12859c60be71753055d7b9845f9bc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 23 Mar 2015 16:47:16 +0000 Subject: [PATCH 35/46] Merge branch 'no-comment-bubble' into 'master' Don't show commit comment button when user is not signed in. Address private issue https://dev.gitlab.org/gitlab/gitlabhq/issues/2167. See merge request !429 --- CHANGELOG | 3 +++ app/views/projects/diffs/_text_file.html.haml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 62fbdd25c6f..08bc3e9d625 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -28,6 +28,9 @@ v 7.10.0 (unreleased) - Restrict permissions on backup files - Improve oauth accounts UI in profile page - Add ability to unlink connected accounts + - Replace commits calendar with faster contribution calendar that includes issues and merge requests + - Add inifinite scroll to user page activity + - Don't show commit comment button when user is not signed in. v 7.9.0 (unreleased) - Add HipChat integration documentation (Stan Hu) diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index b1c987563f1..e691db9c08e 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -16,7 +16,7 @@ - else %td.old_line = link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code - - if @comments_allowed + - if @comments_allowed && can?(current_user, :write_note, @project) = link_to_new_diff_note(line_code) %td.new_line{data: {linenumber: line.new_pos}} = link_to raw(type == "old" ? " " : line.new_pos) , "##{line_code}", id: line_code -- GitLab From c91162c53eae1849bfffb479fa76868f5d11d42b Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 24 Mar 2015 15:05:30 -0700 Subject: [PATCH 36/46] Update changelog. --- CHANGELOG | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 08bc3e9d625..b782ad4c42d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,38 +1,15 @@ Please view this file on the master branch, on stable branches it's out of date. -v 7.10.0 (unreleased) +v 7.9.1 - Include missing events and fix save functionality in admin service template settings form (Stan Hu) - Fix "Import projects from" button to show the correct instructions (Stan Hu) - - Fix dots in Wiki slugs causing errors (Stan Hu) - Fix OAuth2 issue importing a new project from GitHub and GitLab (Stan Hu) - - Update poltergeist to version 1.6.0 to support PhantomJS 2.0 (Zeger-Jan van de Weg) - - Fix cross references when usernames, milestones, or project names contain underscores (Stan Hu) - - Disable reference creation for comments surrounded by code/preformatted blocks (Stan Hu) - - enable line wrapping per default and remove the checkbox to toggle it (Hannes Rosenögger) - - extend the commit calendar to show the actual commits made on a date (Hannes Rosenögger) - - Fix a link in the patch update guide - - Add a service to support external wikis (Hannes Rosenögger) - - List new commits for newly pushed branch in activity view. - - Add sidetiq gem dependency to match EE - - Add changelog, license and contribution guide links to project sidebar. - - Improve diff UI - - Fix alignment of navbar toggle button (Cody Mize) - - Identical look of selectboxes in UI - - Move "Import existing repository by URL" option to button. - - Improve error message when save profile has error. - - Passing the name of pushed ref to CI service (requires GitLab CI 7.9+) - - Add location field to user profile - - Fix print view for markdown files and wiki pages - - Improve GitLab performance when working with git repositories - - Add tag message and last commit to tag hook (Kamil Trzciński) - - Restrict permissions on backup files - - Improve oauth accounts UI in profile page - - Add ability to unlink connected accounts - - Replace commits calendar with faster contribution calendar that includes issues and merge requests - - Add inifinite scroll to user page activity + - Fix for LDAP with commas in DN + - Fix missing events and in admin Slack service template settings form (Stan Hu) - Don't show commit comment button when user is not signed in. + - Downgrade gemnasium-gitlab-service gem -v 7.9.0 (unreleased) +v 7.9.0 - Add HipChat integration documentation (Stan Hu) - Update documentation for object_kind field in Webhook push and tag push Webhooks (Stan Hu) - Fix broken email images (Hannes Rosenögger) -- GitLab From b68f9beffe8afce738eda23b1e69250fe7cd3200 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 25 Mar 2015 01:02:34 +0000 Subject: [PATCH 37/46] Merge branch 'milestone_and_labels_links' into 'master' Milestones and labels can be used even when issues are disabled. When Issues are disabled for a project Milestones and Labels can still be used for Merge Requests. See merge request !1739 --- app/helpers/projects_helper.rb | 2 +- app/views/projects/milestones/show.html.haml | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index dd0669209cf..a256f3965a3 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -146,7 +146,7 @@ module ProjectsHelper nav_tabs << feature if project.send :"#{feature}_enabled" end - if project.issues_enabled + if project.issues_enabled || project.merge_requests_enabled nav_tabs << [:milestones, :labels] end diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 110d8967342..25cc0030965 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -60,11 +60,12 @@ Participants %span.badge= @users.count - .pull-right - = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { milestone_id: @milestone.id }), class: "btn btn-grouped", title: "New Issue" do - %i.fa.fa-plus - New Issue - = link_to 'Browse Issues', namespace_project_issues_path(@milestone.project.namespace, @milestone.project, milestone_id: @milestone.id), class: "btn edit-milestone-link btn-grouped" + - if @project.issues_enabled + .pull-right + = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { milestone_id: @milestone.id }), class: "btn btn-grouped", title: "New Issue" do + %i.fa.fa-plus + New Issue + = link_to 'Browse Issues', namespace_project_issues_path(@milestone.project.namespace, @milestone.project, milestone_id: @milestone.id), class: "btn edit-milestone-link btn-grouped" .tab-content .tab-pane.active#tab-issues -- GitLab From 6f6c5f18a010eb96f9e6ff98cf91e6c8a8fb6d8d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 25 Mar 2015 15:42:30 -0700 Subject: [PATCH 38/46] Version 7.9.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 84c5308f033..ac2f3747d99 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.9.0 \ No newline at end of file +7.9.1 \ No newline at end of file -- GitLab From 6e5310f0d1488c8a774b7daf2cd07c46ea5f178f Mon Sep 17 00:00:00 2001 From: King Jin Date: Sun, 5 Apr 2015 13:53:03 +0800 Subject: [PATCH 39/46] update gitlab config, use simplified chinese as default locale --- config/application.rb | 7 ++++++- config/environments/production.rb | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/config/application.rb b/config/application.rb index fa399533e52..aaaa429ab81 100644 --- a/config/application.rb +++ b/config/application.rb @@ -3,6 +3,8 @@ require File.expand_path('../boot', __FILE__) require 'rails/all' require 'devise' I18n.config.enforce_available_locales = false +I18n.default_locale = :zh +I18n.locale = :zh Bundler.require(:default, Rails.env) module Gitlab @@ -25,7 +27,10 @@ module Gitlab # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # config.i18n.default_locale = :de - config.i18n.enforce_available_locales = false + config.i18n.default_locale = :zh + #config.i18n.enforce_available_locales = false + config.i18n.enforce_available_locales = true + config.i18n.fallbacks = true # Configure the default encoding used in templates for Ruby 1.9. config.encoding = "utf-8" diff --git a/config/environments/production.rb b/config/environments/production.rb index 3316ece3873..a4591cb2995 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -62,6 +62,9 @@ Gitlab::Application.configure do # the I18n.default_locale when a translation can not be found) config.i18n.fallbacks = true + ## customization + config.i18n.available_locales = [:zh, :en] + # Send deprecation notices to registered listeners config.active_support.deprecation = :notify -- GitLab From 591b4f823fa305bf0b2b31d1fcb66275b22b1135 Mon Sep 17 00:00:00 2001 From: King Jin Date: Sun, 5 Apr 2015 13:55:47 +0800 Subject: [PATCH 40/46] add i18n scripts, generate i18n file and clean unwanted i18n file --- i18n-scripts/checkClean.bash | 10 ++++++++++ i18n-scripts/genGitTpl.bash | 3 +++ 2 files changed, 13 insertions(+) create mode 100644 i18n-scripts/checkClean.bash create mode 100644 i18n-scripts/genGitTpl.bash diff --git a/i18n-scripts/checkClean.bash b/i18n-scripts/checkClean.bash new file mode 100644 index 00000000000..be7ed4b5a21 --- /dev/null +++ b/i18n-scripts/checkClean.bash @@ -0,0 +1,10 @@ +#!/bin/bash +for i in `ls *\.zh\.*`; +do + #diff appearances_helper.* && rm -i appearances_helper.zh.rb + old=${i/.zh/} + echo " ############### "$old" #############" + diff "$old" "$i" >/dev/null && rm -i "$i" + echo + echo +done diff --git a/i18n-scripts/genGitTpl.bash b/i18n-scripts/genGitTpl.bash new file mode 100644 index 00000000000..9766fae2744 --- /dev/null +++ b/i18n-scripts/genGitTpl.bash @@ -0,0 +1,3 @@ +#!/bin/bash +for i in `ls *html.haml`;do echo $i;cp $i ${i/.html.haml/.zh.html.haml};done +vim -p *zh* \ No newline at end of file -- GitLab From 164cbf43f1c7da20d99a8d14faba3b04a2b62e3c Mon Sep 17 00:00:00 2001 From: King Jin Date: Sun, 5 Apr 2015 13:56:30 +0800 Subject: [PATCH 41/46] add config/locales i18n-zh translation --- config/locales/devise.zh.yml | 60 +++++++++ config/locales/doorkeeper.zh.yml | 73 +++++++++++ config/locales/zh.yml | 212 +++++++++++++++++++++++++++++++ 3 files changed, 345 insertions(+) create mode 100644 config/locales/devise.zh.yml create mode 100644 config/locales/doorkeeper.zh.yml create mode 100644 config/locales/zh.yml diff --git a/config/locales/devise.zh.yml b/config/locales/devise.zh.yml new file mode 100644 index 00000000000..1be6c488e2d --- /dev/null +++ b/config/locales/devise.zh.yml @@ -0,0 +1,60 @@ +# Additional translations at http://github.com/plataformatec/devise/wiki/I18n + +zh: + errors: + messages: + expired: "已经过期, 请获取一个新的" + not_found: "未找到" + already_confirmed: "已经确认, 请登录" + not_locked: "未被锁定" + not_saved: + one: "1处错误发生, %{resource}保存失败:" + other: "%{count} 处错误发生, %{resource}保存失败:" + + devise: + failure: + already_authenticated: '您已经登录.' + unauthenticated: '继续操作前请注册或者登录.' + unconfirmed: '继续操作前请先确认您的帐号.' + locked: '您的帐号已被锁定.' + not_found_in_database: '邮箱或密码错误' + invalid: '邮箱或密码错误.' + invalid_token: '无效的认证token.' + timeout: '您的会话已过期, 请重新登录后再继续.' + inactive: '您的帐号还未激活.' + sessions: + signed_in: '登录成功.' + signed_out: '注销成功.' + users_sessions: + user: + signed_in: '登录成功.' + passwords: + send_instructions: '几分钟后您将收到一封如何重置密码的说明.' + updated: '您的密码已修改成功. 您现在是已登录状态.' + updated_not_active: '您的密码已修改成功.' + send_paranoid_instructions: "如果您的邮箱存在于我们的数据库中,您将收到一封找回密码的邮件." + confirmations: + send_instructions: '几分钟后,您将收到确认帐号的电子邮件.' + send_paranoid_instructions: '如果您的邮箱存在于我们的数据库中,您将收到一封确认账号的邮件.' + confirmed: '您的帐号已经确认成功. 您现在是已登录状态.' + registrations: + signed_up: '欢迎您! 您已经成功注册帐号.' + updated: '您成功更新了您的帐号信息.' + destroyed: '再见! 您的帐号已成功取消. 我们希望很快可以再见到您.' + signed_up_but_unconfirmed: '带确认链接的消息已经发送到您的邮箱. 请打开链接激活您的帐号.' + signed_up_but_inactive: '您已经注册成功. 但是, 我们不能让您登录, 您的帐号还未激活.' + signed_up_but_locked: '您已经成功注册帐号. 但我们不能让您登录, 您的帐号已被锁定.' + unlocks: + send_instructions: '几分钟后您将收到一封如何解锁您帐号的说明邮件.' + unlocked: '您的帐号已经成功解锁. 您现在是已登录状态.' + send_paranoid_instructions: '如果您的帐号存在, 几分钟后您将收到一封如何解锁您帐号的说明邮件.' + omniauth_callbacks: + success: '成功地从 %{kind} 获得授权.' + failure: '因为 %{reason} , 所以您无法从%{kind}获得授权.' + mailer: + confirmation_instructions: + subject: '确认说明' + reset_password_instructions: + subject: '重置密码说明' + unlock_instructions: + subject: '解锁说明' diff --git a/config/locales/doorkeeper.zh.yml b/config/locales/doorkeeper.zh.yml new file mode 100644 index 00000000000..ee45fd81cf1 --- /dev/null +++ b/config/locales/doorkeeper.zh.yml @@ -0,0 +1,73 @@ +zh: + activerecord: + errors: + models: + application: + attributes: + redirect_uri: + fragment_present: '不能包含锚点.' + invalid_uri: '必须是有效的URI地址.' + relative_uri: '必须是绝对URI地址.' + mongoid: + errors: + models: + application: + attributes: + redirect_uri: + fragment_present: '不能包含锚点.' + invalid_uri: '必须是有效的URI地址.' + relative_uri: '必须是绝对URI地址.' + mongo_mapper: + errors: + models: + application: + attributes: + redirect_uri: + fragment_present: '不能包含锚点.' + invalid_uri: '必须是有效的URI地址.' + relative_uri: '必须是绝对URI地址.' + doorkeeper: + errors: + messages: + # Common error messages + invalid_request: '请求缺少必要参数, 如不支持的参数值或参数格式不正确.' + invalid_redirect_uri: '包含的重定向uri地址无效.' + unauthorized_client: '客户端未被授权使用此方式发起请求.' + access_denied: '资源所有者或认证服务器拒绝此请求.' + invalid_scope: '请求的范围无效、未被识别或格式有误.' + server_error: '认证服务器出现意外情况, 无法完成请求.' + temporarily_unavailable: '认证服务器因临时超负荷或正在维护中, 现在无法处理此请求.' + + #configuration error messages + credential_flow_not_configured: '资源所有者密码信息验证流程失败, 因为Doorkeeper.configure.resource_owner_from_credentials未配置.' + resource_owner_authenticator_not_configured: '因Doorkeeper.configure.resource_owner_authenticator未配置, 查找资源所有者失败.' + + # Access grant errors + unsupported_response_type: '认证服务器不支持此类型的返回.' + + # Access token errors + invalid_client: '客户端认证失败, 失败原因为客户端未被识别, 客户端未包含认证信息或不支持的认证方法.' + invalid_grant: '提供的认证授权无效, 已过期, 已被撤消, 与认证请求中使用的跳转地址不匹配或认证授权是授权给其它客户端的.' + unsupported_grant_type: '认证服务器不支持该认证授权类型.' + + # Password Access token errors + invalid_resource_owner: '提供的资源所有者身份信息无效或未找到资源所有者' + + invalid_token: + revoked: "访问Token已经被撤消" + expired: "访问Token已过期" + unknown: "访问Token无效" + scopes: + api: "访问您的API" + + flash: + applications: + create: + notice: '创建应用成功.' + destroy: + notice: '删除应用成功.' + update: + notice: '更新应用成功.' + authorized_applications: + destroy: + notice: '撤消应用授权成功.' diff --git a/config/locales/zh.yml b/config/locales/zh.yml new file mode 100644 index 00000000000..8fb05c30f7f --- /dev/null +++ b/config/locales/zh.yml @@ -0,0 +1,212 @@ +# Sample localization file for English. Add more files in this directory for other locales. +# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. + +zh: + hello: "Hello world" + errors: + messages: + wrong_size: "文件大小有误 (应为 %{file_size})" + size_too_small: "太小 (至少应为 %{file_size})" + size_too_big: "太大 (至多应为 %{file_size})" + date: + abbr_day_names: + - 周日 + - 周一 + - 周二 + - 周三 + - 周四 + - 周五 + - 周六 + abbr_month_names: + - + - 1月 + - 2月 + - 3月 + - 4月 + - 5月 + - 6月 + - 7月 + - 8月 + - 9月 + - 10月 + - 11月 + - 12月 + day_names: + - 星期日 + - 星期一 + - 星期二 + - 星期三 + - 星期四 + - 星期五 + - 星期六 + formats: + default: "%Y-%m-%d" + long: "%Y年%b%d日" + short: "%b%d日" + month_names: + - + - 一月 + - 二月 + - 三月 + - 四月 + - 五月 + - 六月 + - 七月 + - 八月 + - 九月 + - 十月 + - 十一月 + - 十二月 + order: + - :year + - :month + - :day + datetime: + distance_in_words: + about_x_hours: + one: 大约一小时 + other: 大约 %{count} 小时 + about_x_months: + one: 大约一个月 + other: 大约 %{count} 个月 + about_x_years: + one: 大约一年 + other: 大约 %{count} 年 + almost_x_years: + one: 接近一年 + other: 接近 %{count} 年 + half_a_minute: 半分钟 + less_than_x_minutes: + one: 不到一分钟 + other: 不到 %{count} 分钟 + less_than_x_seconds: + one: 不到一秒 + other: 不到 %{count} 秒 + over_x_years: + one: 一年多 + other: "%{count} 年多" + x_days: + one: 一天 + other: "%{count} 天" + x_minutes: + one: 一分钟 + other: "%{count} 分钟" + x_months: + one: 一个月 + other: "%{count} 个月" + x_seconds: + one: 一秒 + other: "%{count} 秒" + prompts: + day: 日 + hour: 时 + minute: 分 + month: 月 + second: 秒 + year: 年 + errors: + format: "%{attribute}%{message}" + messages: + accepted: 必须是可被接受的 + blank: 不能为空字符 + present: 必须是空白 + confirmation: 与确认值不匹配 + empty: 不能留空 + equal_to: 必须等于 %{count} + even: 必须为双数 + exclusion: 是保留关键字 + greater_than: 必须大于 %{count} + greater_than_or_equal_to: 必须大于或等于 %{count} + inclusion: 不包含于列表中 + invalid: 是无效的 + less_than: 必须小于 %{count} + less_than_or_equal_to: 必须小于或等于 %{count} + not_a_number: 不是数字 + not_an_integer: 必须是整数 + odd: 必须为单数 + record_invalid: '验证失败: %{errors}' + restrict_dependent_destroy: + one: 由于 %{record} 需要此记录,所以无法移除记录 + many: 由于 %{record} 需要此记录,所以无法移除记录 + taken: 已经被使用 + too_long: + one: 过长(最长为一个字符) + other: 过长(最长为 %{count} 个字符) + too_short: + one: 过短(最短为一个字符) + other: 过短(最短为 %{count} 个字符) + wrong_length: + one: 长度非法(必须为一个字符) + other: 长度非法(必须为 %{count} 个字符) + other_than: 长度非法(不可为 %{count} 个字符 + template: + body: 如下字段出现错误: + header: + one: 有 1 个错误发生导致「%{model}」无法被保存。 + other: 有 %{count} 个错误发生导致「%{model}」无法被保存。 + helpers: + select: + prompt: 请选择 + submit: + create: 新增%{model} + submit: 保存%{model} + update: 更新%{model} + number: + currency: + format: + delimiter: "," + format: "%u %n" + precision: 2 + separator: "." + significant: false + strip_insignificant_zeros: false + unit: CN¥ + format: + delimiter: "," + precision: 3 + separator: "." + significant: false + strip_insignificant_zeros: false + human: + decimal_units: + format: "%n %u" + units: + billion: 十亿 + million: 百万 + quadrillion: 千兆 + thousand: 千 + trillion: 兆 + unit: '' + format: + delimiter: '' + precision: 1 + significant: false + strip_insignificant_zeros: false + storage_units: + format: "%n %u" + units: + byte: + one: Byte + other: Bytes + gb: GB + kb: KB + mb: MB + tb: TB + percentage: + format: + delimiter: '' + precision: + format: + delimiter: '' + support: + array: + last_word_connector: ", 和 " + two_words_connector: " 和 " + words_connector: ", " + time: + am: 上午 + formats: + default: "%Y年%b%d日 %A %H:%M:%S %Z" + long: "%Y年%b%d日 %H:%M" + short: "%b%d日 %H:%M" + pm: 下午 -- GitLab From f4cdd3444a87725a40a4e6a19eb3f6090ab53b70 Mon Sep 17 00:00:00 2001 From: King Jin Date: Sun, 5 Apr 2015 14:11:37 +0800 Subject: [PATCH 42/46] add i18-zh translation of app dir --- .../application_settings_controller.zh.rb | 44 +++ .../admin/applications_controller.zh.rb | 52 +++ .../admin/broadcast_messages_controller.zh.rb | 39 ++ app/controllers/admin/groups_controller.zh.rb | 64 ++++ app/controllers/admin/hooks_controller.zh.rb | 44 +++ app/controllers/admin/keys_controller.zh.rb | 34 ++ .../admin/services_controller.zh.rb | 54 +++ app/controllers/admin/users_controller.zh.rb | 128 +++++++ app/controllers/application_controller.zh.rb | 332 ++++++++++++++++++ .../omniauth_callbacks_controller.zh.rb | 76 ++++ app/controllers/passwords_controller.zh.rb | 18 + app/controllers/profiles_controller.zh.rb | 74 ++++ app/controllers/projects_controller.zh.rb | 198 +++++++++++ app/helpers/appearances_helper.zh.rb | 21 ++ app/helpers/application_helper.zh.rb | 321 +++++++++++++++++ app/helpers/blob_helper.zh.rb | 64 ++++ app/helpers/commits_helper.zh.rb | 182 ++++++++++ app/helpers/events_helper.zh.rb | 199 +++++++++++ app/helpers/gitlab_markdown_helper.zh.rb | 272 ++++++++++++++ app/helpers/projects_helper.zh.rb | 282 +++++++++++++++ app/helpers/sorting_helper.zh.rb | 96 +++++ app/helpers/visibility_level_helper.zh.rb | 62 ++++ .../application_settings/_form.zh.html.haml | 64 ++++ .../application_settings/show.zh.html.haml | 3 + .../applications/_delete_form.zh.html.haml | 4 + .../admin/applications/_form.zh.html.haml | 23 ++ .../admin/applications/edit.zh.html.haml | 3 + .../admin/applications/index.zh.html.haml | 22 ++ app/views/admin/applications/new.zh.html.haml | 3 + .../admin/applications/show.zh.html.haml | 26 ++ .../admin/background_jobs/show.zh.html.haml | 44 +++ .../broadcast_messages/index.zh.html.haml | 61 ++++ app/views/admin/dashboard/index.zh.html.haml | 137 ++++++++ app/views/admin/groups/_form.zh.html.haml | 27 ++ app/views/admin/groups/index.zh.html.haml | 62 ++++ app/views/admin/groups/new.zh.html.haml | 3 + app/views/admin/groups/show.zh.html.haml | 86 +++++ app/views/admin/hooks/index.zh.html.haml | 36 ++ app/views/admin/logs/show.zh.html.haml | 25 ++ app/views/admin/projects/index.zh.html.haml | 81 +++++ app/views/admin/projects/show.zh.html.haml | 132 +++++++ app/views/admin/services/_form.zh.html.haml | 94 +++++ app/views/admin/services/index.zh.html.haml | 22 ++ app/views/admin/users/_form.zh.html.haml | 90 +++++ app/views/admin/users/edit.zh.html.haml | 7 + app/views/admin/users/index.zh.html.haml | 88 +++++ app/views/admin/users/new.zh.html.haml | 4 + app/views/admin/users/show.zh.html.haml | 227 ++++++++++++ app/views/dashboard/_projects.zh.html.haml | 10 + .../_zero_authorized_projects.zh.html.haml | 53 +++ app/views/dashboard/issues.zh.html.haml | 10 + .../dashboard/merge_requests.zh.html.haml | 10 + .../dashboard/milestones/index.zh.html.haml | 38 ++ .../dashboard/milestones/show.zh.html.haml | 81 +++++ .../dashboard/projects/starred.zh.html.haml | 23 ++ .../devise/confirmations/new.zh.html.haml | 14 + .../confirmation_instructions.zh.html.erb | 9 + .../reset_password_instructions.zh.html.erb | 8 + .../mailer/unlock_instructions.zh.html.erb | 7 + app/views/devise/passwords/edit.zh.html.haml | 19 + app/views/devise/passwords/new.zh.html.haml | 14 + .../devise/registrations/edit.zh.html.erb | 28 ++ .../devise/sessions/_new_base.zh.html.haml | 12 + .../devise/sessions/_new_ldap.zh.html.haml | 4 + app/views/devise/sessions/new.zh.html.haml | 18 + app/views/devise/shared/_links.zh.erb | 19 + .../devise/shared/_omniauth_box.zh.html.haml | 10 + .../devise/shared/_sign_in_link.zh.html.haml | 5 + .../devise/shared/_signin_box.zh.html.haml | 26 ++ .../devise/shared/_signup_box.zh.html.haml | 26 ++ app/views/devise/unlocks/new.zh.html.erb | 12 + .../applications/_delete_form.zh.html.haml | 4 + .../applications/_form.zh.html.haml | 23 ++ .../doorkeeper/applications/edit.zh.html.haml | 2 + .../applications/index.zh.html.haml | 16 + .../doorkeeper/applications/new.zh.html.haml | 2 + .../doorkeeper/applications/show.zh.html.haml | 26 ++ .../authorizations/error.zh.html.haml | 3 + .../authorizations/new.zh.html.haml | 28 ++ .../authorizations/show.zh.html.haml | 3 + .../_delete_form.zh.html.haml | 4 + .../index.zh.html.haml | 16 + app/views/errors/access_denied.zh.html.haml | 5 + app/views/errors/encoding.zh.html.haml | 4 + app/views/errors/git_not_found.zh.html.haml | 5 + app/views/errors/not_found.zh.html.haml | 4 + app/views/errors/omniauth_error.zh.html.haml | 12 + .../events/_event_last_push.zh.html.haml | 14 + .../event/_created_project.zh.html.haml | 27 ++ app/views/explore/groups/index.zh.html.haml | 50 +++ .../explore/projects/_filter.zh.html.haml | 67 ++++ .../explore/projects/_project.zh.html.haml | 24 ++ app/views/explore/projects/index.zh.html.haml | 11 + .../explore/projects/starred.zh.html.haml | 10 + .../explore/projects/trending.zh.html.haml | 11 + app/views/groups/_projects.zh.html.haml | 10 + app/views/groups/_settings_nav.zh.html.haml | 11 + app/views/groups/edit.zh.html.haml | 37 ++ .../group_members/_group_member.zh.html.haml | 37 ++ .../_new_group_member.zh.html.haml | 16 + .../groups/group_members/index.zh.html.haml | 44 +++ app/views/groups/issues.zh.html.haml | 14 + app/views/groups/merge_requests.zh.html.haml | 14 + .../groups/milestones/index.zh.html.haml | 46 +++ app/views/groups/milestones/show.zh.html.haml | 87 +++++ app/views/groups/new.zh.html.haml | 19 + app/views/groups/projects.zh.html.haml | 25 ++ app/views/help/_shortcuts.zh.html.haml | 209 +++++++++++ app/views/help/index.zh.html.haml | 50 +++ app/views/help/ui.zh.html.haml | 226 ++++++++++++ app/views/import/base/create.zh.js.haml | 25 ++ .../import/bitbucket/status.zh.html.haml | 46 +++ app/views/import/github/status.zh.html.haml | 46 +++ app/views/import/gitlab/status.zh.html.haml | 46 +++ .../import/gitorious/status.zh.html.haml | 46 +++ app/views/layouts/_broadcast.zh.html.haml | 4 + .../layouts/_collapse_button.zh.html.haml | 4 + app/views/layouts/_flash.zh.html.haml | 8 + .../layouts/_google_analytics.zh.html.haml | 10 + app/views/layouts/_head.zh.html.haml | 28 ++ app/views/layouts/_head_panel.zh.html.haml | 48 +++ .../layouts/_init_auto_complete.zh.html.haml | 3 + app/views/layouts/_page.zh.html.haml | 23 ++ app/views/layouts/_page_title.zh.html.haml | 2 + app/views/layouts/_piwik.zh.html.haml | 12 + .../layouts/_public_head_panel.zh.html.haml | 22 ++ app/views/layouts/_search.zh.html.haml | 28 ++ app/views/layouts/admin.zh.html.haml | 6 + app/views/layouts/application.zh.html.haml | 6 + app/views/layouts/devise.zh.html.haml | 35 ++ .../layouts/doorkeeper/admin.zh.html.haml | 22 ++ .../doorkeeper/application.zh.html.haml | 15 + app/views/layouts/errors.zh.html.haml | 9 + app/views/layouts/explore.zh.html.haml | 30 ++ app/views/layouts/group.zh.html.haml | 6 + app/views/layouts/nav/_admin.zh.html.haml | 60 ++++ app/views/layouts/nav/_dashboard.zh.html.haml | 38 ++ app/views/layouts/nav/_group.zh.html.haml | 42 +++ app/views/layouts/nav/_profile.zh.html.haml | 50 +++ app/views/layouts/nav/_project.zh.html.haml | 97 +++++ app/views/layouts/navless.zh.html.haml | 10 + app/views/layouts/notify.zh.html.haml | 43 +++ app/views/layouts/profile.zh.html.haml | 6 + .../layouts/project_settings.zh.html.haml | 8 + app/views/layouts/projects.zh.html.haml | 7 + app/views/layouts/public_group.zh.html.haml | 6 + .../layouts/public_projects.zh.html.haml | 6 + app/views/layouts/public_users.zh.html.haml | 6 + app/views/layouts/search.zh.html.haml | 10 + .../_reassigned_issuable_email.zh.html.haml | 10 + .../_reassigned_issuable_email.zh.text.erb | 6 + .../notify/closed_issue_email.zh.html.haml | 2 + .../notify/closed_issue_email.zh.text.haml | 3 + .../closed_merge_request_email.zh.html.haml | 2 + .../closed_merge_request_email.zh.text.haml | 8 + .../group_access_granted_email.zh.html.haml | 4 + .../group_access_granted_email.zh.text.erb | 4 + .../issue_status_changed_email.zh.html.haml | 2 + .../issue_status_changed_email.zh.text.erb | 4 + .../merge_request_status_email.zh.html.haml | 2 + .../merge_request_status_email.zh.text.haml | 8 + .../merged_merge_request_email.zh.html.haml | 2 + .../merged_merge_request_email.zh.text.haml | 8 + app/views/notify/new_email_email.zh.html.haml | 10 + app/views/notify/new_email_email.zh.text.erb | 7 + app/views/notify/new_issue_email.zh.html.haml | 6 + app/views/notify/new_issue_email.zh.text.erb | 5 + .../new_merge_request_email.zh.html.haml | 9 + .../new_merge_request_email.zh.text.erb | 8 + .../notify/new_ssh_key_email.zh.html.haml | 11 + .../notify/new_ssh_key_email.zh.text.erb | 7 + app/views/notify/new_user_email.zh.html.haml | 14 + app/views/notify/new_user_email.zh.text.erb | 8 + .../notify/note_commit_email.zh.text.erb | 9 + app/views/notify/note_issue_email.zh.text.erb | 9 + .../note_merge_request_email.zh.html.haml | 7 + .../note_merge_request_email.zh.text.erb | 9 + .../project_access_granted_email.zh.html.haml | 5 + .../project_access_granted_email.zh.text.erb | 4 + .../project_was_moved_email.zh.html.haml | 15 + .../project_was_moved_email.zh.text.erb | 10 + .../notify/repository_push_email.zh.html.haml | 66 ++++ .../notify/repository_push_email.zh.text.haml | 47 +++ app/views/profiles/accounts/show.zh.html.haml | 78 ++++ app/views/profiles/applications.zh.html.haml | 49 +++ app/views/profiles/design.zh.html.haml | 53 +++ app/views/profiles/emails/index.zh.html.haml | 37 ++ app/views/profiles/history.zh.html.haml | 10 + app/views/profiles/keys/_form.zh.html.haml | 21 ++ app/views/profiles/keys/_key.zh.html.haml | 12 + .../profiles/keys/_key_details.zh.html.haml | 22 ++ .../profiles/keys/_key_table.zh.html.haml | 19 + app/views/profiles/keys/index.zh.html.haml | 12 + app/views/profiles/keys/new.zh.html.haml | 16 + .../notifications/_settings.zh.html.haml | 17 + .../profiles/notifications/show.zh.html.haml | 78 ++++ .../profiles/notifications/update.zh.js.haml | 6 + .../profiles/passwords/edit.zh.html.haml | 38 ++ app/views/profiles/passwords/new.zh.html.haml | 26 ++ app/views/profiles/show.zh.html.haml | 103 ++++++ .../_bitbucket_import_modal.zh.html.haml | 13 + .../projects/_commit_button.zh.html.haml | 6 + app/views/projects/_dropdown.zh.html.haml | 33 ++ .../_github_import_modal.zh.html.haml | 13 + .../_gitlab_import_modal.zh.html.haml | 13 + app/views/projects/_home_panel.zh.html.haml | 44 +++ .../projects/_issuable_form.zh.html.haml | 86 +++++ app/views/projects/_md_preview.zh.html.haml | 13 + app/views/projects/_settings_nav.zh.html.haml | 31 ++ .../projects/_visibility_level.zh.html.haml | 27 ++ app/views/projects/_zen.zh.html.haml | 10 + app/views/projects/blame/show.zh.html.haml | 35 ++ app/views/projects/blob/_actions.zh.html.haml | 22 ++ .../projects/blob/_download.zh.html.haml | 7 + app/views/projects/blob/_remove.zh.html.haml | 22 ++ app/views/projects/blob/_text.zh.html.haml | 13 + app/views/projects/blob/preview.zh.html.haml | 25 ++ .../projects/branches/_branch.zh.html.haml | 29 ++ .../projects/branches/index.zh.html.haml | 31 ++ app/views/projects/branches/new.zh.html.haml | 28 ++ .../projects/commit/_commit_box.zh.html.haml | 52 +++ .../commits/_commit_list.zh.html.haml | 11 + app/views/projects/commits/_head.zh.html.haml | 15 + app/views/projects/commits/show.zh.html.haml | 23 ++ app/views/projects/compare/_form.zh.html.haml | 29 ++ app/views/projects/compare/index.zh.html.haml | 17 + app/views/projects/compare/show.zh.html.haml | 23 ++ .../deploy_keys/_deploy_key.zh.html.haml | 25 ++ .../projects/deploy_keys/_form.zh.html.haml | 24 ++ .../projects/deploy_keys/index.zh.html.haml | 30 ++ .../projects/deploy_keys/new.zh.html.haml | 4 + .../projects/deploy_keys/show.zh.html.haml | 13 + app/views/projects/diffs/_diffs.zh.html.haml | 21 ++ app/views/projects/diffs/_file.zh.html.haml | 49 +++ app/views/projects/diffs/_stats.zh.html.haml | 38 ++ .../projects/diffs/_text_file.zh.html.haml | 36 ++ .../projects/diffs/_warning.zh.html.haml | 19 + app/views/projects/edit.zh.html.haml | 209 +++++++++++ app/views/projects/empty.zh.html.haml | 49 +++ app/views/projects/forks/error.zh.html.haml | 20 ++ app/views/projects/forks/new.zh.html.haml | 39 ++ app/views/projects/graphs/_head.zh.html.haml | 5 + .../projects/graphs/commits.zh.html.haml | 83 +++++ app/views/projects/graphs/show.zh.html.haml | 37 ++ app/views/projects/hooks/index.zh.html.haml | 67 ++++ app/views/projects/imports/new.zh.html.haml | 22 ++ app/views/projects/imports/show.zh.html.haml | 9 + .../projects/issues/_discussion.zh.html.haml | 33 ++ app/views/projects/issues/_form.zh.html.haml | 14 + app/views/projects/issues/_issue.zh.html.haml | 51 +++ .../issues/_issue_context.zh.html.haml | 50 +++ .../projects/issues/_issues.zh.html.haml | 13 + app/views/projects/issues/index.zh.html.haml | 29 ++ app/views/projects/issues/show.zh.html.haml | 40 +++ app/views/projects/labels/_form.zh.html.haml | 33 ++ app/views/projects/labels/_label.zh.html.haml | 10 + app/views/projects/labels/edit.zh.html.haml | 8 + app/views/projects/labels/index.zh.html.haml | 15 + app/views/projects/labels/new.zh.html.haml | 6 + .../merge_requests/_discussion.zh.html.haml | 31 ++ .../merge_requests/_head.zh.html.haml | 5 + .../_merge_request.zh.html.haml | 47 +++ .../_merge_requests.zh.html.haml | 13 + .../merge_requests/_new_compare.zh.html.haml | 89 +++++ .../merge_requests/_new_submit.zh.html.haml | 124 +++++++ .../merge_requests/_show.zh.html.haml | 77 ++++ .../projects/merge_requests/edit.zh.html.haml | 4 + .../merge_requests/index.zh.html.haml | 11 + .../merge_requests/invalid.zh.html.haml | 23 ++ .../projects/milestones/_form.zh.html.haml | 54 +++ .../projects/milestones/_issues.zh.html.haml | 6 + .../milestones/_merge_requests.zh.html.haml | 6 + .../milestones/_milestone.zh.html.haml | 26 ++ .../projects/milestones/index.zh.html.haml | 17 + .../projects/milestones/show.zh.html.haml | 103 ++++++ app/views/projects/network/_head.zh.html.haml | 3 + app/views/projects/network/show.zh.html.haml | 26 ++ app/views/projects/new.zh.html.haml | 119 +++++++ app/views/projects/no_repo.zh.html.haml | 22 ++ .../projects/notes/_edit_form.zh.html.haml | 15 + app/views/projects/notes/_form.zh.html.haml | 24 ++ app/views/projects/notes/_note.zh.html.haml | 69 ++++ .../notes/discussions/_active.zh.html.haml | 21 ++ .../notes/discussions/_commit.zh.html.haml | 27 ++ .../notes/discussions/_outdated.zh.html.haml | 18 + .../_group_members.zh.html.haml | 16 + .../_new_project_member.zh.html.haml | 16 + .../_project_member.zh.html.haml | 35 ++ .../project_members/_team.zh.html.haml | 11 + .../project_members/import.zh.html.haml | 14 + .../project_members/index.zh.html.haml | 36 ++ .../_branches_list.zh.html.haml | 34 ++ .../protected_branches/index.zh.html.haml | 35 ++ .../_download_archive.zh.html.haml | 37 ++ .../projects/repositories/_feed.zh.html.haml | 18 + .../projects/services/_form.zh.html.haml | 105 ++++++ .../projects/services/index.zh.html.haml | 22 ++ app/views/projects/show.zh.html.haml | 89 +++++ .../projects/snippets/_snippet.zh.html.haml | 15 + app/views/projects/snippets/edit.zh.html.haml | 4 + .../projects/snippets/index.zh.html.haml | 15 + app/views/projects/snippets/new.zh.html.haml | 4 + app/views/projects/snippets/show.zh.html.haml | 37 ++ app/views/projects/tree/_spinner.zh.html.haml | 3 + app/views/projects/tree/_tree.zh.html.haml | 53 +++ app/views/projects/wikis/_form.zh.html.haml | 46 +++ .../projects/wikis/_main_links.zh.html.haml | 8 + app/views/projects/wikis/_nav.zh.html.haml | 19 + app/views/projects/wikis/_new.zh.html.haml | 14 + app/views/projects/wikis/edit.zh.html.haml | 13 + app/views/projects/wikis/empty.zh.html.haml | 4 + .../projects/wikis/git_access.zh.html.haml | 31 ++ app/views/projects/wikis/history.zh.html.haml | 30 ++ app/views/projects/wikis/pages.zh.html.haml | 12 + app/views/projects/wikis/show.zh.html.haml | 20 ++ app/views/search/_filter.zh.html.haml | 35 ++ app/views/search/_global_filter.zh.html.haml | 16 + app/views/search/_project_filter.zh.html.haml | 32 ++ app/views/search/_snippet_filter.zh.html.haml | 13 + app/views/search/results/_note.zh.html.haml | 26 ++ .../search/results/_snippet_blob.zh.html.haml | 59 ++++ .../results/_snippet_title.zh.html.haml | 23 ++ app/views/search/show.zh.html.haml | 22 ++ .../_choose_group_avatar_button.zh.html.haml | 7 + app/views/shared/_clone_panel.zh.html.haml | 23 ++ .../_commit_message_container.zh.html.haml | 14 + app/views/shared/_confirm_modal.zh.html.haml | 22 ++ app/views/shared/_event_filter.zh.html.haml | 19 + app/views/shared/_group_form.zh.html.haml | 29 ++ app/views/shared/_group_tips.zh.html.haml | 6 + .../shared/_issuable_filter.zh.html.haml | 119 +++++++ .../shared/_issuable_search_form.zh.html.haml | 9 + app/views/shared/_issues.zh.html.haml | 15 + app/views/shared/_merge_requests.zh.html.haml | 14 + .../shared/_milestones_filter.zh.html.haml | 14 + app/views/shared/_no_password.zh.html.haml | 8 + app/views/shared/_no_ssh.zh.html.haml | 8 + .../shared/_outdated_browser.zh.html.haml | 8 + app/views/shared/_projects_list.zh.html.haml | 17 + app/views/shared/_promo.zh.html.haml | 5 + app/views/shared/_sort_dropdown.zh.html.haml | 22 ++ app/views/snippets/_snippet.zh.html.haml | 23 ++ app/views/snippets/_snippets.zh.html.haml | 7 + .../snippets/current_user_index.zh.html.haml | 39 ++ app/views/snippets/edit.zh.html.haml | 4 + app/views/snippets/index.zh.html.haml | 17 + app/views/snippets/new.zh.html.haml | 4 + app/views/snippets/show.zh.html.haml | 43 +++ app/views/snippets/user_index.zh.html.haml | 13 + app/views/users/_profile.zh.html.haml | 27 ++ app/views/users/_projects.zh.html.haml | 13 + app/views/users/calendar.zh.html.haml | 8 + app/views/users/show.zh.html.haml | 45 +++ 353 files changed, 11925 insertions(+) create mode 100644 app/controllers/admin/application_settings_controller.zh.rb create mode 100644 app/controllers/admin/applications_controller.zh.rb create mode 100644 app/controllers/admin/broadcast_messages_controller.zh.rb create mode 100644 app/controllers/admin/groups_controller.zh.rb create mode 100644 app/controllers/admin/hooks_controller.zh.rb create mode 100644 app/controllers/admin/keys_controller.zh.rb create mode 100644 app/controllers/admin/services_controller.zh.rb create mode 100644 app/controllers/admin/users_controller.zh.rb create mode 100644 app/controllers/application_controller.zh.rb create mode 100644 app/controllers/omniauth_callbacks_controller.zh.rb create mode 100644 app/controllers/passwords_controller.zh.rb create mode 100644 app/controllers/profiles_controller.zh.rb create mode 100644 app/controllers/projects_controller.zh.rb create mode 100644 app/helpers/appearances_helper.zh.rb create mode 100644 app/helpers/application_helper.zh.rb create mode 100644 app/helpers/blob_helper.zh.rb create mode 100644 app/helpers/commits_helper.zh.rb create mode 100644 app/helpers/events_helper.zh.rb create mode 100644 app/helpers/gitlab_markdown_helper.zh.rb create mode 100644 app/helpers/projects_helper.zh.rb create mode 100644 app/helpers/sorting_helper.zh.rb create mode 100644 app/helpers/visibility_level_helper.zh.rb create mode 100644 app/views/admin/application_settings/_form.zh.html.haml create mode 100644 app/views/admin/application_settings/show.zh.html.haml create mode 100644 app/views/admin/applications/_delete_form.zh.html.haml create mode 100644 app/views/admin/applications/_form.zh.html.haml create mode 100644 app/views/admin/applications/edit.zh.html.haml create mode 100644 app/views/admin/applications/index.zh.html.haml create mode 100644 app/views/admin/applications/new.zh.html.haml create mode 100644 app/views/admin/applications/show.zh.html.haml create mode 100644 app/views/admin/background_jobs/show.zh.html.haml create mode 100644 app/views/admin/broadcast_messages/index.zh.html.haml create mode 100644 app/views/admin/dashboard/index.zh.html.haml create mode 100644 app/views/admin/groups/_form.zh.html.haml create mode 100644 app/views/admin/groups/index.zh.html.haml create mode 100644 app/views/admin/groups/new.zh.html.haml create mode 100644 app/views/admin/groups/show.zh.html.haml create mode 100644 app/views/admin/hooks/index.zh.html.haml create mode 100644 app/views/admin/logs/show.zh.html.haml create mode 100644 app/views/admin/projects/index.zh.html.haml create mode 100644 app/views/admin/projects/show.zh.html.haml create mode 100644 app/views/admin/services/_form.zh.html.haml create mode 100644 app/views/admin/services/index.zh.html.haml create mode 100644 app/views/admin/users/_form.zh.html.haml create mode 100644 app/views/admin/users/edit.zh.html.haml create mode 100644 app/views/admin/users/index.zh.html.haml create mode 100644 app/views/admin/users/new.zh.html.haml create mode 100644 app/views/admin/users/show.zh.html.haml create mode 100644 app/views/dashboard/_projects.zh.html.haml create mode 100644 app/views/dashboard/_zero_authorized_projects.zh.html.haml create mode 100644 app/views/dashboard/issues.zh.html.haml create mode 100644 app/views/dashboard/merge_requests.zh.html.haml create mode 100644 app/views/dashboard/milestones/index.zh.html.haml create mode 100644 app/views/dashboard/milestones/show.zh.html.haml create mode 100644 app/views/dashboard/projects/starred.zh.html.haml create mode 100644 app/views/devise/confirmations/new.zh.html.haml create mode 100644 app/views/devise/mailer/confirmation_instructions.zh.html.erb create mode 100644 app/views/devise/mailer/reset_password_instructions.zh.html.erb create mode 100644 app/views/devise/mailer/unlock_instructions.zh.html.erb create mode 100644 app/views/devise/passwords/edit.zh.html.haml create mode 100644 app/views/devise/passwords/new.zh.html.haml create mode 100644 app/views/devise/registrations/edit.zh.html.erb create mode 100644 app/views/devise/sessions/_new_base.zh.html.haml create mode 100644 app/views/devise/sessions/_new_ldap.zh.html.haml create mode 100644 app/views/devise/sessions/new.zh.html.haml create mode 100644 app/views/devise/shared/_links.zh.erb create mode 100644 app/views/devise/shared/_omniauth_box.zh.html.haml create mode 100644 app/views/devise/shared/_sign_in_link.zh.html.haml create mode 100644 app/views/devise/shared/_signin_box.zh.html.haml create mode 100644 app/views/devise/shared/_signup_box.zh.html.haml create mode 100644 app/views/devise/unlocks/new.zh.html.erb create mode 100644 app/views/doorkeeper/applications/_delete_form.zh.html.haml create mode 100644 app/views/doorkeeper/applications/_form.zh.html.haml create mode 100644 app/views/doorkeeper/applications/edit.zh.html.haml create mode 100644 app/views/doorkeeper/applications/index.zh.html.haml create mode 100644 app/views/doorkeeper/applications/new.zh.html.haml create mode 100644 app/views/doorkeeper/applications/show.zh.html.haml create mode 100644 app/views/doorkeeper/authorizations/error.zh.html.haml create mode 100644 app/views/doorkeeper/authorizations/new.zh.html.haml create mode 100644 app/views/doorkeeper/authorizations/show.zh.html.haml create mode 100644 app/views/doorkeeper/authorized_applications/_delete_form.zh.html.haml create mode 100644 app/views/doorkeeper/authorized_applications/index.zh.html.haml create mode 100644 app/views/errors/access_denied.zh.html.haml create mode 100644 app/views/errors/encoding.zh.html.haml create mode 100644 app/views/errors/git_not_found.zh.html.haml create mode 100644 app/views/errors/not_found.zh.html.haml create mode 100644 app/views/errors/omniauth_error.zh.html.haml create mode 100644 app/views/events/_event_last_push.zh.html.haml create mode 100644 app/views/events/event/_created_project.zh.html.haml create mode 100644 app/views/explore/groups/index.zh.html.haml create mode 100644 app/views/explore/projects/_filter.zh.html.haml create mode 100644 app/views/explore/projects/_project.zh.html.haml create mode 100644 app/views/explore/projects/index.zh.html.haml create mode 100644 app/views/explore/projects/starred.zh.html.haml create mode 100644 app/views/explore/projects/trending.zh.html.haml create mode 100644 app/views/groups/_projects.zh.html.haml create mode 100644 app/views/groups/_settings_nav.zh.html.haml create mode 100644 app/views/groups/edit.zh.html.haml create mode 100644 app/views/groups/group_members/_group_member.zh.html.haml create mode 100644 app/views/groups/group_members/_new_group_member.zh.html.haml create mode 100644 app/views/groups/group_members/index.zh.html.haml create mode 100644 app/views/groups/issues.zh.html.haml create mode 100644 app/views/groups/merge_requests.zh.html.haml create mode 100644 app/views/groups/milestones/index.zh.html.haml create mode 100644 app/views/groups/milestones/show.zh.html.haml create mode 100644 app/views/groups/new.zh.html.haml create mode 100644 app/views/groups/projects.zh.html.haml create mode 100644 app/views/help/_shortcuts.zh.html.haml create mode 100644 app/views/help/index.zh.html.haml create mode 100644 app/views/help/ui.zh.html.haml create mode 100644 app/views/import/base/create.zh.js.haml create mode 100644 app/views/import/bitbucket/status.zh.html.haml create mode 100644 app/views/import/github/status.zh.html.haml create mode 100644 app/views/import/gitlab/status.zh.html.haml create mode 100644 app/views/import/gitorious/status.zh.html.haml create mode 100644 app/views/layouts/_broadcast.zh.html.haml create mode 100644 app/views/layouts/_collapse_button.zh.html.haml create mode 100644 app/views/layouts/_flash.zh.html.haml create mode 100644 app/views/layouts/_google_analytics.zh.html.haml create mode 100644 app/views/layouts/_head.zh.html.haml create mode 100644 app/views/layouts/_head_panel.zh.html.haml create mode 100644 app/views/layouts/_init_auto_complete.zh.html.haml create mode 100644 app/views/layouts/_page.zh.html.haml create mode 100644 app/views/layouts/_page_title.zh.html.haml create mode 100644 app/views/layouts/_piwik.zh.html.haml create mode 100644 app/views/layouts/_public_head_panel.zh.html.haml create mode 100644 app/views/layouts/_search.zh.html.haml create mode 100644 app/views/layouts/admin.zh.html.haml create mode 100644 app/views/layouts/application.zh.html.haml create mode 100644 app/views/layouts/devise.zh.html.haml create mode 100644 app/views/layouts/doorkeeper/admin.zh.html.haml create mode 100644 app/views/layouts/doorkeeper/application.zh.html.haml create mode 100644 app/views/layouts/errors.zh.html.haml create mode 100644 app/views/layouts/explore.zh.html.haml create mode 100644 app/views/layouts/group.zh.html.haml create mode 100644 app/views/layouts/nav/_admin.zh.html.haml create mode 100644 app/views/layouts/nav/_dashboard.zh.html.haml create mode 100644 app/views/layouts/nav/_group.zh.html.haml create mode 100644 app/views/layouts/nav/_profile.zh.html.haml create mode 100644 app/views/layouts/nav/_project.zh.html.haml create mode 100644 app/views/layouts/navless.zh.html.haml create mode 100644 app/views/layouts/notify.zh.html.haml create mode 100644 app/views/layouts/profile.zh.html.haml create mode 100644 app/views/layouts/project_settings.zh.html.haml create mode 100644 app/views/layouts/projects.zh.html.haml create mode 100644 app/views/layouts/public_group.zh.html.haml create mode 100644 app/views/layouts/public_projects.zh.html.haml create mode 100644 app/views/layouts/public_users.zh.html.haml create mode 100644 app/views/layouts/search.zh.html.haml create mode 100644 app/views/notify/_reassigned_issuable_email.zh.html.haml create mode 100644 app/views/notify/_reassigned_issuable_email.zh.text.erb create mode 100644 app/views/notify/closed_issue_email.zh.html.haml create mode 100644 app/views/notify/closed_issue_email.zh.text.haml create mode 100644 app/views/notify/closed_merge_request_email.zh.html.haml create mode 100644 app/views/notify/closed_merge_request_email.zh.text.haml create mode 100644 app/views/notify/group_access_granted_email.zh.html.haml create mode 100644 app/views/notify/group_access_granted_email.zh.text.erb create mode 100644 app/views/notify/issue_status_changed_email.zh.html.haml create mode 100644 app/views/notify/issue_status_changed_email.zh.text.erb create mode 100644 app/views/notify/merge_request_status_email.zh.html.haml create mode 100644 app/views/notify/merge_request_status_email.zh.text.haml create mode 100644 app/views/notify/merged_merge_request_email.zh.html.haml create mode 100644 app/views/notify/merged_merge_request_email.zh.text.haml create mode 100644 app/views/notify/new_email_email.zh.html.haml create mode 100644 app/views/notify/new_email_email.zh.text.erb create mode 100644 app/views/notify/new_issue_email.zh.html.haml create mode 100644 app/views/notify/new_issue_email.zh.text.erb create mode 100644 app/views/notify/new_merge_request_email.zh.html.haml create mode 100644 app/views/notify/new_merge_request_email.zh.text.erb create mode 100644 app/views/notify/new_ssh_key_email.zh.html.haml create mode 100644 app/views/notify/new_ssh_key_email.zh.text.erb create mode 100644 app/views/notify/new_user_email.zh.html.haml create mode 100644 app/views/notify/new_user_email.zh.text.erb create mode 100644 app/views/notify/note_commit_email.zh.text.erb create mode 100644 app/views/notify/note_issue_email.zh.text.erb create mode 100644 app/views/notify/note_merge_request_email.zh.html.haml create mode 100644 app/views/notify/note_merge_request_email.zh.text.erb create mode 100644 app/views/notify/project_access_granted_email.zh.html.haml create mode 100644 app/views/notify/project_access_granted_email.zh.text.erb create mode 100644 app/views/notify/project_was_moved_email.zh.html.haml create mode 100644 app/views/notify/project_was_moved_email.zh.text.erb create mode 100644 app/views/notify/repository_push_email.zh.html.haml create mode 100644 app/views/notify/repository_push_email.zh.text.haml create mode 100644 app/views/profiles/accounts/show.zh.html.haml create mode 100644 app/views/profiles/applications.zh.html.haml create mode 100644 app/views/profiles/design.zh.html.haml create mode 100644 app/views/profiles/emails/index.zh.html.haml create mode 100644 app/views/profiles/history.zh.html.haml create mode 100644 app/views/profiles/keys/_form.zh.html.haml create mode 100644 app/views/profiles/keys/_key.zh.html.haml create mode 100644 app/views/profiles/keys/_key_details.zh.html.haml create mode 100644 app/views/profiles/keys/_key_table.zh.html.haml create mode 100644 app/views/profiles/keys/index.zh.html.haml create mode 100644 app/views/profiles/keys/new.zh.html.haml create mode 100644 app/views/profiles/notifications/_settings.zh.html.haml create mode 100644 app/views/profiles/notifications/show.zh.html.haml create mode 100644 app/views/profiles/notifications/update.zh.js.haml create mode 100644 app/views/profiles/passwords/edit.zh.html.haml create mode 100644 app/views/profiles/passwords/new.zh.html.haml create mode 100644 app/views/profiles/show.zh.html.haml create mode 100644 app/views/projects/_bitbucket_import_modal.zh.html.haml create mode 100644 app/views/projects/_commit_button.zh.html.haml create mode 100644 app/views/projects/_dropdown.zh.html.haml create mode 100644 app/views/projects/_github_import_modal.zh.html.haml create mode 100644 app/views/projects/_gitlab_import_modal.zh.html.haml create mode 100644 app/views/projects/_home_panel.zh.html.haml create mode 100644 app/views/projects/_issuable_form.zh.html.haml create mode 100644 app/views/projects/_md_preview.zh.html.haml create mode 100644 app/views/projects/_settings_nav.zh.html.haml create mode 100644 app/views/projects/_visibility_level.zh.html.haml create mode 100644 app/views/projects/_zen.zh.html.haml create mode 100644 app/views/projects/blame/show.zh.html.haml create mode 100644 app/views/projects/blob/_actions.zh.html.haml create mode 100644 app/views/projects/blob/_download.zh.html.haml create mode 100644 app/views/projects/blob/_remove.zh.html.haml create mode 100644 app/views/projects/blob/_text.zh.html.haml create mode 100644 app/views/projects/blob/preview.zh.html.haml create mode 100644 app/views/projects/branches/_branch.zh.html.haml create mode 100644 app/views/projects/branches/index.zh.html.haml create mode 100644 app/views/projects/branches/new.zh.html.haml create mode 100644 app/views/projects/commit/_commit_box.zh.html.haml create mode 100644 app/views/projects/commits/_commit_list.zh.html.haml create mode 100644 app/views/projects/commits/_head.zh.html.haml create mode 100644 app/views/projects/commits/show.zh.html.haml create mode 100644 app/views/projects/compare/_form.zh.html.haml create mode 100644 app/views/projects/compare/index.zh.html.haml create mode 100644 app/views/projects/compare/show.zh.html.haml create mode 100644 app/views/projects/deploy_keys/_deploy_key.zh.html.haml create mode 100644 app/views/projects/deploy_keys/_form.zh.html.haml create mode 100644 app/views/projects/deploy_keys/index.zh.html.haml create mode 100644 app/views/projects/deploy_keys/new.zh.html.haml create mode 100644 app/views/projects/deploy_keys/show.zh.html.haml create mode 100644 app/views/projects/diffs/_diffs.zh.html.haml create mode 100644 app/views/projects/diffs/_file.zh.html.haml create mode 100644 app/views/projects/diffs/_stats.zh.html.haml create mode 100644 app/views/projects/diffs/_text_file.zh.html.haml create mode 100644 app/views/projects/diffs/_warning.zh.html.haml create mode 100644 app/views/projects/edit.zh.html.haml create mode 100644 app/views/projects/empty.zh.html.haml create mode 100644 app/views/projects/forks/error.zh.html.haml create mode 100644 app/views/projects/forks/new.zh.html.haml create mode 100644 app/views/projects/graphs/_head.zh.html.haml create mode 100644 app/views/projects/graphs/commits.zh.html.haml create mode 100644 app/views/projects/graphs/show.zh.html.haml create mode 100644 app/views/projects/hooks/index.zh.html.haml create mode 100644 app/views/projects/imports/new.zh.html.haml create mode 100644 app/views/projects/imports/show.zh.html.haml create mode 100644 app/views/projects/issues/_discussion.zh.html.haml create mode 100644 app/views/projects/issues/_form.zh.html.haml create mode 100644 app/views/projects/issues/_issue.zh.html.haml create mode 100644 app/views/projects/issues/_issue_context.zh.html.haml create mode 100644 app/views/projects/issues/_issues.zh.html.haml create mode 100644 app/views/projects/issues/index.zh.html.haml create mode 100644 app/views/projects/issues/show.zh.html.haml create mode 100644 app/views/projects/labels/_form.zh.html.haml create mode 100644 app/views/projects/labels/_label.zh.html.haml create mode 100644 app/views/projects/labels/edit.zh.html.haml create mode 100644 app/views/projects/labels/index.zh.html.haml create mode 100644 app/views/projects/labels/new.zh.html.haml create mode 100644 app/views/projects/merge_requests/_discussion.zh.html.haml create mode 100644 app/views/projects/merge_requests/_head.zh.html.haml create mode 100644 app/views/projects/merge_requests/_merge_request.zh.html.haml create mode 100644 app/views/projects/merge_requests/_merge_requests.zh.html.haml create mode 100644 app/views/projects/merge_requests/_new_compare.zh.html.haml create mode 100644 app/views/projects/merge_requests/_new_submit.zh.html.haml create mode 100644 app/views/projects/merge_requests/_show.zh.html.haml create mode 100644 app/views/projects/merge_requests/edit.zh.html.haml create mode 100644 app/views/projects/merge_requests/index.zh.html.haml create mode 100644 app/views/projects/merge_requests/invalid.zh.html.haml create mode 100644 app/views/projects/milestones/_form.zh.html.haml create mode 100644 app/views/projects/milestones/_issues.zh.html.haml create mode 100644 app/views/projects/milestones/_merge_requests.zh.html.haml create mode 100644 app/views/projects/milestones/_milestone.zh.html.haml create mode 100644 app/views/projects/milestones/index.zh.html.haml create mode 100644 app/views/projects/milestones/show.zh.html.haml create mode 100644 app/views/projects/network/_head.zh.html.haml create mode 100644 app/views/projects/network/show.zh.html.haml create mode 100644 app/views/projects/new.zh.html.haml create mode 100644 app/views/projects/no_repo.zh.html.haml create mode 100644 app/views/projects/notes/_edit_form.zh.html.haml create mode 100644 app/views/projects/notes/_form.zh.html.haml create mode 100644 app/views/projects/notes/_note.zh.html.haml create mode 100644 app/views/projects/notes/discussions/_active.zh.html.haml create mode 100644 app/views/projects/notes/discussions/_commit.zh.html.haml create mode 100644 app/views/projects/notes/discussions/_outdated.zh.html.haml create mode 100644 app/views/projects/project_members/_group_members.zh.html.haml create mode 100644 app/views/projects/project_members/_new_project_member.zh.html.haml create mode 100644 app/views/projects/project_members/_project_member.zh.html.haml create mode 100644 app/views/projects/project_members/_team.zh.html.haml create mode 100644 app/views/projects/project_members/import.zh.html.haml create mode 100644 app/views/projects/project_members/index.zh.html.haml create mode 100644 app/views/projects/protected_branches/_branches_list.zh.html.haml create mode 100644 app/views/projects/protected_branches/index.zh.html.haml create mode 100644 app/views/projects/repositories/_download_archive.zh.html.haml create mode 100644 app/views/projects/repositories/_feed.zh.html.haml create mode 100644 app/views/projects/services/_form.zh.html.haml create mode 100644 app/views/projects/services/index.zh.html.haml create mode 100644 app/views/projects/show.zh.html.haml create mode 100644 app/views/projects/snippets/_snippet.zh.html.haml create mode 100644 app/views/projects/snippets/edit.zh.html.haml create mode 100644 app/views/projects/snippets/index.zh.html.haml create mode 100644 app/views/projects/snippets/new.zh.html.haml create mode 100644 app/views/projects/snippets/show.zh.html.haml create mode 100644 app/views/projects/tree/_spinner.zh.html.haml create mode 100644 app/views/projects/tree/_tree.zh.html.haml create mode 100644 app/views/projects/wikis/_form.zh.html.haml create mode 100644 app/views/projects/wikis/_main_links.zh.html.haml create mode 100644 app/views/projects/wikis/_nav.zh.html.haml create mode 100644 app/views/projects/wikis/_new.zh.html.haml create mode 100644 app/views/projects/wikis/edit.zh.html.haml create mode 100644 app/views/projects/wikis/empty.zh.html.haml create mode 100644 app/views/projects/wikis/git_access.zh.html.haml create mode 100644 app/views/projects/wikis/history.zh.html.haml create mode 100644 app/views/projects/wikis/pages.zh.html.haml create mode 100644 app/views/projects/wikis/show.zh.html.haml create mode 100644 app/views/search/_filter.zh.html.haml create mode 100644 app/views/search/_global_filter.zh.html.haml create mode 100644 app/views/search/_project_filter.zh.html.haml create mode 100644 app/views/search/_snippet_filter.zh.html.haml create mode 100644 app/views/search/results/_note.zh.html.haml create mode 100644 app/views/search/results/_snippet_blob.zh.html.haml create mode 100644 app/views/search/results/_snippet_title.zh.html.haml create mode 100644 app/views/search/show.zh.html.haml create mode 100644 app/views/shared/_choose_group_avatar_button.zh.html.haml create mode 100644 app/views/shared/_clone_panel.zh.html.haml create mode 100644 app/views/shared/_commit_message_container.zh.html.haml create mode 100644 app/views/shared/_confirm_modal.zh.html.haml create mode 100644 app/views/shared/_event_filter.zh.html.haml create mode 100644 app/views/shared/_group_form.zh.html.haml create mode 100644 app/views/shared/_group_tips.zh.html.haml create mode 100644 app/views/shared/_issuable_filter.zh.html.haml create mode 100644 app/views/shared/_issuable_search_form.zh.html.haml create mode 100644 app/views/shared/_issues.zh.html.haml create mode 100644 app/views/shared/_merge_requests.zh.html.haml create mode 100644 app/views/shared/_milestones_filter.zh.html.haml create mode 100644 app/views/shared/_no_password.zh.html.haml create mode 100644 app/views/shared/_no_ssh.zh.html.haml create mode 100644 app/views/shared/_outdated_browser.zh.html.haml create mode 100644 app/views/shared/_projects_list.zh.html.haml create mode 100644 app/views/shared/_promo.zh.html.haml create mode 100644 app/views/shared/_sort_dropdown.zh.html.haml create mode 100644 app/views/snippets/_snippet.zh.html.haml create mode 100644 app/views/snippets/_snippets.zh.html.haml create mode 100644 app/views/snippets/current_user_index.zh.html.haml create mode 100644 app/views/snippets/edit.zh.html.haml create mode 100644 app/views/snippets/index.zh.html.haml create mode 100644 app/views/snippets/new.zh.html.haml create mode 100644 app/views/snippets/show.zh.html.haml create mode 100644 app/views/snippets/user_index.zh.html.haml create mode 100644 app/views/users/_profile.zh.html.haml create mode 100644 app/views/users/_projects.zh.html.haml create mode 100644 app/views/users/calendar.zh.html.haml create mode 100644 app/views/users/show.zh.html.haml diff --git a/app/controllers/admin/application_settings_controller.zh.rb b/app/controllers/admin/application_settings_controller.zh.rb new file mode 100644 index 00000000000..19106637212 --- /dev/null +++ b/app/controllers/admin/application_settings_controller.zh.rb @@ -0,0 +1,44 @@ +class Admin::ApplicationSettingsController < Admin::ApplicationController + before_filter :set_application_setting + + def show + end + + def update + if @application_setting.update_attributes(application_setting_params) + redirect_to admin_application_settings_path, + notice: '成功保存应用设置' + else + render :show + end + end + + private + + def set_application_setting + @application_setting = ApplicationSetting.current + end + + def application_setting_params + restricted_levels = params[:application_setting][:restricted_visibility_levels] + if restricted_levels.nil? + params[:application_setting][:restricted_visibility_levels] = [] + else + restricted_levels.map! do |level| + level.to_i + end + end + + params.require(:application_setting).permit( + :default_projects_limit, + :default_branch_protection, + :signup_enabled, + :signin_enabled, + :gravatar_enabled, + :twitter_sharing_enabled, + :sign_in_text, + :home_page_url, + restricted_visibility_levels: [] + ) + end +end diff --git a/app/controllers/admin/applications_controller.zh.rb b/app/controllers/admin/applications_controller.zh.rb new file mode 100644 index 00000000000..d2b2a3db335 --- /dev/null +++ b/app/controllers/admin/applications_controller.zh.rb @@ -0,0 +1,52 @@ +class Admin::ApplicationsController < Admin::ApplicationController + before_action :set_application, only: [:show, :edit, :update, :destroy] + + def index + @applications = Doorkeeper::Application.where("owner_id IS NULL") + end + + def show + end + + def new + @application = Doorkeeper::Application.new + end + + def edit + end + + def create + @application = Doorkeeper::Application.new(application_params) + + if @application.save + flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create]) + redirect_to admin_application_url(@application) + else + render :new + end + end + + def update + if @application.update(application_params) + redirect_to admin_application_path(@application), notice: '成功更新应用.' + else + render :edit + end + end + + def destroy + @application.destroy + redirect_to admin_applications_url, notice: '成功删除应用.' + end + + private + + def set_application + @application = Doorkeeper::Application.where("owner_id IS NULL").find(params[:id]) + end + + # Only allow a trusted parameter "white list" through. + def application_params + params[:doorkeeper_application].permit(:name, :redirect_uri) + end +end diff --git a/app/controllers/admin/broadcast_messages_controller.zh.rb b/app/controllers/admin/broadcast_messages_controller.zh.rb new file mode 100644 index 00000000000..7145422645a --- /dev/null +++ b/app/controllers/admin/broadcast_messages_controller.zh.rb @@ -0,0 +1,39 @@ +class Admin::BroadcastMessagesController < Admin::ApplicationController + before_filter :broadcast_messages + + def index + @broadcast_message = BroadcastMessage.new + end + + def create + @broadcast_message = BroadcastMessage.new(broadcast_message_params) + + if @broadcast_message.save + redirect_to admin_broadcast_messages_path, notice: '成功创建广播消息.' + else + render :index + end + end + + def destroy + BroadcastMessage.find(params[:id]).destroy + + respond_to do |format| + format.html { redirect_to :back } + format.js { render nothing: true } + end + end + + protected + + def broadcast_messages + @broadcast_messages ||= BroadcastMessage.order("starts_at DESC").page(params[:page]) + end + + def broadcast_message_params + params.require(:broadcast_message).permit( + :alert_type, :color, :ends_at, :font, + :message, :starts_at + ) + end +end diff --git a/app/controllers/admin/groups_controller.zh.rb b/app/controllers/admin/groups_controller.zh.rb new file mode 100644 index 00000000000..0a0261461af --- /dev/null +++ b/app/controllers/admin/groups_controller.zh.rb @@ -0,0 +1,64 @@ +class Admin::GroupsController < Admin::ApplicationController + before_filter :group, only: [:edit, :show, :update, :destroy, :project_update, :members_update] + + def index + @groups = Group.all + @groups = @groups.sort(@sort = params[:sort]) + @groups = @groups.search(params[:name]) if params[:name].present? + @groups = @groups.page(params[:page]).per(PER_PAGE) + end + + def show + @members = @group.members.order("access_level DESC").page(params[:members_page]).per(PER_PAGE) + @projects = @group.projects.page(params[:projects_page]).per(PER_PAGE) + end + + def new + @group = Group.new + end + + def edit + end + + def create + @group = Group.new(group_params) + @group.name = @group.path.dup unless @group.name + + if @group.save + @group.add_owner(current_user) + redirect_to [:admin, @group], notice: '成功创建组.' + else + render "new" + end + end + + def update + if @group.update_attributes(group_params) + redirect_to [:admin, @group], notice: 'Group was successfully updated.' + else + render "edit" + end + end + + def members_update + @group.add_users(params[:user_ids].split(','), params[:access_level]) + + redirect_to [:admin, @group], notice: 'Users were successfully added.' + end + + def destroy + @group.destroy + + redirect_to admin_groups_path, notice: 'Group was successfully deleted.' + end + + private + + def group + @group = Group.find_by(path: params[:id]) + end + + def group_params + params.require(:group).permit(:name, :description, :path, :avatar) + end +end diff --git a/app/controllers/admin/hooks_controller.zh.rb b/app/controllers/admin/hooks_controller.zh.rb new file mode 100644 index 00000000000..4513058dd17 --- /dev/null +++ b/app/controllers/admin/hooks_controller.zh.rb @@ -0,0 +1,44 @@ +class Admin::HooksController < Admin::ApplicationController + def index + @hooks = SystemHook.all + @hook = SystemHook.new + end + + def create + @hook = SystemHook.new(hook_params) + + if @hook.save + redirect_to admin_hooks_path, notice: '成功创建钩子.' + else + @hooks = SystemHook.all + render :index + end + end + + def destroy + @hook = SystemHook.find(params[:id]) + @hook.destroy + + redirect_to admin_hooks_path + end + + + def test + @hook = SystemHook.find(params[:hook_id]) + data = { + event_name: "project_create", + name: "Ruby", + path: "ruby", + project_id: 1, + owner_name: "Someone", + owner_email: "example@gitlabhq.com" + } + @hook.execute(data) + + redirect_to :back + end + + def hook_params + params.require(:hook).permit(:url) + end +end diff --git a/app/controllers/admin/keys_controller.zh.rb b/app/controllers/admin/keys_controller.zh.rb new file mode 100644 index 00000000000..d1b91d7bc23 --- /dev/null +++ b/app/controllers/admin/keys_controller.zh.rb @@ -0,0 +1,34 @@ +class Admin::KeysController < Admin::ApplicationController + before_filter :user, only: [:show, :destroy] + + def show + @key = user.keys.find(params[:id]) + + respond_to do |format| + format.html + format.js { render nothing: true } + end + end + + def destroy + key = user.keys.find(params[:id]) + + respond_to do |format| + if key.destroy + format.html { redirect_to [:admin, user], notice: '成功移除用户key.' } + else + format.html { redirect_to [:admin, user], alert: '移除用户key失败.' } + end + end + end + + protected + + def user + @user ||= User.find_by!(username: params[:user_id]) + end + + def key_params + params.require(:user_id, :id) + end +end diff --git a/app/controllers/admin/services_controller.zh.rb b/app/controllers/admin/services_controller.zh.rb new file mode 100644 index 00000000000..b96eba412d8 --- /dev/null +++ b/app/controllers/admin/services_controller.zh.rb @@ -0,0 +1,54 @@ +class Admin::ServicesController < Admin::ApplicationController + before_filter :service, only: [:edit, :update] + + def index + @services = services_templates + end + + def edit + unless service.present? + redirect_to admin_application_settings_services_path, + alert: "未知服务或服务不存在" + end + end + + def update + if service.update_attributes(application_services_params[:service]) + redirect_to admin_application_settings_services_path, + notice: '成功保存应用设置' + else + render :edit + end + end + + private + + def services_templates + templates = [] + + Service.available_services_names.each do |service_name| + service_template = service_name.concat("_service").camelize.constantize + templates << service_template.where(template: true).first_or_create + end + + templates + end + + def service + @service ||= Service.where(id: params[:id], template: true).first + end + + def application_services_params + params.permit(:id, + service: [ + :title, :token, :type, :active, :api_key, :subdomain, + :room, :recipients, :project_url, :webhook, + :user_key, :device, :priority, :sound, :bamboo_url, :username, :password, + :build_key, :server, :teamcity_url, :build_type, + :description, :issues_url, :new_issue_url, :restrict_to_branch, + :send_from_committer_email, :disable_diffs, + :push_events, :tag_push_events, :note_events, :issues_events, + :merge_requests_events + ]) + end +end diff --git a/app/controllers/admin/users_controller.zh.rb b/app/controllers/admin/users_controller.zh.rb new file mode 100644 index 00000000000..44c0787c9f6 --- /dev/null +++ b/app/controllers/admin/users_controller.zh.rb @@ -0,0 +1,128 @@ +class Admin::UsersController < Admin::ApplicationController + before_filter :user, only: [:show, :edit, :update, :destroy] + + def index + @users = User.order_name_asc.filter(params[:filter]) + @users = @users.search(params[:name]) if params[:name].present? + @users = @users.sort(@sort = params[:sort]) + @users = @users.page(params[:page]) + end + + def show + @personal_projects = user.personal_projects + @joined_projects = user.projects.joined(@user) + @keys = user.keys + end + + def new + @user = User.new + end + + def edit + user + end + + def block + if user.block + redirect_to :back, notice: "屏蔽成功" + else + redirect_to :back, alert: "出错了. 用户未被屏蔽" + end + end + + def unblock + if user.activate + redirect_to :back, notice: "取消屏蔽成功" + else + redirect_to :back, alert: "出错了. 用户未被屏蔽" + end + end + + def create + opts = { + force_random_password: true, + password_expires_at: nil + } + + @user = User.new(user_params.merge(opts)) + @user.created_by_id = current_user.id + @user.generate_password + @user.generate_reset_token + @user.skip_confirmation! + + respond_to do |format| + if @user.save + format.html { redirect_to [:admin, @user], notice: '成功创建用户.' } + format.json { render json: @user, status: :created, location: @user } + else + format.html { render "new" } + format.json { render json: @user.errors, status: :unprocessable_entity } + end + end + end + + def update + user_params_with_pass = user_params.dup + + if params[:user][:password].present? + user_params_with_pass.merge!( + password: params[:user][:password], + password_confirmation: params[:user][:password_confirmation], + ) + end + + respond_to do |format| + if user.update_attributes(user_params_with_pass) + user.confirm! + format.html { redirect_to [:admin, user], notice: '成功更新用户.' } + format.json { head :ok } + else + # restore username to keep form action url. + user.username = params[:id] + format.html { render "edit" } + format.json { render json: user.errors, status: :unprocessable_entity } + end + end + end + + def destroy + # 1. Remove groups where user is the only owner + user.solo_owned_groups.map(&:destroy) + + # 2. Remove user with all authored content including personal projects + user.destroy + + respond_to do |format| + format.html { redirect_to admin_users_path } + format.json { head :ok } + end + end + + def remove_email + email = user.emails.find(params[:email_id]) + email.destroy + + user.set_notification_email + user.save if user.notification_email_changed? + + respond_to do |format| + format.html { redirect_to :back, notice: "成功删除邮箱." } + format.js { render nothing: true } + end + end + + protected + + def user + @user ||= User.find_by!(username: params[:id]) + end + + def user_params + params.require(:user).permit( + :email, :remember_me, :bio, :name, :username, + :skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, :force_random_password, + :extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key, :hide_no_password, + :projects_limit, :can_create_group, :admin, :key_id + ) + end +end diff --git a/app/controllers/application_controller.zh.rb b/app/controllers/application_controller.zh.rb new file mode 100644 index 00000000000..040f9248a82 --- /dev/null +++ b/app/controllers/application_controller.zh.rb @@ -0,0 +1,332 @@ +require 'gon' + +class ApplicationController < ActionController::Base + include Gitlab::CurrentSettings + include GitlabRoutingHelper + + PER_PAGE = 20 + + before_filter :authenticate_user_from_token! + before_filter :authenticate_user! + before_filter :reject_blocked! + before_filter :check_password_expiration + before_filter :ldap_security_check + before_filter :default_headers + before_filter :add_gon_variables + before_filter :configure_permitted_parameters, if: :devise_controller? + before_filter :require_email, unless: :devise_controller? + + protect_from_forgery with: :exception + + helper_method :abilities, :can?, :current_application_settings + helper_method :github_import_enabled?, :gitlab_import_enabled?, :bitbucket_import_enabled? + + rescue_from Encoding::CompatibilityError do |exception| + log_exception(exception) + render "errors/encoding", layout: "errors", status: 500 + end + + rescue_from ActiveRecord::RecordNotFound do |exception| + log_exception(exception) + render "errors/not_found", layout: "errors", status: 404 + end + + protected + + # From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example + # https://gist.github.com/josevalim/fb706b1e933ef01e4fb6 + def authenticate_user_from_token! + user_token = if params[:authenticity_token].presence + params[:authenticity_token].presence + elsif params[:private_token].presence + params[:private_token].presence + end + user = user_token && User.find_by_authentication_token(user_token.to_s) + + if user + # Notice we are passing store false, so the user is not + # actually stored in the session and a token is needed + # for every request. If you want the token to work as a + # sign in token, you can simply remove store: false. + sign_in user, store: false + end + end + + def authenticate_user!(*args) + # If user is not signed-in and tries to access root_path - redirect him to landing page + if current_application_settings.home_page_url.present? + if current_user.nil? && controller_name == 'dashboard' && action_name == 'show' + redirect_to current_application_settings.home_page_url and return + end + end + + super(*args) + end + + def log_exception(exception) + application_trace = ActionDispatch::ExceptionWrapper.new(env, exception).application_trace + application_trace.map!{ |t| " #{t}\n" } + logger.error "\n#{exception.class.name} (#{exception.message}):\n#{application_trace.join}" + end + + def reject_blocked! + if current_user && current_user.blocked? + sign_out current_user + flash[:alert] = "Your account is blocked. Retry when an admin has unblocked it." + redirect_to new_user_session_path + end + end + + def after_sign_in_path_for(resource) + if resource.is_a?(User) && resource.respond_to?(:blocked?) && resource.blocked? + sign_out resource + flash[:alert] = "您的帐号已经被屏蔽. 管理员取消屏蔽后再重试." + new_user_session_path + else + stored_location_for(:redirect) || stored_location_for(resource) || root_path + end + end + + def abilities + Ability.abilities + end + + def can?(object, action, subject) + abilities.allowed?(object, action, subject) + end + + def project + unless @project + namespace = params[:namespace_id] + id = params[:project_id] || params[:id] + + # Redirect from + # localhost/group/project.git + # to + # localhost/group/project + # + if id =~ /\.git\Z/ + redirect_to request.original_url.gsub(/\.git\Z/, '') and return + end + + @project = Project.find_with_namespace("#{namespace}/#{id}") + + if @project and can?(current_user, :read_project, @project) + @project + elsif current_user.nil? + @project = nil + authenticate_user! + else + @project = nil + render_404 and return + end + end + @project + end + + def repository + @repository ||= project.repository + rescue Grit::NoSuchPathError(e) + log_exception(e) + nil + end + + def authorize_project!(action) + return access_denied! unless can?(current_user, action, project) + end + + def authorize_labels! + # Labels should be accessible for issues and/or merge requests + authorize_read_issue! || authorize_read_merge_request! + end + + def access_denied! + render "errors/access_denied", layout: "errors", status: 404 + end + + def not_found! + render "errors/not_found", layout: "errors", status: 404 + end + + def git_not_found! + render "errors/git_not_found", layout: "errors", status: 404 + end + + def method_missing(method_sym, *arguments, &block) + if method_sym.to_s =~ /^authorize_(.*)!$/ + authorize_project!($1.to_sym) + else + super + end + end + + def render_403 + head :forbidden + end + + def render_404 + render file: Rails.root.join("public", "404"), layout: false, status: "404" + end + + def require_non_empty_project + redirect_to @project if @project.empty_repo? + end + + def no_cache_headers + response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate" + response.headers["Pragma"] = "no-cache" + response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT" + end + + def default_headers + headers['X-Frame-Options'] = 'DENY' + 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 + end + + def add_gon_variables + gon.default_issues_tracker = Project.new.default_issue_tracker.to_param + gon.api_version = API::API.version + gon.relative_url_root = Gitlab.config.gitlab.relative_url_root + gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s + + if current_user + gon.current_user_id = current_user.id + gon.api_token = current_user.private_token + end + end + + def check_password_expiration + if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user? + redirect_to new_profile_password_path and return + end + end + + def ldap_security_check + if current_user && current_user.requires_ldap_check? + unless Gitlab::LDAP::Access.allowed?(current_user) + sign_out current_user + flash[:alert] = "您的LDAP帐号访问被拒绝." + redirect_to new_user_session_path + end + end + end + + def event_filter + filters = cookies['event_filter'].split(',') if cookies['event_filter'].present? + @event_filter ||= EventFilter.new(filters) + end + + def gitlab_ldap_access(&block) + Gitlab::LDAP::Access.open { |access| block.call(access) } + end + + # JSON for infinite scroll via Pager object + def pager_json(partial, count) + html = render_to_string( + partial, + layout: false, + formats: [:html] + ) + + render json: { + html: html, + count: count + } + end + + def view_to_html_string(partial) + render_to_string( + partial, + layout: false, + formats: [:html] + ) + end + + def configure_permitted_parameters + devise_parameter_sanitizer.sanitize(:sign_in) { |u| u.permit(:username, :email, :password, :login, :remember_me) } + end + + def hexdigest(string) + Digest::SHA1.hexdigest string + end + + def require_email + if current_user && current_user.temp_oauth_email? + redirect_to profile_path, notice: '请通过您的邮箱地址补充您的用户资料' and return + end + end + + def set_filters_params + params[:sort] ||= 'created_desc' + params[:scope] = 'all' if params[:scope].blank? + params[:state] = 'opened' if params[:state].blank? + + @filter_params = params.dup + + if @project + @filter_params[:project_id] = @project.id + elsif @group + @filter_params[:group_id] = @group.id + else + # TODO: this filter ignore issues/mr created in public or + # internal repos where you are not a member. Enable this filter + # or improve current implementation to filter only issues you + # created or assigned or mentioned + #@filter_params[:authorized_only] = true + end + + @filter_params + end + + def set_filter_values(collection) + assignee_id = @filter_params[:assignee_id] + author_id = @filter_params[:author_id] + milestone_id = @filter_params[:milestone_id] + + @sort = @filter_params[:sort] + @assignees = User.where(id: collection.pluck(:assignee_id)) + @authors = User.where(id: collection.pluck(:author_id)) + @milestones = Milestone.where(id: collection.pluck(:milestone_id)) + + if assignee_id.present? && !assignee_id.to_i.zero? + @assignee = @assignees.find_by(id: assignee_id) + end + + if author_id.present? && !author_id.to_i.zero? + @author = @authors.find_by(id: author_id) + end + + if milestone_id.present? && !milestone_id.to_i.zero? + @milestone = @milestones.find_by(id: milestone_id) + end + end + + def get_issues_collection + set_filters_params + issues = IssuesFinder.new.execute(current_user, @filter_params) + set_filter_values(issues) + issues + end + + def get_merge_requests_collection + set_filters_params + merge_requests = MergeRequestsFinder.new.execute(current_user, @filter_params) + set_filter_values(merge_requests) + merge_requests + end + + def github_import_enabled? + OauthHelper.enabled_oauth_providers.include?(:github) + end + + def gitlab_import_enabled? + OauthHelper.enabled_oauth_providers.include?(:gitlab) + end + + def bitbucket_import_enabled? + OauthHelper.enabled_oauth_providers.include?(:bitbucket) && Gitlab::BitbucketImport.public_key.present? + end +end diff --git a/app/controllers/omniauth_callbacks_controller.zh.rb b/app/controllers/omniauth_callbacks_controller.zh.rb new file mode 100644 index 00000000000..b52ec7c9518 --- /dev/null +++ b/app/controllers/omniauth_callbacks_controller.zh.rb @@ -0,0 +1,76 @@ +class OmniauthCallbacksController < Devise::OmniauthCallbacksController + Gitlab.config.omniauth.providers.each do |provider| + define_method provider['name'] do + handle_omniauth + end + end + + # Extend the standard message generation to accept our custom exception + def failure_message + exception = env["omniauth.error"] + error = exception.error_reason if exception.respond_to?(:error_reason) + error ||= exception.error if exception.respond_to?(:error) + error ||= exception.message if exception.respond_to?(:message) + error ||= env["omniauth.error.type"].to_s + error.to_s.humanize if error + end + + # We only find ourselves here + # if the authentication to LDAP was successful. + def ldap + @user = Gitlab::LDAP::User.new(oauth) + @user.save if @user.changed? # will also save new users + gl_user = @user.gl_user + gl_user.remember_me = true if @user.persisted? + + # Do additional LDAP checks for the user filter and EE features + if @user.allowed? + sign_in_and_redirect(gl_user) + else + flash[:alert] = "您的LDAP帐号访问受限." + redirect_to new_user_session_path + end + end + + def omniauth_error + @provider = params[:provider] + @error = params[:error] + render 'errors/omniauth_error', layout: "errors", status: 422 + end + + private + + def handle_omniauth + if current_user + # Add new authentication method + current_user.identities.find_or_create_by(extern_uid: oauth['uid'], provider: oauth['provider']) + redirect_to profile_account_path, notice: '认证方法更新成功' + else + @user = Gitlab::OAuth::User.new(oauth) + @user.save + + # Only allow properly saved users to login. + if @user.persisted? && @user.valid? + sign_in_and_redirect(@user.gl_user) + else + error_message = + if @user.gl_user.errors.any? + @user.gl_user.errors.map do |attribute, message| + "#{attribute} #{message}" + end.join(", ") + else + '' + end + + redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return + end + end + rescue Gitlab::OAuth::ForbiddenAction => e + flash[:notice] = e.message + redirect_to new_user_session_path + end + + def oauth + @oauth ||= request.env['omniauth.auth'] + end +end diff --git a/app/controllers/passwords_controller.zh.rb b/app/controllers/passwords_controller.zh.rb new file mode 100644 index 00000000000..18ce6216112 --- /dev/null +++ b/app/controllers/passwords_controller.zh.rb @@ -0,0 +1,18 @@ +class PasswordsController < Devise::PasswordsController + + def create + email = resource_params[:email] + resource_found = resource_class.find_by_email(email) + if resource_found && resource_found.ldap_user? + flash[:alert] = "LDAP用户不能重置密码." + respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name)) and return + end + + self.resource = resource_class.send_reset_password_instructions(resource_params) + if successfully_sent?(resource) + respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name)) + else + respond_with(resource) + end + end +end diff --git a/app/controllers/profiles_controller.zh.rb b/app/controllers/profiles_controller.zh.rb new file mode 100644 index 00000000000..40a791a71f6 --- /dev/null +++ b/app/controllers/profiles_controller.zh.rb @@ -0,0 +1,74 @@ +class ProfilesController < ApplicationController + include ActionView::Helpers::SanitizeHelper + + before_filter :user + before_filter :authorize_change_username!, only: :update_username + skip_before_filter :require_email, only: [:show, :update] + + layout 'profile' + + def show + end + + def design + end + + def applications + @applications = current_user.oauth_applications + @authorized_tokens = current_user.oauth_authorized_tokens + @authorized_apps = @authorized_tokens.map(&:application).uniq + end + + def update + user_params.except!(:email) if @user.ldap_user? + + if @user.update_attributes(user_params) + flash[:notice] = "成功更新用户资料" + else + flash[:alert] = "更新用户资料失败" + end + + respond_to do |format| + format.html { redirect_to :back } + format.js + end + end + + def reset_private_token + if current_user.reset_authentication_token! + flash[:notice] = "Token更新成功" + end + + redirect_to profile_account_path + end + + def history + @events = current_user.recent_events.page(params[:page]).per(PER_PAGE) + end + + def update_username + @user.update_attributes(username: user_params[:username]) + + respond_to do |format| + format.js + end + end + + private + + def user + @user = current_user + end + + def authorize_change_username! + return render_404 unless @user.can_change_username? + end + + def user_params + params.require(:user).permit( + :email, :password, :password_confirmation, :bio, :name, :username, + :skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, + :avatar, :hide_no_ssh_key, :hide_no_password + ) + end +end diff --git a/app/controllers/projects_controller.zh.rb b/app/controllers/projects_controller.zh.rb new file mode 100644 index 00000000000..6b0195e0924 --- /dev/null +++ b/app/controllers/projects_controller.zh.rb @@ -0,0 +1,198 @@ +class ProjectsController < ApplicationController + prepend_before_filter :render_go_import, only: [:show] + skip_before_filter :authenticate_user!, only: [:show] + before_filter :project, except: [:new, :create] + before_filter :repository, except: [:new, :create] + + # Authorize + before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive] + before_filter :set_title, only: [:new, :create] + before_filter :event_filter, only: :show + + layout 'navless', only: [:new, :create, :fork] + + def new + @project = Project.new + end + + def edit + render 'edit', layout: 'project_settings' + end + + def create + @project = ::Projects::CreateService.new(current_user, project_params).execute + + if @project.saved? + redirect_to( + project_path(@project), + notice: '创建项目成功.' + ) + else + render 'new' + end + end + + def update + status = ::Projects::UpdateService.new(@project, current_user, project_params).execute + + respond_to do |format| + if status + flash[:notice] = '更新项目成功.' + format.html do + redirect_to( + edit_project_path(@project), + notice: '更新项目成功.' + ) + end + format.js + else + format.html { render 'edit', layout: 'project_settings' } + format.js + end + end + 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 + end + end + + def show + if @project.import_in_progress? + redirect_to namespace_project_import_path(@project.namespace, @project) + return + end + + limit = (params[:limit] || 20).to_i + + @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', layout: user_layout + else + @last_push = current_user.recent_push(@project.id) if current_user + render :show, layout: user_layout + end + else + render 'projects/no_repo', layout: user_layout + end + end + + format.json do + @events = @project.events.recent + @events = event_filter.apply_filter(@events).with_associations + @events = @events.limit(limit).offset(params[:offset] || 0) + pager_json('events/_events', @events.count) + end + end + end + + def destroy + return access_denied! unless can?(current_user, :remove_project, @project) + + ::Projects::DestroyService.new(@project, current_user, {}).execute + + respond_to do |format| + format.html do + flash[:alert] = '项目已删除.' + + if request.referer.include?('/admin') + redirect_to admin_namespaces_projects_path + else + redirect_to dashboard_path + end + end + end + end + + def autocomplete_sources + note_type = params['type'] + note_id = params['type_id'] + autocomplete = ::Projects::AutocompleteService.new(@project) + participants = ::Projects::ParticipantsService.new(@project, current_user).execute(note_type, note_id) + + @suggestions = { + emojis: autocomplete_emojis, + issues: autocomplete.issues, + mergerequests: autocomplete.merge_requests, + members: participants + } + + respond_to do |format| + format.json { render json: @suggestions } + end + end + + def archive + return access_denied! unless can?(current_user, :archive_project, @project) + @project.archive! + + respond_to do |format| + format.html { redirect_to project_path(@project) } + end + end + + def unarchive + return access_denied! unless can?(current_user, :archive_project, @project) + @project.unarchive! + + respond_to do |format| + format.html { redirect_to project_path(@project) } + end + end + + def toggle_star + current_user.toggle_star(@project) + @project.reload + render json: { star_count: @project.star_count } + end + + def markdown_preview + render text: view_context.markdown(params[:md_text]) + end + + private + + def set_title + @title = 'New Project' + end + + def user_layout + current_user ? 'projects' : 'public_projects' + end + + def project_params + params.require(:project).permit( + :name, :path, :description, :issues_tracker, :tag_list, + :issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch, + :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar + ) + end + + def autocomplete_emojis + Rails.cache.fetch("autocomplete-emoji-#{Gemojione::VERSION}") do + Emoji.emojis.map do |name, emoji| + { + name: name, + path: view_context.image_url("emoji/#{emoji["unicode"]}.png") + } + end + end + end + + def render_go_import + return unless params["go-get"] == "1" + + @namespace = params[:namespace_id] + @id = params[:project_id] || params[:id] + @id = @id.gsub(/\.git\Z/, "") + + render "go_import", layout: false + end +end diff --git a/app/helpers/appearances_helper.zh.rb b/app/helpers/appearances_helper.zh.rb new file mode 100644 index 00000000000..bf0488793d5 --- /dev/null +++ b/app/helpers/appearances_helper.zh.rb @@ -0,0 +1,21 @@ +module AppearancesHelper + def brand_item + nil + end + + def brand_title + 'GitLab社区版' + end + + def brand_image + nil + end + + def brand_text + nil + end + + def brand_header_logo + image_tag 'logo-white.png' + end +end diff --git a/app/helpers/application_helper.zh.rb b/app/helpers/application_helper.zh.rb new file mode 100644 index 00000000000..8aad57fe693 --- /dev/null +++ b/app/helpers/application_helper.zh.rb @@ -0,0 +1,321 @@ +require 'digest/md5' +require 'uri' + +module ApplicationHelper + COLOR_SCHEMES = { + 1 => 'white', + 2 => 'dark', + 3 => 'solarized-light', + 4 => 'solarized-dark', + 5 => 'monokai', + } + COLOR_SCHEMES.default = 'white' + + # Helper method to access the COLOR_SCHEMES + # + # The keys are the `color_scheme_ids` + # The values are the `name` of the scheme. + # + # The preview images are `name-scheme-preview.png` + # The stylesheets should use the css class `.name` + def color_schemes + COLOR_SCHEMES.freeze + end + + # Check if a particular controller is the current one + # + # args - One or more controller names to check + # + # Examples + # + # # On TreeController + # current_controller?(:tree) # => true + # current_controller?(:commits) # => false + # current_controller?(:commits, :tree) # => true + def current_controller?(*args) + args.any? { |v| v.to_s.downcase == controller.controller_name } + end + + # Check if a particular action is the current one + # + # args - One or more action names to check + # + # Examples + # + # # On Projects#new + # current_action?(:new) # => true + # current_action?(:create) # => false + # current_action?(:new, :create) # => true + def current_action?(*args) + args.any? { |v| v.to_s.downcase == action_name } + end + + def project_icon(project_id, options = {}) + project = + if project_id.is_a?(Project) + project = project_id + else + Project.find_with_namespace(project_id) + end + + if project.avatar_url + image_tag project.avatar_url, options + else # generated icon + project_identicon(project, options) + end + end + + def project_identicon(project, options = {}) + allowed_colors = { + red: 'FFEBEE', + purple: 'F3E5F5', + indigo: 'E8EAF6', + blue: 'E3F2FD', + teal: 'E0F2F1', + orange: 'FBE9E7', + gray: 'EEEEEE' + } + + options[:class] ||= '' + options[:class] << ' identicon' + bg_key = project.id % 7 + style = "background-color: ##{ allowed_colors.values[bg_key] }; color: #555" + + content_tag(:div, class: options[:class], style: style) do + project.name[0, 1].upcase + end + end + + def avatar_icon(user_email = '', size = nil) + user = User.find_by(email: user_email) + + if user + user.avatar_url(size) || default_avatar + else + gravatar_icon(user_email, size) + end + end + + def gravatar_icon(user_email = '', size = nil) + GravatarService.new.execute(user_email, size) || + default_avatar + end + + def default_avatar + image_path('no_avatar.png') + end + + def last_commit(project) + if project.repo_exists? + time_ago_with_tooltip(project.repository.commit.committed_date) + else + 'Never' + end + rescue + 'Never' + end + + def grouped_options_refs + repository = @project.repository + + options = [ + ['Branches', repository.branch_names], + ['Tags', VersionSorter.rsort(repository.tag_names)] + ] + + # If reference is commit id - we should add it to branch/tag selectbox + if(@ref && !options.flatten.include?(@ref) && + @ref =~ /^[0-9a-zA-Z]{6,52}$/) + options << ['Commit', [@ref]] + end + + grouped_options_for_select(options, @ref || @project.default_branch) + end + + def emoji_autocomplete_source + # should be an array of strings + # so to_s can be called, because it is sufficient and to_json is too slow + Emoji.names.to_s + end + + def app_theme + Gitlab::Theme.css_class_by_id(current_user.try(:theme_id)) + end + + def theme_type + Gitlab::Theme.type_css_class_by_id(current_user.try(:theme_id)) + end + + def user_color_scheme_class + COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user) + end + + # Define whenever show last push event + # with suggestion to create MR + def show_last_push_widget?(event) + # Skip if event is not about added or modified non-master branch + return false unless event && event.last_push_to_non_root? && !event.rm_ref? + + project = event.project + + # Skip if project repo is empty or MR disabled + return false unless project && !project.empty_repo? && project.merge_requests_enabled + + # Skip if user already created appropriate MR + return false if project.merge_requests.where(source_branch: event.branch_name).opened.any? + + # Skip if user removed branch right after that + return false unless project.repository.branch_names.include?(event.branch_name) + + true + end + + def hexdigest(string) + Digest::SHA1.hexdigest string + end + + def authbutton(provider, size = 64) + file_name = "#{provider.to_s.split('_').first}_#{size}.png" + image_tag(image_path("authbuttons/#{file_name}"), alt: "Sign in with #{provider.to_s.titleize}") + end + + def simple_sanitize(str) + sanitize(str, tags: %w(a span)) + end + + + def body_data_page + path = controller.controller_path.split('/') + namespace = path.first if path.second + + [namespace, controller.controller_name, controller.action_name].compact.join(':') + end + + # shortcut for gitlab config + def gitlab_config + Gitlab.config.gitlab + end + + # shortcut for gitlab extra config + def extra_config + Gitlab.config.extra + end + + def search_placeholder + if @project && @project.persisted? + '在该项目内搜索' + elsif @snippet || @snippets || @show_snippets + '搜索代码片段' + elsif @group && @group.persisted? + '组内搜索' + else + '搜索' + end + end + + def broadcast_message + BroadcastMessage.current + end + + def time_ago_with_tooltip(date, placement = 'top', html_class = 'time_ago') + capture_haml do + haml_tag :time, date.to_s, + class: html_class, datetime: date.getutc.iso8601, title: date.stamp('Aug 21, 2011 9:23pm'), + data: { toggle: 'tooltip', placement: placement } + + haml_tag :script, "$('." + html_class + "').timeago().tooltip()" + end.html_safe + end + + def render_markup(file_name, file_content) + GitHub::Markup.render(file_name, file_content). + force_encoding(file_content.encoding).html_safe + rescue RuntimeError + simple_format(file_content) + end + + def markup?(filename) + Gitlab::MarkdownHelper.markup?(filename) + end + + def gitlab_markdown?(filename) + Gitlab::MarkdownHelper.gitlab_markdown?(filename) + end + + def link_to(name = nil, options = nil, html_options = nil, &block) + begin + uri = URI(options) + host = uri.host + absolute_uri = uri.absolute? + rescue URI::InvalidURIError, ArgumentError + host = nil + absolute_uri = nil + end + + # Add 'nofollow' only to external links + if host && host != Gitlab.config.gitlab.host && absolute_uri + if html_options + if html_options[:rel] + html_options[:rel] << ' nofollow' + else + html_options.merge!(rel: 'nofollow') + end + else + html_options = Hash.new + html_options[:rel] = 'nofollow' + end + end + + super + end + + def escaped_autolink(text) + auto_link ERB::Util.html_escape(text), link: :urls + end + + def promo_host + 'about.gitlab.com' + end + + def promo_url + 'https://' + promo_host + end + + def page_filter_path(options={}) + exist_opts = { + state: params[:state], + scope: params[:scope], + label_name: params[:label_name], + milestone_id: params[:milestone_id], + assignee_id: params[:assignee_id], + author_id: params[:author_id], + sort: params[:sort], + } + + options = exist_opts.merge(options) + + path = request.path + path << "?#{options.to_param}" + path + end + + def outdated_browser? + browser.ie? && browser.version.to_i < 10 + end + + def path_to_key(key, admin = false) + if admin + admin_user_key_path(@user, key) + else + profile_key_path(key) + end + end + + def nav_sidebar_class + if nav_menu_collapsed? + "page-sidebar-collapsed" + else + "page-sidebar-expanded" + end + end +end diff --git a/app/helpers/blob_helper.zh.rb b/app/helpers/blob_helper.zh.rb new file mode 100644 index 00000000000..ecdb458efc8 --- /dev/null +++ b/app/helpers/blob_helper.zh.rb @@ -0,0 +1,64 @@ +module BlobHelper + def highlight(blob_name, blob_content, nowrap = false) + formatter = Rugments::Formatters::HTML.new( + nowrap: nowrap, + cssclass: 'code highlight', + lineanchors: true, + lineanchorsid: 'LC' + ) + + begin + lexer = Rugments::Lexer.guess(filename: blob_name, source: blob_content) + rescue Rugments::Lexer::AmbiguousGuess + lexer = Rugments::Lexers::PlainText + end + + formatter.format(lexer.lex(blob_content)).html_safe + end + + def no_highlight_files + %w(credits changelog news copying copyright license authors) + end + + def edit_blob_link(project, ref, path, options = {}) + blob = + begin + project.repository.blob_at(ref, path) + rescue + nil + end + + if blob && blob.text? + text = 'Edit' + after = options[:after] || '' + from_mr = options[:from_merge_request_id] + link_opts = {} + link_opts[:from_merge_request_id] = from_mr if from_mr + cls = 'btn btn-small' + if allowed_tree_edit?(project, ref) + link_to(text, + namespace_project_edit_blob_path(project.namespace, project, + tree_join(ref, path), + link_opts), + class: cls + ) + else + content_tag :span, text, class: cls + ' disabled' + end + after.html_safe + else + '' + end + end + + def leave_edit_message + "退出编辑模式?\n所有未保存的修改将丢失." + end + + def editing_preview_title(filename) + if Gitlab::MarkdownHelper.previewable?(filename) + '预览' + else + '预览修改' + end + end +end diff --git a/app/helpers/commits_helper.zh.rb b/app/helpers/commits_helper.zh.rb new file mode 100644 index 00000000000..78664f62ebb --- /dev/null +++ b/app/helpers/commits_helper.zh.rb @@ -0,0 +1,182 @@ +# encoding: utf-8 +module CommitsHelper + # Returns a link to the commit author. If the author has a matching user and + # is a member of the current @project it will link to the team member page. + # Otherwise it will link to the author email as specified in the commit. + # + # options: + # avatar: true will prepend the avatar image + # size: size of the avatar image in px + def commit_author_link(commit, options = {}) + commit_person_link(commit, options.merge(source: :author)) + end + + # Just like #author_link but for the committer. + def commit_committer_link(commit, options = {}) + commit_person_link(commit, options.merge(source: :committer)) + end + + def image_diff_class(diff) + if diff.deleted_file + "已删除" + elsif diff.new_file + "已添加" + else + nil + end + end + + def commit_to_html(commit, project, inline = true) + template = inline ? "inline_commit" : "commit" + escape_javascript(render "projects/commits/#{template}", commit: commit, project: project) unless commit.nil? + end + + # Breadcrumb links for a Project and, if applicable, a tree path + def commits_breadcrumbs + return unless @project && @ref + + # Add the root project link and the arrow icon + crumbs = content_tag(:li) do + link_to( + @project.path, + namespace_project_commits_path(@project.namespace, @project, @ref) + ) + end + + if @path + parts = @path.split('/') + + parts.each_with_index do |part, i| + crumbs << content_tag(:li) do + # The text is just the individual part, but the link needs all the parts before it + link_to( + part, + namespace_project_commits_path( + @project.namespace, + @project, + tree_join(@ref, parts[0..i].join('/')) + ) + ) + end + end + end + + crumbs.html_safe + end + + # Return Project default branch, if it present in array + # Else - first branch in array (mb last actual branch) + def commit_default_branch(project, branches) + branches.include?(project.default_branch) ? branches.delete(project.default_branch) : branches.pop + end + + # Returns the sorted alphabetically links to branches, separated by a comma + def commit_branches_links(project, branches) + branches.sort.map do |branch| + link_to( + namespace_project_tree_path(project.namespace, project, branch) + ) do + content_tag :span, class: 'label label-gray' do + icon('code-fork') + ' ' + branch + end + end + end.join(" ").html_safe + end + + # Returns the sorted links to tags, separated by a comma + def commit_tags_links(project, tags) + sorted = VersionSorter.rsort(tags) + sorted.map do |tag| + link_to( + namespace_project_commits_path(project.namespace, project, + project.repository.find_tag(tag).name) + ) do + content_tag :span, class: 'label label-gray' do + icon('tag') + ' ' + tag + end + end + end.join(" ").html_safe + end + + def link_to_browse_code(project, commit) + if current_controller?(:projects, :commits) + if @repo.blob_at(commit.id, @path) + return link_to( + "浏览文件 »", + namespace_project_blob_path(project.namespace, project, + tree_join(commit.id, @path)), + class: "pull-right" + ) + elsif @path.present? + return link_to( + "浏览目录 »", + namespace_project_tree_path(project.namespace, project, + tree_join(commit.id, @path)), + class: "pull-right" + ) + end + end + link_to( + "浏览代码 »", + namespace_project_tree_path(project.namespace, project, commit), + class: "pull-right" + ) + end + + protected + + # Private: Returns a link to a person. If the person has a matching user and + # is a member of the current @project it will link to the team member page. + # Otherwise it will link to the person email as specified in the commit. + # + # options: + # source: one of :author or :committer + # avatar: true will prepend the avatar image + # size: size of the avatar image in px + def commit_person_link(commit, options = {}) + source_name = clean(commit.send "#{options[:source]}_name".to_sym) + source_email = clean(commit.send "#{options[:source]}_email".to_sym) + + user = User.find_for_commit(source_email, source_name) + person_name = user.nil? ? source_name : user.name + person_email = user.nil? ? source_email : user.email + + text = + if options[:avatar] + avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "") + %Q{#{avatar} #{person_name}} + else + person_name + end + + options = { + class: "commit-#{options[:source]}-link has_tooltip", + data: { :'original-title' => sanitize(source_email) } + } + + if user.nil? + mail_to(source_email, text.html_safe, options) + else + link_to(text.html_safe, user_path(user), options) + end + end + + def view_file_btn(commit_sha, diff, project) + link_to( + namespace_project_blob_path(project.namespace, project, + tree_join(commit_sha, diff.new_path)), + class: 'btn btn-small view-file js-view-file' + ) do + raw('View file @') + content_tag(:span, commit_sha[0..6], + class: 'commit-short-id') + end + end + + def truncate_sha(sha) + Commit.truncate_sha(sha) + end + + def clean(string) + Sanitize.clean(string, remove_contents: true) + end +end diff --git a/app/helpers/events_helper.zh.rb b/app/helpers/events_helper.zh.rb new file mode 100644 index 00000000000..81bd259cdcb --- /dev/null +++ b/app/helpers/events_helper.zh.rb @@ -0,0 +1,199 @@ +module EventsHelper + def link_to_author(event) + author = event.author + + if author + link_to author.name, user_path(author.username) + else + event.author_name + end + end + + def event_action_name(event) + target = if event.target_type + if event.note? + event.note_target_type + else + event.target_type.titleize.downcase + end + else + 'project' + end + + [event.action_name, target].join(" ") + end + + def event_filter_link(key, tooltip) + key = key.to_s + active = if @event_filter.active? key + 'active' + end + + content_tag :li, class: "filter_icon #{active}" do + link_to request.path, class: 'has_tooltip event_filter_link', id: "#{key}_event_filter", 'data-original-title' => '按' + tooltip.downcase + '筛选' do + icon(icon_for_event[key]) + content_tag(:span, ' ' + tooltip) + end + end + end + + def icon_for_event + { + EventFilter.push => 'upload', + EventFilter.merged => 'check-square-o', + EventFilter.comments => 'comments', + EventFilter.team => 'user', + } + end + + def event_feed_title(event) + words = [] + words << event.author_name + words << event_action_name(event) + + if event.push? + words << event.ref_type + words << event.ref_name + words << "at" + elsif event.commented? + if event.note_commit? + words << event.note_short_commit_id + else + words << "##{truncate event.note_target_iid}" + end + words << "at" + elsif event.target + words << "##{event.target_iid}:" + words << event.target.title if event.target.respond_to?(:title) + words << "at" + end + + words << event.project_name + + words.join(" ") + end + + def event_feed_url(event) + if event.issue? + namespace_project_issue_url(event.project.namespace, event.project, + event.issue) + elsif event.merge_request? + namespace_project_merge_request_url(event.project.namespace, + event.project, event.merge_request) + elsif event.note? && event.note_commit? + namespace_project_commit_url(event.project.namespace, event.project, + event.note_target) + elsif event.note? + if event.note_target + if event.note_commit? + namespace_project_commit_path(event.project.namespace, event.project, + event.note_commit_id, + anchor: dom_id(event.target)) + elsif event.note_project_snippet? + namespace_project_snippet_path(event.project.namespace, + event.project, event.note_target) + else + event_note_target_path(event) + end + end + elsif event.push? + if event.push_with_commits? + if event.commits_count > 1 + namespace_project_compare_url(event.project.namespace, event.project, + from: event.commit_from, to: + event.commit_to) + else + namespace_project_commit_url(event.project.namespace, event.project, + id: event.commit_to) + end + else + namespace_project_commits_url(event.project.namespace, event.project, + event.ref_name) + end + end + end + + def event_feed_summary(event) + if event.issue? + render "events/event_issue", issue: event.issue + elsif event.push? + render "events/event_push", event: event + elsif event.merge_request? + render "events/event_merge_request", merge_request: event.merge_request + elsif event.note? + render "events/event_note", note: event.note + end + end + + def event_note_target_path(event) + if event.note? && event.note_commit? + namespace_project_commit_path(event.project.namespace, event.project, + event.note_target) + else + polymorphic_path([event.project.namespace.becomes(Namespace), + event.project, event.note_target], + anchor: dom_id(event.target)) + end + end + + def event_note_title_html(event) + if event.note_target + if event.note_commit? + link_to( + namespace_project_commit_path(event.project.namespace, event.project, + event.note_commit_id, + anchor: dom_id(event.target)), + class: "commit_short_id" + ) do + "#{event.note_target_type} #{event.note_short_commit_id}" + end + elsif event.note_project_snippet? + link_to(namespace_project_snippet_path(event.project.namespace, + event.project, + event.note_target)) do + "#{event.note_target_type} ##{truncate event.note_target_id}" + end + else + link_to event_note_target_path(event) do + "#{event.note_target_type} ##{truncate event.note_target_iid}" + end + end + else + content_tag :strong do + "(deleted)" + end + end + end + + def event_note(text) + text = first_line_in_markdown(text, 150) + sanitize(text, tags: %w(a img b pre code p span)) + end + + def event_commit_title(message) + escape_once(truncate(message.split("\n").first, length: 70)) + rescue + "--broken encoding" + end + + def event_to_atom(xml, event) + if event.proper? + xml.entry do + event_link = event_feed_url(event) + event_title = event_feed_title(event) + event_summary = event_feed_summary(event) + + xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}" + xml.link href: event_link + xml.title truncate(event_title, length: 80) + xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") + xml.media :thumbnail, width: "40", height: "40", url: avatar_icon(event.author_email) + xml.author do |author| + xml.name event.author_name + xml.email event.author_email + end + + xml.summary(type: "xhtml") { |x| x << event_summary unless event_summary.nil? } + end + end + end +end diff --git a/app/helpers/gitlab_markdown_helper.zh.rb b/app/helpers/gitlab_markdown_helper.zh.rb new file mode 100644 index 00000000000..b7d98447e6f --- /dev/null +++ b/app/helpers/gitlab_markdown_helper.zh.rb @@ -0,0 +1,272 @@ +module GitlabMarkdownHelper + include Gitlab::Markdown + + # Use this in places where you would normally use link_to(gfm(...), ...). + # + # It solves a problem occurring with nested links (i.e. + # "outer text gfm ref more outer text"). This will not be + # interpreted as intended. Browsers will parse something like + # "outer text gfm ref more outer text" (notice the last part is + # not linked any more). link_to_gfm corrects that. It wraps all parts to + # explicitly produce the correct linking behavior (i.e. + # "outer text gfm ref more outer text"). + def link_to_gfm(body, url, html_options = {}) + return "" if body.blank? + + escaped_body = if body =~ /^\.*?}m) do |match| + "#{match}#{link_to("", url, html_options)[0..-5]}" # "".length +1 + end + + link_to(gfm_body.html_safe, url, html_options) + end + + def markdown(text, options={}) + unless (@markdown and options == @options) + @options = options + gitlab_renderer = Redcarpet::Render::GitlabHTML.new(self, + user_color_scheme_class, + { + # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch- + filter_html: true, + with_toc_data: true, + safe_links_only: true + }.merge(options)) + @markdown = Redcarpet::Markdown.new(gitlab_renderer, + # see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use + no_intra_emphasis: true, + tables: true, + fenced_code_blocks: true, + autolink: true, + strikethrough: true, + lax_spacing: true, + space_after_headers: true, + superscript: true) + end + @markdown.render(text).html_safe + end + + # Return the first line of +text+, up to +max_chars+, after parsing the line + # as Markdown. HTML tags in the parsed output are not counted toward the + # +max_chars+ limit. If the length limit falls within a tag's contents, then + # the tag contents are truncated without removing the closing tag. + def first_line_in_markdown(text, max_chars = nil) + md = markdown(text).strip + + truncate_visible(md, max_chars || md.length) if md.present? + end + + def render_wiki_content(wiki_page) + if wiki_page.format == :markdown + markdown(wiki_page.content) + else + wiki_page.formatted_content.html_safe + end + end + + def create_relative_links(text) + paths = extract_paths(text) + + paths.uniq.each do |file_path| + # If project does not have repository + # its nothing to rebuild + # + # TODO: pass project variable to markdown helper instead of using + # instance variable. Right now it generates invalid path for pages out + # of project scope. Example: search results where can be rendered markdown + # from different projects + if @repository && @repository.exists? && !@repository.empty? + new_path = rebuild_path(file_path) + # Finds quoted path so we don't replace other mentions of the string + # eg. "doc/api" will be replaced and "/home/doc/api/text" won't + text.gsub!("\"#{file_path}\"", "\"/#{new_path}\"") + end + end + + text + end + + def extract_paths(text) + links = substitute_links(text) + image_links = substitute_image_links(text) + links + image_links + end + + def substitute_links(text) + links = text.scan(//) + relative_links = links.flatten.reject{ |link| link_to_ignore? link } + relative_links + end + + def substitute_image_links(text) + links = text.scan(/ + true + else + ignored_protocols.map{ |protocol| link.include?(protocol) }.any? + end + end + + def ignored_protocols + ["http://","https://", "ftp://", "mailto:", "smb://"] + end + + def rebuild_path(file_path) + file_path = file_path.dup + file_path.gsub!(/(#.*)/, "") + id = $1 || "" + file_path = relative_file_path(file_path) + file_path = sanitize_slashes(file_path) + + [ + Gitlab.config.gitlab.relative_url_root, + @project.path_with_namespace, + path_with_ref(file_path), + file_path + ].compact.join("/").gsub(/^\/*|\/*$/, '') + id + end + + def sanitize_slashes(path) + path[0] = "" if path.start_with?("/") + path.chop if path.end_with?("/") + path + end + + def relative_file_path(path) + requested_path = @path + nested_path = build_nested_path(path, requested_path) + return nested_path if file_exists?(nested_path) + path + end + + # Covering a special case, when the link is referencing file in the same directory eg: + # If we are at doc/api/README.md and the README.md contains relative links like [Users](users.md) + # this takes the request path(doc/api/README.md), and replaces the README.md with users.md so the path looks like doc/api/users.md + # If we are at doc/api and the README.md shown in below the tree view + # this takes the request path(doc/api) and adds users.md so the path looks like doc/api/users.md + def build_nested_path(path, request_path) + return request_path if path == "" + return path unless request_path + if local_path(request_path) == "tree" + base = request_path.split("/").push(path) + base.join("/") + else + base = request_path.split("/") + base.pop + base.push(path).join("/") + end + end + + # Checks if the path exists in the repo + # eg. checks if doc/README.md exists, if not then link to blob + def path_with_ref(path) + if file_exists?(path) + "#{local_path(path)}/#{correct_ref}" + else + "blob/#{correct_ref}" + end + end + + def file_exists?(path) + return false if path.nil? + return @repository.blob_at(current_sha, path).present? || @repository.tree(current_sha, path).entries.any? + end + + # Check if the path is pointing to a directory(tree) or a file(blob) + # eg. doc/api is directory and doc/README.md is file + def local_path(path) + return "tree" if @repository.tree(current_sha, path).entries.any? + return "raw" if @repository.blob_at(current_sha, path).image? + return "blob" + end + + def current_sha + if @commit + @commit.id + elsif @repository && !@repository.empty? + if @ref + @repository.commit(@ref).try(:sha) + else + @repository.head_commit.sha + end + end + end + + # We will assume that if no ref exists we can point to master + def correct_ref + @ref ? @ref : "master" + end + + private + + # Return +text+, truncated to +max_chars+ characters, excluding any HTML + # tags. + def truncate_visible(text, max_chars) + doc = Nokogiri::HTML.fragment(text) + content_length = 0 + truncated = false + + doc.traverse do |node| + if node.text? || node.content.empty? + if truncated + node.remove + next + end + + # Handle line breaks within a node + if node.content.strip.lines.length > 1 + node.content = "#{node.content.lines.first.chomp}..." + truncated = true + end + + num_remaining = max_chars - content_length + if node.content.length > num_remaining + node.content = node.content.truncate(num_remaining) + truncated = true + end + content_length += node.content.length + end + + truncated = truncate_if_block(node, truncated) + end + + doc.to_html + end + + # Used by #truncate_visible. If +node+ is the first block element, and the + # text hasn't already been truncated, then append "..." to the node contents + # and return true. Otherwise return false. + def truncate_if_block(node, truncated) + if node.element? && node.description.block? && !truncated + node.content = "#{node.content}..." if node.next_sibling + true + else + truncated + end + end + + def cross_project_reference(project, entity) + path = project.path_with_namespace + + if entity.kind_of?(Issue) + [path, entity.iid].join('#') + elsif entity.kind_of?(MergeRequest) + [path, entity.iid].join('!') + else + raise '不支持的类型' + end + end +end diff --git a/app/helpers/projects_helper.zh.rb b/app/helpers/projects_helper.zh.rb new file mode 100644 index 00000000000..05c0232c3b0 --- /dev/null +++ b/app/helpers/projects_helper.zh.rb @@ -0,0 +1,282 @@ +module ProjectsHelper + def remove_from_project_team_message(project, user) + "您即将把#{user.name}移出#{project.name}项目组. 您确定?" + end + + def link_to_project(project) + link_to [project.namespace.becomes(Namespace), project] do + title = content_tag(:span, project.name, class: 'project-name') + + if project.namespace + namespace = content_tag(:span, "#{project.namespace.human_name} / ", class: 'namespace-name') + title = namespace + title + end + + title + end + end + + def link_to_member(project, author, opts = {}) + default_opts = { avatar: true, name: true, size: 16 } + opts = default_opts.merge(opts) + + return "(deleted)" unless author + + author_html = "" + + # Build avatar image tag + author_html << image_tag(avatar_icon(author.try(:email), opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar] + + # Build name span tag + author_html << content_tag(:span, sanitize(author.name), class: 'author') if opts[:name] + + author_html = author_html.html_safe + + if opts[:name] + link_to(author_html, user_path(author), class: "author_link").html_safe + else + link_to(author_html, user_path(author), class: "author_link has_tooltip", data: { :'original-title' => sanitize(author.name) } ).html_safe + end + end + + def project_title(project) + if project.group + content_tag :span do + link_to( + simple_sanitize(project.group.name), group_path(project.group) + ) + ' / ' + + link_to(simple_sanitize(project.name), + project_path(project)) + end + else + owner = project.namespace.owner + content_tag :span do + link_to( + simple_sanitize(owner.name), user_path(owner) + ) + ' / ' + + link_to(simple_sanitize(project.name), + project_path(project)) + end + end + end + + def remove_project_message(project) + "您即将删除#{project.name_with_namespace}.\n 删除项目将 无法 恢复!\n 您 绝对 确定?" + end + + def transfer_project_message(project) + "您即将移交 #{project.name_with_namespace} 给其它人. 您 绝对 确定?" + end + + def project_nav_tabs + @nav_tabs ||= get_project_nav_tabs(@project, current_user) + end + + def project_nav_tab?(name) + project_nav_tabs.include? name + end + + def project_active_milestones + @project.milestones.active.order("due_date, title ASC") + end + + def link_to_toggle_star(title, starred, signed_in) + cls = 'star-btn' + cls << ' disabled' unless signed_in + + toggle_html = content_tag('span', class: 'toggle') do + toggle_text = if starred + ' Unstar' + else + ' Star' + end + + 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' } + } + + + content_tag 'span', class: starred ? 'turn-on' : 'turn-off' do + link_to( + toggle_star_namespace_project_path(@project.namespace, @project), + link_opts + ) do + toggle_html + ' ' + count_html + end + end + end + + def link_to_toggle_fork + out = icon('code-fork') + out << ' Fork' + out << content_tag(:span, class: 'count') do + @project.forks_count.to_s + end + end + + private + + def get_project_nav_tabs(project, current_user) + nav_tabs = [:home] + + if !project.empty_repo? && can?(current_user, :download_code, project) + nav_tabs << [:files, :commits, :network, :graphs] + end + + if project.repo_exists? && project.merge_requests_enabled + nav_tabs << :merge_requests + end + + if can?(current_user, :admin_project, project) + nav_tabs << :settings + end + + [:issues, :wiki, :snippets].each do |feature| + nav_tabs << feature if project.send :"#{feature}_enabled" + end + + if project.issues_enabled || project.merge_requests_enabled + nav_tabs << [:milestones, :labels] + end + + nav_tabs.flatten + end + + def git_user_name + if current_user + current_user.name + else + "您的名字" + end + end + + def git_user_email + if current_user + current_user.email + else + "your@email.com" + end + end + + def repository_size(project = nil) + "#{(project || @project).repository_size} MB" + rescue + # In order to prevent 500 error + # when application cannot allocate memory + # to calculate repo size - just show 'Unknown' + '未知' + end + + def project_head_title + title = @project.name_with_namespace + + title = if current_controller?(:tree) + "#{@project.path}\/#{@path} at #{@ref} - " + title + elsif current_controller?(:issues) + if current_action?(:show) + "问题 ##{@issue.iid} - #{@issue.title} - " + title + else + "问题 - " + title + end + elsif current_controller?(:blob) + if current_action?(:new) || current_action?(:create) + "新文件 at #{@ref}" + elsif current_action?(:show) + "#{@blob.path} at #{@ref}" + elsif @blob + "编辑文件 #{@blob.path} at #{@ref}" + end + elsif current_controller?(:commits) + "提交 at #{@ref} - " + title + elsif current_controller?(:merge_requests) + if current_action?(:show) + "合并请求 ##{@merge_request.iid} - " + title + else + "合并请求 - " + title + end + elsif current_controller?(:wikis) + "Wiki - " + title + elsif current_controller?(:network) + "网络图 - " + title + elsif current_controller?(:graphs) + "图示 - " + title + else + title + end + + title + end + + def default_url_to_repo(project = nil) + project = project || @project + current_user ? project.url_to_repo : project.http_url_to_repo + end + + def default_clone_protocol + current_user ? "ssh" : "http" + end + + def project_last_activity(project) + if project.last_activity_at + time_ago_with_tooltip(project.last_activity_at, 'bottom', 'last_activity_time_ago') + else + "Never" + end + end + + def contribution_guide_url(project) + if project && project.repository.contribution_guide + namespace_project_blob_path( + project.namespace, + project, + tree_join(project.default_branch, + project.repository.contribution_guide.name) + ) + end + end + + def hidden_pass_url(original_url) + result = URI(original_url) + result.password = '*****' unless result.password.nil? + result + rescue + original_url + end + + def project_wiki_path_with_version(proj, page, version, is_newest) + url_params = is_newest ? {} : { version_id: version } + namespace_project_wiki_path(proj.namespace, proj, page, url_params) + end + + def project_status_css_class(status) + case status + when "started" + "active" + when "failed" + "danger" + when "finished" + "success" + end + end + + def service_field_value(type, value) + return value unless type == 'password' + + if value.present? + "***********" + else + nil + end + end +end diff --git a/app/helpers/sorting_helper.zh.rb b/app/helpers/sorting_helper.zh.rb new file mode 100644 index 00000000000..4fba1b180c7 --- /dev/null +++ b/app/helpers/sorting_helper.zh.rb @@ -0,0 +1,96 @@ +module SortingHelper + def sort_options_hash + { + sort_value_name => sort_title_name, + sort_value_recently_updated => sort_title_recently_updated, + sort_value_oldest_updated => sort_title_oldest_updated, + sort_value_recently_created => sort_title_recently_created, + sort_value_oldest_created => sort_title_oldest_created, + sort_value_milestone_soon => sort_title_milestone_soon, + sort_value_milestone_later => sort_title_milestone_later, + sort_value_largest_repo => sort_title_largest_repo, + sort_value_recently_signin => sort_title_recently_signin, + sort_value_oldest_signin => sort_title_oldest_signin, + } + end + + def sort_title_oldest_updated + '最先更新的在前' + end + + def sort_title_recently_updated + '最近更新的在前' + end + + def sort_title_oldest_created + '最先创建的在前' + end + + def sort_title_recently_created + '最新创建的在前' + end + + def sort_title_milestone_soon + '快到期的里程碑在前' + end + + def sort_title_milestone_later + '最晚到期的里程碑在前' + end + + def sort_title_name + '名称' + end + + def sort_title_largest_repo + '最大的仓库' + end + + def sort_title_recently_signin + '最近登录' + end + + def sort_title_oldest_signin + '最先登录的在前' + end + + def sort_value_oldest_updated + '更新时间升序' + end + + def sort_value_recently_updated + '更新时间降序' + end + + def sort_value_oldest_created + '创建时间升序' + end + + def sort_value_recently_created + '创建时间降序' + end + + def sort_value_milestone_soon + '里程碑到期时间升序' + end + + def sort_value_milestone_later + '里程碑到期时间降序' + end + + def sort_value_name + '名称升序' + end + + def sort_value_largest_repo + '仓库大小降序' + end + + def sort_value_recently_signin + '最近登录的在前' + end + + def sort_value_oldest_signin + '最先登录的在前' + end +end diff --git a/app/helpers/visibility_level_helper.zh.rb b/app/helpers/visibility_level_helper.zh.rb new file mode 100644 index 00000000000..b701c5ce223 --- /dev/null +++ b/app/helpers/visibility_level_helper.zh.rb @@ -0,0 +1,62 @@ +module VisibilityLevelHelper + def visibility_level_color(level) + case level + when Gitlab::VisibilityLevel::PRIVATE + 'vs-private' + when Gitlab::VisibilityLevel::INTERNAL + 'vs-internal' + when Gitlab::VisibilityLevel::PUBLIC + 'vs-public' + end + end + + def visibility_level_description(level) + capture_haml do + haml_tag :span do + case level + when Gitlab::VisibilityLevel::PRIVATE + haml_concat "给每个用户的项目访问权限必须明确定义." + when Gitlab::VisibilityLevel::INTERNAL + haml_concat "项目可以被任何登录的用户克隆." + when Gitlab::VisibilityLevel::PUBLIC + haml_concat "项目可以在未认证的情况下被克隆." + end + end + end + end + + def snippet_visibility_level_description(level) + capture_haml do + haml_tag :span do + case level + when Gitlab::VisibilityLevel::PRIVATE + haml_concat "代码片段仅自己可见" + when Gitlab::VisibilityLevel::INTERNAL + haml_concat "代码片段对登录用户可见." + when Gitlab::VisibilityLevel::PUBLIC + haml_concat "代码片段对任何人可见, 勿需认证登录." + end + end + end + end + + def visibility_level_icon(level) + case level + when Gitlab::VisibilityLevel::PRIVATE + private_icon + when Gitlab::VisibilityLevel::INTERNAL + internal_icon + when Gitlab::VisibilityLevel::PUBLIC + public_icon + end + end + + def visibility_level_label(level) + Project.visibility_levels.key(level) + end + + def restricted_visibility_levels(show_all = false) + return [] if current_user.is_admin? && !show_all + current_application_settings.restricted_visibility_levels || [] + end +end diff --git a/app/views/admin/application_settings/_form.zh.html.haml b/app/views/admin/application_settings/_form.zh.html.haml new file mode 100644 index 00000000000..3d7413aed49 --- /dev/null +++ b/app/views/admin/application_settings/_form.zh.html.haml @@ -0,0 +1,64 @@ += form_for @application_setting, url: admin_application_settings_path, html: { class: 'form-horizontal fieldset-form' } do |f| + - if @application_setting.errors.any? + #error_explanation + .alert.alert-danger + - @application_setting.errors.full_messages.each do |msg| + %p= msg + + %fieldset + %legend 特性 + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :signup_enabled do + = f.check_box :signup_enabled + 注册已启用 + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :signin_enabled do + = f.check_box :signin_enabled + 登录已启用 + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :gravatar_enabled do + = f.check_box :gravatar_enabled + Gravatar已启用 + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :twitter_sharing_enabled do + = f.check_box :twitter_sharing_enabled, :'aria-describedby' => 'twitter_help_block' + %strong Twitter已启用 + %span.help-block#twitter_help_block 给用户显示一个按钮, 点击按钮可以分享他们新创建的公开或内部项目到twitter + %fieldset + %legend 杂项 + .form-group + = f.label :default_projects_limit, class: 'control-label col-sm-2' + .col-sm-10 + = f.number_field :default_projects_limit, class: 'form-control' + .form-group + = f.label :default_branch_protection, class: 'control-label col-sm-2' + .col-sm-10 + = f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, @application_setting.default_branch_protection), {}, class: 'form-control' + .form-group + = f.label :restricted_visibility_levels, class: 'control-label col-sm-2' + .col-sm-10 + - data_attrs = { toggle: 'buttons' } + .btn-group{ data: data_attrs } + - restricted_level_checkboxes('restricted-visibility-help').each do |level| + = level + %span.help-block#restricted-visibility-help 非管理员用户不能在项目或代码片段中使用所选的等级 + .form-group + = f.label :home_page_url, class: 'control-label col-sm-2' + .col-sm-10 + = f.text_field :home_page_url, class: 'form-control', placeholder: 'http://company.example.com', :'aria-describedby' => 'home_help_block' + %span.help-block#home_help_block 我们会重定向非登录用户到此页面 + .form-group + = f.label :sign_in_text, class: 'control-label col-sm-2' + .col-sm-10 + = f.text_area :sign_in_text, class: 'form-control', rows: 4 + .help-block Markdown已启用 + .form-actions + = f.submit '保存', class: 'btn btn-primary' diff --git a/app/views/admin/application_settings/show.zh.html.haml b/app/views/admin/application_settings/show.zh.html.haml new file mode 100644 index 00000000000..ed84cb7fbce --- /dev/null +++ b/app/views/admin/application_settings/show.zh.html.haml @@ -0,0 +1,3 @@ +%h3.page-title 应用设置 +%hr += render 'form' diff --git a/app/views/admin/applications/_delete_form.zh.html.haml b/app/views/admin/applications/_delete_form.zh.html.haml new file mode 100644 index 00000000000..75bf763e02e --- /dev/null +++ b/app/views/admin/applications/_delete_form.zh.html.haml @@ -0,0 +1,4 @@ +- submit_btn_css ||= 'btn btn-link btn-remove btn-sm' += form_tag admin_application_path(application) do + %input{:name => "_method", :type => "hidden", :value => "delete"}/ + = submit_tag '删除', onclick: "return confirm('您确定?')", class: submit_btn_css \ No newline at end of file diff --git a/app/views/admin/applications/_form.zh.html.haml b/app/views/admin/applications/_form.zh.html.haml new file mode 100644 index 00000000000..07858fed412 --- /dev/null +++ b/app/views/admin/applications/_form.zh.html.haml @@ -0,0 +1,23 @@ += form_for [:admin, @application], url: @url, html: {class: 'form-horizontal', role: 'form'} do |f| + - if application.errors.any? + .alert.alert-danger{"data-alert" => ""} + %p 悲剧了! 检查您的表单可能有错误 + = content_tag :div, class: "form-group#{' has-error' if application.errors[:name].present?}" do + = f.label :name, class: 'col-sm-2 control-label' + .col-sm-10 + = f.text_field :name, class: 'form-control' + = doorkeeper_errors_for application, :name + = content_tag :div, class: "form-group#{' has-error' if application.errors[:redirect_uri].present?}" do + = f.label :redirect_uri, class: 'col-sm-2 control-label' + .col-sm-10 + = f.text_area :redirect_uri, class: 'form-control' + = doorkeeper_errors_for application, :redirect_uri + %span.help-block + 一行一个URI + - if Doorkeeper.configuration.native_redirect_uri + %span.help-block + 本地测试使用 + %code= Doorkeeper.configuration.native_redirect_uri + .form-actions + = f.submit '提交', class: "btn btn-primary wide" + = link_to "取消", admin_applications_path, class: "btn btn-default" diff --git a/app/views/admin/applications/edit.zh.html.haml b/app/views/admin/applications/edit.zh.html.haml new file mode 100644 index 00000000000..d550c40645a --- /dev/null +++ b/app/views/admin/applications/edit.zh.html.haml @@ -0,0 +1,3 @@ +%h3.page-title 编辑应用 +- @url = admin_application_path(@application) += render 'form', application: @application \ No newline at end of file diff --git a/app/views/admin/applications/index.zh.html.haml b/app/views/admin/applications/index.zh.html.haml new file mode 100644 index 00000000000..d672bed1d8f --- /dev/null +++ b/app/views/admin/applications/index.zh.html.haml @@ -0,0 +1,22 @@ +%h3.page-title + 系统OAuth应用 +%p.light + 系统OAuth应用不属于某个用户只能由管理员管理 +%hr +%p= link_to '新建应用', new_admin_application_path, class: 'btn btn-success' +%table.table.table-striped + %thead + %tr + %th 名称 + %th 回调地址 + %th 客户端 + %th + %th + %tbody.oauth-applications + - @applications.each do |application| + %tr{:id => "application_#{application.id}"} + %td= link_to application.name, admin_application_path(application) + %td= application.redirect_uri + %td= application.access_tokens.map(&:resource_owner_id).uniq.count + %td= link_to '编辑', edit_admin_application_path(application), class: 'btn btn-link' + %td= render 'delete_form', application: application diff --git a/app/views/admin/applications/new.zh.html.haml b/app/views/admin/applications/new.zh.html.haml new file mode 100644 index 00000000000..fe286c03734 --- /dev/null +++ b/app/views/admin/applications/new.zh.html.haml @@ -0,0 +1,3 @@ +%h3.page-title 新建应用 +- @url = admin_applications_path += render 'form', application: @application \ No newline at end of file diff --git a/app/views/admin/applications/show.zh.html.haml b/app/views/admin/applications/show.zh.html.haml new file mode 100644 index 00000000000..dd5e28f2ef0 --- /dev/null +++ b/app/views/admin/applications/show.zh.html.haml @@ -0,0 +1,26 @@ +%h3.page-title + 应用: #{@application.name} + + +%table.table + %tr + %td + 应用Id + %td + %code#application_id= @application.uid + %tr + %td + 私匙: + %td + %code#secret= @application.secret + + %tr + %td + 回调地址 + %td + - @application.redirect_uri.split.each do |uri| + %div + %span.monospace= uri +.form-actions + = link_to '编辑', edit_admin_application_path(@application), class: 'btn btn-primary wide pull-left' + = render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10' diff --git a/app/views/admin/background_jobs/show.zh.html.haml b/app/views/admin/background_jobs/show.zh.html.haml new file mode 100644 index 00000000000..de9ef259c9b --- /dev/null +++ b/app/views/admin/background_jobs/show.zh.html.haml @@ -0,0 +1,44 @@ +%h3.page-title 后台执行的任务 +%p.light GitLab使用 #{link_to "sidekiq", "http://sidekiq.org/"} 库实现异步任务的处理 + +%hr + +.panel.panel-default + .panel-heading Sidekiq运行中的进程 + .panel-body + - if @sidekiq_processes.empty? + %h4.cred + %i.fa.fa-exclamation-triangle + 没有运行中的sidekiq进程. 请重启GitLab + - else + %table.table + %thead + %th 用户 + %th 进程ID + %th CPU + %th 内存 + %th 状态 + %th 开始 + %th 命令 + %tbody + - @sidekiq_processes.each do |process| + - next unless process.match(/(sidekiq \d+\.\d+\.\d+.+$)/) + - data = process.strip.split(' ') + %tr + %td= gitlab_config.user + - 5.times do + %td= data.shift + %td= data.join(' ') + + .clearfix + %p + %i.fa.fa-exclamation-circle + 如果显示'[25 of 25 busy]', 请使用 'sudo service gitlab reload' 重启GitLab服务. + %p + %i.fa.fa-exclamation-circle + 如果不止一个sidekiq进程在列表中, 停止GitLab, 杀死剩余的sidekiq进程 ( sudo pkill -u #{gitlab_config.user} -f sidekiq ) 后重启GitLab服务. + + + +.panel.panel-default + %iframe{src: sidekiq_path, width: '100%', height: 900, style: "border: none"} diff --git a/app/views/admin/broadcast_messages/index.zh.html.haml b/app/views/admin/broadcast_messages/index.zh.html.haml new file mode 100644 index 00000000000..eea84e2886f --- /dev/null +++ b/app/views/admin/broadcast_messages/index.zh.html.haml @@ -0,0 +1,61 @@ +%h3.page-title + 广播信息 +%p.light + 广播信息会显示给每个用户, 可用于通知用户常规维护、最新更新等. +.broadcast-message-preview + %i.fa.fa-bullhorn + %span 您的消息显示在这里 + += form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal'} do |f| + -if @broadcast_message.errors.any? + .alert.alert-danger + - @broadcast_message.errors.full_messages.each do |msg| + %p= msg + .form-group + = f.label :message, class: 'control-label' + .col-sm-10 + = f.text_area :message, class: "form-control", rows: 2, required: true + %div + = link_to '#', class: 'js-toggle-colors-link' do + 自定义颜色 + .form-group.js-toggle-colors-container.hide + = f.label :color, "Background Color", class: 'control-label' + .col-sm-10 + = f.text_field :color, placeholder: "#AA33EE", class: "form-control" + .light 以#号开始的6位十六进制值. + .form-group.js-toggle-colors-container.hide + = f.label :font, "Font Color", class: 'control-label' + .col-sm-10 + = f.text_field :font, placeholder: "#224466", class: "form-control" + .light 以#号开始的6位十六进制值. + .form-group + = f.label :starts_at, class: 'control-label' + .col-sm-10.datetime-controls + = f.datetime_select :starts_at + .form-group + = f.label :ends_at, class: 'control-label' + .col-sm-10.datetime-controls + = f.datetime_select :ends_at + .form-actions + = f.submit "添加广播信息", class: "btn btn-create" + +-if @broadcast_messages.any? + %ul.bordered-list.broadcast-messages + - @broadcast_messages.each do |broadcast_message| + %li + .pull-right + - if broadcast_message.starts_at + %strong + #{broadcast_message.starts_at.to_s(:short)} + \... + - if broadcast_message.ends_at + %strong + #{broadcast_message.ends_at.to_s(:short)} +   + = link_to [:admin, broadcast_message], method: :delete, remote: true, class: 'remove-row btn btn-xs' do + %i.fa.fa-times.cred + + .message= broadcast_message.message + + + = paginate @broadcast_messages diff --git a/app/views/admin/dashboard/index.zh.html.haml b/app/views/admin/dashboard/index.zh.html.haml new file mode 100644 index 00000000000..56c69efb9e7 --- /dev/null +++ b/app/views/admin/dashboard/index.zh.html.haml @@ -0,0 +1,137 @@ +.admin-dashboard + .row + .col-md-4 + %h4 统计数据 + %hr + %p + Fork + %span.light.pull-right + = ForkedProjectLink.count + %p + 问题 + %span.light.pull-right + = Issue.count + %p + 合并请求 + %span.light.pull-right + = MergeRequest.count + %p + 笔记 + %span.light.pull-right + = Note.count + %p + 代码片段 + %span.light.pull-right + = Snippet.count + %p + SSH Key + %span.light.pull-right + = Key.count + %p + 里程碑 + %span.light.pull-right + = Milestone.count + %p + 活跃用户 + %span.light.pull-right + = User.active.count + .col-md-4 + %h4 + 特性 + %hr + %p + 注册 + %span.light.pull-right + = boolean_to_icon signup_enabled? + %p + LDAP + %span.light.pull-right + = boolean_to_icon Gitlab.config.ldap.enabled + %p + Gravatar(头像) + %span.light.pull-right + = boolean_to_icon gravatar_enabled? + %p + OmniAuth(认证) + %span.light.pull-right + = boolean_to_icon Gitlab.config.omniauth.enabled + .col-md-4 + %h4 组件 + %hr + %p + GitLab + %span.pull-right + = Gitlab::VERSION + %p + GitLab Shell + %span.pull-right + = Gitlab::Shell.new.version + %p + GitLab API + %span.pull-right + = API::API::version + %p + Ruby + %span.pull-right + #{RUBY_VERSION}p#{RUBY_PATCHLEVEL} + + %p + Rails + %span.pull-right + #{Rails::VERSION::STRING} + %hr + .row + .col-sm-4 + .light-well + %h4 项目 + .data + = link_to admin_namespaces_projects_path do + %h1= Project.count + %hr + = link_to('新建项目', new_project_path, class: "btn btn-new") + .col-sm-4 + .light-well + %h4 用户 + .data + = link_to admin_users_path do + %h1= User.count + %hr + = link_to '新建用户', new_admin_user_path, class: "btn btn-new" + .col-sm-4 + .light-well + %h4 组 + .data + = link_to admin_groups_path do + %h1= Group.count + %hr + = link_to '新建组', new_admin_group_path, class: "btn btn-new" + + .row.prepend-top-10 + .col-md-4 + %h4 最近的项目 + %hr + - @projects.each do |project| + %p + = link_to project.name_with_namespace, [:admin, project.namespace.becomes(Namespace), project], class: 'str-truncated' + %span.light.pull-right + #{time_ago_with_tooltip(project.created_at)} + + .col-md-4 + %h4 最近注册的用户 + %hr + - @users.each do |user| + %p + = link_to [:admin, user], class: 'str-truncated' do + = user.name + %span.light.pull-right + #{time_ago_with_tooltip(user.created_at)} + + .col-md-4 + %h4 最近创建的组 + %hr + - @groups.each do |group| + %p + = link_to [:admin, group], class: 'str-truncated' do + = group.name + %span.light.pull-right + #{time_ago_with_tooltip(group.created_at)} diff --git a/app/views/admin/groups/_form.zh.html.haml b/app/views/admin/groups/_form.zh.html.haml new file mode 100644 index 00000000000..211a6fffc92 --- /dev/null +++ b/app/views/admin/groups/_form.zh.html.haml @@ -0,0 +1,27 @@ += form_for [:admin, @group], html: { class: "form-horizontal" } do |f| + - if @group.errors.any? + .alert.alert-danger + %span= @group.errors.full_messages.first + + = render 'shared/group_form', f: f + + .form-group.group-description-holder + = f.label :avatar, "Group avatar", class: 'control-label' + .col-sm-10 + = render 'shared/choose_group_avatar_button', f: f + + - if @group.new_record? + .form-group + .col-sm-2 + .col-sm-10 + .alert.alert-info + = render 'shared/group_tips' + .form-actions + = f.submit '创建组', class: "btn btn-create" + = link_to '取消', admin_groups_path, class: "btn btn-cancel" + + - else + .form-actions + = f.submit '保存修改', class: "btn btn-primary" + = link_to '取消', admin_group_path(@group), class: "btn btn-cancel" + diff --git a/app/views/admin/groups/index.zh.html.haml b/app/views/admin/groups/index.zh.html.haml new file mode 100644 index 00000000000..cc2d5635b7f --- /dev/null +++ b/app/views/admin/groups/index.zh.html.haml @@ -0,0 +1,62 @@ +%h3.page-title + Groups (#{@groups.total_count}) + = link_to '创建组', new_admin_group_path, class: "btn btn-new pull-right" + +%p.light + 组用来方便您组织项目. + 用户组用于组织相关项目. + +%hr += form_tag admin_groups_path, method: :get, class: 'form-inline' do + = hidden_field_tag :sort, @sort + .form-group + = text_field_tag :name, params[:name], class: "form-control input-mn-300" + = button_tag "搜索", class: "btn submit btn-primary" + + .pull-right + .dropdown.inline + %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"} + %span.light sort: + - if @sort.present? + = sort_options_hash[@sort] + - else + = sort_title_recently_created + %b.caret + %ul.dropdown-menu + %li + = link_to admin_groups_path(sort: sort_value_recently_created) do + = sort_title_recently_created + = link_to admin_groups_path(sort: sort_value_oldest_created) do + = sort_title_oldest_created + = link_to admin_groups_path(sort: sort_value_recently_updated) do + = sort_title_recently_updated + = link_to admin_groups_path(sort: sort_value_oldest_updated) do + = sort_title_oldest_updated + +%hr + +%ul.bordered-list + - @groups.each do |group| + %li + .clearfix + .pull-right.prepend-top-10 + = link_to '编辑', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-sm" + = link_to '删除', [:admin, group], data: {confirm: "删除 #{group.name}? 您确定?"}, method: :delete, class: "btn btn-sm btn-remove" + + %h4 + = link_to [:admin, group] do + %i.fa.fa-folder + = group.name + + → + %span.monospace + %strong #{group.path}/ + .clearfix + %p + = truncate group.description, length: 150 + .clearfix + %p.light + #{pluralize(group.members.size, 'member')}, #{pluralize(group.projects.count, 'project')} + + += paginate @groups, theme: "gitlab" diff --git a/app/views/admin/groups/new.zh.html.haml b/app/views/admin/groups/new.zh.html.haml new file mode 100644 index 00000000000..70e632fa8a3 --- /dev/null +++ b/app/views/admin/groups/new.zh.html.haml @@ -0,0 +1,3 @@ +%h3.page-title 新建组 +%hr += render 'form' diff --git a/app/views/admin/groups/show.zh.html.haml b/app/views/admin/groups/show.zh.html.haml new file mode 100644 index 00000000000..b3344fe962d --- /dev/null +++ b/app/views/admin/groups/show.zh.html.haml @@ -0,0 +1,86 @@ +%h3.page-title + Group: #{@group.name} + + = link_to edit_admin_group_path(@group), class: "btn pull-right" do + %i.fa.fa-pencil-square-o + 编辑 +%hr +.row + .col-md-6 + .panel.panel-default + .panel-heading + 组信息: + %ul.well-list + %li + = image_tag group_icon(@group), class: "avatar s60" + %li + %span.light 名称: + %strong= @group.name + %li + %span.light 路径: + %strong + = @group.path + + %li + %span.light 描述: + %strong + = @group.description + + %li + %span.light 创建于: + %strong + = @group.created_at.stamp("March 1, 1999") + + .panel.panel-default + .panel-heading + %h3.panel-title + 项目 + %span.badge + #{@group.projects.count} + %ul.well-list + - @projects.each do |project| + %li + %strong + = link_to project.name_with_namespace, [:admin, project.namespace.becomes(Namespace), project] + %span.label.label-gray + = repository_size(project) + %span.pull-right.light + %span.monospace= project.path_with_namespace + ".git" + .panel-footer + = paginate @projects, param_name: 'projects_page', theme: 'gitlab' + + .col-md-6 + .panel.panel-default + .panel-heading + 添加用户到组: + .panel-body.form-holder + %p.light + 阅读更多关于项目权限的信息 + %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" + + = form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put do + %div + = users_select_tag(:user_ids, multiple: true) + %div.prepend-top-10 + = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2" + %hr + = button_tag '添加用户到组', class: "btn btn-create" + .panel.panel-default + .panel-heading + %h3.panel-title + 成员 + %span.badge + #{@group.group_members.count} + %ul.well-list.group-users-list + - @members.each do |member| + - user = member.user + %li{class: dom_class(member), id: dom_id(user)} + .list-item-name + %strong + = link_to user.name, admin_user_path(user) + %span.pull-right.light + = member.human_access + = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: '从组中删除用户' do + %i.fa.fa-minus.fa-inverse + .panel-footer + = paginate @members, param_name: 'members_page', theme: 'gitlab' diff --git a/app/views/admin/hooks/index.zh.html.haml b/app/views/admin/hooks/index.zh.html.haml new file mode 100644 index 00000000000..7aee0b1d168 --- /dev/null +++ b/app/views/admin/hooks/index.zh.html.haml @@ -0,0 +1,36 @@ +%h3.page-title + 系统钩子 + +%p.light + #{link_to "系统钩子 ", help_page_path("system_hooks", "system_hooks"), class: "vlink"} 用于绑定GitLab用户或项目创建事件. + +%hr + + += form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-horizontal' } do |f| + -if @hook.errors.any? + .alert.alert-danger + - @hook.errors.full_messages.each do |msg| + %p= msg + .form-group + = f.label :url, "URL:", class: 'control-label' + .col-sm-10 + = f.text_field :url, class: "form-control" + .form-actions + = f.submit "添加系统钩子", class: "btn btn-create" +%hr + +-if @hooks.any? + .panel.panel-default + .panel-heading + 系统钩子(#{@hooks.count}) + %ul.well-list + - @hooks.each do |hook| + %li + .list-item-name + = link_to admin_hook_path(hook) do + %strong= hook.url + + .pull-right + = link_to '测试钩子', admin_hook_test_path(hook), class: "btn btn-sm" + = link_to '删除钩子', admin_hook_path(hook), data: { confirm: '您确定?' }, method: :delete, class: "btn btn-remove btn-sm" diff --git a/app/views/admin/logs/show.zh.html.haml b/app/views/admin/logs/show.zh.html.haml new file mode 100644 index 00000000000..0c78d94b3bb --- /dev/null +++ b/app/views/admin/logs/show.zh.html.haml @@ -0,0 +1,25 @@ +- loggers = [Gitlab::GitLogger, Gitlab::AppLogger, + Gitlab::ProductionLogger, Gitlab::SidekiqLogger] +%ul.nav.nav-tabs.log-tabs + - loggers.each do |klass| + %li{ class: (klass == Gitlab::GitLogger ? 'active' : '') } + = link_to klass::file_name, "##{klass::file_name_noext}", + 'data-toggle' => 'tab' +%p.light 为了避免出现性能问题管理员日志仅输出最近的2000行. +.tab-content + - loggers.each do |klass| + .tab-pane{ class: (klass == Gitlab::GitLogger ? 'active' : ''), + id: klass::file_name_noext } + .file-holder#README + .file-title + %i.fa.fa-file + = klass::file_name + .pull-right + = link_to '#', class: 'log-bottom' do + %i.fa.fa-arrow-down + 向下滚 + .file-content.logs + %ol + - klass.read_latest.each do |line| + %li + %p= line diff --git a/app/views/admin/projects/index.zh.html.haml b/app/views/admin/projects/index.zh.html.haml new file mode 100644 index 00000000000..1babd632e22 --- /dev/null +++ b/app/views/admin/projects/index.zh.html.haml @@ -0,0 +1,81 @@ +.row + = link_to '#aside', class: 'show-aside' do + %i.fa.fa-angle-left + %aside.col-md-3 + .admin-filter + = form_tag admin_namespaces_projects_path, method: :get, class: '' do + .form-group + = label_tag :name, '名称:' + = text_field_tag :name, params[:name], class: "form-control" + + .form-group + = label_tag :namespace_id, "命名空间" + = namespace_select_tag :namespace_id, selected: params[:namespace_id], class: 'input-large' + + .form-group + %strong 活动 + .checkbox + = label_tag :with_push do + = check_box_tag :with_push, 1, params[:with_push] + %span 产生了推送事件的项目 + .checkbox + = label_tag :abandoned do + = check_box_tag :abandoned, 1, params[:abandoned] + %span 近6月没有活动 + + %fieldset + %strong 可见度: + .visibility-levels + - Project.visibility_levels.each do |label, level| + .checkbox + %label + = check_box_tag 'visibility_levels[]', level, params[:visibility_levels].present? && params[:visibility_levels].include?(level.to_s) + %span.descr + = visibility_level_icon(level) + = label + %hr + = hidden_field_tag :sort, params[:sort] + = button_tag "搜索", class: "btn submit btn-primary" + = link_to "重置", admin_namespaces_projects_path, class: "btn btn-cancel" + + %section.col-md-9 + .panel.panel-default + .panel-heading + 项目 (#{@projects.total_count}) + .panel-head-actions + .dropdown.inline + %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'} + %span.light sort: + - if @sort.present? + = sort_options_hash[@sort] + - else + = sort_title_recently_created + %b.caret + %ul.dropdown-menu + %li + = link_to admin_namespaces_projects_path(sort: sort_value_recently_created) do + = sort_title_recently_created + = link_to admin_namespaces_projects_path(sort: sort_value_oldest_created) do + = sort_title_oldest_created + = link_to admin_namespaces_projects_path(sort: sort_value_recently_updated) do + = sort_title_recently_updated + = link_to admin_namespaces_projects_path(sort: sort_value_oldest_updated) do + = sort_title_oldest_updated + = link_to admin_namespaces_projects_path(sort: sort_value_largest_repo) do + = sort_title_largest_repo + = link_to '新建项目', new_project_path, class: "btn btn-sm btn-success" + %ul.well-list + - @projects.each do |project| + %li + .list-item-name + %span{ class: visibility_level_color(project.visibility_level) } + = visibility_level_icon(project.visibility_level) + = link_to project.name_with_namespace, [:admin, project.namespace.becomes(Namespace), project] + .pull-right + %span.label.label-gray + = repository_size(project) + = link_to '编辑', edit_namespace_project_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn btn-sm" + = link_to '删除', [project.namespace.becomes(Namespace), project], data: { confirm: remove_project_message(project) }, method: :delete, class: "btn btn-sm btn-remove" + - if @projects.blank? + .nothing-here-block 0 projects matches + = paginate @projects, theme: "gitlab" diff --git a/app/views/admin/projects/show.zh.html.haml b/app/views/admin/projects/show.zh.html.haml new file mode 100644 index 00000000000..e8bfd380b0e --- /dev/null +++ b/app/views/admin/projects/show.zh.html.haml @@ -0,0 +1,132 @@ +%h3.page-title + 项目: #{@project.name_with_namespace} + = link_to edit_project_path(@project), class: "btn pull-right" do + %i.fa.fa-pencil-square-o + 编辑 +%hr +.row + .col-md-6 + .panel.panel-default + .panel-heading + 项目信息: + %ul.well-list + %li + %span.light 项目名: + %strong + = link_to @project.name, project_path(@project) + %li + %span.light 命名空间: + %strong + - if @project.namespace + = link_to @project.namespace.human_name, [:admin, @project.group || @project.owner] + - else + 全局的 + %li + %span.light 所有者: + %strong + - if @project.owner + = link_to @project.owner_name, [:admin, @project.owner] + - else + (已删除) + + %li + %span.light 创建者: + %strong + = @project.creator.try(:name) || '(已删除)' + + %li + %span.light 创建于: + %strong + = @project.created_at.stamp("March 1, 1999") + + %li + %span.light http: + %strong + = link_to @project.http_url_to_repo + %li + %span.light ssh: + %strong + = link_to @project.ssh_url_to_repo + - if @project.repository.exists? + %li + %span.light fs: + %strong + = @repository.path_to_repo + + %li + %span.light 大小 + %strong + = repository_size(@project) + + %li + %span.light 上次提交: + %strong + = last_commit(@project) + - else + %li + %span.light 仓库: + %strong.cred + 不存在 + + %li + %span.light 访问控制: + %strong + %span{ class: visibility_level_color(@project.visibility_level) } + = visibility_level_icon(@project.visibility_level) + = visibility_level_label(@project.visibility_level) + + .panel.panel-default + .panel-heading + 移交项目 + .panel-body + = form_for @project, url: transfer_admin_namespace_project_path(@project.namespace, @project), method: :put, html: { class: 'form-horizontal' } do |f| + .form-group + = f.label :new_namespace_id, "命名空间", class: 'control-label' + .col-sm-10 + = namespace_select_tag :new_namespace_id, selected: params[:namespace_id], class: 'input-large' + + .form-group + .col-sm-2 + .col-sm-10 + = f.submit '移交', class: 'btn btn-primary' + + .col-md-6 + - if @group + .panel.panel-default + .panel-heading + %strong #{@group.name} + 组成员 (#{@group.group_members.count}) + .pull-right + = link_to admin_group_path(@group), class: 'btn btn-sm' do + %i.fa.fa-pencil-square-o + %ul.well-list + - @group_members.each do |member| + = render 'groups/group_members/group_member', member: member, show_controls: false + .panel-footer + = paginate @group_members, param_name: 'group_members_page', theme: 'gitlab' + + .panel.panel-default + .panel-heading + 项目成员 + %small + (#{@project.users.count}) + .pull-right + = link_to namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-xs" do + %i.fa.fa-pencil-square-o + 管理访问权限 + %ul.well-list.project_members + - @project_members.each do |project_member| + - user = project_member.user + %li.project_member + .list-item-name + %strong + = link_to user.name, admin_user_path(user) + .pull-right + - if project_member.owner? + %span.light 所有者 + - else + %span.light= project_member.human_access + = link_to namespace_project_project_member_path(@project.namespace, @project, user), data: { confirm: remove_from_project_team_message(@project, user)}, method: :delete, remote: true, class: "btn btn-sm btn-remove" do + %i.fa.fa-times + .panel-footer + = paginate @project_members, param_name: 'project_members_page', theme: 'gitlab' diff --git a/app/views/admin/services/_form.zh.html.haml b/app/views/admin/services/_form.zh.html.haml new file mode 100644 index 00000000000..2e570733739 --- /dev/null +++ b/app/views/admin/services/_form.zh.html.haml @@ -0,0 +1,94 @@ +%h3.page-title + = @service.title + +%p #{@service.description} 模板 + += form_for :service, url: admin_application_settings_service_path, method: :put, html: { class: 'form-horizontal fieldset-form' } do |f| + - if @service.errors.any? + #error_explanation + .alert.alert-danger + - @service.errors.full_messages.each do |msg| + %p= msg + - if @service.help.present? + .alert.alert-info + = preserve do + = markdown @service.help + + .form-group + = f.label :active, "激活", class: "control-label" + .col-sm-10 + = f.check_box :active + + - if @service.supported_events.length > 1 + .form-group + = f.label :url, "触发器", class: 'control-label' + .col-sm-10 + - if @service.supported_events.include?("push") + %div + = f.check_box :push_events, class: 'pull-left' + .prepend-left-20 + = f.label :push_events, class: 'list-label' do + %strong 推送事件 + %p.light + 此url会在向仓库推送的时候触发 + - if @service.supported_events.include?("tag_push") + %div + = f.check_box :tag_push_events, class: 'pull-left' + .prepend-left-20 + = f.label :tag_push_events, class: 'list-label' do + %strong 标签推送事件 + %p.light + 此url会在新标签推往仓库的时候触发 + - if @service.supported_events.include?("note") + %div + = f.check_box :note_events, class: 'pull-left' + .prepend-left-20 + = f.label :note_events, class: 'list-label' do + %strong 评论 + %p.light + 此url会在有人添加评论的时候触发 + - if @service.supported_events.include?("issue") + %div + = f.check_box :issues_events, class: 'pull-left' + .prepend-left-20 + = f.label :issues_events, class: 'list-label' do + %strong 问题事件 + %p.light + 此url会在新问题被创建的时候触发 + - if @service.supported_events.include?("merge_request") + %div + = f.check_box :merge_requests_events, class: 'pull-left' + .prepend-left-20 + = f.label :merge_requests_events, class: 'list-label' do + %strong 合并请求事件 + %p.light + 此url会在新的合并请求创建的时候触发 + + - @service.fields.each do |field| + - name = field[:name] + - title = field[:title] || name.humanize + - value = @service.send(name) unless field[:type] == 'password' + - type = field[:type] + - placeholder = field[:placeholder] + - choices = field[:choices] + - default_choice = field[:default_choice] + - help = field[:help] + + .form-group + = f.label name, title, class: "control-label" + .col-sm-10 + - if type == 'text' + = f.text_field name, class: "form-control", placeholder: placeholder + - elsif type == 'textarea' + = f.text_area name, rows: 5, class: "form-control", placeholder: placeholder + - elsif type == 'checkbox' + = f.check_box name + - elsif type == 'select' + = f.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" } + - elsif type == 'password' + = f.password_field name, class: 'form-control' + - if help + %span.help-block= help + + .form-actions + = f.submit '保存', class: 'btn btn-save' diff --git a/app/views/admin/services/index.zh.html.haml b/app/views/admin/services/index.zh.html.haml new file mode 100644 index 00000000000..5587a8c747a --- /dev/null +++ b/app/views/admin/services/index.zh.html.haml @@ -0,0 +1,22 @@ +%h3.page-title 服务模板 +%p.light 服务模板允许您为项目服务设置默认值 + +%table.table + %thead + %tr + %th + %th 服务 + %th 描述 + %th 最近编辑 + - @services.sort_by(&:title).each do |service| + %tr + %td + = icon("copy", class: 'clgray') + %td + = link_to edit_admin_application_settings_service_path(service.id) do + %strong= service.title + %td + = service.description + %td.light + = time_ago_in_words service.updated_at + ago diff --git a/app/views/admin/users/_form.zh.html.haml b/app/views/admin/users/_form.zh.html.haml new file mode 100644 index 00000000000..92dc550a0dc --- /dev/null +++ b/app/views/admin/users/_form.zh.html.haml @@ -0,0 +1,90 @@ +.user_new + = form_for [:admin, @user], html: { class: 'form-horizontal fieldset-form' } do |f| + -if @user.errors.any? + #error_explanation + .alert.alert-danger + - @user.errors.full_messages.each do |msg| + %p= msg + + %fieldset + %legend 帐号 + .form-group + = f.label :name, class: 'control-label' + .col-sm-10 + = f.text_field :name, required: true, autocomplete: "off", class: 'form-control' + %span.help-inline * 必填 + .form-group + = f.label :username, class: 'control-label' + .col-sm-10 + = f.text_field :username, required: true, autocomplete: "off", class: 'form-control' + %span.help-inline * 必填 + .form-group + = f.label :email, class: 'control-label' + .col-sm-10 + = f.text_field :email, required: true, autocomplete: "off", class: 'form-control' + %span.help-inline * 必填 + + - if @user.new_record? + %fieldset + %legend 密码 + .form-group + = f.label :password, class: 'control-label' + .col-sm-10 + %strong + 重置链接将会生成并发送给用户. + %br + 用户在第一次登录的时候会被强制要求设置密码. + - else + %fieldset + %legend Password + .form-group + = f.label :password, class: 'control-label' + .col-sm-10= f.password_field :password, disabled: f.object.force_random_password, class: 'form-control' + .form-group + = f.label :password_confirmation, class: 'control-label' + .col-sm-10= f.password_field :password_confirmation, disabled: f.object.force_random_password, class: 'form-control' + + %fieldset + %legend 访问控制 + .form-group + = f.label :projects_limit, class: 'control-label' + .col-sm-10= f.number_field :projects_limit, class: 'form-control' + + .form-group + = f.label :can_create_group, class: 'control-label' + .col-sm-10= f.check_box :can_create_group + + .form-group + = f.label :admin, class: 'control-label' + - if current_user == @user + .col-sm-10= f.check_box :admin, disabled: true + .col-sm-10 您不能删除你自己的管理员权限 + - else + .col-sm-10= f.check_box :admin + %fieldset + %legend 用户资料 + .form-group + = f.label :avatar, class: 'control-label' + .col-sm-10 + = f.file_field :avatar + + .form-group + = f.label :skype, class: 'control-label' + .col-sm-10= f.text_field :skype, class: 'form-control' + .form-group + = f.label :linkedin, class: 'control-label' + .col-sm-10= f.text_field :linkedin, class: 'form-control' + .form-group + = f.label :twitter, class: 'control-label' + .col-sm-10= f.text_field :twitter, class: 'form-control' + .form-group + = f.label :website_url, '网站', class: 'control-label' + .col-sm-10= f.text_field :website_url, class: 'form-control' + + .form-actions + - if @user.new_record? + = f.submit '创建用户', class: "btn btn-create" + = link_to '取消', admin_users_path, class: "btn btn-cancel" + - else + = f.submit '保存修改', class: "btn btn-save" + = link_to '取消', admin_user_path(@user), class: "btn btn-cancel" diff --git a/app/views/admin/users/edit.zh.html.haml b/app/views/admin/users/edit.zh.html.haml new file mode 100644 index 00000000000..f745b6219da --- /dev/null +++ b/app/views/admin/users/edit.zh.html.haml @@ -0,0 +1,7 @@ +%h3.page-title + 编辑用户: #{@user.name} +.back-link + = link_to admin_user_path(@user) do + ← 返回用户页 +%hr += render 'form' diff --git a/app/views/admin/users/index.zh.html.haml b/app/views/admin/users/index.zh.html.haml new file mode 100644 index 00000000000..2b3221beb06 --- /dev/null +++ b/app/views/admin/users/index.zh.html.haml @@ -0,0 +1,88 @@ +.row + = link_to '#aside', class: 'show-aside' do + %i.fa.fa-angle-left + %aside.col-md-3 + .admin-filter + %ul.nav.nav-pills.nav-stacked + %li{class: "#{'active' unless params[:filter]}"} + = link_to admin_users_path do + 激活状态 + %small.pull-right= User.active.count + %li{class: "#{'active' if params[:filter] == "admins"}"} + = link_to admin_users_path(filter: "admins") do + 管理员 + %small.pull-right= User.admins.count + %li{class: "#{'active' if params[:filter] == "blocked"}"} + = link_to admin_users_path(filter: "blocked") do + 被屏蔽 + %small.pull-right= User.blocked.count + %li{class: "#{'active' if params[:filter] == "wop"}"} + = link_to admin_users_path(filter: "wop") do + 无项目 + %small.pull-right= User.without_projects.count + %hr + = form_tag admin_users_path, method: :get, class: 'form-inline' do + .form-group + = search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control' + = button_tag class: 'btn btn-primary' do + %i.fa.fa-search + %hr + = link_to '重置', admin_users_path, class: "btn btn-cancel" + + %section.col-md-9 + .panel.panel-default + .panel-heading + 用户 (#{@users.total_count}) + .panel-head-actions + .dropdown.inline + %a.dropdown-toggle.btn.btn-sm{href: '#', "data-toggle" => "dropdown"} + %span.light sort: + - if @sort.present? + = sort_options_hash[@sort] + - else + = sort_title_name + %b.caret + %ul.dropdown-menu + %li + = link_to admin_users_path(sort: sort_value_name) do + = sort_title_name + = link_to admin_users_path(sort: sort_value_recently_signin) do + = sort_title_recently_signin + = link_to admin_users_path(sort: sort_value_oldest_signin) do + = sort_title_oldest_signin + = link_to admin_users_path(sort: sort_value_recently_created) do + = sort_title_recently_created + = link_to admin_users_path(sort: sort_value_oldest_created) do + = sort_title_oldest_created + = link_to admin_users_path(sort: sort_value_recently_updated) do + = sort_title_recently_updated + = link_to admin_users_path(sort: sort_value_oldest_updated) do + = sort_title_oldest_updated + + = link_to '新建用户', new_admin_user_path, class: "btn btn-new btn-sm" + %ul.well-list + - @users.each do |user| + %li + .list-item-name + - if user.blocked? + %i.fa.fa-lock.cred + - else + %i.fa.fa-user.cgreen + = link_to user.name, [:admin, user] + - if user.admin? + %strong.cred (Admin) + - if user == current_user + %span.cred 就是您! + .pull-right + %span.light + %i.fa.fa-envelope + = mail_to user.email, user.email, class: 'light' +   + = link_to '编辑', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-sm" + - unless user == current_user + - if user.blocked? + = link_to '取消屏蔽', unblock_admin_user_path(user), method: :put, class: "btn btn-sm success" + - else + = link_to '屏蔽', block_admin_user_path(user), data: {confirm: '用户即将被屏蔽! 您确定?'}, method: :put, class: "btn btn-sm btn-remove" + = link_to '删除', [:admin, user], data: { confirm: "用户 #{user.name} 即将被删除! 所有链接到这个用户的的tickets也会被删除! 或许您可以屏蔽这个用户? 您确定?" }, method: :delete, class: "btn btn-sm btn-remove" + = paginate @users, theme: "gitlab" diff --git a/app/views/admin/users/new.zh.html.haml b/app/views/admin/users/new.zh.html.haml new file mode 100644 index 00000000000..6cd83c5a41e --- /dev/null +++ b/app/views/admin/users/new.zh.html.haml @@ -0,0 +1,4 @@ +%h3.page-title + 新建用户 +%hr += render 'form' diff --git a/app/views/admin/users/show.zh.html.haml b/app/views/admin/users/show.zh.html.haml new file mode 100644 index 00000000000..5c23d04f4f5 --- /dev/null +++ b/app/views/admin/users/show.zh.html.haml @@ -0,0 +1,227 @@ +%h3.page-title + 用户: + = @user.name + - if @user.blocked? + %span.cred (被屏蔽) + - if @user.admin + %span.cred (管理员) + + .pull-right + = link_to edit_admin_user_path(@user), class: "btn btn-grouped" do + %i.fa.fa-pencil-square-o + 编辑 +%hr +%ul.nav.nav-tabs + %li.active + %a{"data-toggle" => "tab", href: "#account"} 帐号 + %li + %a{"data-toggle" => "tab", href: "#profile"} 用户资料 + %li + %a{"data-toggle" => "tab", href: "#groups"} 组 + %li + %a{"data-toggle" => "tab", href: "#projects"} 项目 + %li + %a{"data-toggle" => "tab", href: "#ssh-keys"} SSH key + +.tab-content + #account.tab-pane.active + .row + .col-md-6 + .panel.panel-default + .panel-heading + 帐号: + %ul.well-list + %li + %span.light 名称: + %strong= @user.name + %li + %span.light 用户名: + %strong + = @user.username + %li + %span.light 邮箱: + %strong + = mail_to @user.email + - @user.emails.each do |email| + %li + %span.light 备用邮箱: + %strong= email.email + = link_to remove_email_admin_user_path(@user, email), data: { confirm: "您确定要删除邮箱 #{email.email}?" }, method: :delete, class: "btn-xs btn btn-remove pull-right", title: '删除备用邮箱', id: "remove_email_#{email.id}" do + %i.fa.fa-times + + %li + %span.light 能否创建组: + %strong + = @user.can_create_group ? "能" : "不能" + %li + %span.light 个人项目限制数: + %strong + = @user.projects_limit + %li + %span.light 用户创建于: + %strong + = @user.created_at.stamp("Nov 12, 2031") + - if @user.confirmed_at + %li + %span.light 确认于: + %strong + = @user.confirmed_at.stamp("Nov 12, 2031") + - else + %li + %span.light 是否确认: + %strong.cred + 否 + + %li + %span.light 当前登录于: + %strong + - if @user.current_sign_in_at + = @user.current_sign_in_at.stamp("Nov 12, 2031") + - else + 未曾登录 + + %li + %span.light 最近登录于: + %strong + - if @user.last_sign_in_at + = @user.last_sign_in_at.stamp("Nov 12, 2031") + - else + 未曾登录 + + %li + %span.light 登录次数: + %strong + = @user.sign_in_count + + - if @user.ldap_user? + %li + %span.light LDAP uid: + %strong + = @user.ldap_identity.extern_uid + + - if @user.created_by + %li + %span.light 创建者: + %strong + = link_to @user.created_by.name, [:admin, @user.created_by] + + .col-md-6 + - unless @user == current_user + - if @user.blocked? + .panel.panel-info + .panel-heading + 用户被屏蔽 + .panel-body + %p 屏蔽用户会有以下影响: + %ul + %li 用户不能登录 + %li 用户不能访问git仓库 + %li 个人项目会被保留 + %li 拥有的组会被保留 + %br + = link_to '取消屏蔽用户', unblock_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: '您确定?' } + - else + .panel.panel-warning + .panel-heading + 屏蔽该用户 + .panel-body + %p 屏蔽用户会有以下影响: + %ul + %li 用户不能登录 + %li 用户不能访问git仓库 + %li 用户会被移出参与的项目和组 + %li 个人项目会被保留 + %li 拥有的组会被保留 + %br + = link_to '屏蔽用户', block_admin_user_path(@user), data: { confirm: '用户即将被屏蔽! 您确定?' }, method: :put, class: "btn btn-warning" + + .panel.panel-danger + .panel-heading + 删除用户 + .panel-body + %p 删除用户会有以下影响: + %ul + %li 所有的用户内容像提交的问题, 代码片段, 评论等将被删除 + - rp = @user.personal_projects.count + - unless rp.zero? + %li #{pluralize rp, 'personal project'} will be removed and cannot be restored + - if @user.solo_owned_groups.present? + %li + 组及其内容也会被删除: + %strong #{@user.solo_owned_groups.map(&:name).join(', ')} + %br + = link_to '删除用户', [:admin, @user], data: { confirm: "用户 #{@user.name} 即将被删除! 您确定?" }, method: :delete, class: "btn btn-remove" + + #profile.tab-pane + .row + .col-md-6 + .panel.panel-default + .panel-heading + = @user.name + %ul.well-list + %li + = image_tag avatar_icon(@user.email, 60), class: "avatar s60" + %li + %span.light 用户资料页: + %strong + = link_to user_path(@user) do + = @user.username + .col-md-6 + = render 'users/profile', user: @user + + #groups.tab-pane + - if @user.group_members.present? + .panel.panel-default + .panel-heading 组: + %ul.well-list + - @user.group_members.each do |group_member| + - group = group_member.group + %li.group_member + %span{class: ("list-item-name" unless group_member.owner?)} + %strong= link_to group.name, admin_group_path(group) + .pull-right + %span.light= group_member.human_access + - unless group_member.owner? + = link_to group_group_member_path(group, group_member), data: { confirm: remove_user_from_group_message(group, @user) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: '从组中删除用户' do + %i.fa.fa-times.fa-inverse + - else + .nothing-here-block 该用户没属于任务组. + + #projects.tab-pane + - if @user.groups.any? + .panel.panel-default + .panel-heading 组项目 + %ul.well-list + - @user.groups.each do |group| + %li + %strong= group.name + – access to + #{pluralize(group.projects.count, 'project')} + + .row + .col-md-6 + = render 'users/projects', projects: @personal_projects + + .col-md-6 + .panel.panel-default + .panel-heading 加入的项目 (#{@joined_projects.count}) + %ul.well-list + - @joined_projects.sort_by(&:name_with_namespace).each do |project| + - member = project.team.find_member(@user.id) + %li.project_member + .list-item-name + = link_to admin_namespace_project_path(project.namespace, project), class: dom_class(project) do + = project.name_with_namespace + + - if member + .pull-right + - if member.owner? + %span.light Owner + - else + %span.light= member.human_access + + - if member.respond_to? :project + = link_to namespace_project_project_member_path(project.namespace, project, @user), data: { confirm: remove_from_project_team_message(project, @user) }, remote: true, method: :delete, class: "btn-xs btn btn-remove", title: '从项目中删除用户' do + %i.fa.fa-times + #ssh-keys.tab-pane + = render 'profiles/keys/key_table', admin: true diff --git a/app/views/dashboard/_projects.zh.html.haml b/app/views/dashboard/_projects.zh.html.haml new file mode 100644 index 00000000000..523e0f594cb --- /dev/null +++ b/app/views/dashboard/_projects.zh.html.haml @@ -0,0 +1,10 @@ +.panel.panel-default + .panel-heading.clearfix + .input-group + = search_field_tag :filter_projects, nil, placeholder: '按名称筛选', class: 'projects-list-filter form-control' + - if current_user.can_create_project? + .input-group-addon.dash-new-project + = link_to new_project_path do + %strong 新建项目 + + = render 'shared/projects_list', projects: @projects, projects_limit: 20 diff --git a/app/views/dashboard/_zero_authorized_projects.zh.html.haml b/app/views/dashboard/_zero_authorized_projects.zh.html.haml new file mode 100644 index 00000000000..67711f102e6 --- /dev/null +++ b/app/views/dashboard/_zero_authorized_projects.zh.html.haml @@ -0,0 +1,53 @@ +- publicish_project_count = Project.publicish(current_user).count +%h3.page-title 欢迎来到 GitLab! +%p.light Self-hosted Git管理应用 +%hr +%div + .dashboard-intro-icon + %i.fa.fa-bookmark-o + .dashboard-intro-text + %p.slead + 您现在还没有任何项目的访问权限. + %br + - if current_user.can_create_project? + 您最多可以创建的项目数为 + %strong= current_user.projects_limit + - else + 如果您被添加到某个项目, 将会显示在这里. + + - if current_user.can_create_project? + .link_holder + = link_to new_project_path, class: "btn btn-new" do + %i.fa.fa-plus + 新建项目 + +- if current_user.can_create_group? + %hr + %div + .dashboard-intro-icon + %i.fa.fa-users + .dashboard-intro-text + %p.slead + 您可以为多个独立的项目创建组. + %br + 组是管理项目和成员的最好方式. + .link_holder + = link_to new_group_path, class: "btn btn-new" do + %i.fa.fa-plus + 新建组 + +-if publicish_project_count > 0 + %hr + %div + .dashboard-intro-icon + %i.fa.fa-globe + .dashboard-intro-text + %p.slead + 在这台服务器上共有 + %strong= publicish_project_count + 个公开项目. + %br + 公开项目是让每个人都有只读权限的最简单方式. + .link_holder + = link_to trending_explore_projects_path, class: "btn btn-new" do + 浏览公开项目 diff --git a/app/views/dashboard/issues.zh.html.haml b/app/views/dashboard/issues.zh.html.haml new file mode 100644 index 00000000000..4eece8755bb --- /dev/null +++ b/app/views/dashboard/issues.zh.html.haml @@ -0,0 +1,10 @@ +%h3.page-title + 问题 + +%p.light + 列出所有我有查看权限项目的所有问题. +%hr + +.append-bottom-20 + = render 'shared/issuable_filter' += render 'shared/issues' diff --git a/app/views/dashboard/merge_requests.zh.html.haml b/app/views/dashboard/merge_requests.zh.html.haml new file mode 100644 index 00000000000..64c4920b2fd --- /dev/null +++ b/app/views/dashboard/merge_requests.zh.html.haml @@ -0,0 +1,10 @@ +%h3.page-title + 合并请求 + + +%p.light + 列出所有我有查看权限的所有项目的所有合并请求. +%hr +.append-bottom-20 + = render 'shared/issuable_filter' += render 'shared/merge_requests' diff --git a/app/views/dashboard/milestones/index.zh.html.haml b/app/views/dashboard/milestones/index.zh.html.haml new file mode 100644 index 00000000000..e606bf2f07e --- /dev/null +++ b/app/views/dashboard/milestones/index.zh.html.haml @@ -0,0 +1,38 @@ +%h3.page-title + 里程碑 + %span.pull-right #{@dashboard_milestones.count} 个里程碑 + +%p.light + 列出所有您有权限项目的所有里程碑. + +%hr + += render 'shared/milestones_filter' +.milestones + .panel.panel-default + %ul.well-list + - if @dashboard_milestones.blank? + %li + .nothing-here-block 无里程碑可显示 + - else + - @dashboard_milestones.each do |milestone| + %li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) } + %h4 + = link_to_gfm truncate(milestone.title, length: 100), dashboard_milestone_path(milestone.safe_title, title: milestone.title) + %div + %div + = link_to dashboard_milestone_path(milestone.safe_title, title: milestone.title) do + = pluralize milestone.issue_count, 'Issue' +   + = link_to dashboard_milestone_path(milestone.safe_title, title: milestone.title) do + = pluralize milestone.merge_requests_count, 'Merge Request' +   + %span.light #{milestone.percent_complete}% complete + = milestone_progress_bar(milestone) + %div + %br + - milestone.milestones.each do |milestone| + = link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) do + %span.label.label-default + = milestone.project.name_with_namespace + = paginate @dashboard_milestones, theme: "gitlab" diff --git a/app/views/dashboard/milestones/show.zh.html.haml b/app/views/dashboard/milestones/show.zh.html.haml new file mode 100644 index 00000000000..57cce9ab749 --- /dev/null +++ b/app/views/dashboard/milestones/show.zh.html.haml @@ -0,0 +1,81 @@ +%h4.page-title + .issue-box{ class: "issue-box-#{@dashboard_milestone.closed? ? 'closed' : 'open'}" } + - if @dashboard_milestone.closed? + Closed + - else + Open + Milestone #{@dashboard_milestone.title} + +%hr +- if (@dashboard_milestone.total_items_count == @dashboard_milestone.closed_items_count) && @dashboard_milestone.active? + .alert.alert-success + %span All issues for this milestone are closed. You may close the milestone now. + +.description +%table.table + %thead + %tr + %th Project + %th Open issues + %th State + %th Due date + - @dashboard_milestone.milestones.each do |milestone| + %tr + %td + = link_to "#{milestone.project.name_with_namespace}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) + %td + = milestone.issues.opened.count + %td + - if milestone.closed? + Closed + - else + Open + %td + = milestone.expires_at + +.context + %p.lead + Progress: + #{@dashboard_milestone.closed_items_count} closed + – + #{@dashboard_milestone.open_items_count} open + = milestone_progress_bar(@dashboard_milestone) + +%ul.nav.nav-tabs + %li.active + = link_to '#tab-issues', 'data-toggle' => 'tab' do + Issues + %span.badge= @dashboard_milestone.issue_count + %li + = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do + Merge Requests + %span.badge= @dashboard_milestone.merge_requests_count + %li + = link_to '#tab-participants', 'data-toggle' => 'tab' do + Participants + %span.badge= @dashboard_milestone.participants.count + +.tab-content + .tab-pane.active#tab-issues + .row + .col-md-6 + = render 'issues', title: "Open", issues: @dashboard_milestone.opened_issues + .col-md-6 + = render 'issues', title: "Closed", issues: @dashboard_milestone.closed_issues + + .tab-pane#tab-merge-requests + .row + .col-md-6 + = render 'merge_requests', title: "Open", merge_requests: @dashboard_milestone.opened_merge_requests + .col-md-6 + = render 'merge_requests', title: "Closed", merge_requests: @dashboard_milestone.closed_merge_requests + + .tab-pane#tab-participants + %ul.bordered-list + - @dashboard_milestone.participants.each do |user| + %li + = link_to user, title: user.name, class: "darken" do + = image_tag avatar_icon(user.email, 32), class: "avatar s32" + %strong= truncate(user.name, lenght: 40) + %br + %small.cgray= user.username diff --git a/app/views/dashboard/projects/starred.zh.html.haml b/app/views/dashboard/projects/starred.zh.html.haml new file mode 100644 index 00000000000..628e14b5959 --- /dev/null +++ b/app/views/dashboard/projects/starred.zh.html.haml @@ -0,0 +1,23 @@ +- if @projects.any? + .dashboard.row + %section.activities.col-md-8 + = render 'dashboard/activities' + %aside.col-md-4 + .panel.panel-default + .panel-heading.clearfix + .input-group + = search_field_tag :filter_projects, nil, placeholder: '按名称筛选', class: 'projects-list-filter form-control' + - if current_user.can_create_project? + %span.input-group-btn + = link_to new_project_path, class: 'btn btn-success' do + 新建项目 + + = render 'shared/projects_list', projects: @projects, + projects_limit: 20, stars: true, avatar: false + + = link_to '#aside', class: 'show-aside' do + %i.fa.fa-angle-left + +- else + %h3 您还没有收藏过项目 + %p.slead 访问项目页在星号上点击后会显示在此页. diff --git a/app/views/devise/confirmations/new.zh.html.haml b/app/views/devise/confirmations/new.zh.html.haml new file mode 100644 index 00000000000..2af50531c6f --- /dev/null +++ b/app/views/devise/confirmations/new.zh.html.haml @@ -0,0 +1,14 @@ +.login-box + .login-heading + %h3 重新发送确认说明 + .login-body + = form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| + .devise-errors + = devise_error_messages! + .clearfix.append-bottom-20 + = f.email_field :email, placeholder: 'Email', class: "form-control", required: true + .clearfix + = f.submit "Resend confirmation instructions", class: 'btn btn-success' + +.clearfix.prepend-top-20 + = render 'devise/shared/sign_in_link' diff --git a/app/views/devise/mailer/confirmation_instructions.zh.html.erb b/app/views/devise/mailer/confirmation_instructions.zh.html.erb new file mode 100644 index 00000000000..e61c9ac8a96 --- /dev/null +++ b/app/views/devise/mailer/confirmation_instructions.zh.html.erb @@ -0,0 +1,9 @@ +

Welcome <%= @resource.name %>!

+ +<% if @resource.unconfirmed_email.present? %> +

您可以通过以下链接确认您的email (<%= @resource.unconfirmed_email %>):

+<% else %> +

您可以通过以下链接确认您的帐号:

+<% end %> + +

<%= link_to '确认我的帐号', confirmation_url(@resource, confirmation_token: @token) %>

diff --git a/app/views/devise/mailer/reset_password_instructions.zh.html.erb b/app/views/devise/mailer/reset_password_instructions.zh.html.erb new file mode 100644 index 00000000000..37d3d0a6ce8 --- /dev/null +++ b/app/views/devise/mailer/reset_password_instructions.zh.html.erb @@ -0,0 +1,8 @@ +

Hello <%= @resource.email %>!

+ +

有人请求了修改您密码的链接, 您可以访问以下链接修改密码.

+ +

<%= link_to '修改我的密码', edit_password_url(@resource, reset_password_token: @token) %>

+ +

如果不是您本人操作, 请忽略此邮件.

+

您的密码在您访问以上链接之前密码是不会变的, 您可以访问以上链接创建新密码.

diff --git a/app/views/devise/mailer/unlock_instructions.zh.html.erb b/app/views/devise/mailer/unlock_instructions.zh.html.erb new file mode 100644 index 00000000000..457e2c1bb12 --- /dev/null +++ b/app/views/devise/mailer/unlock_instructions.zh.html.erb @@ -0,0 +1,7 @@ +

Hello <%= @resource.email %>!

+ +

您的帐号因超过登录失败限制次数被锁定.

+ +

点击以下链接解锁您的帐号:

+ +

<%= link_to '解锁我的帐号', unlock_url(@resource, unlock_token: @token) %>

diff --git a/app/views/devise/passwords/edit.zh.html.haml b/app/views/devise/passwords/edit.zh.html.haml new file mode 100644 index 00000000000..c36c78317f5 --- /dev/null +++ b/app/views/devise/passwords/edit.zh.html.haml @@ -0,0 +1,19 @@ +.login-box + .login-heading + %h3 修改您的密码 + .login-body + = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| + .devise-errors + = devise_error_messages! + = f.hidden_field :reset_password_token + %div + = f.password_field :password, class: "form-control top", placeholder: "New password", required: true + %div + = f.password_field :password_confirmation, class: "form-control bottom", placeholder: "Confirm new password", required: true + .clearfix + = f.submit "修改我的密码", class: "btn btn-primary" + +.clearfix.prepend-top-20 + %p + = link_to "没有收到确认说明?", new_confirmation_path(resource_name) + = render 'devise/shared/sign_in_link' diff --git a/app/views/devise/passwords/new.zh.html.haml b/app/views/devise/passwords/new.zh.html.haml new file mode 100644 index 00000000000..9dbf368d700 --- /dev/null +++ b/app/views/devise/passwords/new.zh.html.haml @@ -0,0 +1,14 @@ +.login-box + .login-heading + %h3 重置密码 + .login-body + = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| + .devise-errors + = devise_error_messages! + .clearfix.append-bottom-20 + = f.email_field :email, placeholder: "Email", class: "form-control", required: true + .clearfix + = f.submit "重置密码", class: "btn-primary btn" + +.clearfix.prepend-top-20 + = render 'devise/shared/sign_in_link' diff --git a/app/views/devise/registrations/edit.zh.html.erb b/app/views/devise/registrations/edit.zh.html.erb new file mode 100644 index 00000000000..54cd29f21cf --- /dev/null +++ b/app/views/devise/registrations/edit.zh.html.erb @@ -0,0 +1,28 @@ +

Edit <%= resource_name.to_s.humanize %>

+ +<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> + <%= devise_error_messages! %> + +
<%= f.label :email %>
+ <%= f.email_field :email %>
+ +
<%= f.label :name %>
+ <%= f.text_field :name %>
+ +
<%= f.label :password %> (如果您不想修改的话请留空)
+ <%= f.password_field :password %>
+ +
<%= f.label :password_confirmation %>
+ <%= f.password_field :password_confirmation %>
+ +
<%= f.label :current_password %> (我们需要您的当前密码确认您的修改)
+ <%= f.password_field :current_password %>
+ +
<%= f.submit "更新", class: "input_button" %>
+<% end %> + +

取消我的帐号

+ +

不高兴了? <%= link_to "取消我的帐号", registration_path(resource_name), data: { confirm: "您确认?" }, method: :delete %>.

+ +<%= link_to "返回", :back %> diff --git a/app/views/devise/sessions/_new_base.zh.html.haml b/app/views/devise/sessions/_new_base.zh.html.haml new file mode 100644 index 00000000000..be637571c54 --- /dev/null +++ b/app/views/devise/sessions/_new_base.zh.html.haml @@ -0,0 +1,12 @@ += form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| + = f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus" + = f.password_field :password, class: "form-control bottom", placeholder: "Password" + - if devise_mapping.rememberable? + .remember-me.checkbox + %label{for: "user_remember_me"} + = f.check_box :remember_me + %span 记信我 + .pull-right + = link_to "忘记了您的密码?", new_password_path(resource_name) + %div + = f.submit "注册", class: "btn btn-save" diff --git a/app/views/devise/sessions/_new_ldap.zh.html.haml b/app/views/devise/sessions/_new_ldap.zh.html.haml new file mode 100644 index 00000000000..3555da3821e --- /dev/null +++ b/app/views/devise/sessions/_new_ldap.zh.html.haml @@ -0,0 +1,4 @@ += form_tag(user_omniauth_callback_path(server['provider_name']), id: 'new_ldap_user' ) do + = text_field_tag :username, nil, {class: "form-control top", placeholder: "#{server['label']} Login", autofocus: "autofocus"} + = password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"} + = button_tag "#{server['label']} 注册", class: "btn-save btn" diff --git a/app/views/devise/sessions/new.zh.html.haml b/app/views/devise/sessions/new.zh.html.haml new file mode 100644 index 00000000000..36f0e02ed67 --- /dev/null +++ b/app/views/devise/sessions/new.zh.html.haml @@ -0,0 +1,18 @@ +%div + - if signin_enabled? || ldap_enabled? + = render 'devise/shared/signin_box' + + -# Omniauth fits between signin/ldap signin and signup and does not have a surrounding box + - if Gitlab.config.omniauth.enabled && devise_mapping.omniauthable? + .clearfix.prepend-top-20 + = render 'devise/shared/omniauth_box' + + -# Signup only makes sense if you can also sign-in + - if signin_enabled? && signup_enabled? + .prepend-top-20 + = render 'devise/shared/signup_box' + + -# Show a message if none of the mechanisms above are enabled + - if !signin_enabled? && !ldap_enabled? && !(Gitlab.config.omniauth.enabled && devise_mapping.omniauthable?) + %div + 没有配置认证方法. diff --git a/app/views/devise/shared/_links.zh.erb b/app/views/devise/shared/_links.zh.erb new file mode 100644 index 00000000000..6b8a39a1e33 --- /dev/null +++ b/app/views/devise/shared/_links.zh.erb @@ -0,0 +1,19 @@ +<%- if controller_name != 'sessions' %> + <%= link_to "登录", new_session_path(resource_name), class: "btn" %>
+<% end -%> + +<%- if devise_mapping.registerable? && controller_name != 'registrations' && gitlab_config.signup_enabled %> + <%= link_to "注册", new_registration_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.recoverable? && controller_name != 'passwords' %> +<%= link_to "忘记您的密码?", new_password_path(resource_name), class: "btn" %>
+<% end -%> + +<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> + <%= link_to "没有收到确认说明?", new_confirmation_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> + <%= link_to "没有收到解锁说明?", new_unlock_path(resource_name) %>
+<% end -%> diff --git a/app/views/devise/shared/_omniauth_box.zh.html.haml b/app/views/devise/shared/_omniauth_box.zh.html.haml new file mode 100644 index 00000000000..4cd1c303b22 --- /dev/null +++ b/app/views/devise/shared/_omniauth_box.zh.html.haml @@ -0,0 +1,10 @@ +%p + %span.light + Sign in with   + - providers = additional_providers + - providers.each do |provider| + %span.light + - if default_providers.include?(provider) + = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider) + - else + = link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), class: "btn" diff --git a/app/views/devise/shared/_sign_in_link.zh.html.haml b/app/views/devise/shared/_sign_in_link.zh.html.haml new file mode 100644 index 00000000000..e553c0b2639 --- /dev/null +++ b/app/views/devise/shared/_sign_in_link.zh.html.haml @@ -0,0 +1,5 @@ +%p + %span.light + 已经有登录帐号和密码? + %strong + = link_to "登录", new_session_path(resource_name) diff --git a/app/views/devise/shared/_signin_box.zh.html.haml b/app/views/devise/shared/_signin_box.zh.html.haml new file mode 100644 index 00000000000..fe2c81440d5 --- /dev/null +++ b/app/views/devise/shared/_signin_box.zh.html.haml @@ -0,0 +1,26 @@ +.login-box + - if signup_enabled? + .login-heading + %h3 已有用户? 登录 + - else + .login-heading + %h3 Sign in + .login-body + - if ldap_enabled? + %ul.nav.nav-tabs + - @ldap_servers.each_with_index do |server, i| + %li{class: (:active if i.zero?)} + = link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab' + - if signin_enabled? + %li + = link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab' + .tab-content + - @ldap_servers.each_with_index do |server, i| + %div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero?)} + = render 'devise/sessions/new_ldap', server: server + - if signin_enabled? + %div#tab-signin.tab-pane + = render 'devise/sessions/new_base' + + - elsif signin_enabled? + = render 'devise/sessions/new_base' diff --git a/app/views/devise/shared/_signup_box.zh.html.haml b/app/views/devise/shared/_signup_box.zh.html.haml new file mode 100644 index 00000000000..2a596392140 --- /dev/null +++ b/app/views/devise/shared/_signup_box.zh.html.haml @@ -0,0 +1,26 @@ +.login-box + - if signin_enabled? + .login-heading + %h3 新用户? 创建帐号 + - else + .login-heading + %h3 创建帐号 + .login-body + = form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| + .devise-errors + = devise_error_messages! + %div + = f.text_field :name, class: "form-control top", placeholder: "Name", required: true + %div + = f.text_field :username, class: "form-control middle", placeholder: "Username", required: true + %div + = f.email_field :email, class: "form-control middle", placeholder: "Email", required: true + .form-group.append-bottom-20#password-strength + = f.password_field :password, class: "form-control bottom", id: "user_password_sign_up", placeholder: "Password", required: true + %div + = f.submit "Sign up", class: "btn-create btn" + +.clearfix.prepend-top-20 + %p + %span.light 没有收到确认邮件? + = link_to "再次发送", new_confirmation_path(resource_name) diff --git a/app/views/devise/unlocks/new.zh.html.erb b/app/views/devise/unlocks/new.zh.html.erb new file mode 100644 index 00000000000..6ce16e443e6 --- /dev/null +++ b/app/views/devise/unlocks/new.zh.html.erb @@ -0,0 +1,12 @@ +

重新发送解锁说明

+ +<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> + <%= devise_error_messages! %> + +
<%= f.label :email %>
+ <%= f.email_field :email %>
+ +
<%= f.submit "Resend unlock instructions" %>
+<% end %> + +<%= render partial: "devise/shared/links" %> diff --git a/app/views/doorkeeper/applications/_delete_form.zh.html.haml b/app/views/doorkeeper/applications/_delete_form.zh.html.haml new file mode 100644 index 00000000000..d2263fc6cea --- /dev/null +++ b/app/views/doorkeeper/applications/_delete_form.zh.html.haml @@ -0,0 +1,4 @@ +- submit_btn_css ||= 'btn btn-link btn-remove btn-sm' += form_tag oauth_application_path(application) do + %input{:name => "_method", :type => "hidden", :value => "delete"}/ + = submit_tag '删除', onclick: "return confirm('您确定?')", class: submit_btn_css \ No newline at end of file diff --git a/app/views/doorkeeper/applications/_form.zh.html.haml b/app/views/doorkeeper/applications/_form.zh.html.haml new file mode 100644 index 00000000000..0abcc5f6d03 --- /dev/null +++ b/app/views/doorkeeper/applications/_form.zh.html.haml @@ -0,0 +1,23 @@ += form_for application, url: doorkeeper_submit_path(application), html: {class: 'form-horizontal', role: 'form'} do |f| + - if application.errors.any? + .alert.alert-danger{"data-alert" => ""} + %p 惨了! 检查您的表单看有没有错误发生 + = content_tag :div, class: "form-group#{' has-error' if application.errors[:name].present?}" do + = f.label :name, class: 'col-sm-2 control-label' + .col-sm-10 + = f.text_field :name, class: 'form-control' + = doorkeeper_errors_for application, :name + = content_tag :div, class: "form-group#{' has-error' if application.errors[:redirect_uri].present?}" do + = f.label :redirect_uri, class: 'col-sm-2 control-label' + .col-sm-10 + = f.text_area :redirect_uri, class: 'form-control' + = doorkeeper_errors_for application, :redirect_uri + %span.help-block + 一行一个URI + - if Doorkeeper.configuration.native_redirect_uri + %span.help-block + 用于本地测试 + %code= Doorkeeper.configuration.native_redirect_uri + .form-actions + = f.submit '提交', class: "btn btn-primary wide" + = link_to "取消", applications_profile_path, class: "btn btn-default" diff --git a/app/views/doorkeeper/applications/edit.zh.html.haml b/app/views/doorkeeper/applications/edit.zh.html.haml new file mode 100644 index 00000000000..adf4a1d080a --- /dev/null +++ b/app/views/doorkeeper/applications/edit.zh.html.haml @@ -0,0 +1,2 @@ +%h3.page-title 编辑应用 += render 'form', application: @application \ No newline at end of file diff --git a/app/views/doorkeeper/applications/index.zh.html.haml b/app/views/doorkeeper/applications/index.zh.html.haml new file mode 100644 index 00000000000..740a33d9d61 --- /dev/null +++ b/app/views/doorkeeper/applications/index.zh.html.haml @@ -0,0 +1,16 @@ +%h3.page-title 您的应用 +%p= link_to '新建应用', new_oauth_application_path, class: 'btn btn-success' +%table.table.table-striped + %thead + %tr + %th 名称 + %th 回调URL + %th + %th + %tbody + - @applications.each do |application| + %tr{:id => "application_#{application.id}"} + %td= link_to application.name, oauth_application_path(application) + %td= application.redirect_uri + %td= link_to '编辑', edit_oauth_application_path(application), class: 'btn btn-link' + %td= render 'delete_form', application: application \ No newline at end of file diff --git a/app/views/doorkeeper/applications/new.zh.html.haml b/app/views/doorkeeper/applications/new.zh.html.haml new file mode 100644 index 00000000000..5c877d24b21 --- /dev/null +++ b/app/views/doorkeeper/applications/new.zh.html.haml @@ -0,0 +1,2 @@ +%h3.page-title 新建应用 += render 'form', application: @application \ No newline at end of file diff --git a/app/views/doorkeeper/applications/show.zh.html.haml b/app/views/doorkeeper/applications/show.zh.html.haml new file mode 100644 index 00000000000..bd9cb3093e4 --- /dev/null +++ b/app/views/doorkeeper/applications/show.zh.html.haml @@ -0,0 +1,26 @@ +%h3.page-title + 应用: #{@application.name} + + +%table.table + %tr + %td + 应用Id + %td + %code#application_id= @application.uid + %tr + %td + 私匙: + %td + %code#secret= @application.secret + + %tr + %td + 回调url + %td + - @application.redirect_uri.split.each do |uri| + %div + %span.monospace= uri +.form-actions + = link_to '编辑', edit_oauth_application_path(@application), class: 'btn btn-primary wide pull-left' + = render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10' diff --git a/app/views/doorkeeper/authorizations/error.zh.html.haml b/app/views/doorkeeper/authorizations/error.zh.html.haml new file mode 100644 index 00000000000..2f844339b6d --- /dev/null +++ b/app/views/doorkeeper/authorizations/error.zh.html.haml @@ -0,0 +1,3 @@ +%h3.page-title 有一处错误 +%main{:role => "main"} + %pre= @pre_auth.error_response.body[:error_description] \ No newline at end of file diff --git a/app/views/doorkeeper/authorizations/new.zh.html.haml b/app/views/doorkeeper/authorizations/new.zh.html.haml new file mode 100644 index 00000000000..4a03e1f8322 --- /dev/null +++ b/app/views/doorkeeper/authorizations/new.zh.html.haml @@ -0,0 +1,28 @@ +%h3.page-title 需要认证 +%main{:role => "main"} + %p.h4 + 认证 + %strong.text-info= @pre_auth.client.name + 使用您的帐号? + - if @pre_auth.scopes + #oauth-permissions + %p 该应用将会: + %ul.text-info + - @pre_auth.scopes.each do |scope| + %li= t scope, scope: [:doorkeeper, :scopes] + %hr/ + .actions + = form_tag oauth_authorization_path, method: :post do + = hidden_field_tag :client_id, @pre_auth.client.uid + = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri + = hidden_field_tag :state, @pre_auth.state + = hidden_field_tag :response_type, @pre_auth.response_type + = hidden_field_tag :scope, @pre_auth.scope + = submit_tag "认证", class: "btn btn-success wide pull-left" + = form_tag oauth_authorization_path, method: :delete do + = hidden_field_tag :client_id, @pre_auth.client.uid + = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri + = hidden_field_tag :state, @pre_auth.state + = hidden_field_tag :response_type, @pre_auth.response_type + = hidden_field_tag :scope, @pre_auth.scope + = submit_tag "拒绝", class: "btn btn-danger prepend-left-10" \ No newline at end of file diff --git a/app/views/doorkeeper/authorizations/show.zh.html.haml b/app/views/doorkeeper/authorizations/show.zh.html.haml new file mode 100644 index 00000000000..12302a273aa --- /dev/null +++ b/app/views/doorkeeper/authorizations/show.zh.html.haml @@ -0,0 +1,3 @@ +%h3.page-title 认证代码: +%main{:role => "main"} + %code#authorization_code= params[:code] \ No newline at end of file diff --git a/app/views/doorkeeper/authorized_applications/_delete_form.zh.html.haml b/app/views/doorkeeper/authorized_applications/_delete_form.zh.html.haml new file mode 100644 index 00000000000..c6f8e537dfa --- /dev/null +++ b/app/views/doorkeeper/authorized_applications/_delete_form.zh.html.haml @@ -0,0 +1,4 @@ +- submit_btn_css ||= 'btn btn-link btn-remove' += form_tag oauth_authorized_application_path(application) do + %input{:name => "_method", :type => "hidden", :value => "delete"}/ + = submit_tag '撤消认证', onclick: "return confirm('您确定?')", class: 'btn btn-link btn-remove btn-sm' \ No newline at end of file diff --git a/app/views/doorkeeper/authorized_applications/index.zh.html.haml b/app/views/doorkeeper/authorized_applications/index.zh.html.haml new file mode 100644 index 00000000000..c1d01e1e759 --- /dev/null +++ b/app/views/doorkeeper/authorized_applications/index.zh.html.haml @@ -0,0 +1,16 @@ +%header.page-header + %h1 您已认证的应用 +%main{:role => "main"} + %table.table.table-striped + %thead + %tr + %th 应用 + %th 创建于 + %th + %th + %tbody + - @applications.each do |application| + %tr + %td= application.name + %td= application.created_at.strftime('%Y-%m-%d %H:%M:%S') + %td= render 'delete_form', application: application \ No newline at end of file diff --git a/app/views/errors/access_denied.zh.html.haml b/app/views/errors/access_denied.zh.html.haml new file mode 100644 index 00000000000..68043b5d498 --- /dev/null +++ b/app/views/errors/access_denied.zh.html.haml @@ -0,0 +1,5 @@ +%h1 403 +%h3 访问被拒绝 +%hr +%p 不允许您访问此页面. +%p 访问#{link_to "这里", help_page_path("permissions", "permissions"), class: "vlink"}了解更多关于项目权限的知识 diff --git a/app/views/errors/encoding.zh.html.haml b/app/views/errors/encoding.zh.html.haml new file mode 100644 index 00000000000..8e38275e3a6 --- /dev/null +++ b/app/views/errors/encoding.zh.html.haml @@ -0,0 +1,4 @@ +%h1 500 +%h3 编码错误 +%hr +%p 页面因为编码错误无法加载. diff --git a/app/views/errors/git_not_found.zh.html.haml b/app/views/errors/git_not_found.zh.html.haml new file mode 100644 index 00000000000..c939cc7163f --- /dev/null +++ b/app/views/errors/git_not_found.zh.html.haml @@ -0,0 +1,5 @@ +%h1 404 +%h3 Git资源未找到 +%hr +%p + 应用无法访问仓库的某个分支或提交. 已经被移走. diff --git a/app/views/errors/not_found.zh.html.haml b/app/views/errors/not_found.zh.html.haml new file mode 100644 index 00000000000..dd026143d62 --- /dev/null +++ b/app/views/errors/not_found.zh.html.haml @@ -0,0 +1,4 @@ +%h1 404 +%h3 您要查找的资源不存在. +%hr +%p 填输入的地址有误或页面已经迁移. diff --git a/app/views/errors/omniauth_error.zh.html.haml b/app/views/errors/omniauth_error.zh.html.haml new file mode 100644 index 00000000000..2fbc6db729a --- /dev/null +++ b/app/views/errors/omniauth_error.zh.html.haml @@ -0,0 +1,12 @@ +%h1 422 +%h3 使用 #{@provider} 认证登录失败 +%hr +%p 因 #{@error} 登录失败. +%p 您可以按以下步骤处理: + +%ul + %li 尝试使用邮箱登录 + %li 尝试使用用户名登录 + %li 如果您忘记了您的密码, 尝试使用#{ link_to "密码恢复", new_password_path(resource_name) } 恢复. + +%p 如果以上都无效, 请联系GitLab管理员. diff --git a/app/views/events/_event_last_push.zh.html.haml b/app/views/events/_event_last_push.zh.html.haml new file mode 100644 index 00000000000..74463c1e3b7 --- /dev/null +++ b/app/views/events/_event_last_push.zh.html.haml @@ -0,0 +1,14 @@ +- if show_last_push_widget?(event) + .event-last-push + .event-last-push-text + %span 您推送到 + = link_to namespace_project_commits_path(event.project.namespace, event.project, event.ref_name) do + %strong= event.ref_name + at + %strong= link_to_project event.project + #{time_ago_with_tooltip(event.created_at)} + + .pull-right + = link_to new_mr_path_from_push_event(event), title: "新建合并请求", class: "btn btn-create btn-sm" do + 新建合并请求 + %hr diff --git a/app/views/events/event/_created_project.zh.html.haml b/app/views/events/event/_created_project.zh.html.haml new file mode 100644 index 00000000000..f14d1e9eea6 --- /dev/null +++ b/app/views/events/event/_created_project.zh.html.haml @@ -0,0 +1,27 @@ +.event-title + %span.author_name= link_to_author event + %span.event_label{class: event.action_name} + = event_action_name(event) + + - if event.project + = link_to_project event.project + - else + = event.project_name + +- if current_user == event.author && !event.project.private? && twitter_sharing_enabled? + .event-body + .event-note + .md + %p + 恭喜您! 为何不将您的成熟分享给其它人也? + + %a.twitter-share-button{ | + href: "https://twitter.com/share", | + "data-url" => event.project.web_url, | + "data-text" => "我刚在GitLab上新建了一个项目! GitLab是在您的服务器上做版本控制的软件.", | + "data-size" => "medium", | + "data-related" => "gitlab", | + "data-hashtags" => "gitlab", | + "data-count" => "none"} + Tweet + %script{src: "//platform.twitter.com/widgets.js"} \ No newline at end of file diff --git a/app/views/explore/groups/index.zh.html.haml b/app/views/explore/groups/index.zh.html.haml new file mode 100644 index 00000000000..67b9f2dd26b --- /dev/null +++ b/app/views/explore/groups/index.zh.html.haml @@ -0,0 +1,50 @@ +.clearfix + .pull-left + = form_tag explore_groups_path, method: :get, class: 'form-inline form-tiny' do |f| + = hidden_field_tag :sort, @sort + .form-group + = search_field_tag :search, params[:search], placeholder: "按名字筛选", class: "form-control search-text-input input-mn-300", id: "groups_search" + .form-group + = button_tag '搜索', class: "btn btn-primary wide" + + .pull-right + .dropdown.inline + %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} + %span.light sort: + - if @sort.present? + = sort_options_hash[@sort] + - else + = sort_title_recently_created + %b.caret + %ul.dropdown-menu + %li + = link_to explore_groups_path(sort: sort_value_recently_created) do + = sort_title_recently_created + = link_to explore_groups_path(sort: sort_value_oldest_created) do + = sort_title_oldest_created + = link_to explore_groups_path(sort: sort_value_recently_updated) do + = sort_title_recently_updated + = link_to explore_groups_path(sort: sort_value_oldest_updated) do + = sort_title_oldest_updated + +%hr + +%ul.bordered-list + - @groups.each do |group| + %li + .clearfix + %h4 + = link_to group_path(id: group.path) do + %i.fa.fa-users + = group.name + .clearfix + %p + = truncate group.description, length: 150 + .clearfix + %p.light + #{pluralize(group.members.size, 'member')}, #{pluralize(group.projects.count, 'project')} + - unless @groups.present? + .nothing-here-block 无公开组 + + += paginate @groups, theme: "gitlab" diff --git a/app/views/explore/projects/_filter.zh.html.haml b/app/views/explore/projects/_filter.zh.html.haml new file mode 100644 index 00000000000..4683119a42a --- /dev/null +++ b/app/views/explore/projects/_filter.zh.html.haml @@ -0,0 +1,67 @@ +.pull-left + = form_tag explore_projects_filter_path, method: :get, class: 'form-inline form-tiny' do |f| + .form-group + = search_field_tag :search, params[:search], placeholder: "按名字筛选", class: "form-control search-text-input input-mn-300", id: "projects_search" + .form-group + = button_tag '搜索', class: "btn btn-primary wide" + +.pull-right.hidden-sm.hidden-xs + - if current_user + .dropdown.inline.append-right-10 + %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"} + %i.fa.fa-globe + %span.light Visibility: + - if params[:visibility_level].present? + = visibility_level_label(params[:visibility_level].to_i) + - else + Any + %b.caret + %ul.dropdown-menu + %li + = link_to explore_projects_filter_path(visibility_level: nil) do + Any + - Gitlab::VisibilityLevel.values.each do |level| + %li{ class: (level.to_s == params[:visibility_level]) ? 'active' : 'light' } + = link_to explore_projects_filter_path(visibility_level: level) do + = visibility_level_icon(level) + = visibility_level_label(level) + + - if @tags.present? + .dropdown.inline.append-right-10 + %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"} + %i.fa.fa-tags + %span.light Tags: + - if params[:tag].present? + = params[:tag] + - else + Any + %b.caret + %ul.dropdown-menu + %li + = link_to explore_projects_filter_path(tag: nil) do + Any + + - @tags.each do |tag| + %li{ class: (tag.name == params[:tag]) ? 'active' : 'light' } + = link_to explore_projects_filter_path(tag: tag.name) do + %i.fa.fa-tag + = tag.name + + .dropdown.inline + %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} + %span.light sort: + - if @sort.present? + = sort_options_hash[@sort] + - else + = sort_title_recently_created + %b.caret + %ul.dropdown-menu + %li + = link_to explore_projects_filter_path(sort: sort_value_recently_created) do + = sort_title_recently_created + = link_to explore_projects_filter_path(sort: sort_value_oldest_created) do + = sort_title_oldest_created + = link_to explore_projects_filter_path(sort: sort_value_recently_updated) do + = sort_title_recently_updated + = link_to explore_projects_filter_path(sort: sort_value_oldest_updated) do + = sort_title_oldest_updated diff --git a/app/views/explore/projects/_project.zh.html.haml b/app/views/explore/projects/_project.zh.html.haml new file mode 100644 index 00000000000..0330112eff8 --- /dev/null +++ b/app/views/explore/projects/_project.zh.html.haml @@ -0,0 +1,24 @@ +%li + %h4.project-title + .project-access-icon + = visibility_level_icon(project.visibility_level) + = link_to project.name_with_namespace, [project.namespace.becomes(Namespace), project] + %span.pull-right + %i.fa.fa-star + = project.star_count + + .project-info + - if project.description.present? + %p.project-description.str-truncated + = project.description + + .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(project.repository.branch_names.count, 'branch'), namespace_project_branches_path(project.namespace, project) + · + = link_to pluralize(project.repository.tag_names.count, 'tag'), namespace_project_tags_path(project.namespace, project) + - else + %i.fa.fa-exclamation-triangle + 空仓库 diff --git a/app/views/explore/projects/index.zh.html.haml b/app/views/explore/projects/index.zh.html.haml new file mode 100644 index 00000000000..d52516ffa68 --- /dev/null +++ b/app/views/explore/projects/index.zh.html.haml @@ -0,0 +1,11 @@ +.clearfix + = render 'filter' + +%hr +.public-projects + %ul.bordered-list.top-list + = render @projects + - unless @projects.present? + .nothing-here-block 无公开项目 + + = paginate @projects, theme: "gitlab" diff --git a/app/views/explore/projects/starred.zh.html.haml b/app/views/explore/projects/starred.zh.html.haml new file mode 100644 index 00000000000..8697874a9b2 --- /dev/null +++ b/app/views/explore/projects/starred.zh.html.haml @@ -0,0 +1,10 @@ +.explore-trending-block + %p.lead + %i.fa.fa-star + 查看收藏最多的项目 + %hr + .public-projects + %ul.bordered-list + = render @starred_projects + + = paginate @starred_projects, theme: 'gitlab' diff --git a/app/views/explore/projects/trending.zh.html.haml b/app/views/explore/projects/trending.zh.html.haml new file mode 100644 index 00000000000..446be9ad916 --- /dev/null +++ b/app/views/explore/projects/trending.zh.html.haml @@ -0,0 +1,11 @@ +.explore-trending-block + %p.lead + %i.fa.fa-comments-o + 查看上月讨论最多的项目 + %hr + .public-projects + %ul.bordered-list + = render @trending_projects + + .center + = link_to '显示所有项目', explore_projects_path, class: 'btn btn-primary' diff --git a/app/views/groups/_projects.zh.html.haml b/app/views/groups/_projects.zh.html.haml new file mode 100644 index 00000000000..40f7f204d67 --- /dev/null +++ b/app/views/groups/_projects.zh.html.haml @@ -0,0 +1,10 @@ +.panel.panel-default + .panel-heading.clearfix + .input-group + = search_field_tag :filter_projects, nil, placeholder: '按名称筛选', class: 'projects-list-filter form-control' + - if can? current_user, :create_projects, @group + .input-group-addon.dash-new-project + = link_to new_project_path(namespace_id: @group.id) do + %strong 新建项目 + + = render 'shared/projects_list', projects: @projects, projects_limit: 20 diff --git a/app/views/groups/_settings_nav.zh.html.haml b/app/views/groups/_settings_nav.zh.html.haml new file mode 100644 index 00000000000..2dafc13cc70 --- /dev/null +++ b/app/views/groups/_settings_nav.zh.html.haml @@ -0,0 +1,11 @@ +%ul.sidebar-subnav + = nav_link(path: 'groups#edit') do + = link_to edit_group_path(@group), title: '组' do + %i.fa.fa-pencil-square-o + %span + 组 + = nav_link(path: 'groups#projects') do + = link_to projects_group_path(@group), title: '项目' do + %i.fa.fa-folder + %span + 项目 diff --git a/app/views/groups/edit.zh.html.haml b/app/views/groups/edit.zh.html.haml new file mode 100644 index 00000000000..37c55a3a93c --- /dev/null +++ b/app/views/groups/edit.zh.html.haml @@ -0,0 +1,37 @@ +.panel.panel-default + .panel-heading + %strong= @group.name + 组设置: + .panel-body + = form_for @group, html: { multipart: true, class: "form-horizontal" }, authenticity_token: true do |f| + - if @group.errors.any? + .alert.alert-danger + %span= @group.errors.full_messages.first + = render 'shared/group_form', f: f + + .form-group + .col-sm-2 + .col-sm-10 + = image_tag group_icon(@group), alt: '', class: 'avatar group-avatar s160' + %p.light + - if @group.avatar? + 您可以在此修改您的组头像 + - else + 您可以在此上传组头像 + = render 'shared/choose_group_avatar_button', f: f + - if @group.avatar? + %hr + = link_to '删除头像', group_avatar_path(@group.to_param), data: { confirm: "组头像将会被删除. 您确定?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" + + .form-actions + = f.submit '保存修改', class: "btn btn-save" + +.panel.panel-danger + .panel-heading 删除组 + .panel-body + %p + 删除组将会导致所有的子项目和资源被删除. + %br + %strong 删除的组不可恢复! + + = link_to '删除组', @group, data: {confirm: '删除组不可恢复! 您确定?'}, method: :delete, class: "btn btn-remove" diff --git a/app/views/groups/group_members/_group_member.zh.html.haml b/app/views/groups/group_members/_group_member.zh.html.haml new file mode 100644 index 00000000000..d11e8de20c4 --- /dev/null +++ b/app/views/groups/group_members/_group_member.zh.html.haml @@ -0,0 +1,37 @@ +- user = member.user +- return unless user +- show_roles = true if show_roles.nil? + +%li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)} + %span{class: ("list-item-name" if show_controls)} + = image_tag avatar_icon(user.email, 16), class: "avatar s16" + %strong= user.name + %span.cgray= user.username + - if user == current_user + %span.label.label-success 就是您 + - if user.blocked? + %label.label.label-danger + %strong 已屏蔽 + + - if show_roles + %span.pull-right + %strong= member.human_access + - if show_controls + - if can?(current_user, :modify_group_member, member) + = button_tag class: "btn-xs btn js-toggle-button", + title: '编辑访问控制', type: 'button' do + %i.fa.fa-pencil-square-o + - if can?(current_user, :destroy_group_member, member) +   + - if current_user == user + = link_to leave_group_group_members_path(@group), data: { confirm: leave_group_message(@group.name)}, method: :delete, class: "btn-xs btn btn-remove", title: '从组中删除用户' do + %i.fa.fa-minus.fa-inverse + - else + = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: '从组中删除用户' do + %i.fa.fa-minus.fa-inverse + + .edit-member.hide.js-toggle-content + = form_for [@group, member], remote: true do |f| + .alert.prepend-top-20 + = f.select :access_level, options_for_select(GroupMember.access_level_roles, member.access_level) + = f.submit '保存', class: 'btn btn-save btn-sm' diff --git a/app/views/groups/group_members/_new_group_member.zh.html.haml b/app/views/groups/group_members/_new_group_member.zh.html.haml new file mode 100644 index 00000000000..89b8211088c --- /dev/null +++ b/app/views/groups/group_members/_new_group_member.zh.html.haml @@ -0,0 +1,16 @@ += form_for @group_member, url: group_group_members_path(@group), html: { class: 'form-horizontal users-group-form' } do |f| + .form-group + = f.label :user_ids, "People", class: 'control-label' + .col-sm-10= users_select_tag(:user_ids, multiple: true, class: 'input-large') + + .form-group + = f.label :access_level, "组访问控制", class: 'control-label' + .col-sm-10 + = select_tag :access_level, options_for_select(GroupMember.access_level_roles, @group_member.access_level), class: "project-access-select select2" + .help-block + 点 + %strong= link_to "此", help_page_path("permissions", "permissions"), class: "vlink" + 阅读更多关于角色权限的信息. + + .form-actions + = f.submit '添加用户到组', class: "btn btn-create" diff --git a/app/views/groups/group_members/index.zh.html.haml b/app/views/groups/group_members/index.zh.html.haml new file mode 100644 index 00000000000..04cbb0178d5 --- /dev/null +++ b/app/views/groups/group_members/index.zh.html.haml @@ -0,0 +1,44 @@ +- show_roles = should_user_see_group_roles?(current_user, @group) + +%h3.page-title + 组成员 +- if show_roles + %p.light + 组成员拥有所有组项目的访问权限. + 点 + %strong= link_to "此", help_page_path("permissions", "permissions"), class: "vlink" + 阅读更多关于权限的信息 + +%hr + +.clearfix.js-toggle-container + = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do + .form-group + = search_field_tag :search, params[:search], { placeholder: '按名称查找已有成员', class: 'form-control search-text-input input-mn-300' } + = button_tag '搜索', class: 'btn' + + - if current_user && current_user.can?(:manage_group, @group) + .pull-right + = button_tag class: 'btn btn-new js-toggle-button', type: 'button' do + 添加成员 + %i.fa.fa-chevron-down + + .js-toggle-content.hide.new-group-member-holder + = render "new_group_member" + +.panel.panel-default.prepend-top-20 + .panel-heading + %strong #{@group.name} + 组成员 + %small + (#{@members.total_count}) + %ul.well-list + - @members.each do |member| + = render 'groups/group_members/group_member', member: member, show_roles: show_roles, show_controls: true + += paginate @members, theme: 'gitlab' + +:coffeescript + $('form.member-search-form').on 'submit', (event) -> + event.preventDefault() + Turbolinks.visit @.action + '?' + $(@).serialize() diff --git a/app/views/groups/issues.zh.html.haml b/app/views/groups/issues.zh.html.haml new file mode 100644 index 00000000000..939d06f424e --- /dev/null +++ b/app/views/groups/issues.zh.html.haml @@ -0,0 +1,14 @@ +%h3.page-title + 问题 + +%p.light + 只有来自于 + %strong #{@group.name} + 组的问题显示在这里 + - if current_user + 查看所有问题请访问 #{link_to '面板', issues_dashboard_path} 页面. +%hr + +.append-bottom-20 + = render 'shared/issuable_filter' += render 'shared/issues' diff --git a/app/views/groups/merge_requests.zh.html.haml b/app/views/groups/merge_requests.zh.html.haml new file mode 100644 index 00000000000..4167781975e --- /dev/null +++ b/app/views/groups/merge_requests.zh.html.haml @@ -0,0 +1,14 @@ +%h3.page-title + 合并请求 + +%p.light + 只有来自于 + %strong #{@group.name} + 组的合并请求显示在这里. + - if current_user + To see all merge requests you should visit + 查看所有的合并请求您可以访问 #{link_to '面板', merge_requests_dashboard_path}. +%hr +.append-bottom-20 + = render 'shared/issuable_filter' += render 'shared/merge_requests' diff --git a/app/views/groups/milestones/index.zh.html.haml b/app/views/groups/milestones/index.zh.html.haml new file mode 100644 index 00000000000..d06ca4b75e9 --- /dev/null +++ b/app/views/groups/milestones/index.zh.html.haml @@ -0,0 +1,46 @@ +%h3.page-title + 里程碑 + %span.pull-right #{@group_milestones.count} milestones + +%p.light + 只有来自于 + %strong #{@group.name} + 组的里程碑显示在这里. + +%hr + += render 'shared/milestones_filter' +.milestones + .panel.panel-default + %ul.well-list + - if @group_milestones.blank? + %li + .nothing-here-block 无里程碑可显示 + - else + - @group_milestones.each do |milestone| + %li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) } + .pull-right + - if can?(current_user, :manage_group, @group) + - if milestone.closed? + = link_to '重新打开里程碑', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen" + - else + = link_to '关闭里程碑', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close" + %h4 + = link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title, title: milestone.title) + %div + %div + = link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do + = pluralize milestone.issue_count, 'Issue' +   + = link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do + = pluralize milestone.merge_requests_count, 'Merge Request' +   + %span.light #{milestone.percent_complete}% complete + = milestone_progress_bar(milestone) + %div + %br + - milestone.milestones.each do |milestone| + = link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) do + %span.label.label-default + = milestone.project.name + = paginate @group_milestones, theme: "gitlab" diff --git a/app/views/groups/milestones/show.zh.html.haml b/app/views/groups/milestones/show.zh.html.haml new file mode 100644 index 00000000000..6a7cbbc447f --- /dev/null +++ b/app/views/groups/milestones/show.zh.html.haml @@ -0,0 +1,87 @@ +%h4.page-title + .issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" } + - if @group_milestone.closed? + 已关闭 + - else + 打开状态 + 里程碑 #{@group_milestone.title} + .pull-right + - if can?(current_user, :manage_group, @group) + - if @group_milestone.active? + = link_to '关闭里程碑', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close" + - else + = link_to '重新打开里程碑', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen" + +%hr +- if (@group_milestone.total_items_count == @group_milestone.closed_items_count) && @group_milestone.active? + .alert.alert-success + %span 该里程碑的所有问题都是关闭状态. 您现在可以关闭里程碑. + +.description +%table.table + %thead + %tr + %th 项目 + %th 打开状态的问题 + %th 状态 + %th 到期日期 + - @group_milestone.milestones.each do |milestone| + %tr + %td + = link_to "#{milestone.project.name}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) + %td + = milestone.issues.opened.count + %td + - if milestone.closed? + 已关闭 + - else + 打开状态 + %td + = milestone.expires_at + +.context + %p.lead + 进度: + #{@group_milestone.closed_items_count} 个已关闭 + – + #{@group_milestone.open_items_count} 个是打开状态 + = milestone_progress_bar(@group_milestone) + +%ul.nav.nav-tabs + %li.active + = link_to '#tab-issues', 'data-toggle' => 'tab' do + 问题 + %span.badge= @group_milestone.issue_count + %li + = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do + 合并请求 + %span.badge= @group_milestone.merge_requests_count + %li + = link_to '#tab-participants', 'data-toggle' => 'tab' do + 参与者 + %span.badge= @group_milestone.participants.count + +.tab-content + .tab-pane.active#tab-issues + .row + .col-md-6 + = render 'issues', title: "打开状态", issues: @group_milestone.opened_issues + .col-md-6 + = render 'issues', title: "已关闭", issues: @group_milestone.closed_issues + + .tab-pane#tab-merge-requests + .row + .col-md-6 + = render 'merge_requests', title: "打开状态", merge_requests: @group_milestone.opened_merge_requests + .col-md-6 + = render 'merge_requests', title: "已关闭", merge_requests: @group_milestone.closed_merge_requests + + .tab-pane#tab-participants + %ul.bordered-list + - @group_milestone.participants.each do |user| + %li + = link_to user, title: user.name, class: "darken" do + = image_tag avatar_icon(user.email, 32), class: "avatar s32" + %strong= truncate(user.name, lenght: 40) + %br + %small.cgray= user.username diff --git a/app/views/groups/new.zh.html.haml b/app/views/groups/new.zh.html.haml new file mode 100644 index 00000000000..dc393613adf --- /dev/null +++ b/app/views/groups/new.zh.html.haml @@ -0,0 +1,19 @@ += form_for @group, html: { class: 'group-form form-horizontal' } do |f| + - if @group.errors.any? + .alert.alert-danger + %span= @group.errors.full_messages.first + + = render 'shared/group_form', f: f, autofocus: true + + .form-group.group-description-holder + = f.label :avatar, "组头像", class: 'control-label' + .col-sm-10 + = render 'shared/choose_group_avatar_button', f: f + + .form-group + .col-sm-2 + .col-sm-10 + = render 'shared/group_tips' + + .form-actions + = f.submit '创建组', class: "btn btn-create", tabindex: 3 diff --git a/app/views/groups/projects.zh.html.haml b/app/views/groups/projects.zh.html.haml new file mode 100644 index 00000000000..ddbabbb03df --- /dev/null +++ b/app/views/groups/projects.zh.html.haml @@ -0,0 +1,25 @@ +.panel.panel-default + .panel-heading + %strong= @group.name + 项目: + - if can? current_user, :manage_group, @group + .panel-head-actions + = link_to new_project_path(namespace_id: @group.id), class: "btn btn-sm btn-success" do + %i.fa.fa-plus + 新建项目 + %ul.well-list + - @projects.each do |project| + %li + .list-item-name + = visibility_level_icon(project.visibility_level) + %strong= link_to project.name_with_namespace, project + %span.label.label-gray + = repository_size(project) + .pull-right + = link_to '成员', namespace_project_project_members_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn btn-sm" + = link_to '编辑', edit_namespace_project_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn btn-sm" + = link_to '删除', project, data: { confirm: remove_project_message(project)}, method: :delete, class: "btn btn-sm btn-remove" + - if @projects.blank? + .nothing-here-block 该组还没有项目 + += paginate @projects, theme: "gitlab" diff --git a/app/views/help/_shortcuts.zh.html.haml b/app/views/help/_shortcuts.zh.html.haml new file mode 100644 index 00000000000..08fa91bf72a --- /dev/null +++ b/app/views/help/_shortcuts.zh.html.haml @@ -0,0 +1,209 @@ +#modal-shortcuts.modal.hide{tabindex: -1} + .modal-dialog + .modal-content + .modal-header + %a.close{href: "#", "data-dismiss" => "modal"} × + %h4 + 键盘快捷键 + %small + = link_to '(显示所有)', '#', class: 'js-more-help-button' + .modal-body.shortcuts-cheatsheet + .col-lg-4 + %table.shortcut-mappings + %tbody + %tr + %th + %th 全局快捷键 + %tr + %td.shortcut + .key s + %td 搜索框取得焦点 + %tr + %td.shortcut + .key ? + %td 显示此窗口 + %tbody + %tr + %th + %th 浏览项目文件 + %tr + %td.shortcut + .key + %i.fa.fa-arrow-up + %td 上移所选项 + %tr + %td.shortcut + .key + %i.fa.fa-arrow-down + %td 下移所选项 + %tr + %td.shortcut + .key enter + %td 打开所选 + + .col-lg-4 + %table.shortcut-mappings + %tbody{ class: 'hidden-shortcut project', style: 'display:none' } + %tr + %th + %th 全局面表盘 + %tr + %td.shortcut + .key g + .key a + %td + 前往活动动态 + %tr + %td.shortcut + .key g + .key p + %td + 前往项目列表页 + %tr + %td.shortcut + .key g + .key i + %td + 前往问题列表页 + %tr + %td.shortcut + .key g + .key m + %td + 前往合并请求页 + %tbody + %tr + %th + %th 项目 + %tr + %td.shortcut + .key g + .key p + %td + 前往项目的活动动态页 + %tr + %td.shortcut + .key g + .key f + %td + 前往文件列表页 + %tr + %td.shortcut + .key g + .key c + %td + 前往提交列表页 + %tr + %td.shortcut + .key g + .key n + %td + 前往网络图示页 + %tr + %td.shortcut + .key g + .key g + %td + 前往图示页 + %tr + %td.shortcut + .key g + .key i + %td + 前往问题列表页 + %tr + %td.shortcut + .key g + .key m + %td + 前往合并请求页 + %tr + %td.shortcut + .key g + .key s + %td + 前往代码片段页 + .col-lg-4 + %table.shortcut-mappings + %tbody{ class: 'hidden-shortcut network', style: 'display:none' } + %tr + %th + %th 网络图示页 + %tr + %td.shortcut + .key + %i.fa.fa-arrow-left + \/ + .key h + %td 向左滚 + %tr + %td.shortcut + .key + %i.fa.fa-arrow-right + \/ + .key l + %td 向右滚 + %tr + %td.shortcut + .key + %i.fa.fa-arrow-up + \/ + .key k + %td 向上滚 + %tr + %td.shortcut + .key + %i.fa.fa-arrow-down + \/ + .key j + %td 向下滚 + %tr + %td.shortcut + .key + shift + %i.fa.fa-arrow-up + \/ + .key + shift k + %td 滚至顶部 + %tr + %td.shortcut + .key + shift + %i.fa.fa-arrow-down + \/ + .key + shift j + %td 滚至底部 + %tbody{ class: 'hidden-shortcut issues', style: 'display:none' } + %tr + %th + %th 问题列表 + %tr + %td.shortcut + .key a + %td 修改指定人 + %tr + %td.shortcut + .key m + %td 修改里程碑 + %tbody{ class: 'hidden-shortcut merge_reuests', style: 'display:none' } + %tr + %th + %th 合并请求 + %tr + %td.shortcut + .key a + %td 修改指定人 + %tr + %td.shortcut + .key m + %td 修改里程碑 + + +:javascript + $('.js-more-help-button').click(function(e){ + $(this).remove() + $('.hidden-shortcut').show() + e.preventDefault() + }); diff --git a/app/views/help/index.zh.html.haml b/app/views/help/index.zh.html.haml new file mode 100644 index 00000000000..e7f8c92c0c2 --- /dev/null +++ b/app/views/help/index.zh.html.haml @@ -0,0 +1,50 @@ +%div + %h1 + GitLab + %span= Gitlab::VERSION + %small= Gitlab::REVISION + %p.slead + GitLab是用于协作编码的开源软件. + %br + 支持细分控制权限, 管理git仓库保证您的代码安全. + %br + 代码审核和合并请求增强合作. + %br + 每个项目还可以开启问题跟踪和wiki. + %br + 被超过10万家的组织采用, GitLab是git仓库管理解决方案中最受欢迎的. + %br + 访问 #{link_to promo_host, promo_url, target: '_blank'} 了解更多关于GitLab的信息. + +%hr + +.row + .col-md-8 + .documentation-index + = preserve do + - readme_text = File.read(Rails.root.join("doc", "README.md")) + - text = readme_text.dup + - readme_text.scan(/\]\(([^(]+)\)/) { |match| text.gsub!(match.first, "help/#{match.first}") } + = markdown text + + .col-md-4 + .panel.panel-default + .panel-heading + 快捷帮助 + %ul.well-list + %li + 访问我们网站 + = link_to '取得帮助', promo_url + '/getting-help/' + %li + 使用此页顶部的 + = link_to '搜索栏', '#', onclick: 'Shortcuts.focusSearch(event)' + %li + 使用 + = link_to '快捷键', '#', onclick: 'Shortcuts.showHelp(event)' + %li + 通过 + = link_to '订阅', 'https://about.gitlab.com/pricing/' + 获取支持 + %li + = link_to '对比', 'https://about.gitlab.com/features/#compare' + GitLab各版本 diff --git a/app/views/help/ui.zh.html.haml b/app/views/help/ui.zh.html.haml new file mode 100644 index 00000000000..d1b5b2a68e0 --- /dev/null +++ b/app/views/help/ui.zh.html.haml @@ -0,0 +1,226 @@ +- lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed fermentum nisi sapien, non consequat lectus aliquam ultrices. Suspendisse sodales est euismod nunc condimentum, a consectetur diam ornare." + +.gitlab-ui-dev-kit + %h1 GitLab UI开发包 + %p.light + 使用浏览器的页面检视器(inspector)检查以下示例元素的class和结构. + %hr + %ul + %li + = link_to '区块', '#blocks' + %li + = link_to '列表', '#lists' + %li + = link_to '表格', '#tables' + %li + = link_to '按钮', '#buttons' + %li + = link_to '面板', '#panels' + %li + = link_to '警告', '#alerts' + %li + = link_to '表单', '#forms' + %li + = link_to '文件', '#file' + %li + = link_to 'Markdown', '#markdown' + + %h2#blocks 区块 + + %h3 + %code .well + + + .well + %h4 Something + = lorem + + + %h2#lists 列表 + + %h3 + %code .well-list + %ul.well-list + %li + 某条目 + %li + 某条目 + %li + 某条目 + + %h3 + %code .panel .well-list + + .panel.panel-default + .panel-heading My list + %ul.well-list + %li + 某条目 + %li + 某条目 + %li + 某条目 + + %h3 + %code .bordered-list + %ul.bordered-list + %li + 某条目 + %li + 某条目 + %li + 某条目 + + + + %h2#tables 表格 + + .example + %table.table + %thead + %tr + %th # + %th 名 + %th 姓 + %th 用户名 + %tbody + %tr + %td 1 + %td Mark + %td Otto + %td @mdo + %tr + %td 2 + %td Jacob + %td Thornton + %td @fat + %tr + %td 3 + %td Larry + %td the Bird + %td @twitter + + + %h2#buttons 按钮 + + .example + %button.btn.btn-default{:type => "button"} 默认 + %button.btn.btn-primary{:type => "button"} 主要 + %button.btn.btn-success{:type => "button"} 成功 + %button.btn.btn-info{:type => "button"} 信息 + %button.btn.btn-warning{:type => "button"} 警告 + %button.btn.btn-danger{:type => "button"} 危险 + %button.btn.btn-link{:type => "button"} 链接 + + %h2#panels 面板 + + .row + .col-md-6 + .panel.panel-success + .panel-heading 成功 + .panel-body + = lorem + .panel.panel-primary + .panel-heading 主要 + .panel-body + = lorem + .panel.panel-info + .panel-heading 信息 + .panel-body + = lorem + .col-md-6 + .panel.panel-warning + .panel-heading 警告 + .panel-body + = lorem + .panel.panel-danger + .panel-heading 危险 + .panel-body + = lorem + + %h2#alert 警告提醒 + + .row + .col-md-6 + .alert.alert-success + = lorem + .alert.alert-primary + = lorem + .alert.alert-info + = lorem + .col-md-6 + .alert.alert-warning + = lorem + .alert.alert-danger + = lorem + + %h2#forms 表单 + + %h3 + %code form.horizontal-form + + %form.form-horizontal + .form-group + %label.col-sm-2.control-label{:for => "inputEmail3"} 邮箱 + .col-sm-10 + %input#inputEmail3.form-control{:placeholder => "邮箱", :type => "email"}/ + .form-group + %label.col-sm-2.control-label{:for => "inputPassword3"} 密码 + .col-sm-10 + %input#inputPassword3.form-control{:placeholder => "密码", :type => "password"}/ + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + %label + %input{:type => "checkbox"}/ + 记住我 + .form-group + .col-sm-offset-2.col-sm-10 + %button.btn.btn-default{:type => "submit"} 登录 + + %h3 + %code form + + %form + .form-group + %label{:for => "exampleInputEmail1"} 邮箱地址 + %input#exampleInputEmail1.form-control{:placeholder => "输入邮箱", :type => "email"}/ + .form-group + %label{:for => "exampleInputPassword1"} 密码 + %input#exampleInputPassword1.form-control{:placeholder => "密码", :type => "password"}/ + .checkbox + %label + %input{:type => "checkbox"}/ + 记住我 + %button.btn.btn-default{:type => "submit"} 登录 + + %h2#file 文件 + %h3 + %code .file-holder + + - blob = Snippet.new(content: "Wow\nSuch\nFile") + .example + .file-holder + .file-title + 超酷的文件 + .file-actions + .btn-group + %a.btn 编辑 + %a.btn 删除 + .file-contenta.code + = render 'shared/file_highlight', blob: blob + + + %h2#markdown Markdown + %h3 + %code .md或.wiki及其它 + + Markdown渲染使用有微少差别的css, 显示效果见下面的元素: + + %ul + %li 评论 + %li 问题, 合并请求描述 + %li wiki页 + %li 帮助页 + + 您可以查看 #{link_to 'Markdown帮助页', help_page_path("markdown", "markdown")} 了解markdown是如何渲染的. diff --git a/app/views/import/base/create.zh.js.haml b/app/views/import/base/create.zh.js.haml new file mode 100644 index 00000000000..8bafba0e58c --- /dev/null +++ b/app/views/import/base/create.zh.js.haml @@ -0,0 +1,25 @@ +- if @already_been_taken + :plain + target_field = $("tr#repo_#{@repo_id} .import-target") + origin_target = target_field.text() + project_name = "#{@project_name}" + origin_namespace = "#{@target_namespace}" + target_field.empty() + target_field.append("

该命名空间已被使用! 请选其它的

") + target_field.append("") + target_field.append("/" + project_name) + target_field.data("project_name", project_name) + target_field.find('input').prop("value", origin_namespace) +- elsif @access_denied + :plain + job = $("tr#repo_#{@repo_id}") + job.find(".import-actions").html("

访问被拒绝! 请验证您可以添加布署key到该仓库.

"") +- else + :plain + job = $("tr#repo_#{@repo_id}") + job.attr("id", "project_#{@project.id}") + target_field = job.find(".import-target") + target_field.empty() + target_field.append('#{link_to @project.path_with_namespace, [@project.namespace.becomes(Namespace), @project]}') + $("table.import-jobs tbody").prepend(job) + job.addClass("active").find(".import-actions").html(" started") diff --git a/app/views/import/bitbucket/status.zh.html.haml b/app/views/import/bitbucket/status.zh.html.haml new file mode 100644 index 00000000000..c20bf269722 --- /dev/null +++ b/app/views/import/bitbucket/status.zh.html.haml @@ -0,0 +1,46 @@ +%h3.page-title + %i.fa.fa-bitbucket + 从Bitbucket导入项目 + +%p.light + 选择您要导入的项目. +%hr +%p + = button_tag '导入所有项目', class: "btn btn-success js-import-all" + +%table.table.import-jobs + %thead + %tr + %th 从Bitbucket + %th 到GitLab + %th 状态 + %tbody + - @already_added_projects.each do |project| + %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"} + %td + = link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: "_blank" + %td + %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] + %td.job-status + - if project.import_status == 'finished' + %span + %i.fa.fa-check + 已完成 + - elsif project.import_status == 'started' + %i.fa.fa-spinner.fa-spin + 已开始 + - else + = project.human_import_status_name + + - @repos.each do |repo| + %tr{id: "repo_#{repo["owner"]}___#{repo["slug"]}"} + %td + = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank" + %td.import-target + = "#{repo["owner"]}/#{repo["slug"]}" + %td.import-actions.job-status + = button_tag "导入", class: "btn js-add-to-import" + +:coffeescript + $ -> + new ImporterStatus("#{jobs_import_bitbucket_path}", "#{import_bitbucket_path}") diff --git a/app/views/import/github/status.zh.html.haml b/app/views/import/github/status.zh.html.haml new file mode 100644 index 00000000000..cd658c6d44c --- /dev/null +++ b/app/views/import/github/status.zh.html.haml @@ -0,0 +1,46 @@ +%h3.page-title + %i.fa.fa-github + 从GitHub导入项目 + +%p.light + 选择您要导入的项目. +%hr +%p + = button_tag '导入所有项目', class: "btn btn-success js-import-all" + +%table.table.import-jobs + %thead + %tr + %th 从GitHub + %th 到GitLab + %th 状态 + %tbody + - @already_added_projects.each do |project| + %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"} + %td + = link_to project.import_source, "https://github.com/#{project.import_source}", target: "_blank" + %td + %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] + %td.job-status + - if project.import_status == 'finished' + %span + %i.fa.fa-check + 已完成 + - elsif project.import_status == 'started' + %i.fa.fa-spinner.fa-spin + 已开始 + - else + = project.human_import_status_name + + - @repos.each do |repo| + %tr{id: "repo_#{repo.id}"} + %td + = link_to repo.full_name, "https://github.com/#{repo.full_name}", target: "_blank" + %td.import-target + = repo.full_name + %td.import-actions.job-status + = button_tag "导入", class: "btn js-add-to-import" + +:coffeescript + $ -> + new ImporterStatus("#{jobs_import_github_path}", "#{import_github_path}") diff --git a/app/views/import/gitlab/status.zh.html.haml b/app/views/import/gitlab/status.zh.html.haml new file mode 100644 index 00000000000..b5dcd40abf6 --- /dev/null +++ b/app/views/import/gitlab/status.zh.html.haml @@ -0,0 +1,46 @@ +%h3.page-title + %i.fa.fa-heart + 从GitLab.com导入项目 + +%p.light + 选择您要导入的项目. +%hr +%p + = button_tag '导入所有项目', class: "btn btn-success js-import-all" + +%table.table.import-jobs + %thead + %tr + %th 从GitLab.com + %th 到该GitLab实例 + %th 状态 + %tbody + - @already_added_projects.each do |project| + %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"} + %td + = link_to project.import_source, "https://gitlab.com/#{project.import_source}", target: "_blank" + %td + %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] + %td.job-status + - if project.import_status == 'finished' + %span + %i.fa.fa-check + 已完成 + - elsif project.import_status == 'started' + %i.fa.fa-spinner.fa-spin + 已开始 + - else + = project.human_import_status_name + + - @repos.each do |repo| + %tr{id: "repo_#{repo["id"]}"} + %td + = link_to repo["path_with_namespace"], "https://gitlab.com/#{repo["path_with_namespace"]}", target: "_blank" + %td.import-target + = repo["path_with_namespace"] + %td.import-actions.job-status + = button_tag "导入", class: "btn js-add-to-import" + +:coffeescript + $ -> + new ImporterStatus("#{jobs_import_gitlab_path}", "#{import_gitlab_path}") diff --git a/app/views/import/gitorious/status.zh.html.haml b/app/views/import/gitorious/status.zh.html.haml new file mode 100644 index 00000000000..03fe4efdd44 --- /dev/null +++ b/app/views/import/gitorious/status.zh.html.haml @@ -0,0 +1,46 @@ +%h3.page-title + %i.icon-gitorious.icon-gitorious-big + 从Gitorious导入项目 + +%p.light + 选择您要导入的项目. +%hr +%p + = button_tag '导入所有项目', class: "btn btn-success js-import-all" + +%table.table.import-jobs + %thead + %tr + %th 从Gitorious.org + %th 到GitLab + %th 状态 + %tbody + - @already_added_projects.each do |project| + %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"} + %td + = link_to project.import_source, "https://gitorious.org/#{project.import_source}", target: "_blank" + %td + %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] + %td.job-status + - if project.import_status == 'finished' + %span + %i.fa.fa-check + 已完成 + - elsif project.import_status == 'started' + %i.fa.fa-spinner.fa-spin + 已开始 + - else + = project.human_import_status_name + + - @repos.each do |repo| + %tr{id: "repo_#{repo.id}"} + %td + = link_to repo.full_name, "https://gitorious.org/#{repo.full_name}", target: "_blank" + %td.import-target + = repo.full_name + %td.import-actions.job-status + = button_tag "导入", class: "btn js-add-to-import" + +:coffeescript + $ -> + new ImporterStatus("#{jobs_import_gitorious_path}", "#{import_gitorious_path}") diff --git a/app/views/layouts/_broadcast.zh.html.haml b/app/views/layouts/_broadcast.zh.html.haml new file mode 100644 index 00000000000..e7d477c225e --- /dev/null +++ b/app/views/layouts/_broadcast.zh.html.haml @@ -0,0 +1,4 @@ +- if broadcast_message.present? + .broadcast-message{ style: broadcast_styling(broadcast_message) } + %i.fa.fa-bullhorn + = broadcast_message.message diff --git a/app/views/layouts/_collapse_button.zh.html.haml b/app/views/layouts/_collapse_button.zh.html.haml new file mode 100644 index 00000000000..60308026da5 --- /dev/null +++ b/app/views/layouts/_collapse_button.zh.html.haml @@ -0,0 +1,4 @@ +- if nav_menu_collapsed? + = link_to icon('angle-right'), '#', class: 'toggle-nav-collapse', title: "打开/关闭" +- else + = link_to icon('angle-left'), '#', class: 'toggle-nav-collapse', title: "打开/关闭" diff --git a/app/views/layouts/_flash.zh.html.haml b/app/views/layouts/_flash.zh.html.haml new file mode 100644 index 00000000000..cc8ea066cb9 --- /dev/null +++ b/app/views/layouts/_flash.zh.html.haml @@ -0,0 +1,8 @@ +.flash-container + - if alert + .flash-alert + = alert + + - elsif notice + .flash-notice + = notice diff --git a/app/views/layouts/_google_analytics.zh.html.haml b/app/views/layouts/_google_analytics.zh.html.haml new file mode 100644 index 00000000000..81e03c7eff2 --- /dev/null +++ b/app/views/layouts/_google_analytics.zh.html.haml @@ -0,0 +1,10 @@ +:javascript + var _gaq = _gaq || []; + _gaq.push(['_setAccount', '#{extra_config.google_analytics_id}']); + _gaq.push(['_trackPageview']); + + (function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); diff --git a/app/views/layouts/_head.zh.html.haml b/app/views/layouts/_head.zh.html.haml new file mode 100644 index 00000000000..3ad5f2ff684 --- /dev/null +++ b/app/views/layouts/_head.zh.html.haml @@ -0,0 +1,28 @@ +%head + %meta{charset: "utf-8"} + %meta{content: "GitLab社区版", name: "description"} + + %title + = "#{title} | " if defined?(title) + GitLab + = favicon_link_tag 'favicon.ico' + = 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'} + + = render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id') + = render 'layouts/piwik' if extra_config.has_key?('piwik_url') && extra_config.has_key?('piwik_site_id') + + -# Atom feed + - if current_user + - if controller_name == 'projects' && action_name == 'index' + = auto_discovery_link_tag :atom, projects_url(:atom, private_token: current_user.private_token), title: "Dashboard feed" + - if @project && !@project.new_record? + - if current_controller?(:tree, :commits) + = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "Recent commits to #{@project.name}:#{@ref}") + - if current_controller?(:issues) + = auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") diff --git a/app/views/layouts/_head_panel.zh.html.haml b/app/views/layouts/_head_panel.zh.html.haml new file mode 100644 index 00000000000..c74ccff121b --- /dev/null +++ b/app/views/layouts/_head_panel.zh.html.haml @@ -0,0 +1,48 @@ +%header.navbar.navbar-fixed-top.navbar-gitlab + .navbar-inner + .container + %div.app_logo + = link_to root_path, class: "home has_bottom_tooltip", title: "仪表盘" do + = brand_header_logo + %h1.title= title + + %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"} + %span.sr-only 切换导航 + %i.fa.fa-bars + + .navbar-collapse.collapse + %ul.nav.navbar-nav + %li.hidden-sm.hidden-xs + = render "layouts/search" + %li.visible-sm.visible-xs + = link_to search_path, title: "搜索", class: 'has_bottom_tooltip', 'data-original-title' => 'Search area' do + %i.fa.fa-search + %li + = link_to help_path, title: '帮助', class: 'has_bottom_tooltip', + 'data-original-title' => 'Help' do + %i.fa.fa-question-circle + %li + = link_to explore_root_path, title: "探索", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do + %i.fa.fa-globe + %li + = link_to user_snippets_path(current_user), title: "我的代码片段", class: 'has_bottom_tooltip', 'data-original-title' => 'My snippets' do + %i.fa.fa-clipboard + - if current_user.is_admin? + %li + = link_to admin_root_path, title: "管理区域", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do + %i.fa.fa-cogs + - if current_user.can_create_project? + %li + = link_to new_project_path, title: "新建项目", class: 'has_bottom_tooltip', 'data-original-title' => 'New project' do + %i.fa.fa-plus + %li + = link_to profile_path, title: "用户资料设置", class: 'has_bottom_tooltip', 'data-original-title' => 'Profile settings"' do + %i.fa.fa-user + %li + = link_to destroy_user_session_path, class: "logout", method: :delete, title: "注销", class: 'has_bottom_tooltip', 'data-original-title' => 'Logout' do + %i.fa.fa-sign-out + %li.hidden-xs + = link_to current_user, class: "profile-pic has_bottom_tooltip", id: 'profile-pic', 'data-original-title' => 'Your profile' do + = image_tag avatar_icon(current_user.email, 60), alt: '用户活动' + += render 'shared/outdated_browser' diff --git a/app/views/layouts/_init_auto_complete.zh.html.haml b/app/views/layouts/_init_auto_complete.zh.html.haml new file mode 100644 index 00000000000..3c58f10e759 --- /dev/null +++ b/app/views/layouts/_init_auto_complete.zh.html.haml @@ -0,0 +1,3 @@ +:javascript + GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(@project.namespace, @project, type: @noteable.class, type_id: params[:id])}" + GitLab.GfmAutoComplete.setup(); diff --git a/app/views/layouts/_page.zh.html.haml b/app/views/layouts/_page.zh.html.haml new file mode 100644 index 00000000000..422966cdc55 --- /dev/null +++ b/app/views/layouts/_page.zh.html.haml @@ -0,0 +1,23 @@ +- if defined?(sidebar) + .page-with-sidebar{ class: nav_sidebar_class } + = render "layouts/broadcast" + .sidebar-wrapper + = render(sidebar) + .collapse-nav + = render partial: 'layouts/collapse_button' + .content-wrapper + .container-fluid + .content + = render "layouts/flash" + .clearfix + = yield +- else + .container.navless-container + .content + = yield + += yield :embedded_scripts + +:coffeescript + $('.page-sidebar-collapsed .nav-sidebar a').tooltip placement: "right" + diff --git a/app/views/layouts/_page_title.zh.html.haml b/app/views/layouts/_page_title.zh.html.haml new file mode 100644 index 00000000000..54da5074763 --- /dev/null +++ b/app/views/layouts/_page_title.zh.html.haml @@ -0,0 +1,2 @@ +- if content_for?(:page-title) + = yield :page-title diff --git a/app/views/layouts/_piwik.zh.html.haml b/app/views/layouts/_piwik.zh.html.haml new file mode 100644 index 00000000000..135e8daca26 --- /dev/null +++ b/app/views/layouts/_piwik.zh.html.haml @@ -0,0 +1,12 @@ +:javascript + var _paq = _paq || []; + _paq.push(["trackPageView"]); + _paq.push(["enableLinkTracking"]); + + (function() { + var u=(("https:" == document.location.protocol) ? "https" : "http") + "://#{extra_config.piwik_url}/"; + _paq.push(["setTrackerUrl", u+"piwik.php"]); + _paq.push(["setSiteId", "#{extra_config.piwik_site_id}"]); + var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0]; g.type="text/javascript"; + g.defer=true; g.async=true; g.src=u+"piwik.js"; s.parentNode.insertBefore(g,s); + })(); diff --git a/app/views/layouts/_public_head_panel.zh.html.haml b/app/views/layouts/_public_head_panel.zh.html.haml new file mode 100644 index 00000000000..7e30845351c --- /dev/null +++ b/app/views/layouts/_public_head_panel.zh.html.haml @@ -0,0 +1,22 @@ +%header.navbar.navbar-fixed-top.navbar-gitlab + .navbar-inner + .container + %div.app_logo + = link_to explore_root_path, class: "home" do + = brand_header_logo + %h1.title= title + + %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"} + %span.sr-only 切换导航 + %i.fa.fa-bars + + - unless current_controller?('sessions') + .pull-right.hidden-xs + = link_to "登录", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-new append-right-10' + + .navbar-collapse.collapse + %ul.nav.navbar-nav + %li.visible-xs + = link_to "登录", new_session_path(:user, redirect_to_referer: 'yes') + += render 'shared/outdated_browser' diff --git a/app/views/layouts/_search.zh.html.haml b/app/views/layouts/_search.zh.html.haml new file mode 100644 index 00000000000..04f79846858 --- /dev/null +++ b/app/views/layouts/_search.zh.html.haml @@ -0,0 +1,28 @@ +.search + = form_tag search_path, method: :get, class: 'navbar-form pull-left' do |f| + = search_field_tag "search", nil, placeholder: search_placeholder, class: "search-input" + = hidden_field_tag :group_id, @group.try(:id) + - if @project && @project.persisted? + = hidden_field_tag :project_id, @project.id + + - if current_controller?(:issues) + = hidden_field_tag :scope, 'issues' + - elsif current_controller?(:merge_requests) + = hidden_field_tag :scope, 'merge_requests' + - elsif current_controller?(:wikis) + = hidden_field_tag :scope, 'wiki_blobs' + - else + = hidden_field_tag :search_code, true + + - if @snippet || @snippets + = hidden_field_tag :snippets, true + = hidden_field_tag :repository_ref, @ref + = button_tag 'Go' if ENV['RAILS_ENV'] == 'test' + .search-autocomplete-opts.hide{:'data-autocomplete-path' => search_autocomplete_path, :'data-autocomplete-project-id' => @project.try(:id), :'data-autocomplete-project-ref' => @ref } + +:javascript + $('.search-input').on('keyup', function(e) { + if (e.keyCode == 27) { + $('.search-input').blur() + } + }) diff --git a/app/views/layouts/admin.zh.html.haml b/app/views/layouts/admin.zh.html.haml new file mode 100644 index 00000000000..1c3bfd1120d --- /dev/null +++ b/app/views/layouts/admin.zh.html.haml @@ -0,0 +1,6 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: "管理区域" + %body{class: "#{app_theme} admin", :'data-page' => body_data_page} + = render "layouts/head_panel", title: link_to("管理区域", admin_root_path) + = render 'layouts/page', sidebar: 'layouts/nav/admin' diff --git a/app/views/layouts/application.zh.html.haml b/app/views/layouts/application.zh.html.haml new file mode 100644 index 00000000000..d4994b90979 --- /dev/null +++ b/app/views/layouts/application.zh.html.haml @@ -0,0 +1,6 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: "仪表盘" + %body{class: "#{app_theme} application", :'data-page' => body_data_page } + = render "layouts/head_panel", title: link_to("仪表盘", root_path) + = render 'layouts/page', sidebar: 'layouts/nav/dashboard' diff --git a/app/views/layouts/devise.zh.html.haml b/app/views/layouts/devise.zh.html.haml new file mode 100644 index 00000000000..80ba9fd9b9e --- /dev/null +++ b/app/views/layouts/devise.zh.html.haml @@ -0,0 +1,35 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head" + %body.ui_mars.login-page.application + = render "layouts/broadcast" + = render "layouts/public_head_panel", title: '' + .container.navless-container + .content + = render "layouts/flash" + .row.prepend-top-20 + .col-sm-5.pull-right + = yield + .col-sm-7.brand-holder.pull-left + %h1 + = brand_title + - if brand_item + = brand_image + = brand_text + - else + %h3 代码协作开源软件 + + %p + 具有细分的访问控制, 管理git仓库保持您的代码安全. + 合并语法, 代码审核, 增强合作. + 每个项目可以有问题跟踪和wiki. + + - if extra_sign_in_text.present? + = markdown(extra_sign_in_text) + + %hr + .container + .footer-links + = link_to "探索", explore_root_path + = link_to "文档", "http://doc.gitlab.com/" + = link_to "关于GitLab", "https://about.gitlab.com/" diff --git a/app/views/layouts/doorkeeper/admin.zh.html.haml b/app/views/layouts/doorkeeper/admin.zh.html.haml new file mode 100644 index 00000000000..650de77973e --- /dev/null +++ b/app/views/layouts/doorkeeper/admin.zh.html.haml @@ -0,0 +1,22 @@ +!!! +%html + %head + %meta{:charset => "utf-8"} + %meta{:content => "IE=edge", "http-equiv" => "X-UA-Compatible"} + %meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"} + %title Doorkeeper + = stylesheet_link_tag "doorkeeper/admin/application" + = csrf_meta_tags + %body + .navbar.navbar-inverse.navbar-fixed-top{:role => "navigation"} + .container + .navbar-header + = link_to 'OAuth2 Provider', oauth_applications_path, class: 'navbar-brand' + %ul.nav.navbar-nav + = content_tag :li, class: "#{'active' if request.path == oauth_applications_path}" do + = link_to '应用', oauth_applications_path + .container + - if flash[:notice].present? + .alert.alert-info + = flash[:notice] + = yield \ No newline at end of file diff --git a/app/views/layouts/doorkeeper/application.zh.html.haml b/app/views/layouts/doorkeeper/application.zh.html.haml new file mode 100644 index 00000000000..9854f56fa94 --- /dev/null +++ b/app/views/layouts/doorkeeper/application.zh.html.haml @@ -0,0 +1,15 @@ +!!! +%html + %head + %title 需要OAuth认证 + %meta{:charset => "utf-8"} + %meta{:content => "IE=edge", "http-equiv" => "X-UA-Compatible"} + %meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"} + = stylesheet_link_tag "doorkeeper/application" + = csrf_meta_tags + %body + #container + - if flash[:notice].present? + .alert.alert-info + = flash[:notice] + = yield \ No newline at end of file diff --git a/app/views/layouts/errors.zh.html.haml b/app/views/layouts/errors.zh.html.haml new file mode 100644 index 00000000000..d7198a7a7ba --- /dev/null +++ b/app/views/layouts/errors.zh.html.haml @@ -0,0 +1,9 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: "Error" + %body{class: "#{app_theme} application"} + = render "layouts/head_panel", title: "" if current_user + .container.navless-container + = render "layouts/flash" + .error-page + = yield diff --git a/app/views/layouts/explore.zh.html.haml b/app/views/layouts/explore.zh.html.haml new file mode 100644 index 00000000000..4916245b33d --- /dev/null +++ b/app/views/layouts/explore.zh.html.haml @@ -0,0 +1,30 @@ +- page_title = '探索' +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: page_title + %body{class: "#{app_theme} application", :'data-page' => body_data_page} + = render "layouts/broadcast" + - if current_user + = render "layouts/head_panel", title: link_to(page_title, explore_root_path) + - else + = render "layouts/public_head_panel", title: link_to(page_title, explore_root_path) + .container.navless-container + .content + .explore-title + %h3 + 探索GitLab + %p.lead + 发现项目和组. 与其它人分享项目 + + + %ul.nav.nav-tabs + = nav_link(path: 'projects#trending') do + = link_to '项目趋势', explore_root_path + = nav_link(path: 'projects#starred') do + = link_to '收藏最多的项目', starred_explore_projects_path + = nav_link(path: 'projects#index') do + = link_to '所有项目', explore_projects_path + = nav_link(controller: :groups) do + = link_to '所有组', explore_groups_path + + = yield diff --git a/app/views/layouts/group.zh.html.haml b/app/views/layouts/group.zh.html.haml new file mode 100644 index 00000000000..be88fe288f2 --- /dev/null +++ b/app/views/layouts/group.zh.html.haml @@ -0,0 +1,6 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: group_head_title + %body{class: "#{app_theme} application", :'data-page' => body_data_page} + = render "layouts/head_panel", title: link_to(@group.name, group_path(@group)) + = render 'layouts/page', sidebar: 'layouts/nav/group' diff --git a/app/views/layouts/nav/_admin.zh.html.haml b/app/views/layouts/nav/_admin.zh.html.haml new file mode 100644 index 00000000000..9b00a2e55dc --- /dev/null +++ b/app/views/layouts/nav/_admin.zh.html.haml @@ -0,0 +1,60 @@ +%ul.nav.nav-sidebar + = nav_link(controller: :dashboard, html_options: {class: 'home'}) do + = link_to admin_root_path, title: "状态" do + %i.fa.fa-dashboard + %span + 概况 + = nav_link(controller: :projects) do + = link_to admin_namespaces_projects_path, title: '项目' do + %i.fa.fa-cube + %span + 项目 + = nav_link(controller: :users) do + = link_to admin_users_path, title: '用户' do + %i.fa.fa-user + %span + 用户 + = nav_link(controller: :groups) do + = link_to admin_groups_path, title: '组' do + %i.fa.fa-group + %span + 组 + = nav_link(controller: :logs) do + = link_to admin_logs_path, title: '日志' do + %i.fa.fa-file-text + %span + 日志 + = nav_link(controller: :broadcast_messages) do + = link_to admin_broadcast_messages_path, title: '广播消息' do + %i.fa.fa-bullhorn + %span + 消息 + = nav_link(controller: :hooks) do + = link_to admin_hooks_path, title: '钩子' do + %i.fa.fa-external-link + %span + 钩子 + = nav_link(controller: :background_jobs) do + = link_to admin_background_jobs_path, title: '后台任务' do + %i.fa.fa-cog + %span + 后台任务 + + = nav_link(controller: :applications) do + = link_to admin_applications_path, title: '应用' do + %i.fa.fa-cloud + %span + 应用 + + = nav_link(controller: :services) do + = link_to admin_application_settings_services_path, title: '服务模板' do + %i.fa.fa-copy + %span + 服务模板 + + = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do + = link_to admin_application_settings_path, title: '设置' do + %i.fa.fa-cogs + %span + 设置 + diff --git a/app/views/layouts/nav/_dashboard.zh.html.haml b/app/views/layouts/nav/_dashboard.zh.html.haml new file mode 100644 index 00000000000..203351fa6e4 --- /dev/null +++ b/app/views/layouts/nav/_dashboard.zh.html.haml @@ -0,0 +1,38 @@ +%ul.nav.nav-sidebar + = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do + = link_to root_path, title: '首页', class: 'shortcuts-activity' do + %i.fa.fa-dashboard + %span + 您的项目 + = nav_link(path: 'projects#starred') do + = link_to starred_dashboard_projects_path, title: '收藏的项目' do + %i.fa.fa-star + %span + 收藏的项目 + = nav_link(controller: :groups) do + = link_to dashboard_groups_path, title: '组' do + %i.fa.fa-group + %span + 组 + = nav_link(controller: :milestones) do + = link_to dashboard_milestones_path, title: '里程碑' do + %i.fa.fa-clock-o + %span + 里程碑 + = nav_link(path: 'dashboard#issues') do + = link_to assigned_issues_dashboard_path, title: '问题', class: 'shortcuts-issues' do + %i.fa.fa-exclamation-circle + %span + 问题 + %span.count= current_user.assigned_issues.opened.count + = nav_link(path: 'dashboard#merge_requests') do + = link_to assigned_mrs_dashboard_path, title: '合并请求', class: 'shortcuts-merge_requests' do + %i.fa.fa-tasks + %span + 合并请求 + %span.count= current_user.assigned_merge_requests.opened.count + = nav_link(controller: :help) do + = link_to help_path, title: '帮助' do + %i.fa.fa-question-circle + %span + 帮助 diff --git a/app/views/layouts/nav/_group.zh.html.haml b/app/views/layouts/nav/_group.zh.html.haml new file mode 100644 index 00000000000..af1a1d485ed --- /dev/null +++ b/app/views/layouts/nav/_group.zh.html.haml @@ -0,0 +1,42 @@ +%ul.nav.nav-sidebar + = nav_link(path: 'groups#show', html_options: {class: 'home'}) do + = link_to group_path(@group), title: "首页" do + %i.fa.fa-dashboard + %span + 活动 + - if current_user + = nav_link(controller: [:group, :milestones]) do + = link_to group_milestones_path(@group), title: '里程碑' do + %i.fa.fa-clock-o + %span + 里程碑 + = nav_link(path: 'groups#issues') do + = link_to issues_group_path(@group), title: '问题' do + %i.fa.fa-exclamation-circle + %span + 问题 + - if current_user + %span.count= Issue.opened.of_group(@group).count + = nav_link(path: 'groups#merge_requests') do + = link_to merge_requests_group_path(@group), title: '合并请求' do + %i.fa.fa-tasks + %span + 合并请求 + - if current_user + %span.count= MergeRequest.opened.of_group(@group).count + = nav_link(controller: [:group_members]) do + = link_to group_group_members_path(@group), title: '成员' do + %i.fa.fa-users + %span + 成员 + + - if can?(current_user, :manage_group, @group) + = nav_link(html_options: { class: "#{"active" if group_settings_page?} separate-item" }) do + = link_to edit_group_path(@group), title: '设置', class: "tab no-highlight" do + %i.fa.fa-cogs + %span + 设置 + %i.fa.fa-angle-down + + - if group_settings_page? + = render 'groups/settings_nav' diff --git a/app/views/layouts/nav/_profile.zh.html.haml b/app/views/layouts/nav/_profile.zh.html.haml new file mode 100644 index 00000000000..0b3d400fc08 --- /dev/null +++ b/app/views/layouts/nav/_profile.zh.html.haml @@ -0,0 +1,50 @@ +%ul.nav.nav-sidebar + = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do + = link_to profile_path, title: "用户资料" do + %i.fa.fa-user + %span + 用户资料 + = nav_link(controller: :accounts) do + = link_to profile_account_path, title: '帐号' do + %i.fa.fa-gear + %span + 帐号 + = nav_link(path: ['profiles#applications', 'applications#edit', 'applications#show', 'applications#new']) do + = link_to applications_profile_path, title: '应用' do + %i.fa.fa-cloud + %span + 应用 + = nav_link(controller: :emails) do + = link_to profile_emails_path, title: '邮箱' do + %i.fa.fa-envelope-o + %span + 邮箱 + %span.count= current_user.emails.count + 1 + - unless current_user.ldap_user? + = nav_link(controller: :passwords) do + = link_to edit_profile_password_path, title: '密码' do + %i.fa.fa-lock + %span + 密码 + = nav_link(controller: :notifications) do + = link_to profile_notifications_path, title: '通知' do + %i.fa.fa-inbox + %span + 通知 + + = nav_link(controller: :keys) do + = link_to profile_keys_path, title: 'SSH Key' do + %i.fa.fa-key + %span + SSH Key + %span.count= current_user.keys.count + = nav_link(path: 'profiles#design') do + = link_to design_profile_path, title: '设计' do + %i.fa.fa-image + %span + 设计 + = nav_link(path: 'profiles#history') do + = link_to history_profile_path, title: '历史记录' do + %i.fa.fa-history + %span + 历史记录 diff --git a/app/views/layouts/nav/_project.zh.html.haml b/app/views/layouts/nav/_project.zh.html.haml new file mode 100644 index 00000000000..c7663167678 --- /dev/null +++ b/app/views/layouts/nav/_project.zh.html.haml @@ -0,0 +1,97 @@ +%ul.project-navigation.nav.nav-sidebar + - if @project_settings_nav + = nav_link do + = link_to project_path(@project), title: '返回项目', class: "" do + %i.fa.fa-caret-square-o-left + %span + 返回项目 + + %li.separate-item + + = render 'projects/settings_nav' + + - else + = nav_link(path: 'projects#show', html_options: {class: "home"}) do + = link_to project_path(@project), title: '项目', class: 'shortcuts-project' do + %i.fa.fa-dashboard + %span + 项目 + - 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: '文件', class: 'shortcuts-tree' do + %i.fa.fa-files-o + %span + 文件 + + - if project_nav_tab? :commits + = nav_link(controller: %w(commit commits compare repositories tags branches)) do + = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref), title: '提交', class: 'shortcuts-commits' do + %i.fa.fa-history + %span + 提交 + + - if project_nav_tab? :network + = nav_link(controller: %w(network)) do + = link_to namespace_project_network_path(@project.namespace, @project, @ref || @repository.root_ref), title: '网络', class: 'shortcuts-network' do + %i.fa.fa-code-fork + %span + 网络 + + - if project_nav_tab? :graphs + = nav_link(controller: %w(graphs)) do + = link_to namespace_project_graph_path(@project.namespace, @project, @ref || @repository.root_ref), title: '图示', class: 'shortcuts-graphs' do + %i.fa.fa-area-chart + %span + 图示 + + - if project_nav_tab? :milestones + = nav_link(controller: :milestones) do + = link_to namespace_project_milestones_path(@project.namespace, @project), title: '里程碑' do + %i.fa.fa-clock-o + %span + 里程碑 + + - if project_nav_tab? :issues + = nav_link(controller: :issues) do + = link_to url_for_project_issues, title: '问题', class: 'shortcuts-issues' do + %i.fa.fa-exclamation-circle + %span + 问题 + - if @project.default_issues_tracker? + %span.count.issue_counter= @project.issues.opened.count + + - if project_nav_tab? :merge_requests + = nav_link(controller: :merge_requests) do + = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: '合并请求', class: 'shortcuts-merge_requests' do + %i.fa.fa-tasks + %span + 合并请求 + %span.count.merge_counter= @project.merge_requests.opened.count + + - if project_nav_tab? :labels + = nav_link(controller: :labels) do + = link_to namespace_project_labels_path(@project.namespace, @project), title: '标签(label)' do + %i.fa.fa-tags + %span + 标签 + + - if project_nav_tab? :wiki + = nav_link(controller: :wikis) do + = link_to namespace_project_wiki_path(@project.namespace, @project, :home), title: 'Wiki', class: 'shortcuts-wiki' do + %i.fa.fa-book + %span + Wiki + + - if project_nav_tab? :snippets + = nav_link(controller: :snippets) do + = link_to namespace_project_snippets_path(@project.namespace, @project), title: '代码片段', class: 'shortcuts-snippets' do + %i.fa.fa-file-text-o + %span + 代码片段 + + - if project_nav_tab? :settings + = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do + = link_to edit_project_path(@project), title: '设置', class: "stat-tab tab no-highlight" do + %i.fa.fa-cogs + %span + 设置 diff --git a/app/views/layouts/navless.zh.html.haml b/app/views/layouts/navless.zh.html.haml new file mode 100644 index 00000000000..bf6c4ed1bd5 --- /dev/null +++ b/app/views/layouts/navless.zh.html.haml @@ -0,0 +1,10 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: @title + %body{class: "#{app_theme} application", :'data-page' => body_data_page} + = render "layouts/broadcast" + = render "layouts/head_panel", title: defined?(@title_url) ? link_to(@title, @title_url) : @title + .container.navless-container + .content + = render "layouts/flash" + = yield diff --git a/app/views/layouts/notify.zh.html.haml b/app/views/layouts/notify.zh.html.haml new file mode 100644 index 00000000000..a637d5befd4 --- /dev/null +++ b/app/views/layouts/notify.zh.html.haml @@ -0,0 +1,43 @@ +%html{lang: "zh"} + %head + %meta{content: "text/html; charset=utf-8", "http-equiv" => "Content-Type"} + %title + GitLab + :css + img { + max-width: 100%; + height: auto; + } + p.details { + font-style:italic; + color:#777 + } + .footer p { + font-size:small; + color:#777 + } + pre.commit-message { + white-space: pre-wrap; + } + .file-stats a { + text-decoration: none; + } + .file-stats .new-file { + color: #090; + } + .file-stats .deleted-file { + color: #B00; + } + #{add_email_highlight_css} + %body + %div.content + = yield + %div.footer{style: "margin-top: 10px;"} + %p + \— + %br + - if @target_url + #{link_to "在GitLab中查看", @target_url} + = email_action @target_url + - if @project && !@disable_footer + 您收到这个通知是因为您是 #{link_to_unless @target_url, @project.name_with_namespace, namespace_project_url(@project.namespace, @project)} 项目组的成员. diff --git a/app/views/layouts/profile.zh.html.haml b/app/views/layouts/profile.zh.html.haml new file mode 100644 index 00000000000..9124c7e2c55 --- /dev/null +++ b/app/views/layouts/profile.zh.html.haml @@ -0,0 +1,6 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: "用户资料" + %body{class: "#{app_theme} profile", :'data-page' => body_data_page} + = render "layouts/head_panel", title: link_to("用户资料", profile_path) + = render 'layouts/page', sidebar: 'layouts/nav/profile' diff --git a/app/views/layouts/project_settings.zh.html.haml b/app/views/layouts/project_settings.zh.html.haml new file mode 100644 index 00000000000..0ae45517922 --- /dev/null +++ b/app/views/layouts/project_settings.zh.html.haml @@ -0,0 +1,8 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: @project.name_with_namespace + %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } + = render "layouts/head_panel", title: project_title(@project) + = render "layouts/init_auto_complete" + - @project_settings_nav = true + = render 'layouts/page', sidebar: 'layouts/nav/project' diff --git a/app/views/layouts/projects.zh.html.haml b/app/views/layouts/projects.zh.html.haml new file mode 100644 index 00000000000..98f13f90bda --- /dev/null +++ b/app/views/layouts/projects.zh.html.haml @@ -0,0 +1,7 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: project_head_title + %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } + = render "layouts/head_panel", title: project_title(@project) + = render "layouts/init_auto_complete" + = render 'layouts/page', sidebar: 'layouts/nav/project' diff --git a/app/views/layouts/public_group.zh.html.haml b/app/views/layouts/public_group.zh.html.haml new file mode 100644 index 00000000000..00f7c96338e --- /dev/null +++ b/app/views/layouts/public_group.zh.html.haml @@ -0,0 +1,6 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: group_head_title + %body{class: "#{app_theme} application", :'data-page' => body_data_page} + = render "layouts/public_head_panel", title: link_to(@group.name, group_path(@group)) + = render 'layouts/page', sidebar: 'layouts/nav/group' diff --git a/app/views/layouts/public_projects.zh.html.haml b/app/views/layouts/public_projects.zh.html.haml new file mode 100644 index 00000000000..c8c3075f3dd --- /dev/null +++ b/app/views/layouts/public_projects.zh.html.haml @@ -0,0 +1,6 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: @project.name_with_namespace + %body{class: "#{app_theme} application", :'data-page' => body_data_page} + = render "layouts/public_head_panel", title: project_title(@project) + = render 'layouts/page', sidebar: 'layouts/nav/project' diff --git a/app/views/layouts/public_users.zh.html.haml b/app/views/layouts/public_users.zh.html.haml new file mode 100644 index 00000000000..8ca35ee0f3e --- /dev/null +++ b/app/views/layouts/public_users.zh.html.haml @@ -0,0 +1,6 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: @title + %body{class: "#{app_theme} application", :'data-page' => body_data_page} + = render "layouts/public_head_panel", title: defined?(@title_url) ? link_to(@title, @title_url) : @title + = render 'layouts/page' diff --git a/app/views/layouts/search.zh.html.haml b/app/views/layouts/search.zh.html.haml new file mode 100644 index 00000000000..cb90f542480 --- /dev/null +++ b/app/views/layouts/search.zh.html.haml @@ -0,0 +1,10 @@ +!!! 5 +%html{ lang: "zh"} + = render "layouts/head", title: "搜索" + %body{class: "#{app_theme} application", :'data-page' => body_data_page} + = render "layouts/broadcast" + = render "layouts/head_panel", title: link_to("搜索", search_path) + .container.navless-container + .content + = render "layouts/flash" + = yield diff --git a/app/views/notify/_reassigned_issuable_email.zh.html.haml b/app/views/notify/_reassigned_issuable_email.zh.html.haml new file mode 100644 index 00000000000..cbaf29475f0 --- /dev/null +++ b/app/views/notify/_reassigned_issuable_email.zh.html.haml @@ -0,0 +1,10 @@ +%p + 指定人发生改变 + - if @previous_assignee + 原为 + %strong #{@previous_assignee.name} + 修改为 + - if issuable.assignee_id + %strong #{issuable.assignee_name} + - else + %strong 未指定 diff --git a/app/views/notify/_reassigned_issuable_email.zh.text.erb b/app/views/notify/_reassigned_issuable_email.zh.text.erb new file mode 100644 index 00000000000..f24e2ba879a --- /dev/null +++ b/app/views/notify/_reassigned_issuable_email.zh.text.erb @@ -0,0 +1,6 @@ +重新指定 <%= issuable.class.model_name.human.titleize %> <%= issuable.iid %> + +<%= url_for([issuable.project.namespace.becomes(Namespace), issuable.project, issuable, {only_path: false}]) %> + +指定人发生改变 <%= "from #{@previous_assignee.name}" if @previous_assignee -%> + to <%= "#{issuable.assignee_id ? issuable.assignee_name : '未指定'}" %> diff --git a/app/views/notify/closed_issue_email.zh.html.haml b/app/views/notify/closed_issue_email.zh.html.haml new file mode 100644 index 00000000000..70ff98034da --- /dev/null +++ b/app/views/notify/closed_issue_email.zh.html.haml @@ -0,0 +1,2 @@ +%p + = "问题被#{@updated_by.name}关闭" diff --git a/app/views/notify/closed_issue_email.zh.text.haml b/app/views/notify/closed_issue_email.zh.text.haml new file mode 100644 index 00000000000..4291547716f --- /dev/null +++ b/app/views/notify/closed_issue_email.zh.text.haml @@ -0,0 +1,3 @@ += "问题被{@updated_by.name}关闭" + +问题 ##{@issue.iid}: #{namespace_project_issue_url(@issue.project.namespace, @issue.project, @issue)} diff --git a/app/views/notify/closed_merge_request_email.zh.html.haml b/app/views/notify/closed_merge_request_email.zh.html.haml new file mode 100644 index 00000000000..fc2011ad422 --- /dev/null +++ b/app/views/notify/closed_merge_request_email.zh.html.haml @@ -0,0 +1,2 @@ +%p + = "#{@updated_by.name}关闭了合并请求##{@merge_request.iid}" diff --git a/app/views/notify/closed_merge_request_email.zh.text.haml b/app/views/notify/closed_merge_request_email.zh.text.haml new file mode 100644 index 00000000000..836783e06e5 --- /dev/null +++ b/app/views/notify/closed_merge_request_email.zh.text.haml @@ -0,0 +1,8 @@ += "#{@updated_by.name}关闭了合并请求##{@merge_request.iid}" + +合并请求url: #{namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request)} + += merge_path_description(@merge_request, 'to') + +作者: #{@merge_request.author_name} +指定给: #{@merge_request.assignee_name} diff --git a/app/views/notify/group_access_granted_email.zh.html.haml b/app/views/notify/group_access_granted_email.zh.html.haml new file mode 100644 index 00000000000..3ee449e92bc --- /dev/null +++ b/app/views/notify/group_access_granted_email.zh.html.haml @@ -0,0 +1,4 @@ +%p + = "您已经授权 #{@group_member.human_access} 访问组" + = link_to group_url(@group) do + = @group.name diff --git a/app/views/notify/group_access_granted_email.zh.text.erb b/app/views/notify/group_access_granted_email.zh.text.erb new file mode 100644 index 00000000000..f6046366947 --- /dev/null +++ b/app/views/notify/group_access_granted_email.zh.text.erb @@ -0,0 +1,4 @@ + +您已经授权 <%= @group_member.human_access %> 访问组 <%= @group.name %> + +<%= url_for(group_url(@group)) %> diff --git a/app/views/notify/issue_status_changed_email.zh.html.haml b/app/views/notify/issue_status_changed_email.zh.html.haml new file mode 100644 index 00000000000..c58a26590fd --- /dev/null +++ b/app/views/notify/issue_status_changed_email.zh.html.haml @@ -0,0 +1,2 @@ +%p + = "#{@updated_by.name}将问题状态修改为#{@issue_status}" diff --git a/app/views/notify/issue_status_changed_email.zh.text.erb b/app/views/notify/issue_status_changed_email.zh.text.erb new file mode 100644 index 00000000000..810d57a4fb8 --- /dev/null +++ b/app/views/notify/issue_status_changed_email.zh.text.erb @@ -0,0 +1,4 @@ +<%= @updated_by.name %>将状态修改为<%= @issue_status %> + +问题 <%= @issue.iid %>: <%= url_for(namespace_project_issue_url(@issue.project.namespace, @issue.project, @issue)) %> + diff --git a/app/views/notify/merge_request_status_email.zh.html.haml b/app/views/notify/merge_request_status_email.zh.html.haml new file mode 100644 index 00000000000..2c4b46db802 --- /dev/null +++ b/app/views/notify/merge_request_status_email.zh.html.haml @@ -0,0 +1,2 @@ +%p + = "#{@updated_by.name}把合并请求##{@merge_request.iid}修改为#{@mr_status}" diff --git a/app/views/notify/merge_request_status_email.zh.text.haml b/app/views/notify/merge_request_status_email.zh.text.haml new file mode 100644 index 00000000000..75d96820d5f --- /dev/null +++ b/app/views/notify/merge_request_status_email.zh.text.haml @@ -0,0 +1,8 @@ += "#{@updated_by.name}把合并请求##{@merge_request.iid}修改为#{@mr_status}" + +合并请求url: #{namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request)} + += merge_path_description(@merge_request, 'to') + +作者: #{@merge_request.author_name} +指定给: #{@merge_request.assignee_name} diff --git a/app/views/notify/merged_merge_request_email.zh.html.haml b/app/views/notify/merged_merge_request_email.zh.html.haml new file mode 100644 index 00000000000..a7cf702c0a0 --- /dev/null +++ b/app/views/notify/merged_merge_request_email.zh.html.haml @@ -0,0 +1,2 @@ +%p + = "合并请求 ##{@merge_request.iid} 被合并" diff --git a/app/views/notify/merged_merge_request_email.zh.text.haml b/app/views/notify/merged_merge_request_email.zh.text.haml new file mode 100644 index 00000000000..67e166fb7bc --- /dev/null +++ b/app/views/notify/merged_merge_request_email.zh.text.haml @@ -0,0 +1,8 @@ += "合并请求##{@merge_request.iid}被合并" + +合并请求Url: #{namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request)} + += merge_path_description(@merge_request, 'to') + +作者: #{@merge_request.author_name} +指定给: #{@merge_request.assignee_name} diff --git a/app/views/notify/new_email_email.zh.html.haml b/app/views/notify/new_email_email.zh.html.haml new file mode 100644 index 00000000000..31fae835ee6 --- /dev/null +++ b/app/views/notify/new_email_email.zh.html.haml @@ -0,0 +1,10 @@ +%p + Hi #{@user.name}! +%p + 一封新邮件被添加到您帐号: +%p + 邮箱: + %code= @email.email +%p + 如果这封邮件是错误添加的, 您可以在此删除 + = link_to "邮件", profile_emails_url diff --git a/app/views/notify/new_email_email.zh.text.erb b/app/views/notify/new_email_email.zh.text.erb new file mode 100644 index 00000000000..efea968aa55 --- /dev/null +++ b/app/views/notify/new_email_email.zh.text.erb @@ -0,0 +1,7 @@ +Hi <%= @user.name %>! + +一封新邮件添加到您的帐号: + +邮箱.................. <%= @email.email %> + +如果这封邮件是错误添加的, 您可以在此移除邮件: <%= profile_emails_url %> diff --git a/app/views/notify/new_issue_email.zh.html.haml b/app/views/notify/new_issue_email.zh.html.haml new file mode 100644 index 00000000000..b6628b75d32 --- /dev/null +++ b/app/views/notify/new_issue_email.zh.html.haml @@ -0,0 +1,6 @@ +-if @issue.description + = replace_image_links_with_base64(markdown(@issue.description), @issue.project) + +- if @issue.assignee_id.present? + %p + 指定给: #{@issue.assignee_name} diff --git a/app/views/notify/new_issue_email.zh.text.erb b/app/views/notify/new_issue_email.zh.text.erb new file mode 100644 index 00000000000..f2f3ce3527e --- /dev/null +++ b/app/views/notify/new_issue_email.zh.text.erb @@ -0,0 +1,5 @@ +新问题已创建. + +问题 <%= @issue.iid %>: <%= url_for(namespace_project_issue_url(@issue.project.namespace, @issue.project, @issue)) %> +作者: <%= @issue.author_name %> +指定给: <%= @issue.assignee_name %> diff --git a/app/views/notify/new_merge_request_email.zh.html.haml b/app/views/notify/new_merge_request_email.zh.html.haml new file mode 100644 index 00000000000..b401ffcd311 --- /dev/null +++ b/app/views/notify/new_merge_request_email.zh.html.haml @@ -0,0 +1,9 @@ +%p.details + != merge_path_description(@merge_request, '→') + +- if @merge_request.assignee_id.present? + %p + 指定给: #{@merge_request.author_name} → #{@merge_request.assignee_name} + +-if @merge_request.description + = replace_image_links_with_base64(markdown(@merge_request.description), @merge_request.project) diff --git a/app/views/notify/new_merge_request_email.zh.text.erb b/app/views/notify/new_merge_request_email.zh.text.erb new file mode 100644 index 00000000000..5f4012a790e --- /dev/null +++ b/app/views/notify/new_merge_request_email.zh.text.erb @@ -0,0 +1,8 @@ +新的合并请求#<%= @merge_request.iid %> + +<%= url_for(namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request)) %> + +<%= merge_path_description(@merge_request, 'to') %> +作者: <%= @merge_request.author_name %> +指定给: <%= @merge_request.assignee_name %> + diff --git a/app/views/notify/new_ssh_key_email.zh.html.haml b/app/views/notify/new_ssh_key_email.zh.html.haml new file mode 100644 index 00000000000..12df1e7c20a --- /dev/null +++ b/app/views/notify/new_ssh_key_email.zh.html.haml @@ -0,0 +1,11 @@ +%p + Hi #{@user.name}! +%p + 新的公用key添加至您的帐号: +%p + 标题: + %code= @key.title +%p + 如果这个key是错误添加, 您可以前往 + = link_to "SSH Key", profile_keys_url + 列表中找到并删除它 diff --git a/app/views/notify/new_ssh_key_email.zh.text.erb b/app/views/notify/new_ssh_key_email.zh.text.erb new file mode 100644 index 00000000000..c73156fa6de --- /dev/null +++ b/app/views/notify/new_ssh_key_email.zh.text.erb @@ -0,0 +1,7 @@ +Hi <%= @user.name %>! + +新的公用key添加至您的帐号: + +标题: <%= @key.title %> + +如果这个key是错误添加, 您可以前往<%= profile_keys_url %>删除 diff --git a/app/views/notify/new_user_email.zh.html.haml b/app/views/notify/new_user_email.zh.html.haml new file mode 100644 index 00000000000..1ac18ff7fe0 --- /dev/null +++ b/app/views/notify/new_user_email.zh.html.haml @@ -0,0 +1,14 @@ +%p + Hi #{@user['name']}! +%p + - if Gitlab.config.gitlab.signup_enabled + 您的帐号添加成功. + - else + 管理员为您创建了帐号. 现在您是公司GitLab应用的成员之一. +%p + 登录名.......................................... + %code= @user['email'] + +- if @user.created_by_id + %p + = link_to "点此设置密码", edit_password_url(@user, :reset_password_token => @token) diff --git a/app/views/notify/new_user_email.zh.text.erb b/app/views/notify/new_user_email.zh.text.erb new file mode 100644 index 00000000000..19f75e208e9 --- /dev/null +++ b/app/views/notify/new_user_email.zh.text.erb @@ -0,0 +1,8 @@ +Hi <%= @user.name %>! + +管理员为您创建了帐号. 现在您是公司GitLab应用的成员之一. + +登录名.................. <%= @user.email %> +<% if @user.created_by_id %> + <%= link_to "点此设置密码", edit_password_url(@user, :reset_password_token => @token) %> +<% end %> diff --git a/app/views/notify/note_commit_email.zh.text.erb b/app/views/notify/note_commit_email.zh.text.erb new file mode 100644 index 00000000000..69789362648 --- /dev/null +++ b/app/views/notify/note_commit_email.zh.text.erb @@ -0,0 +1,9 @@ +提交 <%= @commit.short_id %> 有了新评论 + +<%= url_for(namespace_project_commit_url(@note.project.namespace, @note.project, id: @commit.id, anchor: "note_#{@note.id}")) %> + + +作者: <%= @note.author_name %> + +<%= @note.note %> + diff --git a/app/views/notify/note_issue_email.zh.text.erb b/app/views/notify/note_issue_email.zh.text.erb new file mode 100644 index 00000000000..3abf5ea420a --- /dev/null +++ b/app/views/notify/note_issue_email.zh.text.erb @@ -0,0 +1,9 @@ +问题# <%= @issue.iid %> 有了新评论 + +<%= url_for(namespace_project_issue_url(@issue.project.namespace, @issue.project, @issue, anchor: "note_#{@note.id}")) %> + + +作者: <%= @note.author_name %> + +<%= @note.note %> + diff --git a/app/views/notify/note_merge_request_email.zh.html.haml b/app/views/notify/note_merge_request_email.zh.html.haml new file mode 100644 index 00000000000..4d36ecd6f28 --- /dev/null +++ b/app/views/notify/note_merge_request_email.zh.html.haml @@ -0,0 +1,7 @@ +- if @note.diff_file_name + %p.details + 对比有了新的评论 + = link_to @note.diff_file_name, @target_url + \: + += render 'note_message' diff --git a/app/views/notify/note_merge_request_email.zh.text.erb b/app/views/notify/note_merge_request_email.zh.text.erb new file mode 100644 index 00000000000..1bd6658b040 --- /dev/null +++ b/app/views/notify/note_merge_request_email.zh.text.erb @@ -0,0 +1,9 @@ +合并请求# <%= @merge_request.iid %> 有了新评论 + +<%= url_for(namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request, anchor: "note_#{@note.id}")) %> + + +<%= @note.author_name %> + +<%= @note.note %> + diff --git a/app/views/notify/project_access_granted_email.zh.html.haml b/app/views/notify/project_access_granted_email.zh.html.haml new file mode 100644 index 00000000000..b366451f9a3 --- /dev/null +++ b/app/views/notify/project_access_granted_email.zh.html.haml @@ -0,0 +1,5 @@ +%p + = "您已经授权 #{@project_member.human_access} 访问项目" +%p + = link_to namespace_project_url(@project.namespace, @project) do + = @project.name_with_namespace diff --git a/app/views/notify/project_access_granted_email.zh.text.erb b/app/views/notify/project_access_granted_email.zh.text.erb new file mode 100644 index 00000000000..54a1e9213e9 --- /dev/null +++ b/app/views/notify/project_access_granted_email.zh.text.erb @@ -0,0 +1,4 @@ + +您已经授权 <%= @project_member.human_access %> 访问项目 <%= @project.name_with_namespace %> + +<%= url_for(namespace_project_url(@project.namespace, @project)) %> diff --git a/app/views/notify/project_was_moved_email.zh.html.haml b/app/views/notify/project_was_moved_email.zh.html.haml new file mode 100644 index 00000000000..99f02b09927 --- /dev/null +++ b/app/views/notify/project_was_moved_email.zh.html.haml @@ -0,0 +1,15 @@ +%p + 项目已被移往新地址 +%p + 项目现在在 + = link_to namespace_project_url(@project.namespace, @project) do + = @project.name_with_namespace +%p + 更新您本地仓库的远程url, 运行(用于ssh): +%p{ style: "background: #f5f5f5; padding:10px; border:1px solid #ddd" } + git remote set-url origin #{@project.ssh_url_to_repo} +%p + 或运行(用于http或https): +%p{ style: "background: #f5f5f5; padding:10px; border:1px solid #ddd" } + git remote set-url origin #{@project.http_url_to_repo} +%br diff --git a/app/views/notify/project_was_moved_email.zh.text.erb b/app/views/notify/project_was_moved_email.zh.text.erb new file mode 100644 index 00000000000..66e60f93a04 --- /dev/null +++ b/app/views/notify/project_was_moved_email.zh.text.erb @@ -0,0 +1,10 @@ +项目已被移往新地址 + +项目现在在 +<%= namespace_project_url(@project.namespace, @project) %> + + +更新您本地仓库的远程url, 运行(用于ssh): + git remote set-url origin <%= @project.ssh_url_to_repo %> +或运行(用于http或https): + git remote set-url origin <%= @project.http_url_to_repo %> diff --git a/app/views/notify/repository_push_email.zh.html.haml b/app/views/notify/repository_push_email.zh.html.haml new file mode 100644 index 00000000000..46f0260fcef --- /dev/null +++ b/app/views/notify/repository_push_email.zh.html.haml @@ -0,0 +1,66 @@ +%h3 #{@author.name} 推送到 #{@branch} at #{link_to @project.name_with_namespace, namespace_project_url(@project.namespace, @project)} + +- if @reverse_compare + %p + %strong 警告: + 推送不包含新提交, 但是强制推送将删除下面的提交和修改. + +%h4 + = @reverse_compare ? "删除的提交:" : "提交:" + +%ul + - @commits.each do |commit| + %li + %strong #{link_to commit.short_id, namespace_project_commit_url(@project.namespace, @project, commit)} + %div + %span by #{commit.author_name} + %i at #{commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")} + %pre.commit-message + = commit.safe_message + +%h4 #{pluralize @diffs.count, "changed file"}: + +%ul + - @diffs.each_with_index do |diff, i| + %li.file-stats + %a{href: "#{@target_url if @disable_diffs}#diff-#{i}" } + - if diff.deleted_file + %span.deleted-file + − + = diff.old_path + - elsif diff.renamed_file + = diff.old_path + → + = diff.new_path + - elsif diff.new_file + %span.new-file + + + = diff.new_path + - else + = diff.new_path + +- unless @disable_diffs + %h4 修改: + - @diffs.each_with_index do |diff, i| + %li{id: "diff-#{i}"} + %a{href: @target_url + "#diff-#{i}"} + - if diff.deleted_file + %strong + = diff.old_path + 被删除 + - elsif diff.renamed_file + %strong + = diff.old_path + → + %strong + = diff.new_path + - else + %strong + = diff.new_path + %hr + %pre + = color_email_diff(diff.diff) + %br + +- if @compare.timeout + %h5 差别很大. 为了避免性能问题修改被隐藏 diff --git a/app/views/notify/repository_push_email.zh.text.haml b/app/views/notify/repository_push_email.zh.text.haml new file mode 100644 index 00000000000..00f5433fe96 --- /dev/null +++ b/app/views/notify/repository_push_email.zh.text.haml @@ -0,0 +1,47 @@ +#{@author.name} 推送到 #{@branch} at #{@project.name_with_namespace} +\ +\ +- if @reverse_compare + 警告: 推送不包含新提交, 但是强制推送将删除下面的提交和修改. + \ + \ += @reverse_compare ? "已删除的提交:" : "提交:" +- @commits.each do |commit| + #{commit.short_id} by #{commit.author_name} at #{commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")} + #{commit.safe_message} + \- - - - - +\ +\ +#{pluralize @diffs.count, "changed file"}: +\ +- @diffs.each do |diff| + - if diff.deleted_file + \- − #{diff.old_path} + - elsif diff.renamed_file + \- #{diff.old_path} → #{diff.new_path} + - elsif diff.new_file + \- + #{diff.new_path} + - else + \- #{diff.new_path} +- unless @disable_diffs + \ + \ + 修改: + - @diffs.each do |diff| + \ + \===================================== + - if diff.deleted_file + #{diff.old_path} 被删除 + - elsif diff.renamed_file + #{diff.old_path} → #{diff.new_path} + - else + = diff.new_path + \===================================== + != diff.diff +- if @compare.timeout + \ + \ + 差别很大. 为了避免性能问题修改被隐藏 +\ +\ +在GitLab中查看: #{@target_url} diff --git a/app/views/profiles/accounts/show.zh.html.haml b/app/views/profiles/accounts/show.zh.html.haml new file mode 100644 index 00000000000..50d88ceb436 --- /dev/null +++ b/app/views/profiles/accounts/show.zh.html.haml @@ -0,0 +1,78 @@ +%h3.page-title + 帐号设置 +%p.light + 您可以在此修改您的用户名和私匙. + - if current_user.ldap_user? + 对于LDAP帐号某些选项不可用 +%hr + + +.account-page + %fieldset.update-token + %legend + 重置私匙 + %div + = form_for @user, url: reset_private_token_profile_path, method: :put do |f| + .data + %p + 您的私匙用于不经认证的情况下访问项目资源. + %br + 可用于RSS推送或API. + %span.cred + 请保密! + + %p.cgray + - if current_user.private_token + = text_field_tag "token", current_user.private_token, class: "form-control" + %div + = f.submit '重置私匙', data: { confirm: "Are you sure?" }, class: "btn btn-primary btn-build-token" + - else + %span 您还没有. 点击生成修复问题. + = f.submit '生成', class: "btn success btn-build-token" + + + - if show_profile_social_tab? + %fieldset + %legend 社交帐号 + .oauth_select_holder.append-bottom-10 + %p 点击图标使用以下服务激活登录 + - enabled_social_providers.each do |provider| + %span{class: oauth_active_class(provider) } + = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider) + + - if show_profile_username_tab? + %fieldset.update-username + %legend + 修改用户名 + = form_for @user, url: update_username_profile_path, method: :put, remote: true do |f| + %p + 修改用户名会改变所有您的私有项目的路径! + %div + = f.text_field :username, required: true, class: 'form-control' +   + .loading-gif.hide + %p + %i.fa.fa-spinner.fa-spin + 保存新用户名 + %p.light + = user_url(@user) + %div + = f.submit '保存用户名', class: "btn btn-warning" + + - if show_profile_remove_tab? + %fieldset.remove-account + %legend + 删除帐号 + %div + %p 删除帐号会有以下影响: + %ul + %li 所有的用户内容如问题、代码片段和评论会被删除 + - rp = current_user.personal_projects.count + - unless rp.zero? + %li #{pluralize rp, 'personal project'} 会被删除且不可恢复 + - if current_user.solo_owned_groups.present? + %li + 下面的组会被抛弃. 您应该移交或删除组. + %strong #{current_user.solo_owned_groups.map(&:name).join(', ')} + = link_to '删除帐号', user_registration_path, data: { confirm: "删除 #{current_user.name}? 您确定?" }, method: :delete, class: "btn btn-remove" + diff --git a/app/views/profiles/applications.zh.html.haml b/app/views/profiles/applications.zh.html.haml new file mode 100644 index 00000000000..4fabdda9393 --- /dev/null +++ b/app/views/profiles/applications.zh.html.haml @@ -0,0 +1,49 @@ +%h3.page-title + 应用设置 +%p.light + 下面为OAuth2协议设置. + +%fieldset.oauth-applications + %legend 您的应用 + %p= link_to '新建应用', new_oauth_application_path, class: 'btn btn-success' + - if @applications.any? + %table.table.table-striped + %thead + %tr + %th 名称 + %th 回调URL + %th 客户端 + %th + %th + %tbody + - @applications.each do |application| + %tr{:id => "application_#{application.id}"} + %td= link_to application.name, oauth_application_path(application) + %td + - application.redirect_uri.split.each do |uri| + %div= uri + %td= application.access_tokens.count + %td= link_to '编辑', edit_oauth_application_path(application), class: 'btn btn-link btn-sm' + %td= render 'doorkeeper/applications/delete_form', application: application + +%fieldset.oauth-authorized-applications.prepend-top-20 + %legend 已认证的应用 + + - if @authorized_tokens.any? + %table.table.table-striped + %thead + %tr + %th 名称 + %th 认证于 + %th 范围 + %th + %tbody + - @authorized_apps.each do |app| + - token = app.authorized_tokens.order('created_at desc').first + %tr{:id => "application_#{app.id}"} + %td= app.name + %td= token.created_at + %td= token.scopes + %td= render 'doorkeeper/authorized_applications/delete_form', application: app + - else + %p.light 您还没有已认证的应用 diff --git a/app/views/profiles/design.zh.html.haml b/app/views/profiles/design.zh.html.haml new file mode 100644 index 00000000000..9f3e65b3ec7 --- /dev/null +++ b/app/views/profiles/design.zh.html.haml @@ -0,0 +1,53 @@ +%h3.page-title + 设计设置 +%p.light + 外观设置会保存到你的用户资料中, 在所有设备中都可用. +%hr + += form_for @user, url: profile_path, remote: true, method: :put do |f| + %fieldset.application-theme + %legend + 应用主题 + .themes_opts + = label_tag do + .prev.default + = f.radio_button :theme_id, 1 + 默认 + + = label_tag do + .prev.classic + = f.radio_button :theme_id, 2 + 经典 + + = label_tag do + .prev.modern + = f.radio_button :theme_id, 3 + 现代 + + = label_tag do + .prev.gray + = f.radio_button :theme_id, 4 + 灰度 + + = label_tag do + .prev.violet + = f.radio_button :theme_id, 5 + 紫色 + + = label_tag do + .prev.blue + = f.radio_button :theme_id, 6 + 蓝色 + %br + .clearfix + + %fieldset.code-preview-theme + %legend + 代码预览主题 + .code_highlight_opts + - color_schemes.each do |color_scheme_id, color_scheme| + = label_tag do + .prev + = image_tag "#{color_scheme}-scheme-preview.png" + = f.radio_button :color_scheme_id, color_scheme_id + = color_scheme.gsub(/[-_]+/, ' ').humanize diff --git a/app/views/profiles/emails/index.zh.html.haml b/app/views/profiles/emails/index.zh.html.haml new file mode 100644 index 00000000000..e864c5aa430 --- /dev/null +++ b/app/views/profiles/emails/index.zh.html.haml @@ -0,0 +1,37 @@ +%h3.page-title + 邮箱设置 +%p.light + 您的 + %b 主邮箱 + 会用于头像检测及基于网页的操作如编辑和合并. + %br + 您的 + %b 通知邮箱 + 会用于帐号通知. + %br + 所有的邮箱地址会用于表明提交身份. + +%hr + +.panel.panel-default + .panel-heading + 邮箱 (#{@emails.count + 1}) + %ul.well-list#emails-table + %li + %strong= @primary + %span.label.label-success Primary Email + - @emails.each do |email| + %li + %strong= email.email + %span.cgray + 添加于 #{time_ago_with_tooltip(email.created_at)} + = link_to '删除', profile_email_path(email), data: { confirm: '您确定?'}, method: :delete, class: 'btn btn-sm btn-remove pull-right' + +%h4 Add email address += form_for 'email', url: profile_emails_path, html: { class: 'form-horizontal' } do |f| + .form-group + = f.label :email, class: 'control-label' + .col-sm-10 + = f.text_field :email, class: 'form-control' + .form-actions + = f.submit '添加邮箱', class: 'btn btn-create' diff --git a/app/views/profiles/history.zh.html.haml b/app/views/profiles/history.zh.html.haml new file mode 100644 index 00000000000..3c75c51574f --- /dev/null +++ b/app/views/profiles/history.zh.html.haml @@ -0,0 +1,10 @@ +%h3.page-title + 我的帐号历史 +%p.light + 所有您帐号的事件会显示在下面 +%hr +.profile_history + = render @events +%hr += paginate @events, theme: "gitlab" + diff --git a/app/views/profiles/keys/_form.zh.html.haml b/app/views/profiles/keys/_form.zh.html.haml new file mode 100644 index 00000000000..f17291e3ff1 --- /dev/null +++ b/app/views/profiles/keys/_form.zh.html.haml @@ -0,0 +1,21 @@ +%div + = form_for [:profile, @key], html: { class: 'form-horizontal' } do |f| + - if @key.errors.any? + .alert.alert-danger + %ul + - @key.errors.full_messages.each do |msg| + %li= msg + + .form-group + = f.label :title, class: 'control-label' + .col-sm-10= f.text_field :title, class: "form-control" + .form-group + = f.label :key, class: 'control-label' + .col-sm-10 + = f.text_area :key, class: "form-control", rows: 8 + + + .form-actions + = f.submit '添加key', class: "btn btn-create" + = link_to "取消", profile_keys_path, class: "btn btn-cancel" + diff --git a/app/views/profiles/keys/_key.zh.html.haml b/app/views/profiles/keys/_key.zh.html.haml new file mode 100644 index 00000000000..87fb208b293 --- /dev/null +++ b/app/views/profiles/keys/_key.zh.html.haml @@ -0,0 +1,12 @@ +%tr + %td + = link_to path_to_key(key, is_admin) do + %strong= key.title + %td + %span + (#{key.fingerprint}) + %td + %span.cgray + 添加于 #{time_ago_with_tooltip(key.created_at)} + %td + = link_to '删除', path_to_key(key, is_admin), data: { confirm: '您确定?'}, method: :delete, class: "btn btn-sm btn-remove delete-key pull-right" diff --git a/app/views/profiles/keys/_key_details.zh.html.haml b/app/views/profiles/keys/_key_details.zh.html.haml new file mode 100644 index 00000000000..3b484112873 --- /dev/null +++ b/app/views/profiles/keys/_key_details.zh.html.haml @@ -0,0 +1,22 @@ +- is_admin = defined?(admin) ? true : false +.row + .col-md-4 + .panel.panel-default + .panel-heading + SSH Key + %ul.well-list + %li + %span.light 标题: + %strong= @key.title + %li + %span.light 创建于: + %strong= @key.created_at.stamp("Aug 21, 2011") + + .col-md-8 + %p + %span.light 指纹: + %strong= @key.fingerprint + %pre.well-pre + = @key.key + .pull-right + = link_to '删除', path_to_key(@key, is_admin), data: {confirm: '您确定?'}, method: :delete, class: "btn btn-remove delete-key" diff --git a/app/views/profiles/keys/_key_table.zh.html.haml b/app/views/profiles/keys/_key_table.zh.html.haml new file mode 100644 index 00000000000..3ed9a9662c8 --- /dev/null +++ b/app/views/profiles/keys/_key_table.zh.html.haml @@ -0,0 +1,19 @@ +- is_admin = defined?(admin) ? true : false +.panel.panel-default + - if @keys.any? + %table.table + %thead.panel-heading + %tr + %th 标题 + %th 指纹 + %th 添加于 + %th + %tbody + - @keys.each do |key| + = render 'profiles/keys/key', key: key, is_admin: is_admin + - else + .nothing-here-block + - if is_admin + 用户还没有SSH Key + - else + 还没有可以用于访问您帐号的SSH Key. diff --git a/app/views/profiles/keys/index.zh.html.haml b/app/views/profiles/keys/index.zh.html.haml new file mode 100644 index 00000000000..1adebd43574 --- /dev/null +++ b/app/views/profiles/keys/index.zh.html.haml @@ -0,0 +1,12 @@ +%h3.page-title + SSH Key设置 + .pull-right + = link_to "添加SSH Key", new_profile_key_path, class: "btn btn-new" +%p.light + 我的SSH Key: #{@keys.count} + %br + 在添加SSH Key之前您需要 + = link_to "生成.", help_page_path("ssh", "README") +%hr + += render 'key_table' diff --git a/app/views/profiles/keys/new.zh.html.haml b/app/views/profiles/keys/new.zh.html.haml new file mode 100644 index 00000000000..1dce3250b18 --- /dev/null +++ b/app/views/profiles/keys/new.zh.html.haml @@ -0,0 +1,16 @@ +%h3.page-title 添加SSH Key +%p.light + 在此粘贴您的public key. 阅读 #{link_to "SSH帮助页", help_page_path("ssh", "README")} 了解更多关于如何生成key的信息. +%hr += render 'form' + +:javascript + $('#key_key').on('focusout', function(){ + var title = $('#key_title'), + val = $('#key_key').val(), + comment = val.match(/^\S+ \S+ (.+)$/); + + if( comment && comment.length > 1 && title.val() == '' ){ + $('#key_title').val( comment[1] ); + } + }); diff --git a/app/views/profiles/notifications/_settings.zh.html.haml b/app/views/profiles/notifications/_settings.zh.html.haml new file mode 100644 index 00000000000..2c85d2a9b2b --- /dev/null +++ b/app/views/profiles/notifications/_settings.zh.html.haml @@ -0,0 +1,17 @@ +%li + %span.notification.fa.fa-holder + - if notification.global? + = notification_icon(@notification) + - else + = notification_icon(notification) + + %span.str-truncated + - if membership.kind_of? GroupMember + = link_to membership.group.name, membership.group + - else + = link_to_project(membership.project) + .pull-right + = form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do + = hidden_field_tag :notification_type, type, id: dom_id(membership, 'notification_type') + = hidden_field_tag :notification_id, membership.id, id: dom_id(membership, 'notification_id') + = select_tag :notification_level, options_for_select(Notification.options_with_labels, notification.level), class: 'trigger-submit' diff --git a/app/views/profiles/notifications/show.zh.html.haml b/app/views/profiles/notifications/show.zh.html.haml new file mode 100644 index 00000000000..5f25aa7334e --- /dev/null +++ b/app/views/profiles/notifications/show.zh.html.haml @@ -0,0 +1,78 @@ +%h3.page-title + 通知设置 +%p.light + 这些是全局通知设置. +%hr + += form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications form-horizontal global-notifications-form' } do |f| + -if @user.errors.any? + %div.alert.alert-danger + %ul + - @user.errors.full_messages.each do |msg| + %li= msg + + = hidden_field_tag :notification_type, 'global' + + .form-group + = f.label :notification_email, class: "control-label" + .col-sm-10 + = f.select :notification_email, @user.all_emails, { include_blank: false }, class: "form-control" + + .form-group + = f.label :notification_level, class: 'control-label' + .col-sm-10 + .radio + = f.label :notification_level, value: Notification::N_DISABLED do + = f.radio_button :notification_level, Notification::N_DISABLED + .level-title + 已禁用 + %p 您不会收到任何邮件通知 + + .radio + = f.label :notification_level, value: Notification::N_MENTION do + = f.radio_button :notification_level, Notification::N_MENTION + .level-title + 提及(Mention) + %p 您只会收到评论中@了您的通知信息 + + .radio + = f.label :notification_level, value: Notification::N_PARTICIPATING do + = f.radio_button :notification_level, Notification::N_PARTICIPATING + .level-title + 参与 + %p 您只会收到相关资源的通知(如来自于您的提交或已指定的问题) + + .radio + = f.label :notification_level, value: Notification::N_WATCH do + = f.radio_button :notification_level, Notification::N_WATCH + .level-title + 观察 + %p 您会收到您参与项目的所有通知 + + .form-actions + = f.submit '保存修改', class: "btn btn-create" + +.clearfix + %hr +.row.all-notifications + .col-md-6 + %p + 您也可以基于组或项目设置特定的通知设置. + %br + 默认情况下, 所有的项目和组会使用以上的通知设置. + %h4 Groups: + %ul.bordered-list + - @group_members.each do |group_member| + - notification = Notification.new(group_member) + = render 'settings', type: 'group', membership: group_member, notification: notification + + .col-md-6 + %p + 为了设置您拥有组中项目的通知设置, + %br + 您需要是这个项目的成员而不仅是组的成员. + %h4 项目: + %ul.bordered-list + - @project_members.each do |project_member| + - notification = Notification.new(project_member) + = render 'settings', type: 'project', membership: project_member, notification: notification diff --git a/app/views/profiles/notifications/update.zh.js.haml b/app/views/profiles/notifications/update.zh.js.haml new file mode 100644 index 00000000000..08bd02192de --- /dev/null +++ b/app/views/profiles/notifications/update.zh.js.haml @@ -0,0 +1,6 @@ +- if @saved + :plain + new Flash("成功保存通知设置", "notice") +- else + :plain + new Flash("保存通知设置失败", "alert") diff --git a/app/views/profiles/passwords/edit.zh.html.haml b/app/views/profiles/passwords/edit.zh.html.haml new file mode 100644 index 00000000000..113f1933828 --- /dev/null +++ b/app/views/profiles/passwords/edit.zh.html.haml @@ -0,0 +1,38 @@ +%h3.page-title 密码设置 +%p.light + - if @user.password_automatically_set? + 设置您的密码. + - else + 设置您的密码或找回当前密码. +%hr +.update-password + = form_for @user, url: profile_password_path, method: :put, html: { class: 'form-horizontal' } do |f| + %div + %p.slead + - unless @user.password_automatically_set? + 您要修改密码必须提供当前密码. + %br + 成功更新密码后, 您会重定向到登录页面请使用新密码登录. + -if @user.errors.any? + .alert.alert-danger + %ul + - @user.errors.full_messages.each do |msg| + %li= msg + - unless @user.password_automatically_set? + .form-group + = f.label :current_password, class: 'control-label' + .col-sm-10 + = f.password_field :current_password, required: true, class: 'form-control' + %div + = link_to "忘记密码?", reset_profile_password_path, method: :put + + .form-group + = f.label :password, 'New password', class: 'control-label' + .col-sm-10 + = f.password_field :password, required: true, class: 'form-control' + .form-group + = f.label :password_confirmation, class: 'control-label' + .col-sm-10 + = f.password_field :password_confirmation, required: true, class: 'form-control' + .form-actions + = f.submit '保存密码', class: "btn btn-create" diff --git a/app/views/profiles/passwords/new.zh.html.haml b/app/views/profiles/passwords/new.zh.html.haml new file mode 100644 index 00000000000..b3ea2efbcff --- /dev/null +++ b/app/views/profiles/passwords/new.zh.html.haml @@ -0,0 +1,26 @@ +%h3.page-title 设置新密码 +%hr += form_for @user, url: profile_password_path, method: :post, html: { class: 'form-horizontal '} do |f| + %p.slead + 在继续之前请设置新密码. + %br + 成功更新密码之后您会被重定向到登录页. + -if @user.errors.any? + .alert.alert-danger + %ul + - @user.errors.full_messages.each do |msg| + %li= msg + + - unless @user.password_automatically_set? + .form-group + = f.label :current_password, class: 'control-label' + .col-sm-10= f.password_field :current_password, required: true, class: 'form-control' + .form-group + = f.label :password, class: 'control-label' + .col-sm-10= f.password_field :password, required: true, class: 'form-control' + .form-group + = f.label :password_confirmation, class: 'control-label' + .col-sm-10 + = f.password_field :password_confirmation, required: true, class: 'form-control' + .form-actions + = f.submit '设置新密码', class: "btn btn-create" diff --git a/app/views/profiles/show.zh.html.haml b/app/views/profiles/show.zh.html.haml new file mode 100644 index 00000000000..7c3eba87547 --- /dev/null +++ b/app/views/profiles/show.zh.html.haml @@ -0,0 +1,103 @@ +%h3.page-title + 用户资料设置 +%p.light + 该信息会显示在你的用户资料中. + - if current_user.ldap_user? + LDAP帐号某些选项不可用 +%hr + + + += form_for @user, url: profile_path, method: :put, html: { multipart: true, class: "edit_user form-horizontal" }, authenticity_token: true do |f| + -if @user.errors.any? + %div.alert.alert-danger + %ul + - @user.errors.full_messages.each do |msg| + %li= msg + .row + .col-md-7 + .form-group + = f.label :name, class: "control-label" + .col-sm-10 + = f.text_field :name, class: "form-control", required: true + %span.help-block 输入您的名称, 让其它人能认出您. + + .form-group + = f.label :email, class: "control-label" + .col-sm-10 + - if @user.ldap_user? + = f.text_field :email, class: "form-control", required: true, readonly: true + %span.help-block.light + LDAP用记邮箱为只读不可改 + - else + - if @user.temp_oauth_email? + = f.text_field :email, class: "form-control", required: true, value: nil + - else + = f.text_field :email, class: "form-control", required: true + - if @user.unconfirmed_email.present? + %span.help-block + 确认邮件已经发往 + %strong #{@user.unconfirmed_email} + 请点击确认邮件中的链接继续. + + - else + %span.help-block 如果没有上传头像我们也使用邮箱检测头像. + .form-group + = f.label :skype, class: "control-label" + .col-sm-10= f.text_field :skype, class: "form-control" + .form-group + = f.label :linkedin, class: "control-label" + .col-sm-10= f.text_field :linkedin, class: "form-control" + .form-group + = f.label :twitter, class: "control-label" + .col-sm-10= f.text_field :twitter, class: "form-control" + .form-group + = f.label :website_url, 'Website', class: "control-label" + .col-sm-10= f.text_field :website_url, class: "form-control" + .form-group + = f.label :bio, class: "control-label" + .col-sm-10 + = f.text_area :bio, rows: 4, class: "form-control", maxlength: 250 + %span.help-block 以少于250个字符的字介绍自己. + + .col-md-5 + .light-well + = image_tag avatar_icon(@user.email, 160), alt: '', class: 'avatar s160' + + .clearfix + .profile-avatar-form-option + %p.light + - if @user.avatar? + 您可以在此修改您的头像 + - if Gitlab.config.gravatar.enabled + %br + 或删除现有头像还原使用 #{link_to "gravatar.com", "http://gravatar.com"} + - else + 您可以在此上传头像 + - if Gitlab.config.gravatar.enabled + %br + 或在 #{link_to "gravatar.com", "http://gravatar.com"} 修改头像 + %hr + %a.choose-btn.btn.btn-sm.js-choose-user-avatar-button + %i.fa.fa-paperclip + %span 选择文件 ... +   + %span.file_name.js-avatar-filename 文件名... + = f.file_field :avatar, class: "js-user-avatar-input hidden" + .light 允许的最大文件大小为200KB. + - if @user.avatar? + %hr + = link_to 'Remove avatar', profile_avatar_path, data: { confirm: "头像即将被删除. 您确定?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" + + - if @user.public_profile? + .alert.alert-info + %h4 公开的个人资料 + %p 因为您参与了公开项目您的个人资料对公众可见. + + + .row + .col-md-7 + .form-group + .col-sm-2   + .col-sm-10 + = f.submit '保存修改', class: "btn btn-success" diff --git a/app/views/projects/_bitbucket_import_modal.zh.html.haml b/app/views/projects/_bitbucket_import_modal.zh.html.haml new file mode 100644 index 00000000000..aebe071266f --- /dev/null +++ b/app/views/projects/_bitbucket_import_modal.zh.html.haml @@ -0,0 +1,13 @@ +%div#bitbucket_import_modal.modal.hide + .modal-dialog + .modal-content + .modal-header + %a.close{href: "#", "data-dismiss" => "modal"} × + %h3 从Bitbucket导入项目 + .modal-body + 启用从Bitbucket导入项目, + - if current_user.admin? + 您需求 + - else + 您的GitLab管理员需要 + == #{link_to '设置OAuth集成', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/bitbucket.md'}. diff --git a/app/views/projects/_commit_button.zh.html.haml b/app/views/projects/_commit_button.zh.html.haml new file mode 100644 index 00000000000..f158cd3bd7f --- /dev/null +++ b/app/views/projects/_commit_button.zh.html.haml @@ -0,0 +1,6 @@ +.form-actions + .commit-button-annotation + = button_tag '提交修改', + class: 'btn commit-btn js-commit-button btn-create' + = link_to '取消', cancel_path, + class: 'btn btn-cancel', data: {confirm: leave_edit_message} diff --git a/app/views/projects/_dropdown.zh.html.haml b/app/views/projects/_dropdown.zh.html.haml new file mode 100644 index 00000000000..0b3ba2b0955 --- /dev/null +++ b/app/views/projects/_dropdown.zh.html.haml @@ -0,0 +1,33 @@ +- if current_user + .dropdown.pull-right + %a.dropdown-toggle.btn.btn-new{href: '#', "data-toggle" => "dropdown"} + %i.fa.fa-bars + %ul.dropdown-menu + - if @project.issues_enabled && can?(current_user, :write_issue, @project) + %li + = link_to url_for_new_issue, title: "创建问题" do + 创建问题 + - if @project.merge_requests_enabled && can?(current_user, :write_merge_request, @project) + %li + = link_to new_namespace_project_merge_request_path(@project.namespace, @project), title: "新建合并请求" do + 新建合并请求 + - if @project.snippets_enabled && can?(current_user, :write_snippet, @project) + %li + = link_to new_namespace_project_snippet_path(@project.namespace, @project), title: "新建代码片段" do + 新建代码片段 + - if can?(current_user, :admin_project_member, @project) + %li + = link_to namespace_project_project_members_path(@project.namespace, @project), title: "新加项目成员" do + 新加项目成员 + - if can? current_user, :push_code, @project + %li.divider + %li + = link_to new_namespace_project_branch_path(@project.namespace, @project) do + %i.fa.fa-code-fork + Git分支 + %li + = link_to new_namespace_project_tag_path(@project.namespace, @project) do + %i.fa.fa-tag + Git标签 + + diff --git a/app/views/projects/_github_import_modal.zh.html.haml b/app/views/projects/_github_import_modal.zh.html.haml new file mode 100644 index 00000000000..6317c08e4c4 --- /dev/null +++ b/app/views/projects/_github_import_modal.zh.html.haml @@ -0,0 +1,13 @@ +%div#github_import_modal.modal.hide + .modal-dialog + .modal-content + .modal-header + %a.close{href: "#", "data-dismiss" => "modal"} × + %h3 从GitHub导入项目 + .modal-body + 要启用从GitHub导入项目的功能, + - if current_user.admin? + 您需要 + - else + 您的GitLab管理员需要 + == #{link_to '设置OAuth集成', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/github.md'}. \ No newline at end of file diff --git a/app/views/projects/_gitlab_import_modal.zh.html.haml b/app/views/projects/_gitlab_import_modal.zh.html.haml new file mode 100644 index 00000000000..27dd5e5cddd --- /dev/null +++ b/app/views/projects/_gitlab_import_modal.zh.html.haml @@ -0,0 +1,13 @@ +%div#gitlab_import_modal.modal.hide + .modal-dialog + .modal-content + .modal-header + %a.close{href: "#", "data-dismiss" => "modal"} × + %h3 从GitLab.com导入项目 + .modal-body + 要启用从GitLab.com导入项目的功能, + - if current_user.admin? + 您需要 + - else + 您的GitLab管理员需要 + == #{link_to '设置OAuth集成', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/gitlab.md'}. \ No newline at end of file diff --git a/app/views/projects/_home_panel.zh.html.haml b/app/views/projects/_home_panel.zh.html.haml new file mode 100644 index 00000000000..abae2eee4b3 --- /dev/null +++ b/app/views/projects/_home_panel.zh.html.haml @@ -0,0 +1,44 @@ +- empty_repo = @project.empty_repo? +.project-home-panel{:class => ("empty-project" if empty_repo)} + .project-identicon-holder + = project_icon(@project, alt: '', class: 'avatar project-avatar') + .project-home-row + .project-home-desc + - if @project.description.present? + = escaped_autolink(@project.description) + - if can?(current_user, :admin_project, @project) + – + = link_to '编辑', edit_namespace_project_path + - elsif !@project.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 + .star-fork-buttons + - unless @project.empty_repo? + .fork-buttons + - if current_user && can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace + - 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: '前往我fork的项目' do + = link_to_toggle_fork + - else + = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork项目" do + = link_to_toggle_fork + + .star-buttons + %span.star.js-toggler-container{class: @show_star ? 'on' : ''} + - if current_user + = link_to_toggle_star('收藏此项目.', false, true) + = link_to_toggle_star('取消收藏此项目.', true, true) + - else + = link_to_toggle_star('您必须登录后才能收藏项目.', false, false) + + .project-home-row.hidden-xs + - if current_user && !empty_repo + .project-home-dropdown + = render "dropdown" + - unless @project.empty_repo? + - if can? current_user, :download_code, @project + .pull-right.prepend-left-10 + = render 'projects/repositories/download_archive', split_button: true + = render "shared/clone_panel" diff --git a/app/views/projects/_issuable_form.zh.html.haml b/app/views/projects/_issuable_form.zh.html.haml new file mode 100644 index 00000000000..12a38ac59fa --- /dev/null +++ b/app/views/projects/_issuable_form.zh.html.haml @@ -0,0 +1,86 @@ +- if issuable.errors.any? + .row + .col-sm-10.col-sm-offset-2 + .alert.alert-danger + - issuable.errors.full_messages.each do |msg| + %span= msg + %br +.form-group + = f.label :title, class: 'control-label' do + %strong= 'Title *' + .col-sm-10 + = f.text_field :title, maxlength: 255, autofocus: true, + class: 'form-control pad js-gfm-input', required: true +.form-group.issuable-description + = f.label :description, '描述', class: 'control-label' + .col-sm-10 + + = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do + = render 'projects/zen', f: f, attr: :description, + classes: 'description form-control' + .col-sm-12.hint + .pull-left + Parsed with + #{link_to 'GitLab Flavored Markdown', help_page_path('markdown', 'markdown'), target: '_blank'}. + .pull-right + 拖放文件或 + #{link_to '选择文件', '#', class: 'markdown-selector' } 添加附件. + + .clearfix + .error-alert +%hr +.form-group + .issue-assignee + = f.label :assignee_id, class: 'control-label' do + %i.fa.fa-user + 指定给 + .col-sm-10 + = project_users_select_tag("#{issuable.class.model_name.param_key}[assignee_id]", + placeholder: '选择一个用户', class: 'custom-form-control', + selected: issuable.assignee_id) +   + = link_to '指定给我', '#', class: 'btn assign-to-me-link' +.form-group + .issue-milestone + = f.label :milestone_id, class: 'control-label' do + %i.fa.fa-clock-o + 里程碑 + .col-sm-10 + - if milestone_options(issuable).present? + = f.select(:milestone_id, milestone_options(issuable), + { include_blank: '选择里程碑' }, { class: 'select2' }) + - else + .prepend-top-10 + %span.light 没有打开状态的里程碑可用. +   + - if can? current_user, :admin_milestone, issuable.project + = link_to '创建里程碑', new_namespace_project_milestone_path(issuable.project.namespace, issuable.project), target: :blank +.form-group + = f.label :label_ids, class: 'control-label' do + %i.fa.fa-tag + 标签 + .col-sm-10 + - if issuable.project.labels.any? + = f.collection_select :label_ids, issuable.project.labels.all, :id, :name, + { selected: issuable.label_ids }, multiple: true, class: 'select2' + - else + .prepend-top-10 + %span.light 还没有标签. +   + - if can? current_user, :admin_label, issuable.project + = link_to '创建新标签', new_namespace_project_label_path(issuable.project.namespace, issuable.project), target: :blank + +.form-actions + - if !issuable.project.empty_repo? && (guide_url = contribution_guide_url(issuable.project)) && !issuable.persisted? + %p + 请详细阅读该项目的 + %strong #{link_to '贡献指南', guide_url} . + - if issuable.new_record? + = f.submit "提交新的 #{issuable.class.model_name.human.downcase}", class: 'btn btn-create' + - else + = f.submit '保存修改', class: 'btn btn-save' + - if issuable.new_record? + - cancel_project = issuable.source_project + - else + - cancel_project = issuable.project + = link_to '取消', [cancel_project.namespace.becomes(Namespace), cancel_project, issuable], class: 'btn btn-cancel' diff --git a/app/views/projects/_md_preview.zh.html.haml b/app/views/projects/_md_preview.zh.html.haml new file mode 100644 index 00000000000..69064356d83 --- /dev/null +++ b/app/views/projects/_md_preview.zh.html.haml @@ -0,0 +1,13 @@ +%ul.nav.nav-tabs + %li.active + = link_to '#md-write-holder', class: 'js-md-write-button' do + 撰写 + %li + = link_to '#md-preview-holder', class: 'js-md-preview-button', + data: { url: markdown_preview_namespace_project_path(@project.namespace, @project) } do + 预览 +%div + .md-write-holder + = yield + .md-preview-holder.hide + .js-md-preview{class: (preview_class if defined?(preview_class))} diff --git a/app/views/projects/_settings_nav.zh.html.haml b/app/views/projects/_settings_nav.zh.html.haml new file mode 100644 index 00000000000..dbea35d3167 --- /dev/null +++ b/app/views/projects/_settings_nav.zh.html.haml @@ -0,0 +1,31 @@ +%ul.project-settings-nav.sidebar-subnav + = nav_link(path: 'projects#edit') do + = link_to edit_project_path(@project), title: '项目', class: "stat-tab tab " do + %i.fa.fa-pencil-square-o + %span + 项目 + = nav_link(controller: [:project_members, :teams]) do + = link_to namespace_project_project_members_path(@project.namespace, @project), title: '成员', class: "team-tab tab" do + %i.fa.fa-users + %span + 成员 + = nav_link(controller: :deploy_keys) do + = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: '布署Key' do + %i.fa.fa-key + %span + 布署Keys + = nav_link(controller: :hooks) do + = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Web钩子' do + %i.fa.fa-link + %span + Web钩子 + = nav_link(controller: :services) do + = link_to namespace_project_services_path(@project.namespace, @project), title: '服务' do + %i.fa.fa-cogs + %span + 服务 + = nav_link(controller: :protected_branches) do + = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: '受保护的分支' do + %i.fa.fa-lock + %span + 受保护的分支 diff --git a/app/views/projects/_visibility_level.zh.html.haml b/app/views/projects/_visibility_level.zh.html.haml new file mode 100644 index 00000000000..5887ce8b691 --- /dev/null +++ b/app/views/projects/_visibility_level.zh.html.haml @@ -0,0 +1,27 @@ +.form-group.project-visibility-level-holder + = f.label :visibility_level, class: 'control-label' do + 访问等级设置 + = link_to "(?)", help_page_path("public_access", "public_access") + .col-sm-10 + - if can_change_visibility_level + - Gitlab::VisibilityLevel.values.each do |level| + .radio + - restricted = restricted_visibility_levels.include?(level) + = label :project_visibility_level, level do + = f.radio_button :visibility_level, level, checked: (visibility_level == level), disabled: restricted + = visibility_level_icon(level) + .option-title + = visibility_level_label(level) + .option-descr + = visibility_level_description(level) + - unless restricted_visibility_levels.empty? + .col-sm-10 + %span.info + 某些访问等级设置仅限于管理员. + - else + .col-sm-10 + %span.info + = visibility_level_icon(visibility_level) + %strong + = visibility_level_label(visibility_level) + .light= visibility_level_description(visibility_level) diff --git a/app/views/projects/_zen.zh.html.haml b/app/views/projects/_zen.zh.html.haml new file mode 100644 index 00000000000..b8245832881 --- /dev/null +++ b/app/views/projects/_zen.zh.html.haml @@ -0,0 +1,10 @@ +.zennable + %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: 'Leave a comment' + = link_to nil, class: 'zen-enter-link', tabindex: '-1' do + %i.fa.fa-expand + 全屏模式编辑 + = link_to nil, class: 'zen-leave-link' do + %i.fa.fa-compress diff --git a/app/views/projects/blame/show.zh.html.haml b/app/views/projects/blame/show.zh.html.haml new file mode 100644 index 00000000000..5a7888c9f40 --- /dev/null +++ b/app/views/projects/blame/show.zh.html.haml @@ -0,0 +1,35 @@ +%h3.page-title Blame视图 + +#tree-holder.tree-holder + .file-holder + .file-title + %i.fa.fa-file + %strong + = @path + %small= number_to_human_size @blob.size + .file-actions + = render "projects/blob/actions" + .file-content.blame.highlight + %table + - @blame.each do |commit, lines, since| + - commit = Commit.new(commit) + %tr + %td.blame-commit + %span.commit + = link_to commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit), class: "commit_short_id" +   + = commit_author_link(commit, avatar: true, size: 16) +   + = link_to_gfm truncate(commit.title, length: 20), namespace_project_commit_path(@project.namespace, @project, commit.id), class: "row_title" + %td.lines.blame-numbers + %pre + - (since...(since + lines.count)).each do |i| + = i + \ + %td.lines + %pre{class: 'code highlight white'} + %code + :erb + <% lines.each do |line| %> + <%= highlight(@blob.name, line, true).html_safe %> + <% end %> diff --git a/app/views/projects/blob/_actions.zh.html.haml b/app/views/projects/blob/_actions.zh.html.haml new file mode 100644 index 00000000000..db76bc94a2e --- /dev/null +++ b/app/views/projects/blob/_actions.zh.html.haml @@ -0,0 +1,22 @@ +.btn-group.tree-btn-group + = edit_blob_link(@project, @ref, @path) + = link_to 'Raw', namespace_project_raw_path(@project.namespace, @project, @id), + class: 'btn btn-sm', target: '_blank' + -# only show normal/blame view links for text files + - if @blob.text? + - if current_page? namespace_project_blame_path(@project.namespace, @project, @id) + = link_to '常规视图', namespace_project_blob_path(@project.namespace, @project, @id), + class: 'btn btn-sm' + - else + = link_to 'Blame', namespace_project_blame_path(@project.namespace, @project, @id), + class: 'btn btn-sm' unless @blob.empty? + = link_to '历史', namespace_project_commits_path(@project.namespace, @project, @id), + class: 'btn btn-sm' + - if @ref != @commit.sha + = link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project, + tree_join(@commit.sha, @path)), class: 'btn btn-sm' + +- if allowed_tree_edit? + = button_tag class: 'remove-blob btn btn-sm btn-remove', + 'data-toggle' => 'modal', 'data-target' => '#modal-remove-blob' do + 删除 diff --git a/app/views/projects/blob/_download.zh.html.haml b/app/views/projects/blob/_download.zh.html.haml new file mode 100644 index 00000000000..3e9e8cc6403 --- /dev/null +++ b/app/views/projects/blob/_download.zh.html.haml @@ -0,0 +1,7 @@ +.file-content.blob_file.blob-no-preview + .center + = link_to namespace_project_raw_path(@project.namespace, @project, @id) do + %h1.light + %i.fa.fa-download + %h4 + 下载 (#{number_to_human_size blob.size}) diff --git a/app/views/projects/blob/_remove.zh.html.haml b/app/views/projects/blob/_remove.zh.html.haml new file mode 100644 index 00000000000..cf9ab9a19ed --- /dev/null +++ b/app/views/projects/blob/_remove.zh.html.haml @@ -0,0 +1,22 @@ +#modal-remove-blob.modal.hide + .modal-dialog + .modal-content + .modal-header + %a.close{href: "#", "data-dismiss" => "modal"} × + %h3.page-title 删除 #{@blob.name} + %p.light + 来自于分支 + %strong= @ref + + .modal-body + = form_tag namespace_project_blob_path(@project.namespace, @project, @id), method: :delete, class: 'form-horizontal' do + = render 'shared/commit_message_container', params: params, + placeholder: 'Removed this file because...' + .form-group + .col-sm-2 + .col-sm-10 + = button_tag '删除文件', class: 'btn btn-remove btn-remove-file' + = link_to "取消", '#', class: "btn btn-cancel", "data-dismiss" => "modal" + +:javascript + disableButtonIfEmptyField('#commit_message', '.btn-remove-file') diff --git a/app/views/projects/blob/_text.zh.html.haml b/app/views/projects/blob/_text.zh.html.haml new file mode 100644 index 00000000000..b755369ea21 --- /dev/null +++ b/app/views/projects/blob/_text.zh.html.haml @@ -0,0 +1,13 @@ +- if gitlab_markdown?(blob.name) + .file-content.wiki + = preserve do + = markdown(blob.data) +- elsif markup?(blob.name) + .file-content.wiki + = render_markup(blob.name, blob.data) +- else + .file-content.code + - unless blob.empty? + = render 'shared/file_highlight', blob: blob + - else + .nothing-here-block 空文件 diff --git a/app/views/projects/blob/preview.zh.html.haml b/app/views/projects/blob/preview.zh.html.haml new file mode 100644 index 00000000000..b74ca72681a --- /dev/null +++ b/app/views/projects/blob/preview.zh.html.haml @@ -0,0 +1,25 @@ +.diff-file + .diff-content + - if gitlab_markdown?(@blob.name) + .file-content.wiki + = preserve do + = markdown(@content) + - elsif markup?(@blob.name) + .file-content.wiki + = raw render_markup(@blob.name, @content) + - else + .file-content.code + - unless @diff_lines.empty? + %table.text-file + - @diff_lines.each do |line| + %tr.line_holder{ class: "#{line.type}" } + - if line.type == "match" + %td.old_line= "..." + %td.new_line= "..." + %td.line_content.matched= line.text + - else + %td.old_line + %td.new_line + %td.line_content{class: "#{line.type}"}= raw diff_line_content(line.text) + - else + .nothing-here-block 无修改. diff --git a/app/views/projects/branches/_branch.zh.html.haml b/app/views/projects/branches/_branch.zh.html.haml new file mode 100644 index 00000000000..6f6a853bc83 --- /dev/null +++ b/app/views/projects/branches/_branch.zh.html.haml @@ -0,0 +1,29 @@ +- commit = @repository.commit(branch.target) +%li(class="js-branch-#{branch.name}") + %h4 + = link_to namespace_project_tree_path(@project.namespace, @project, branch.name) do + %strong.str-truncated= branch.name + - if branch.name == @repository.root_ref + %span.label.label-info 默认 + - if @project.protected_branch? branch.name + %span.label.label-success + %i.fa.fa-lock + 受保护的 + .pull-right + - if can?(current_user, :download_code, @project) + = render 'projects/repositories/download_archive', ref: branch.name, btn_class: 'btn-grouped btn-group-sm' + - if branch.name != @repository.root_ref + = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: 'btn btn-grouped btn-sm', method: :post, title: "对比" do + %i.fa.fa-files-o + 对比 + + - if can_remove_branch?(@project, branch.name) + = link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-grouped btn-sm btn-remove remove-row', method: :delete, data: { confirm: '删除分支将不可恢复. 您确定?'}, remote: true do + %i.fa.fa-trash-o + + - if commit + %ul.list-unstyled + = render 'projects/commits/inline_commit', commit: commit, project: @project + - else + %p + 不能找到该分支的HEAD提交 diff --git a/app/views/projects/branches/index.zh.html.haml b/app/views/projects/branches/index.zh.html.haml new file mode 100644 index 00000000000..2e0000b4165 --- /dev/null +++ b/app/views/projects/branches/index.zh.html.haml @@ -0,0 +1,31 @@ += render "projects/commits/head" +%h3.page-title + Branches + .pull-right + - if can? current_user, :push_code, @project + = link_to new_namespace_project_branch_path(@project.namespace, @project), class: 'btn btn-create' do + %i.fa.fa-add-sign + 新建分支 +   + .dropdown.inline + %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} + %span.light sort: + - if @sort.present? + = @sort.humanize + - else + 名称 + %b.caret + %ul.dropdown-menu + %li + = link_to namespace_project_branches_path(sort: nil) do + 名称 + = link_to namespace_project_branches_path(sort: 'recently_updated') do + = sort_title_recently_updated + = link_to namespace_project_branches_path(sort: 'last_updated') do + = sort_title_oldest_updated +%hr +- unless @branches.empty? + %ul.bordered-list.top-list.all-branches + - @branches.each do |branch| + = render "projects/branches/branch", branch: branch + = paginate @branches, theme: 'gitlab' diff --git a/app/views/projects/branches/new.zh.html.haml b/app/views/projects/branches/new.zh.html.haml new file mode 100644 index 00000000000..94d10a945f5 --- /dev/null +++ b/app/views/projects/branches/new.zh.html.haml @@ -0,0 +1,28 @@ +- if @error + .alert.alert-danger + %button{ type: "button", class: "close", "data-dismiss" => "alert"} × + = @error +%h3.page-title + %i.fa.fa-code-fork + 新建分支 += form_tag namespace_project_branches_path, method: :post, id: "new-branch-form", class: "form-horizontal" do + .form-group + = label_tag :branch_name, '新分支名称', class: 'control-label' + .col-sm-10 + = text_field_tag :branch_name, params[:branch_name], placeholder: '输入新分支名称', required: true, tabindex: 1, class: 'form-control' + .form-group + = label_tag :ref, '创建来自于', class: 'control-label' + .col-sm-10 + = text_field_tag :ref, params[:ref], placeholder: '已有分支名,标签或提交SHA1值', required: true, tabindex: 2, class: 'form-control' + .form-actions + = button_tag '创建分支', class: 'btn btn-create', tabindex: 3 + = link_to '取消', namespace_project_branches_path(@project.namespace, @project), class: 'btn btn-cancel' + +:javascript + disableButtonIfAnyEmptyField($("#new-branch-form"), ".form-control", ".btn-create"); + var availableTags = #{@project.repository.ref_names.to_json}; + + $("#ref").autocomplete({ + source: availableTags, + minLength: 1 + }); diff --git a/app/views/projects/commit/_commit_box.zh.html.haml b/app/views/projects/commit/_commit_box.zh.html.haml new file mode 100644 index 00000000000..52512a58679 --- /dev/null +++ b/app/views/projects/commit/_commit_box.zh.html.haml @@ -0,0 +1,52 @@ +.pull-right + %div + - if @notes_count > 0 + %span.btn.disabled.btn-grouped + %i.fa.fa-comment + = @notes_count + .pull-left.btn-group + %a.btn.btn-grouped.dropdown-toggle{ data: {toggle: :dropdown} } + %i.fa.fa-download + 下载另存为 + %span.caret + %ul.dropdown-menu + %li= link_to "Email补丁", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch) + %li= link_to "普通diff文件", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff) + = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-primary btn-grouped" do + %span Browse Code » + %div + +%p + %span.light 提交 + = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit) +.commit-info-row + %span.light 作者为 + %strong + = commit_author_link(@commit, avatar: true, size: 24) + #{time_ago_with_tooltip(@commit.authored_date)} + +- if @commit.different_committer? + .commit-info-row + %span.light 提交者为 + %strong + = commit_committer_link(@commit, avatar: true, size: 24) + #{time_ago_with_tooltip(@commit.committed_date)} + +.commit-info-row + %span.cgray= pluralize(@commit.parents.count, "parent") + - @commit.parents.each do |parent| + = link_to parent.short_id, namespace_project_commit_path(@project.namespace, @project, parent) + +.commit-info-row.branches + %i.fa.fa-spinner.fa-spin + +.commit-box + %h3.commit-title + = gfm escape_once(@commit.title) + - if @commit.description.present? + %pre.commit-description + = preserve(gfm(escape_once(@commit.description))) + +:coffeescript + $ -> + $(".commit-info-row.branches").load("#{branches_namespace_project_commit_path(@project.namespace, @project, @commit.id)}") diff --git a/app/views/projects/commits/_commit_list.zh.html.haml b/app/views/projects/commits/_commit_list.zh.html.haml new file mode 100644 index 00000000000..230d6df0b56 --- /dev/null +++ b/app/views/projects/commits/_commit_list.zh.html.haml @@ -0,0 +1,11 @@ +%div.panel.panel-default + .panel-heading + 提交 (#{@commits.count}) + - if @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE + %ul.well-list + - Commit.decorate(@commits.first(MergeRequestDiff::COMMITS_SAFE_SIZE)).each do |commit| + = render "projects/commits/inline_commit", commit: commit, project: @project + %li.warning-row.unstyled + other #{@commits.size - MergeRequestDiff::COMMITS_SAFE_SIZE} commits hidden to prevent performance issues. + - else + %ul.well-list= render Commit.decorate(@commits), project: @project diff --git a/app/views/projects/commits/_head.zh.html.haml b/app/views/projects/commits/_head.zh.html.haml new file mode 100644 index 00000000000..67d114f1758 --- /dev/null +++ b/app/views/projects/commits/_head.zh.html.haml @@ -0,0 +1,15 @@ +%ul.nav.nav-tabs + = nav_link(controller: [:commit, :commits]) do + = link_to '提交', namespace_project_commits_path(@project.namespace, @project, @repository.root_ref) + = nav_link(controller: :compare) do + = link_to '对比', namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: @ref || @repository.root_ref) + + = nav_link(html_options: {class: branches_tab_class}) do + = link_to namespace_project_branches_path(@project.namespace, @project) do + 分支 + %span.badge.js-totalbranch-count= @repository.branches.size + + = nav_link(controller: :tags) do + = link_to namespace_project_tags_path(@project.namespace, @project) do + 标签 + %span.badge.js-totaltags-count= @repository.tags.length diff --git a/app/views/projects/commits/show.zh.html.haml b/app/views/projects/commits/show.zh.html.haml new file mode 100644 index 00000000000..48dcc023353 --- /dev/null +++ b/app/views/projects/commits/show.zh.html.haml @@ -0,0 +1,23 @@ += render "head" + +.tree-ref-holder + = render 'shared/ref_switcher', destination: 'commits' + +- if current_user && current_user.private_token + .commits-feed-holder.hidden-xs.hidden-sm + = link_to namespace_project_commits_path(@project.namespace, @project, @ref, {format: :atom, private_token: current_user.private_token}), title: "RSS推送", class: 'btn' do + %i.fa.fa-rss + 提交RSS推送 + +%ul.breadcrumb.repo-breadcrumb + = commits_breadcrumbs + +%div{id: dom_id(@project)} + #commits-list= render "commits", project: @project +.clear += spinner + +- if @commits.count == @limit + :javascript + CommitsList.init("#{@ref}", #{@limit}); + diff --git a/app/views/projects/compare/_form.zh.html.haml b/app/views/projects/compare/_form.zh.html.haml new file mode 100644 index 00000000000..e087028cbcc --- /dev/null +++ b/app/views/projects/compare/_form.zh.html.haml @@ -0,0 +1,29 @@ += form_tag namespace_project_compare_index_path(@project.namespace, @project), method: :post, class: 'form-inline' do + .clearfix.append-bottom-20 + - if params[:to] && params[:from] + = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'} + .form-group + .input-group.inline-input-group + %span.input-group-addon from + = text_field_tag :from, params[:from], class: "form-control" + = "..." + .form-group + .input-group.inline-input-group + %span.input-group-addon to + = text_field_tag :to, params[:to], class: "form-control" +   + = button_tag "对比", class: "btn btn-create commits-compare-btn" + - if compare_to_mr_button? + = link_to compare_mr_path, class: 'prepend-left-10 btn' do + %strong 发起合并请求 + + +:javascript + var availableTags = #{@project.repository.ref_names.to_json}; + + $("#from, #to").autocomplete({ + source: availableTags, + minLength: 1 + }); + + disableButtonIfEmptyField('#to', '.commits-compare-btn'); diff --git a/app/views/projects/compare/index.zh.html.haml b/app/views/projects/compare/index.zh.html.haml new file mode 100644 index 00000000000..fdeb9e83e80 --- /dev/null +++ b/app/views/projects/compare/index.zh.html.haml @@ -0,0 +1,17 @@ += render "projects/commits/head" + +%h3.page-title + 对比视图 +%p.slead + 对比分支, 标签或提交范围 + %br + 在输入框中填写提交id如 + %code.label-branch 4eedf23 + 或分支/标签名称如 + %code.label-branch master + 然后点击对比按钮后即可查看提交列表和代码对比效果 + %br + 源版本修改显示在第一列, 目标版本修改显示在第二列. + + += render "form" diff --git a/app/views/projects/compare/show.zh.html.haml b/app/views/projects/compare/show.zh.html.haml new file mode 100644 index 00000000000..7826bfc8577 --- /dev/null +++ b/app/views/projects/compare/show.zh.html.haml @@ -0,0 +1,23 @@ += render "projects/commits/head" + +%h3.page-title + 对比视图 + += render "form" + +- if @commits.present? + = render "projects/commits/commit_list" + = render "projects/diffs/diffs", diffs: @diffs, project: @project +- else + .light-well + .center + %h4 + 没有可对比的内容. + %p.slead + - if params[:to] == params[:from] + %span.label-branch #{params[:from]} + 与 + %span.label-branch #{params[:to]} + 是一致的. + - else + 您需要使用不同的分支名称才能得到有效的对比结果. diff --git a/app/views/projects/deploy_keys/_deploy_key.zh.html.haml b/app/views/projects/deploy_keys/_deploy_key.zh.html.haml new file mode 100644 index 00000000000..fd5f5daf8e9 --- /dev/null +++ b/app/views/projects/deploy_keys/_deploy_key.zh.html.haml @@ -0,0 +1,25 @@ +%li + .pull-right + - if @available_keys.include?(deploy_key) + = link_to enable_namespace_project_deploy_key_path(@project.namespace, @project, deploy_key), class: 'btn btn-sm', method: :put do + %i.fa.fa-plus + 启用 + - else + - if deploy_key.projects.count > 1 + = link_to disable_namespace_project_deploy_key_path(@project.namespace, @project, deploy_key), class: 'btn btn-sm', method: :put do + %i.fa.fa-power-off + 禁用 + - else + = link_to '删除', namespace_project_deploy_key_path(@project.namespace, @project, deploy_key), data: { confirm: '您即将删除布署key. 您确定?'}, method: :delete, class: "btn btn-remove delete-key btn-sm pull-right" + + + - key_project = deploy_key.projects.include?(@project) ? @project : deploy_key.projects.first + = link_to namespace_project_deploy_key_path(key_project.namespace, key_project, deploy_key) do + %i.fa.fa-key + %strong= deploy_key.title + + %p.light.prepend-top-10 + - deploy_key.projects.map(&:name_with_namespace).each do |project_name| + %span.label.label-gray.deploy-project-label= project_name + %small.pull-right + 创建于 #{time_ago_with_tooltip(deploy_key.created_at)} diff --git a/app/views/projects/deploy_keys/_form.zh.html.haml b/app/views/projects/deploy_keys/_form.zh.html.haml new file mode 100644 index 00000000000..b84b0aa4204 --- /dev/null +++ b/app/views/projects/deploy_keys/_form.zh.html.haml @@ -0,0 +1,24 @@ +%div + = form_for [@project.namespace.becomes(Namespace), @project, @key], url: namespace_project_deploy_keys_path, html: { class: 'deploy-key-form form-horizontal' } do |f| + -if @key.errors.any? + .alert.alert-danger + %ul + - @key.errors.full_messages.each do |msg| + %li= msg + + .form-group + = f.label :title, class: "control-label" + .col-sm-10= f.text_field :title, class: 'form-control' + .form-group + = f.label :key, class: "control-label" + .col-sm-10 + %p.light + 在此粘贴public key. 点 + = link_to "此", help_page_path("ssh", "README") + 阅读更多关于如何生成public key. + = f.text_area :key, class: "form-control thin_area", rows: 5 + + .form-actions + = f.submit '创建', class: "btn-create btn" + = link_to "删除", namespace_project_deploy_keys_path(@project.namespace, @project), class: "btn btn-cancel" + diff --git a/app/views/projects/deploy_keys/index.zh.html.haml b/app/views/projects/deploy_keys/index.zh.html.haml new file mode 100644 index 00000000000..f9d628c806c --- /dev/null +++ b/app/views/projects/deploy_keys/index.zh.html.haml @@ -0,0 +1,30 @@ +%h3.page-title + 布署key允许只读访问仓库 + + = link_to new_namespace_project_deploy_key_path(@project.namespace, @project), class: "btn btn-new pull-right", title: "New Deploy Key" do + %i.fa.fa-plus + 创建布署key + +%p.light + 布署key可用于持续集成, staging或工作环境服务器. + 您可以创建布署key或添加已有的key. + +%hr.clearfix + +.row + .col-md-6.enabled-keys + %h5 + %strong.cgreen 启用这个项目的布署key + %ul.bordered-list + = render @enabled_keys + - if @enabled_keys.blank? + .light-well + .nothing-here-block #{link_to '新建布署key', new_namespace_project_deploy_key_path(@project.namespace, @project)} 或添加已有的key + .col-md-6.available-keys + %h5 + %strong 用于您有访问权限的项目的key + %ul.bordered-list + = render @available_keys + - if @available_keys.blank? + .light-well + .nothing-here-block 您有访问权限的项目的布署key都会显示在这里. diff --git a/app/views/projects/deploy_keys/new.zh.html.haml b/app/views/projects/deploy_keys/new.zh.html.haml new file mode 100644 index 00000000000..c6c3dc783a1 --- /dev/null +++ b/app/views/projects/deploy_keys/new.zh.html.haml @@ -0,0 +1,4 @@ +%h3.page-title 新建布署key +%hr + += render 'form' diff --git a/app/views/projects/deploy_keys/show.zh.html.haml b/app/views/projects/deploy_keys/show.zh.html.haml new file mode 100644 index 00000000000..1e55dc82d4a --- /dev/null +++ b/app/views/projects/deploy_keys/show.zh.html.haml @@ -0,0 +1,13 @@ +%h3.page-title + 布署key: + = @key.title + %small + 创建于 + = @key.created_at.stamp("Aug 21, 2011") +.back-link + = link_to namespace_project_deploy_keys_path(@project.namespace, @project) do + ← 前往布署key列表 +%hr +%pre= @key.key +.pull-right + = link_to '删除', namespace_project_deploy_key_path(@project.namespace, @project, @key), data: { confirm: '您确定?'}, method: :delete, class: "btn-remove btn delete-key" diff --git a/app/views/projects/diffs/_diffs.zh.html.haml b/app/views/projects/diffs/_diffs.zh.html.haml new file mode 100644 index 00000000000..c3a29c99ef7 --- /dev/null +++ b/app/views/projects/diffs/_diffs.zh.html.haml @@ -0,0 +1,21 @@ +.row.prepend-top-20.append-bottom-10 + .col-md-8 + = render 'projects/diffs/stats', diffs: diffs + .col-md-4 + .btn-group.pull-right + = inline_diff_btn + = parallel_diff_btn + +- if show_diff_size_warning?(diffs) + = render 'projects/diffs/warning', diffs: diffs + +.files + - safe_diff_files(diffs).each_with_index do |diff_file, index| + = render 'projects/diffs/file', diff_file: diff_file, i: index, project: project + +- if @diff_timeout + .alert.alert-danger + %h4 + 收集修改失败 + %p + 可能修改内容过多导致超时操作失败. 请尝试本地执行对比操作 diff --git a/app/views/projects/diffs/_file.zh.html.haml b/app/views/projects/diffs/_file.zh.html.haml new file mode 100644 index 00000000000..e2f851e2e10 --- /dev/null +++ b/app/views/projects/diffs/_file.zh.html.haml @@ -0,0 +1,49 @@ +- blob = project.repository.blob_for_diff(@commit, diff_file.diff) +- return unless blob +- blob_diff_path = namespace_project_blob_diff_path(project.namespace, project, tree_join(@commit.id, diff_file.file_path)) +.diff-file{id: "diff-#{i}", data: {blob_diff_path: blob_diff_path }} + .diff-header{id: "file-path-#{hexdigest(diff_file.new_path || diff_file.old_path)}"} + - if diff_file.deleted_file + %span="#{diff_file.old_path} 已删除" + + .diff-btn-group + - if @commit.parent_ids.present? + = view_file_btn(@commit.parent_id, diff_file, project) + - elsif diff_file.diff.submodule? + - submodule_item = project.repository.blob_at(@commit.id, diff_file.file_path) + = submodule_link(submodule_item, @commit.id) + - else + - if diff_file.renamed_file + %span= "#{diff_file.old_path} 重命名为 #{diff_file.new_path}" + - else + %span= diff_file.new_path + - if diff_file.mode_changed? + %span.file-mode= "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}" + + .diff-btn-group + - if blob.text? + = link_to '#', class: 'js-toggle-diff-comments btn btn-sm active has_tooltip', title: "Toggle comments for this file" do + %i.fa.fa-comments +   + + - if @merge_request && @merge_request.source_project + = edit_blob_link(@merge_request.source_project, + @merge_request.source_branch, diff_file.new_path, + after: ' ', from_merge_request_id: @merge_request.id) + + = view_file_btn(@commit.id, diff_file, project) + + .diff-content.diff-wrap-lines + -# Skipp all non non-supported blobs + - return unless blob.respond_to?('text?') + - if blob.text? + - if params[:view] == 'parallel' + = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i + - else + = render "projects/diffs/text_file", diff_file: diff_file, index: i + - elsif blob.image? + - old_file = project.repository.prev_blob_for_diff(@commit, diff_file) + = render "projects/diffs/image", diff_file: diff_file, old_file: old_file, file: blob, index: i + - else + .nothing-here-block 该文件类型没有预览 + diff --git a/app/views/projects/diffs/_stats.zh.html.haml b/app/views/projects/diffs/_stats.zh.html.haml new file mode 100644 index 00000000000..1625930615a --- /dev/null +++ b/app/views/projects/diffs/_stats.zh.html.haml @@ -0,0 +1,38 @@ +.js-toggle-container + .commit-stat-summary + Showing + = link_to '#', class: 'js-toggle-button' do + %strong #{pluralize(diffs.count, "changed file")} + - if current_controller?(:commit) + - unless @commit.has_zero_stats? + with + %strong.cgreen #{@commit.stats.additions} additions + and + %strong.cred #{@commit.stats.deletions} deletions + .file-stats.js-toggle-content.hide + %ul.bordered-list + - diffs.each_with_index do |diff, i| + %li + - if diff.deleted_file + %span.deleted-file + %a{href: "#diff-#{i}"} + %i.fa.fa-minus + = diff.old_path + - elsif diff.renamed_file + %span.renamed-file + %a{href: "#diff-#{i}"} + %i.fa.fa-minus + = diff.old_path + → + = diff.new_path + - elsif diff.new_file + %span.new-file + %a{href: "#diff-#{i}"} + %i.fa.fa-plus + = diff.new_path + - else + %span.edit-file + %a{href: "#diff-#{i}"} + %i.fa.fa-adjust + = diff.new_path + diff --git a/app/views/projects/diffs/_text_file.zh.html.haml b/app/views/projects/diffs/_text_file.zh.html.haml new file mode 100644 index 00000000000..b74fe77226e --- /dev/null +++ b/app/views/projects/diffs/_text_file.zh.html.haml @@ -0,0 +1,36 @@ +- too_big = diff_file.diff_lines.count > Commit::DIFF_SAFE_LINES +- if too_big + %a.supp_diff_link 修改被屏蔽. 点击显示 + +%table.text-file{class: "#{'hide' if too_big}"} + - last_line = 0 + - diff_file.diff_lines.each_with_index do |line, index| + - type = line.type + - last_line = line.new_pos + - line_code = generate_line_code(diff_file.file_path, line) + - line_old = line.old_pos + %tr.line_holder{ id: line_code, class: "#{type}" } + - if type == "match" + = render "projects/diffs/match_line", {line: line.text, + line_old: line_old, line_new: line.new_pos, bottom: false} + - else + %td.old_line + = link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code + - if @comments_allowed + = link_to_new_diff_note(line_code) + %td.new_line{data: {linenumber: line.new_pos}} + = link_to raw(type == "old" ? " " : line.new_pos) , "##{line_code}", id: line_code + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line.text) + + - if @reply_allowed + - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at) + - unless comments.empty? + = render "projects/notes/diff_notes_with_reply", notes: comments, line: line.text + + - if last_line > 0 + = render "projects/diffs/match_line", {line: "", + line_old: last_line, line_new: last_line, bottom: true} + +- if diff_file.diff.blank? && diff_file.mode_changed? + .file-mode-changed + 文件模式(mode)发生了改变 diff --git a/app/views/projects/diffs/_warning.zh.html.haml b/app/views/projects/diffs/_warning.zh.html.haml new file mode 100644 index 00000000000..2b97f76333c --- /dev/null +++ b/app/views/projects/diffs/_warning.zh.html.haml @@ -0,0 +1,19 @@ +.alert.alert-warning + %h4 + 修改太多. + .pull-right + - unless diff_hard_limit_enabled? + = link_to "重新加载全文对比", url_for(params.merge(force_show_diff: true)), class: "btn btn-sm btn-warning" + + - if current_controller?(:commit) or current_controller?(:merge_requests) + - if current_controller?(:commit) + = link_to "普通文本对比", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff), class: "btn btn-warning btn-sm" + = link_to "邮件补丁", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch), class: "btn btn-warning btn-sm" + - elsif @merge_request && @merge_request.persisted? + = link_to "普通文本对比", merge_request_path(@merge_request, format: :diff), class: "btn btn-warning btn-sm" + = link_to "邮件补丁", merge_request_path(@merge_request, format: :patch), class: "btn btn-warning btn-sm" + %p + 为了保障性能只显示了 + %strong #{allowed_diff_size} of #{diffs.size} + 个文件. + diff --git a/app/views/projects/edit.zh.html.haml b/app/views/projects/edit.zh.html.haml new file mode 100644 index 00000000000..b5477a7e0f3 --- /dev/null +++ b/app/views/projects/edit.zh.html.haml @@ -0,0 +1,209 @@ +.project-edit-container + .project-edit-errors + .project-edit-content + %div + %h3.page-title + 项目设置 + %hr + .panel-body + = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit_project form-horizontal" }, authenticity_token: true do |f| + + %fieldset + .form-group.project_name_holder + = f.label :name, class: 'control-label' do + 项目名称 + .col-sm-10 + = f.text_field :name, placeholder: "示例项目", class: "form-control", id: "project_name_edit" + + + .form-group + = f.label :description, class: 'control-label' do + 项目描述 + %span.light (可选) + .col-sm-10 + = f.text_area :description, placeholder: "超酷的项目", class: "form-control", rows: 3, maxlength: 250 + + - if @project.repository.exists? && @project.repository.branch_names.any? + .form-group + = f.label :default_branch, "默认分支", class: 'control-label' + .col-sm-10= f.select(:default_branch, @repository.branch_names, {}, {class: 'select2 select-wide'}) + + + = render "visibility_level", f: f, visibility_level: @project.visibility_level, can_change_visibility_level: can?(current_user, :change_visibility_level, @project) + + %fieldset.features + %legend + 标签: + .form-group + = f.label :tag_list, "标签", class: 'control-label' + .col-sm-10 + = f.text_field :tag_list, maxlength: 2000, class: "form-control" + %p.hint 以,号分隔标签. + + %fieldset.features + %legend + 功能点: + .form-group + = f.label :issues_enabled, "问题", class: 'control-label' + .col-sm-10 + .checkbox + = f.check_box :issues_enabled + %span.descr 用于此项目的轻量级问题跟踪系统 + + .form-group + = f.label :merge_requests_enabled, "合并请求", class: 'control-label' + .col-sm-10 + .checkbox + = f.check_box :merge_requests_enabled + %span.descr 提交修改给上游合并. + + .form-group + = f.label :wiki_enabled, "Wiki", class: 'control-label' + .col-sm-10 + .checkbox + = f.check_box :wiki_enabled + %span.descr 用于制作项目文档页面 + + .form-group + = f.label :snippets_enabled, "Snippets", class: 'control-label' + .col-sm-10 + .checkbox + = f.check_box :snippets_enabled + %span.descr 与其它人分享git仓库之外的代码 + + %fieldset.features + %legend + 项目头像: + .form-group + .col-sm-2 + .col-sm-10 + - if @project.avatar? + = project_icon("#{@project.namespace.to_param}/#{@project.to_param}", alt: '', class: 'avatar project-avatar s160') + %p.light + - if @project.avatar_in_git + 仓库里的项目头像: #{ @project.avatar_in_git } + %p.light + - if @project.avatar? + 您可以在此修改项目头像 + - else + 您可以在此上传头像 + %a.choose-btn.btn.btn-sm.js-choose-project-avatar-button + %i.icon-paper-clip + %span 选择文件... +   + %span.file_name.js-avatar-filename File name... + = f.file_field :avatar, class: "js-project-avatar-input hidden" + .light 允许的最大文件大小是200KB. + - if @project.avatar? + %hr + = link_to '删除头像', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "将删除项目头像. 您确定?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" + + .form-actions + = f.submit '保存修改', class: "btn btn-save" + + + + .danger-settings + - if can? current_user, :archive_project, @project + - if @project.archived? + .panel.panel-success + .panel-heading + 解包项目 + .panel-body + %p + 解包项目会把项目标识为活跃状态. + %br + 项目将可以提交代码. + %br + %strong 一旦项目被激活, 该项目将会在搜索和面板中显示. + = link_to '解包', unarchive_namespace_project_path(@project.namespace, @project), + data: { confirm: "您确认要解包该项目?\n一旦这个项目被解包, 项目将被激活, 激活后项目可以提交代码." }, + method: :post, class: "btn btn-success" + - else + .panel.panel-warning + .panel-heading + 打包项目 + .panel-body + %p + 打包项目将会将项目标识为只读. + %br + 将会从面板只隐藏且不会在搜索中显示. + %br + %strong 打包的项目将不能提交代码! + = link_to '打包', archive_namespace_project_path(@project.namespace, @project), + data: { confirm: "您确认您要打包此项目?\n打包的项目不能提交代码." }, + method: :post, class: "btn btn-warning" + - else + .nothing-here-block 只有项目所有者能打包项目 + + .panel.panel-default.panel.panel-warning + .panel-heading 重命名项目 + .errors-holder + .panel-body + = form_for([@project.namespace.becomes(Namespace), @project], html: { class: 'form-horizontal' }) do |f| + .form-group.project_name_holder + = f.label :name, class: 'control-label' do + 项目名称 + .col-sm-9 + .form-group + = f.text_field :name, placeholder: "示例项目", class: "form-control" + .form-group + = f.label :path, class: 'control-label' do + %span 路径 + .col-sm-9 + .form-group + .input-group + .input-group-addon + #{URI.join(root_url, @project.namespace.path)}/ + = f.text_field :path, class: 'form-control' + %span.input-group-addon .git + %ul + %li 注意了! 重命名项目会产生意想不到的副作用. + %li 您需要更新您的本地仓库指向新的地址. + .form-actions + = f.submit '重命名', class: "btn btn-warning" + + - if can?(current_user, :change_namespace, @project) + .panel.panel-default.panel.panel-danger + .panel-heading 移交项目 + .errors-holder + .panel-body + = form_for([@project.namespace.becomes(Namespace), @project], url: transfer_namespace_project_path(@project.namespace, @project), method: :put, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f| + .form-group + = label_tag :new_namespace_id, nil, class: 'control-label' do + %span 命名空间 + .col-sm-10 + .form-group + = select_tag :new_namespace_id, namespaces_options(@project.namespace_id), { prompt: '选择命名空间', class: 'select2' } + %ul + %li 注意了! 修改项目命名空间会产生意想不到的副作用. + %li 您只能转移项目到您管理的命名空间. + %li 您需要更新您的本地仓库指向新的地址. + .form-actions + = f.submit '移交', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) } + - else + .nothing-here-block 只有项目所有者可以移交项目 + + - if can?(current_user, :remove_project, @project) + .panel.panel-default.panel.panel-danger + .panel-heading 删除项目 + .panel-body + = form_tag(namespace_project_path(@project.namespace, @project), method: :delete, html: { class: 'form-horizontal'}) do + %p + 删除项目会删除其仓库及其所有关联资源如问题,合并请求等. + %br + %strong 删除的项目不能恢复! + + = link_to '删除项目', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) } + - else + .nothing-here-block 只有项目所有者可以删除项目 + +.save-project-loader.hide + .center + %h2 + %i.fa.fa-spinner.fa-spin + 保存项目. + %p 请稍候, 完成后此页面将会自动刷新. + + += render 'shared/confirm_modal', phrase: @project.path diff --git a/app/views/projects/empty.zh.html.haml b/app/views/projects/empty.zh.html.haml new file mode 100644 index 00000000000..4a8a3476cae --- /dev/null +++ b/app/views/projects/empty.zh.html.haml @@ -0,0 +1,49 @@ +- if current_user && can?(current_user, :download_code, @project) + = render 'shared/no_ssh' + = render 'shared/no_password' + += render "home_panel" + +.center.well + %h3 + 该项目的仓库是空的 + %h4 + 您可以 + = link_to namespace_project_new_blob_path(@project.namespace, @project, 'master'), class: 'btn btn-new btn-lg' do + 添加文件 +  或通过命令行推送 + +%h4 + %strong 命令行说明 +%div.git-empty + %fieldset + %legend Git全局设置 + %pre.dark + :preserve + git config --global user.name "#{git_user_name}" + git config --global user.email "#{git_user_email}" + + %fieldset + %legend 创建新仓库 + %pre.dark + :preserve + mkdir #{@project.path} + cd #{@project.path} + git init + touch README.md + git add README.md + git commit -m "first commit" + git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')} + git push -u origin master + + %fieldset + %legend 推送已有仓库 + %pre.dark + :preserve + cd existing_git_repo + git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')} + git push -u origin master + +- if can? current_user, :remove_project, @project + .prepend-top-20 + = link_to '删除项目', [@project.namespace.becomes(Namespace), @project], data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right" diff --git a/app/views/projects/forks/error.zh.html.haml b/app/views/projects/forks/error.zh.html.haml new file mode 100644 index 00000000000..fba4c544eef --- /dev/null +++ b/app/views/projects/forks/error.zh.html.haml @@ -0,0 +1,20 @@ +- if @forked_project && !@forked_project.saved? + .alert.alert-danger.alert-block + %h4 + %i.fa.fa-code-fork + Fork出错! + %p + 您尝试fork + = link_to_project @project + 但因为下面这些原因失败了: + + + - if @forked_project && @forked_project.errors.any? + %p + – + = @forked_project.errors.full_messages.first + + %p + = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork", class: "btn" do + %i.fa.fa-code-fork + 尝试重新Fork diff --git a/app/views/projects/forks/new.zh.html.haml b/app/views/projects/forks/new.zh.html.haml new file mode 100644 index 00000000000..fda3c22a31f --- /dev/null +++ b/app/views/projects/forks/new.zh.html.haml @@ -0,0 +1,39 @@ +%h3.page-title Fork项目 +%p.lead + 点击fork项目到用户或组 +%hr + +.fork-namespaces + - @namespaces.in_groups_of(6, false) do |group| + .row + - group.each do |namespace| + .col-md-2.col-sm-3 + - if fork = namespace.find_fork_of(@project) + .thumbnail.fork-exists-thumbnail + = link_to project_path(fork), title: "访问fork的项目", class: 'has_tooltip' do + = image_tag namespace_icon(namespace, 200) + .caption + %h4=namespace.human_name + %p + = namespace.path + - else + .thumbnail.fork-thumbnail + = link_to namespace_project_fork_path(@project.namespace, @project, namespace_key: namespace.id), title: "Fork here", method: "POST", class: 'has_tooltip' do + = image_tag namespace_icon(namespace, 200) + .caption + %h4=namespace.human_name + %p + = namespace.path + + %p.light + Fork是项目仓库的一份拷贝. + %br + Fork一个项目允许您做出修改且不影响原有项目. + +.save-project-loader.hide + .center + %h2 + %i.fa.fa-spinner.fa-spin + 正在fork仓库 + %p 请稍候, 操作完成后此页将会自动刷新. + diff --git a/app/views/projects/graphs/_head.zh.html.haml b/app/views/projects/graphs/_head.zh.html.haml new file mode 100644 index 00000000000..39fa2ce2653 --- /dev/null +++ b/app/views/projects/graphs/_head.zh.html.haml @@ -0,0 +1,5 @@ +%ul.nav.nav-tabs + = nav_link(action: :show) do + = link_to '贡献者', namespace_project_graph_path + = nav_link(action: :commits) do + = link_to '提交', commits_namespace_project_graph_path diff --git a/app/views/projects/graphs/commits.zh.html.haml b/app/views/projects/graphs/commits.zh.html.haml new file mode 100644 index 00000000000..0dab19fa0b2 --- /dev/null +++ b/app/views/projects/graphs/commits.zh.html.haml @@ -0,0 +1,83 @@ += render 'head' + +%p.lead + 提交统计 + %strong #{@repository.root_ref} + #{@commits_graph.start_date.strftime('%b %d')} - #{@commits_graph.end_date.strftime('%b %d')} + +.row + .col-md-6 + %ul + %li + %p.lead + %strong #{@commits_graph.commits.size} + 近 + %strong #{@commits_graph.duration} + 天的提交 + %li + %p.lead + 日均提交 + %strong #{@commits_graph.commit_per_day} + %li + %p.lead + 贡献人数 + %strong #{@commits_graph.authors} + .col-md-6 + %div + %p.slead + 每月日均提交 + %canvas#month-chart{width: 800, height: 400} +.row + .col-md-6 + %div + %p.slead + 毎日小时提交量(UTC) + %canvas#hour-chart{width: 800, height: 400} + .col-md-6 + %div + %p.slead + 工作日提交数 + %canvas#weekday-chart{width: 800, height: 400} + +:coffeescript + data = { + labels : #{@commits_per_time.keys.to_json}, + datasets : [{ + fillColor : "rgba(220,220,220,0.5)", + strokeColor : "rgba(220,220,220,1)", + pointColor : "rgba(220,220,220,1)", + pointStrokeColor : "#EEE", + data : #{@commits_per_time.values.to_json} + }] + } + + ctx = $("#hour-chart").get(0).getContext("2d"); + new Chart(ctx).Line(data,{"scaleOverlay": true, responsive: true}); + + data = { + labels : #{@commits_per_week_days.keys.to_json}, + datasets : [{ + fillColor : "rgba(220,220,220,0.5)", + strokeColor : "rgba(220,220,220,1)", + pointColor : "rgba(220,220,220,1)", + pointStrokeColor : "#EEE", + data : #{@commits_per_week_days.values.to_json} + }] + } + + ctx = $("#weekday-chart").get(0).getContext("2d"); + new Chart(ctx).Line(data,{"scaleOverlay": true, responsive: true}); + + data = { + labels : #{@commits_per_month.keys.to_json}, + datasets : [{ + fillColor : "rgba(220,220,220,0.5)", + strokeColor : "rgba(220,220,220,1)", + pointColor : "rgba(220,220,220,1)", + pointStrokeColor : "#EEE", + data : #{@commits_per_month.values.to_json} + }] + } + + ctx = $("#month-chart").get(0).getContext("2d"); + new Chart(ctx).Line(data,{"scaleOverlay": true, responsive: true}); diff --git a/app/views/projects/graphs/show.zh.html.haml b/app/views/projects/graphs/show.zh.html.haml new file mode 100644 index 00000000000..6a26e00ac2a --- /dev/null +++ b/app/views/projects/graphs/show.zh.html.haml @@ -0,0 +1,37 @@ += render 'head' +.loading-graph + .center + %h3.page-title + %i.fa.fa-spinner.fa-spin + 生成仓库图示 + %p.slead 请稍等, 完成后会自动刷新. + +.stat-graph.hide + .header.clearfix + %h3#date_header.page-title + %p.light + #{@project.default_branch}分支的提交, 不含合并提交. 不超过6000个 + %input#brush_change{:type => "hidden"} + .graphs + #contributors-master + #contributors.clearfix + %ol.contributors-list.clearfix + + + +:coffeescript + $.ajax + type: "GET", + url: location.href, + success: (data) -> + graph = new ContributorsStatGraph() + graph.init(data) + + $("#brush_change").change -> + graph.change_date_header() + graph.redraw_authors() + + $(".stat-graph").fadeIn(); + $(".loading-graph").hide(); + dataType: "json" + diff --git a/app/views/projects/hooks/index.zh.html.haml b/app/views/projects/hooks/index.zh.html.haml new file mode 100644 index 00000000000..2b58fe9e070 --- /dev/null +++ b/app/views/projects/hooks/index.zh.html.haml @@ -0,0 +1,67 @@ +%h3.page-title + Web钩子 + +%p.light + #{link_to "Web钩子 ", help_page_path("web_hooks", "web_hooks"), class: "vlink"} 用于绑定项目内发生的事件. + +%hr.clearfix + += form_for [@project.namespace.becomes(Namespace), @project, @hook], as: :hook, url: namespace_project_hooks_path(@project.namespace, @project), html: { class: 'form-horizontal' } do |f| + -if @hook.errors.any? + .alert.alert-danger + - @hook.errors.full_messages.each do |msg| + %p= msg + .form-group + = f.label :url, "URL", class: 'control-label' + .col-sm-10 + = f.text_field :url, class: "form-control", placeholder: 'http://example.com/trigger-ci.json' + .form-group + = f.label :url, "Trigger", class: 'control-label' + .col-sm-10 + %div + = f.check_box :push_events, class: 'pull-left' + .prepend-left-20 + = f.label :push_events, class: 'list-label' do + %strong 推送事件 + %p.light + 此url在推送到仓库的时候触发 + %div + = f.check_box :tag_push_events, class: 'pull-left' + .prepend-left-20 + = f.label :tag_push_events, class: 'list-label' do + %strong 标签推送事件 + %p.light + 此url在新标签推送到仓库的时候触发 + %div + = f.check_box :issues_events, class: 'pull-left' + .prepend-left-20 + = f.label :issues_events, class: 'list-label' do + %strong 问题事件 + %p.light + 此url会在创建新问题的时候触发 + %div + = f.check_box :merge_requests_events, class: 'pull-left' + .prepend-left-20 + = f.label :merge_requests_events, class: 'list-label' do + %strong 合并请求事件 + %p.light + 此url会在合并请求创建的时候触发 + .form-actions + = f.submit "添加Web钩子", class: "btn btn-create" + +-if @hooks.any? + .panel.panel-default + .panel-heading + Web钩子 (#{@hooks.count}) + %ul.well-list + - @hooks.each do |hook| + %li + .pull-right + = link_to '测试钩子', test_namespace_project_hook_path(@project.namespace, @project, hook), class: "btn btn-sm btn-grouped" + = link_to '删除', namespace_project_hook_path(@project.namespace, @project, hook), data: { confirm: '您确定?'}, method: :delete, class: "btn btn-remove btn-sm btn-grouped" + .clearfix + %span.monospace= hook.url + %p + - %w(push_events tag_push_events issues_events merge_requests_events).each do |trigger| + - if hook.send(trigger) + %span.label.label-gray= trigger.titleize diff --git a/app/views/projects/imports/new.zh.html.haml b/app/views/projects/imports/new.zh.html.haml new file mode 100644 index 00000000000..3712d34e36a --- /dev/null +++ b/app/views/projects/imports/new.zh.html.haml @@ -0,0 +1,22 @@ +%h3.page-title + - if @project.import_failed? + 导入失败. 重试? + - else + 导入仓库 + +%hr + += form_for @project, url: namespace_project_import_path(@project.namespace, @project), method: :post, html: { class: 'form-horizontal' } do |f| + .form-group.import-url-data + = f.label :import_url, class: 'control-label' do + %span 导入已有git库 + .col-sm-10 + = f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git' + .alert.alert-info + 此URL必须可以被公共访问或者您可以添加用户名和密码在地址中如https://username:password@gitlab.com/company/project.git. + %br + 导入会在4分钟后超时. 对于大的仓库使用克隆/推送组合的方式. + For SVN repositories, check + 导入svn仓库, 查看 #{link_to "该svn迁移文档.", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"} + .form-actions + = f.submit '开始导入', class: "btn btn-create", tabindex: 4 diff --git a/app/views/projects/imports/show.zh.html.haml b/app/views/projects/imports/show.zh.html.haml new file mode 100644 index 00000000000..1c585333b15 --- /dev/null +++ b/app/views/projects/imports/show.zh.html.haml @@ -0,0 +1,9 @@ +.save-project-loader + .center + %h2 + %i.fa.fa-spinner.fa-spin + 正在导入. + %p.monospace git clone --bare #{hidden_pass_url(@project.import_url)} + %p 请稍等我们正在为你导入仓库. 您随时可以刷新. + :javascript + new ProjectImport(); diff --git a/app/views/projects/issues/_discussion.zh.html.haml b/app/views/projects/issues/_discussion.zh.html.haml new file mode 100644 index 00000000000..409f1ff52d0 --- /dev/null +++ b/app/views/projects/issues/_discussion.zh.html.haml @@ -0,0 +1,33 @@ +- content_for :note_actions do + - if can?(current_user, :modify_issue, @issue) + - if @issue.closed? + = link_to '重新开启问题', issue_path(@issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-grouped btn-reopen js-note-target-reopen", title: '重新开启问题' + - else + = link_to '关闭问题', issue_path(@issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close js-note-target-close", title: "关闭问题" +.row + %section.col-md-9 + .votes-holder.pull-right + #votes= render 'votes/votes_block', votable: @issue + .participants + %span= pluralize(@issue.participants.count, 'participant') + - @issue.participants.each do |participant| + = link_to_member(@project, participant, name: false, size: 24) + .voting_notes#notes= render "projects/notes/notes_with_form" + %aside.col-md-3 + .issuable-affix + .clearfix + %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'} + = cross_project_reference(@project, @issue) + %hr + .context + = render partial: 'issue_context', locals: { issue: @issue } + + - if @issue.labels.any? + .issuable-context-title + %label 标签 + .issue-show-labels + - @issue.labels.each do |label| + = link_to namespace_project_issues_path(@project.namespace, @project, label_name: label.name) do + = render_colored_label(label) + = link_to '#aside', class: 'show-aside' do + %i.fa.fa-angle-left diff --git a/app/views/projects/issues/_form.zh.html.haml b/app/views/projects/issues/_form.zh.html.haml new file mode 100644 index 00000000000..da81768d0d2 --- /dev/null +++ b/app/views/projects/issues/_form.zh.html.haml @@ -0,0 +1,14 @@ +%div.issue-form-holder + %h3.page-title= @issue.new_record? ? "创建问题" : "编辑问题 ##{@issue.iid}" + %hr + + = form_for [@project.namespace.becomes(Namespace), @project, @issue], html: { class: 'form-horizontal issue-form gfm-form' } do |f| + = render 'projects/issuable_form', f: f, issuable: @issue + +:javascript + $('.assign-to-me-link').on('click', function(e){ + $('#issue_assignee_id').val("#{current_user.id}").trigger("change"); + e.preventDefault(); + }); + + window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}"; diff --git a/app/views/projects/issues/_issue.zh.html.haml b/app/views/projects/issues/_issue.zh.html.haml new file mode 100644 index 00000000000..1ff80f71f59 --- /dev/null +++ b/app/views/projects/issues/_issue.zh.html.haml @@ -0,0 +1,51 @@ +%li{ id: dom_id(issue), class: issue_css_classes(issue), url: issue_path(issue) } + - if controller.controller_name == 'issues' + .issue-check + = check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue) + + .issue-title + %span.str-truncated + = link_to_gfm issue.title, issue_path(issue), class: "row_title" + .pull-right.light + - if issue.closed? + %span + 已关闭 + - if issue.notes.any? +   + %span + %i.fa.fa-comments + = issue.notes.count + + .issue-info + %span.light= "##{issue.iid}" + - if issue.assignee + assigned to #{link_to_member(@project, issue.assignee)} + - if issue.votes_count > 0 + = render 'votes/votes_inline', votable: issue + - if issue.milestone + %span + %i.fa.fa-clock-o + = issue.milestone.title + - if issue.tasks? + %span.task-status + = issue.task_status + + .pull-right.issue-updated-at + %small updated #{time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_update_ago')} + + .issue-labels + - issue.labels.each do |label| + = link_to namespace_project_issues_path(issue.project.namespace, issue.project, label_name: label.name) do + = render_colored_label(label) + + .issue-actions + - if can? current_user, :modify_issue, issue + - if issue.closed? + = link_to '重新打开', issue_path(issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-sm btn-grouped reopen_issue btn-reopen", remote: true + - else + = link_to '关闭', issue_path(issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-sm btn-grouped close_issue btn-close", remote: true + = link_to edit_namespace_project_issue_path(issue.project.namespace, issue.project, issue), class: "btn btn-sm edit-issue-link btn-grouped" do + %i.fa.fa-pencil-square-o + 编辑 + + diff --git a/app/views/projects/issues/_issue_context.zh.html.haml b/app/views/projects/issues/_issue_context.zh.html.haml new file mode 100644 index 00000000000..97b8597b70e --- /dev/null +++ b/app/views/projects/issues/_issue_context.zh.html.haml @@ -0,0 +1,50 @@ += form_for [@project.namespace.becomes(Namespace), @project, @issue], remote: true, html: {class: 'edit-issue inline-update'} do |f| + %div.prepend-top-20 + .issuable-context-title + %label + 指定给: + - if issue.assignee + %strong= link_to_member(@project, @issue.assignee, size: 24) + - else + none + - if can?(current_user, :modify_issue, @issue) + = project_users_select_tag('issue[assignee_id]', placeholder: '选择指定人', class: 'custom-form-control js-select2 js-assignee', selected: @issue.assignee_id) + + %div.prepend-top-20.clearfix + .issuable-context-title + %label + 里程碑: + - if issue.milestone + %span.back-to-milestone + = link_to namespace_project_milestone_path(@project.namespace, @project, @issue.milestone) do + %strong + %i.fa.fa-clock-o + = @issue.milestone.title + - else + none + - if can?(current_user, :modify_issue, @issue) + = f.select(:milestone_id, milestone_options(@issue), { include_blank: "请选择里程碑" }, {class: 'select2 select2-compact js-select2 js-milestone'}) + = hidden_field_tag :issue_context + = f.submit class: 'btn' + + - if current_user + %div.prepend-top-20.clearfix + .issuable-context-title + %label + 订阅: + %button.btn.btn-block.subscribe-button + %i.fa.fa-eye + %span= @issue.subscribed?(current_user) ? "取消订阅" : "订阅" + - subscribtion_status = @issue.subscribed?(current_user) ? "订阅成功" : "取消订阅成功" + .subscription-status{"data-status" => subscribtion_status} + .description-block.unsubscribed{class: ( "hidden" if @issue.subscribed?(current_user) )} + 您没有收到该栏目的通知. + .description-block.subscribed{class: ( "hidden" unless @issue.subscribed?(current_user) )} + You're receiving notifications because you're subscribed to this thread. + 您收到通知是因为您订阅了此栏目. + +:coffeescript + $ -> + new Subscription("#{toggle_subscription_namespace_project_issue_path(@issue.project.namespace, @project, @issue)}") + + diff --git a/app/views/projects/issues/_issues.zh.html.haml b/app/views/projects/issues/_issues.zh.html.haml new file mode 100644 index 00000000000..39f17032db8 --- /dev/null +++ b/app/views/projects/issues/_issues.zh.html.haml @@ -0,0 +1,13 @@ +.panel.panel-default + %ul.well-list.issues-list + = render @issues + - if @issues.blank? + %li + .nothing-here-block 无问题可显示 + +- if @issues.present? + .pull-right + %span.issue_counter #{@issues.total_count} + 筛选后的问题 + + = paginate @issues, theme: "gitlab" diff --git a/app/views/projects/issues/index.zh.html.haml b/app/views/projects/issues/index.zh.html.haml new file mode 100644 index 00000000000..4b07c233c3a --- /dev/null +++ b/app/views/projects/issues/index.zh.html.haml @@ -0,0 +1,29 @@ +.append-bottom-10 + .pull-right + .pull-left + - if current_user + .hidden-xs.pull-left + = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do + %i.fa.fa-rss + + = render 'shared/issuable_search_form', path: namespace_project_issues_path(@project.namespace, @project) + + - if can? current_user, :write_issue, @project + = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-left", title: "新建问题", id: "new_issue_link" do + %i.fa.fa-plus + 新建问题 + + = render 'shared/issuable_filter' + + .clearfix + .issues_bulk_update.hide + = form_tag bulk_update_namespace_project_issues_path(@project.namespace, @project), method: :post do + = select_tag('update[state_event]', options_for_select([['Open', 'reopen'], ['Closed', 'close']]), prompt: "Status") + = project_users_select_tag('update[assignee_id]', placeholder: 'Assignee') + = select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone") + = hidden_field_tag 'update[issues_ids]', [] + = hidden_field_tag :state_event, params[:state_event] + = button_tag "更新问题", class: "btn update_selected_issues btn-save" + +.issues-holder + = render "issues" diff --git a/app/views/projects/issues/show.zh.html.haml b/app/views/projects/issues/show.zh.html.haml new file mode 100644 index 00000000000..5de256c5228 --- /dev/null +++ b/app/views/projects/issues/show.zh.html.haml @@ -0,0 +1,40 @@ +.issue + .issue-details + %h4.page-title + .issue-box{ class: issue_box_class(@issue) } + - if @issue.closed? + 已关闭 + - else + 打开状态 + 问题 ##{@issue.iid} + %small.creator + · 由 #{link_to_member(@project, @issue.author)} 创建 #{issue_timestamp(@issue)} + + .pull-right + - if can?(current_user, :write_issue, @project) + = link_to new_namespace_project_issue_path(@project.namespace, @project), class: "btn btn-grouped new-issue-link", title: "New Issue", id: "new_issue_link" do + %i.fa.fa-plus + 新问题 + - if can?(current_user, :modify_issue, @issue) + - if @issue.closed? + = link_to '重新打开', issue_path(@issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-grouped btn-reopen" + - else + = link_to '关闭', issue_path(@issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close", title: "关闭问题" + + = link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: "btn btn-grouped issuable-edit" do + %i.fa.fa-pencil-square-o + 编辑 + + %hr + %h2.issue-title + = gfm escape_once(@issue.title) + %div + - if @issue.description.present? + .description + .wiki + = preserve do + = markdown(@issue.description, parse_tasks: true) + + %hr + .issue-discussion + = render "projects/issues/discussion" diff --git a/app/views/projects/labels/_form.zh.html.haml b/app/views/projects/labels/_form.zh.html.haml new file mode 100644 index 00000000000..7ded4c194b7 --- /dev/null +++ b/app/views/projects/labels/_form.zh.html.haml @@ -0,0 +1,33 @@ += form_for [@project.namespace.becomes(Namespace), @project, @label], html: { class: 'form-horizontal label-form' } do |f| + -if @label.errors.any? + .row + .col-sm-10.col-sm-offset-2 + .alert.alert-danger + - @label.errors.full_messages.each do |msg| + %span= msg + %br + + .form-group + = f.label :title, class: 'control-label' + .col-sm-10 + = f.text_field :title, class: "form-control", required: true + .form-group + = f.label :color, "后景色", class: 'control-label' + .col-sm-10 + .input-group + .input-group-addon.label-color-preview   + = f.color_field :color, placeholder: "#AA33EE", class: "form-control" + .help-block + 以#开头的6位十六进制值 + %br + 或者您可以选择以下建议的颜色之一 + + .suggest-colors + - suggested_colors.each do |color| + = link_to '#', style: "background-color: #{color}", data: { color: color } do +   + + .form-actions + = f.submit '保存', class: 'btn btn-save js-save-button' + = link_to "取消", namespace_project_labels_path(@project.namespace, @project), class: 'btn btn-cancel' + diff --git a/app/views/projects/labels/_label.zh.html.haml b/app/views/projects/labels/_label.zh.html.haml new file mode 100644 index 00000000000..62422beb3d0 --- /dev/null +++ b/app/views/projects/labels/_label.zh.html.haml @@ -0,0 +1,10 @@ +%li{id: dom_id(label)} + = render_colored_label(label) + .pull-right + %strong.append-right-20 + = link_to namespace_project_issues_path(@project.namespace, @project, label_name: label.name) do + = pluralize label.open_issues_count, 'open issue' + + - if can? current_user, :admin_label, @project + = link_to '编辑', edit_namespace_project_label_path(@project.namespace, @project, label), class: 'btn' + = link_to '删除', namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-remove remove-row', method: :delete, remote: true, data: {confirm: "删除该标签? 您确定?"} diff --git a/app/views/projects/labels/edit.zh.html.haml b/app/views/projects/labels/edit.zh.html.haml new file mode 100644 index 00000000000..73e5e7ac977 --- /dev/null +++ b/app/views/projects/labels/edit.zh.html.haml @@ -0,0 +1,8 @@ +%h3 + 编辑标签 + %span.light #{@label.name} +.back-link + = link_to namespace_project_labels_path(@project.namespace, @project) do + ← 前往标签列表 +%hr += render 'form' diff --git a/app/views/projects/labels/index.zh.html.haml b/app/views/projects/labels/index.zh.html.haml new file mode 100644 index 00000000000..e05badbf77b --- /dev/null +++ b/app/views/projects/labels/index.zh.html.haml @@ -0,0 +1,15 @@ +- if can? current_user, :admin_label, @project + = link_to new_namespace_project_label_path(@project.namespace, @project), class: "pull-right btn btn-new" do + 新建标签 +%h3.page-title + 标签 +%hr + +.labels + - if @labels.present? + %ul.bordered-list.manage-labels-list + = render @labels + = paginate @labels, theme: 'gitlab' + - else + .light-well + .nothing-here-block 创建第一个标签或 #{link_to '生成', generate_namespace_project_labels_path(@project.namespace, @project), method: :post} 默认的标签组 diff --git a/app/views/projects/labels/new.zh.html.haml b/app/views/projects/labels/new.zh.html.haml new file mode 100644 index 00000000000..531894f7b59 --- /dev/null +++ b/app/views/projects/labels/new.zh.html.haml @@ -0,0 +1,6 @@ +%h3 新建标签 +.back-link + = link_to namespace_project_labels_path(@project.namespace, @project) do + ← 前往标签列表 +%hr += render 'form' diff --git a/app/views/projects/merge_requests/_discussion.zh.html.haml b/app/views/projects/merge_requests/_discussion.zh.html.haml new file mode 100644 index 00000000000..d8e98c8e0e7 --- /dev/null +++ b/app/views/projects/merge_requests/_discussion.zh.html.haml @@ -0,0 +1,31 @@ +- content_for :note_actions do + - if can?(current_user, :modify_merge_request, @merge_request) + - if @merge_request.open? + = link_to '关闭', merge_request_path(@merge_request, merge_request: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close close-mr-link js-note-target-close", title: "关闭合并请求" + - if @merge_request.closed? + = link_to '重新打开', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link js-note-target-reopen", title: "重新开启合并请求" + +.row + %section.col-md-9 + .votes-holder.pull-right + #votes= render 'votes/votes_block', votable: @merge_request + = render "projects/merge_requests/show/participants" + = render "projects/notes/notes_with_form" + %aside.col-md-3 + .issuable-affix + .clearfix + %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'} + = cross_project_reference(@project, @merge_request) + %hr + .context + = render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request } + + - if @merge_request.labels.any? + .issuable-context-title + %label Labels + .merge-request-show-labels + - @merge_request.labels.each do |label| + = link_to namespace_project_merge_requests_path(@project.namespace, @project, label_name: label.name) do + = render_colored_label(label) + = link_to '#aside', class: 'show-aside' do + %i.fa.fa-angle-left diff --git a/app/views/projects/merge_requests/_head.zh.html.haml b/app/views/projects/merge_requests/_head.zh.html.haml new file mode 100644 index 00000000000..e18af67b683 --- /dev/null +++ b/app/views/projects/merge_requests/_head.zh.html.haml @@ -0,0 +1,5 @@ +.top-tabs + = link_to namespace_project_merge_requests_path(@project.namespace, @project), class: "tab #{'active' if current_page?(namespace_project_merge_requests_path(@project.namespace, @project)) }" do + %span + 合并请求 + diff --git a/app/views/projects/merge_requests/_merge_request.zh.html.haml b/app/views/projects/merge_requests/_merge_request.zh.html.haml new file mode 100644 index 00000000000..e15b0b90af3 --- /dev/null +++ b/app/views/projects/merge_requests/_merge_request.zh.html.haml @@ -0,0 +1,47 @@ +%li{ class: mr_css_classes(merge_request) } + .merge-request-title + %span.str-truncated + = link_to_gfm merge_request.title, merge_request_path(merge_request), class: "row_title" + .pull-right.light + - if merge_request.merged? + %span + %i.fa.fa-check + 已合并 + - elsif merge_request.closed? + %span + %i.fa.fa-close + 已关闭 + - else + %span.hidden-xs.hidden-sm + %span.label-branch< + %i.fa.fa-code-fork + %span= merge_request.target_branch + - if merge_request.notes.any? +   + %span + %i.fa.fa-comments + = merge_request.mr_and_commit_notes.count + .merge-request-info + %span.light= "##{merge_request.iid}" + - if merge_request.assignee + 指定给 #{link_to_member(merge_request.source_project, merge_request.assignee)} + - else + 未指定 + - if merge_request.votes_count > 0 + = render 'votes/votes_inline', votable: merge_request + - if merge_request.milestone_id? + %span + %i.fa.fa-clock-o + = merge_request.milestone.title + - if merge_request.tasks? + %span.task-status + = merge_request.task_status + + + .pull-right.hidden-xs + %small 更新于 #{time_ago_with_tooltip(merge_request.updated_at, 'bottom', 'merge_request_updated_ago')} + + .merge-request-labels + - merge_request.labels.each do |label| + = link_to namespace_project_merge_requests_path(merge_request.project.namespace, merge_request.project, label_name: label.name) do + = render_colored_label(label) diff --git a/app/views/projects/merge_requests/_merge_requests.zh.html.haml b/app/views/projects/merge_requests/_merge_requests.zh.html.haml new file mode 100644 index 00000000000..65b0873dd0b --- /dev/null +++ b/app/views/projects/merge_requests/_merge_requests.zh.html.haml @@ -0,0 +1,13 @@ +.panel.panel-default + %ul.well-list.mr-list + = render @merge_requests + - if @merge_requests.blank? + %li + .nothing-here-block 无合并请求可显示 + +- if @merge_requests.present? + .pull-right + %span.cgray.pull-right 该筛选下有 #{@merge_requests.total_count} 个合并请求 + + = paginate @merge_requests, theme: "gitlab" + diff --git a/app/views/projects/merge_requests/_new_compare.zh.html.haml b/app/views/projects/merge_requests/_new_compare.zh.html.haml new file mode 100644 index 00000000000..f71b093af09 --- /dev/null +++ b/app/views/projects/merge_requests/_new_compare.zh.html.haml @@ -0,0 +1,89 @@ +%h3.page-title 对比新合并请求的分支 +%hr + += form_for [@project.namespace.becomes(Namespace), @project, @merge_request], url: new_namespace_project_merge_request_path(@project.namespace, @project), method: :get, html: { class: "merge-request-form form-inline" } do |f| + .hide.alert.alert-danger.mr-compare-errors + .merge-request-branches.row + .col-md-6 + .panel.panel-default + .panel-heading + %strong 源分支 + .panel-body + = f.select(:source_project_id, [[@merge_request.source_project_path,@merge_request.source_project.id]] , {}, { class: 'source_project select2 span3', disabled: @merge_request.persisted? }) +   + = f.select(:source_branch, @merge_request.source_branches, { include_blank: "请选择分支" }, {class: 'source_branch select2 span2'}) + .panel-footer + .mr_source_commit + + .col-md-6 + .panel.panel-default + .panel-heading + %strong 目标分支 + .panel-body + - projects = @project.forked_from_project.nil? ? [@project] : [@project, @project.forked_from_project] + = f.select(:target_project_id, options_from_collection_for_select(projects, 'id', 'path_with_namespace', f.object.target_project_id), {}, { class: 'target_project select2 span3', disabled: @merge_request.persisted? }) +   + = f.select(:target_branch, @merge_request.target_branches, { include_blank: "请选择分支" }, {class: 'target_branch select2 span2'}) + .panel-footer + .mr_target_commit + + - if @merge_request.errors.any? + .alert.alert-danger + - @merge_request.errors.full_messages.each do |msg| + %div= msg + + - elsif @merge_request.source_branch.present? && @merge_request.target_branch.present? + - if @merge_request.compare_failed + .alert.alert-danger + %h4 对比失败 + %p 我们不能对比选择的分支. 可能主要因为差别太大或连接satellite(注:gitlab组件)超时. 请重试或选择不同的分支. + - else + .light-well + .center + %h4 + 没有内容可合并. + %p.slead + - if @merge_request.source_branch == @merge_request.target_branch + 要获得有效的对比结果请选择不同的分支名. + - else + %span.label-branch #{@merge_request.source_branch} + 和 + %span.label-branch #{@merge_request.target_branch} + 是相同的. + + + %hr + = f.submit '对比分支', class: "btn btn-primary mr-compare-btn" + +:javascript + var source_branch = $("#merge_request_source_branch") + , target_branch = $("#merge_request_target_branch") + , target_project = $("#merge_request_target_project_id"); + + $.get("#{branch_from_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {ref: source_branch.val() }); + $.get("#{branch_to_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {target_project_id: target_project.val(),ref: target_branch.val() }); + + target_project.on("change", function() { + $.get("#{update_branches_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {target_project_id: $(this).val() }); + }); + source_branch.on("change", function() { + $.get("#{branch_from_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {ref: $(this).val() }); + $(".mr-compare-errors").fadeOut(); + $(".mr-compare-btn").enable(); + }); + target_branch.on("change", function() { + $.get("#{branch_to_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {target_project_id: target_project.val(),ref: $(this).val() }); + $(".mr-compare-errors").fadeOut(); + $(".mr-compare-btn").enable(); + }); + + +:coffeescript + + $(".merge-request-form").on 'submit', -> + if $("#merge_request_source_branch").val() is "" or $('#merge_request_target_branch').val() is "" + $(".mr-compare-errors").html("You must select source and target branch to proceed") + $(".mr-compare-errors").fadeIn() + event.preventDefault() + return + diff --git a/app/views/projects/merge_requests/_new_submit.zh.html.haml b/app/views/projects/merge_requests/_new_submit.zh.html.haml new file mode 100644 index 00000000000..984b615a1a0 --- /dev/null +++ b/app/views/projects/merge_requests/_new_submit.zh.html.haml @@ -0,0 +1,124 @@ +%h3.page-title + 新建合并请求 +%p.slead + 从 + %strong.label-branch #{@merge_request.source_project_namespace}:#{@merge_request.source_branch} + %span 合并到 + %strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch} + + %span.pull-right + = link_to '修改分支', new_namespace_project_merge_request_path(@project.namespace, @project) + += form_for [@project.namespace.becomes(Namespace), @project, @merge_request], html: { class: "merge-request-form form-horizontal gfm-form" } do |f| + .merge-request-form-info + .form-group + = f.label :title, class: 'control-label' do + %strong Title * + .col-sm-10 + = f.text_field :title, maxlength: 255, autofocus: true, class: 'form-control pad js-gfm-input', required: true + .form-group.issuable-description + = f.label :description, 'Description', class: 'control-label' + .col-sm-10 + = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do + = render 'projects/zen', f: f, attr: :description, classes: 'description form-control' + + .col-sm-12-hint + .pull-left + 使用 + #{link_to 'Gitlab Flavored Markdown', help_page_path('markdown', 'markdown'), target: '_blank'}. + 解析 + .pull-right + 拖放文件 + 或 #{link_to '选择文件', '#', class: 'markdown-selector'} 添加附件. + + .clearfix + .error-alert + %hr + .form-group + .issue-assignee + = f.label :assignee_id, class: 'control-label' do + %i.fa.fa-user + 指定给 + .col-sm-10 + = project_users_select_tag('merge_request[assignee_id]', placeholder: '选择一个用户', class: 'custom-form-control', selected: @merge_request.assignee_id, project_id: @merge_request.target_project_id) +   + = link_to '指定给我', '#', class: 'btn assign-to-me-link' + .form-group + .issue-milestone + = f.label :milestone_id, class: 'control-label' do + %i.fa.fa-clock-o + 里程碑 + .col-sm-10 + - if milestone_options(@merge_request).present? + = f.select(:milestone_id, milestone_options(@merge_request), {include_blank: '请选择里程碑'}, {class: 'select2'}) + - else + %span.light 无里程碑可选 +   + - if can? current_user, :admin_milestone, @merge_request.target_project + = link_to '新建里程碑', new_namespace_project_milestone_path(@merge_request.target_project.namespace, @merge_request.target_project), target: :blank + .form-group + = f.label :label_ids, class: 'control-label' do + %i.fa.fa-tag + Labels + .col-sm-10 + - if @merge_request.target_project.labels.any? + = f.collection_select :label_ids, @merge_request.target_project.labels.all, :id, :name, {selected: @merge_request.label_ids}, multiple: true, class: 'select2' + - else + %span.light 无标签. +   + - if can? current_user, :admin_label, @merge_request.target_project + = link_to '新建标签', new_namespace_project_label_path(@merge_request.target_project.namespace, @merge_request.target_project), target: :blank + + .form-actions + - if contribution_guide_url(@target_project) + %p + 请阅读 + %strong #{link_to '贡献指南', contribution_guide_url(@target_project)} + to this repository. + = f.hidden_field :source_project_id + = f.hidden_field :source_branch + = f.hidden_field :target_project_id + = f.hidden_field :target_branch + = f.submit '提交合并请求', class: 'btn btn-create' + +.mr-compare.merge-request + %ul.nav.nav-tabs.merge-request-tabs + %li.commits-tab{data: {action: 'commits'}} + = link_to url_for(params) do + %i.fa.fa-history + 提交 + %span.badge= @commits.size + %li.diffs-tab{data: {action: 'diffs'}} + = link_to url_for(params) do + %i.fa.fa-list-alt + 修改 + %span.badge= @diffs.size + + .commits.tab-content + = render "projects/commits/commits", project: @project + .diffs.tab-content + - if @diffs.present? + = render "projects/diffs/diffs", diffs: @diffs, project: @project + - elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE + .alert.alert-danger + %h4 该对比包含的提交个数超过多个 #{MergeRequestDiff::COMMITS_SAFE_SIZE} 个. + %p 为保证性能修改的行未显示. + - else + .alert.alert-danger + %h4 该对比的修改过大. + %p 为保证性能修改的行未显示. + +:javascript + $('.assign-to-me-link').on('click', function(e){ + $('#merge_request_assignee_id').val("#{current_user.id}").trigger("change"); + e.preventDefault(); + }); + + window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}"; + +:javascript + var merge_request + merge_request = new MergeRequest({ + action: 'commits' + }); + diff --git a/app/views/projects/merge_requests/_show.zh.html.haml b/app/views/projects/merge_requests/_show.zh.html.haml new file mode 100644 index 00000000000..067da314bba --- /dev/null +++ b/app/views/projects/merge_requests/_show.zh.html.haml @@ -0,0 +1,77 @@ +.merge-request{'data-url' => merge_request_path(@merge_request)} + .merge-request-details + = render "projects/merge_requests/show/mr_title" + %hr + = render "projects/merge_requests/show/mr_box" + %hr + .append-bottom-20 + .slead + %span 从 + - if @merge_request.for_fork? + %strong.label-branch< + - if @merge_request.source_project + = link_to @merge_request.source_project_namespace, namespace_project_path(@merge_request.source_project.namespace, @merge_request.source_project) + - else + \ #{@merge_request.source_project_namespace} + \:#{@merge_request.source_branch} + %span 到 + %strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch} + - else + %strong.label-branch #{@merge_request.source_branch} + %span 到 + %strong.label-branch #{@merge_request.target_branch} + - if @merge_request.open? + %span.pull-right + .btn-group + %a.btn.dropdown-toggle{ data: {toggle: :dropdown} } + %i.fa.fa-download + 下载为 + %span.caret + %ul.dropdown-menu + %li= link_to "邮件补丁文件", merge_request_path(@merge_request, format: :patch) + %li= link_to "普通对比文件", merge_request_path(@merge_request, format: :diff) + + = render "projects/merge_requests/show/how_to_merge" + = render "projects/merge_requests/show/state_widget" + + - if @commits.present? + %ul.nav.nav-tabs.merge-request-tabs + %li.notes-tab{data: {action: 'notes'}} + = link_to merge_request_path(@merge_request) do + %i.fa.fa-comments + 讨论 + %span.badge= @merge_request.mr_and_commit_notes.count + %li.commits-tab{data: {action: 'commits'}} + = link_to merge_request_path(@merge_request), title: 'Commits' do + %i.fa.fa-history + 提交 + %span.badge= @commits.size + %li.diffs-tab{data: {action: 'diffs'}} + = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request) do + %i.fa.fa-list-alt + 修改 + %span.badge= @merge_request.diffs.size + + .notes.tab-content.voting_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" } + = render "projects/merge_requests/discussion" + .commits.tab-content + = render "projects/merge_requests/show/commits" + .diffs.tab-content + - if current_page?(action: 'diffs') + = render "projects/merge_requests/show/diffs" + + .mr-loading-status + = spinner + + +:javascript + var merge_request; + + merge_request = new MergeRequest({ + url_to_automerge_check: "#{automerge_check_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}", + check_enable: #{@merge_request.unchecked? ? "true" : "false"}, + url_to_ci_check: "#{ci_status_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}", + ci_enable: #{@project.ci_service ? "true" : "false"}, + current_status: "#{@merge_request.merge_status_name}", + action: "#{controller.action_name}" + }); diff --git a/app/views/projects/merge_requests/edit.zh.html.haml b/app/views/projects/merge_requests/edit.zh.html.haml new file mode 100644 index 00000000000..2285b08cf99 --- /dev/null +++ b/app/views/projects/merge_requests/edit.zh.html.haml @@ -0,0 +1,4 @@ +%h3.page-title + = "编辑合并请求 ##{@merge_request.iid}" +%hr += render 'form' diff --git a/app/views/projects/merge_requests/index.zh.html.haml b/app/views/projects/merge_requests/index.zh.html.haml new file mode 100644 index 00000000000..b0345109ff6 --- /dev/null +++ b/app/views/projects/merge_requests/index.zh.html.haml @@ -0,0 +1,11 @@ +.append-bottom-10 + .pull-right + = render 'shared/issuable_search_form', path: namespace_project_merge_requests_path(@project.namespace, @project) + + - if can? current_user, :write_merge_request, @project + = link_to new_namespace_project_merge_request_path(@project.namespace, @project), class: "btn btn-new pull-left", title: "新建合并请求" do + %i.fa.fa-plus + 新建合并请求 + = render 'shared/issuable_filter' +.merge-requests-holder + = render 'merge_requests' diff --git a/app/views/projects/merge_requests/invalid.zh.html.haml b/app/views/projects/merge_requests/invalid.zh.html.haml new file mode 100644 index 00000000000..511333ddaad --- /dev/null +++ b/app/views/projects/merge_requests/invalid.zh.html.haml @@ -0,0 +1,23 @@ +.merge-request + = render "projects/merge_requests/show/mr_title" + = render "projects/merge_requests/show/mr_box" + + .alert.alert-danger + %p + 我们不能正常显示该合并请求因为 + - if @merge_request.for_fork? && !@merge_request.source_project + fork的项目已经被删除 + - elsif !@merge_request.source_branch_exists? + %span.label.label-inverse= @merge_request.source_branch + 不存在于 + %span.label.label-info= @merge_request.source_project_path + - elsif !@merge_request.target_branch_exists? + %span.label.label-inverse= @merge_request.target_branch + 不存在于 + %span.label.label-info= @merge_request.target_project_path + - else + 内部错误 + + %strong + 请关闭合并请求或改成已有的分支 + diff --git a/app/views/projects/milestones/_form.zh.html.haml b/app/views/projects/milestones/_form.zh.html.haml new file mode 100644 index 00000000000..56147cf2367 --- /dev/null +++ b/app/views/projects/milestones/_form.zh.html.haml @@ -0,0 +1,54 @@ +%h3.page-title= @milestone.new_record? ? "新建里程碑" : "编辑里程碑 ##{@milestone.iid}" +.back-link + = link_to namespace_project_milestones_path(@project.namespace, @project) do + ← 前往里程碑列表 + +%hr + += form_for [@project.namespace.becomes(Namespace), @project, @milestone], html: {class: 'form-horizontal milestone-form gfm-form'} do |f| + -if @milestone.errors.any? + .alert.alert-danger + %ul + - @milestone.errors.full_messages.each do |msg| + %li= msg + .row + .col-md-6 + .form-group + = f.label :title, "标题", class: "control-label" + .col-sm-10 + = f.text_field :title, maxlength: 255, class: "form-control" + %p.hint 必填 + .form-group.milestone-description + = f.label :description, "描述", class: "control-label" + .col-sm-10 + = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do + = render 'projects/zen', f: f, attr: :description, classes: 'description form-control' + .hint + .pull-left 使用 #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'} 解析里程碑. + .pull-left 拖放文件或 #{link_to "选择文件", '#', class: 'markdown-selector' } 添加附件. + .clearfix + .error-alert + .col-md-6 + .form-group + = f.label :due_date, "到期日期", class: "control-label" + .col-sm-10= f.hidden_field :due_date + .col-sm-10 + .datepicker + + .form-actions + - if @milestone.new_record? + = f.submit '创建里程碑', class: "btn-create btn" + = link_to "取消", namespace_project_milestones_path(@project.namespace, @project), class: "btn btn-cancel" + -else + = f.submit '保存修改', class: "btn-save btn" + = link_to "取消", namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-cancel" + + +:javascript + disableButtonIfEmptyField("#milestone_title", ".btn-save"); + $( ".datepicker" ).datepicker({ + dateFormat: "yy-mm-dd", + onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) } + }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val())); + + window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}"; diff --git a/app/views/projects/milestones/_issues.zh.html.haml b/app/views/projects/milestones/_issues.zh.html.haml new file mode 100644 index 00000000000..1f2a8e6adb0 --- /dev/null +++ b/app/views/projects/milestones/_issues.zh.html.haml @@ -0,0 +1,6 @@ +.panel.panel-default + .panel-heading= title + %ul{ class: "well-list issues-sortable-list", id: "issues-list-#{id}", "data-state" => id } + - issues.sort_by(&:position).each do |issue| + = render 'issue', issue: issue + %li.light.ui-sort-disabled 拖放可用 diff --git a/app/views/projects/milestones/_merge_requests.zh.html.haml b/app/views/projects/milestones/_merge_requests.zh.html.haml new file mode 100644 index 00000000000..ad8ef8ccdce --- /dev/null +++ b/app/views/projects/milestones/_merge_requests.zh.html.haml @@ -0,0 +1,6 @@ +.panel.panel-default + .panel-heading= title + %ul{ class: "well-list merge_requests-sortable-list", id: "merge_requests-list-#{id}", "data-state" => id } + - merge_requests.sort_by(&:position).each do |merge_request| + = render 'merge_request', merge_request: merge_request + %li.light.ui-sort-disabled 拖放可用 diff --git a/app/views/projects/milestones/_milestone.zh.html.haml b/app/views/projects/milestones/_milestone.zh.html.haml new file mode 100644 index 00000000000..7dc16b7c9c0 --- /dev/null +++ b/app/views/projects/milestones/_milestone.zh.html.haml @@ -0,0 +1,26 @@ +%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone) } + .pull-right + - if can?(current_user, :admin_milestone, milestone.project) and milestone.active? + = link_to edit_namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), class: "btn btn-sm edit-milestone-link btn-grouped" do + %i.fa.fa-pencil-square-o + Edit + = link_to '关闭里程碑', namespace_project_milestone_path(@project.namespace, @project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-sm btn-close" + %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? + %span.cred (已过期) + %small + = milestone.expires_at + - if milestone.is_empty? + %span.muted 空 + - else + %div + %div + = link_to namespace_project_issues_path(milestone.project.namespace, milestone.project, milestone_id: milestone.id) do + = pluralize milestone.issues.count, 'Issue' +   + = link_to namespace_project_merge_requests_path(milestone.project.namespace, milestone.project, milestone_id: milestone.id) do + = pluralize milestone.merge_requests.count, 'Merge Request' +   + %span.light 已完成 #{milestone.percent_complete}% + = milestone_progress_bar(milestone) diff --git a/app/views/projects/milestones/index.zh.html.haml b/app/views/projects/milestones/index.zh.html.haml new file mode 100644 index 00000000000..414c151d387 --- /dev/null +++ b/app/views/projects/milestones/index.zh.html.haml @@ -0,0 +1,17 @@ +.pull-right + - if can? current_user, :admin_milestone, @project + = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "pull-right btn btn-new", title: "新建里程碑" do + %i.fa.fa-plus + 新建里程碑 += render 'shared/milestones_filter' + +.milestones + .panel.panel-default + %ul.well-list + = render @milestones + + - if @milestones.blank? + %li + .nothing-here-block 无里程碑可显示 + + = paginate @milestones, theme: "gitlab" diff --git a/app/views/projects/milestones/show.zh.html.haml b/app/views/projects/milestones/show.zh.html.haml new file mode 100644 index 00000000000..a8cc1da949b --- /dev/null +++ b/app/views/projects/milestones/show.zh.html.haml @@ -0,0 +1,103 @@ +%h4.page-title + .issue-box{ class: issue_box_class(@milestone) } + - if @milestone.closed? + 已关闭 + - elsif @milestone.expired? + 已过期 + - else + 打开状态 + 里程碑 ##{@milestone.iid} + %small.creator + = @milestone.expires_at + .pull-right + - if can?(current_user, :admin_milestone, @project) + = link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped" do + %i.fa.fa-pencil-square-o + 编辑 + - if @milestone.active? + = link_to '关闭里程碑', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped" + - else + = link_to '重新打开里程碑', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped" + +%hr +- if @milestone.issues.any? && @milestone.can_be_closed? + .alert.alert-success + %span 该里程碑析所有问题已经是关闭状态. 您现在可以关闭里程碑. + +%h3.issue-title + = gfm escape_once(@milestone.title) +%div + - if @milestone.description.present? + .description + .wiki + = preserve do + = markdown @milestone.description + +%hr +.context + %p.lead + 进度: + #{@milestone.closed_items_count} 已关闭 + – + #{@milestone.open_items_count} 打开状态 +   + %span.light 已完成 #{@milestone.percent_complete}% + %span.pull-right= @milestone.expires_at + = milestone_progress_bar(@milestone) + + +%ul.nav.nav-tabs + %li.active + = link_to '#tab-issues', 'data-toggle' => 'tab' do + 问题 + %span.badge= @issues.count + %li + = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do + 合并请求 + %span.badge= @merge_requests.count + %li + = link_to '#tab-participants', 'data-toggle' => 'tab' do + 参与者 + %span.badge= @users.count + + - if @project.issues_enabled + .pull-right + = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { milestone_id: @milestone.id }), class: "btn btn-grouped", title: "新建问题" do + %i.fa.fa-plus + 新建问题 + = link_to '浏览问题', namespace_project_issues_path(@milestone.project.namespace, @milestone.project, milestone_id: @milestone.id), class: "btn edit-milestone-link btn-grouped" + +.tab-content + .tab-pane.active#tab-issues + .row + .col-md-4 + = render('issues', title: '未开始的问题(打开状态且未指定人)', issues: @issues.opened.unassigned, id: 'unassigned') + .col-md-4 + = render('issues', title: '进行中的问题(打开状态并已指定人)', issues: @issues.opened.assigned, id: 'ongoing') + .col-md-4 + = render('issues', title: '完成的问题(已关闭)', issues: @issues.closed, id: 'closed') + + .tab-pane#tab-merge-requests + .row + .col-md-3 + = render('merge_requests', title: '进行中的(打开状态并已指定人)', merge_requests: @merge_requests.opened.unassigned, id: 'unassigned') + .col-md-3 + = render('merge_requests', title: '待合并(打开状态且已指定)', merge_requests: @merge_requests.opened.assigned, id: 'ongoing') + .col-md-3 + = render('merge_requests', title: '被拒绝(已关闭)', merge_requests: @merge_requests.declined, id: 'closed') + .col-md-3 + .panel.panel-primary + .panel-heading 已合并 + %ul.well-list + - @merge_requests.merged.each do |merge_request| + = render 'merge_request', merge_request: merge_request + + .tab-pane#tab-participants + %ul.bordered-list + - @users.each do |user| + %li + = link_to user, title: user.name, class: "darken" do + = image_tag avatar_icon(user.email, 32), class: "avatar s32" + %strong= truncate(user.name, lenght: 40) + %br + %small.cgray= user.username diff --git a/app/views/projects/network/_head.zh.html.haml b/app/views/projects/network/_head.zh.html.haml new file mode 100644 index 00000000000..51396092e48 --- /dev/null +++ b/app/views/projects/network/_head.zh.html.haml @@ -0,0 +1,3 @@ +.append-bottom-20 + = render partial: 'shared/ref_switcher', locals: {destination: 'graph'} + .pull-right.visible-lg.light 您可以使用方向键移动图. diff --git a/app/views/projects/network/show.zh.html.haml b/app/views/projects/network/show.zh.html.haml new file mode 100644 index 00000000000..04403edcd58 --- /dev/null +++ b/app/views/projects/network/show.zh.html.haml @@ -0,0 +1,26 @@ += render "head" +.project-network + .controls + = form_tag namespace_project_network_path(@project.namespace, @project, @id), method: :get, class: 'form-inline network-form' do |f| + = text_field_tag :extended_sha1, @options[:extended_sha1], placeholder: "输入完整的SHA1", class: 'search-input form-control input-mx-250 search-sha' + = button_tag class: 'btn btn-success btn-search-sha' do + %i.fa.fa-search + .inline.prepend-left-20 + .checkbox.light + = label_tag :filter_ref do + = check_box_tag :filter_ref, 1, @options[:filter_ref] + %span 以选择的提交作为开始 + + .network-graph + = spinner nil, true + +:javascript + disableButtonIfEmptyField('#extended_sha1', '.btn-search-sha') + + network_graph = new Network({ + url: '#{namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json))}', + commit_url: '#{namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s")}', + ref: '#{@ref}', + commit_id: '#{@commit.id}' + }) + new ShortcutsNetwork(network_graph.branch_graph) diff --git a/app/views/projects/new.zh.html.haml b/app/views/projects/new.zh.html.haml new file mode 100644 index 00000000000..3c119f33ddd --- /dev/null +++ b/app/views/projects/new.zh.html.haml @@ -0,0 +1,119 @@ +.project-edit-container + .project-edit-errors + = render 'projects/errors' + .project-edit-content + + = form_for @project, html: { class: 'new_project form-horizontal' } do |f| + .form-group.project-name-holder + = f.label :path, class: 'control-label' do + %strong 项目路径 + .col-sm-10 + .input-group + = f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 1, autofocus: true + .input-group-addon + \.git + + - if current_user.can_select_namespace? + .form-group + = f.label :namespace_id, class: 'control-label' do + %span 命名空间 + .col-sm-10 + = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'select2', tabindex: 2} + + %hr + + .project-import.js-toggle-container + .form-group + %label.control-label 导入的项目来自于 + .col-sm-10 + - if github_import_enabled? + = link_to status_import_github_path, class: 'btn' do + %i.fa.fa-github + GitHub + - else + = link_to '#', class: 'how_to_import_link light btn' do + %i.fa.fa-github + GitHub + = render 'github_import_modal' + + + - if bitbucket_import_enabled? + = link_to status_import_bitbucket_path, class: 'btn' do + %i.fa.fa-bitbucket + Bitbucket + - else + = link_to '#', class: 'how_to_import_link light btn' do + %i.fa.fa-bitbucket + Bitbucket + = render 'bitbucket_import_modal' + + - unless request.host == 'gitlab.com' + - if gitlab_import_enabled? + = link_to status_import_gitlab_path, class: 'btn' do + %i.fa.fa-heart + GitLab.com + - else + = link_to '#', class: 'how_to_import_link light btn' do + %i.fa.fa-heart + GitLab.com + = render 'gitlab_import_modal' + + = link_to new_import_gitorious_path, class: 'btn' do + %i.icon-gitorious.icon-gitorious-small + Gitorious.org + + = link_to "#", class: 'btn js-toggle-button' do + %i.fa.fa-git + %span 可通过URL访问的任意仓库 + + .js-toggle-content.hide + .form-group.import-url-data + = f.label :import_url, class: 'control-label' do + %span Git仓库的URL地址 + .col-sm-10 + = f.text_field :import_url, class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git' + .alert.alert-info.prepend-top-10 + %ul + %li + 仓库必须通过HTTP(S)可以访问. 如果公众不可访问, 您可以添加认证信息到URL中: https://username:password@gitlab.company.com/group/project.git. + %li + The import will time out after 4 minutes. For big repositories, use a clone/push combination. + 导入超过4分钟将作超时处理. 大的仓库请使用clone/push(克隆/推送)相组合的方法处理. + %li + 如果要迁移SVN仓库, 查看 + #{link_to "此文档", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}. + + %hr.prepend-botton-10 + + .form-group + = f.label :description, class: 'control-label' do + 描述 + %span.light (可选) + .col-sm-10 + = f.text_area :description, placeholder: "超酷的项目", class: "form-control", rows: 3, maxlength: 250, tabindex: 3 + = render "visibility_level", f: f, visibility_level: gitlab_config.default_projects_features.visibility_level, can_change_visibility_level: true + + .form-actions + = f.submit '创建项目', class: "btn btn-create project-submit", tabindex: 4 + + - if current_user.can_create_group? + .pull-right + .light + 需要为多个依赖的项目创建组? + = link_to new_group_path, class: "btn btn-xs" do + 创建组 + +.save-project-loader.hide + .center + %h2 + %i.fa.fa-spinner.fa-spin + 创建项目和仓库. + %p 请稍候, 此页面将在完成后自动刷新. + +:coffeescript + $ -> + $('.how_to_import_link').bind 'click', (e) -> + e.preventDefault() + import_modal = $(this).parent().find(".modal").show() + $('.modal-header .close').bind 'click', -> + $(".modal").hide() diff --git a/app/views/projects/no_repo.zh.html.haml b/app/views/projects/no_repo.zh.html.haml new file mode 100644 index 00000000000..baac6331103 --- /dev/null +++ b/app/views/projects/no_repo.zh.html.haml @@ -0,0 +1,22 @@ +%h2 + %i.fa.fa-warning + 无仓库 + +%p.slead + 该项目的仓库不存在. + %br + 这意味着只有当您创建了一个空仓库或导入一个已有仓库后你才能推送代码. +%hr + +.no-repo-actions + = link_to namespace_project_repository_path(@project.namespace, @project), method: :post, class: 'btn btn-primary' do + 创建空的纯净(--bare)仓库 + + %strong.prepend-left-10.append-right-10 or + + = link_to new_namespace_project_import_path(@project.namespace, @project), class: 'btn' do + 导入仓库 + +- if can? current_user, :remove_project, @project + .prepend-top-20 + = link_to '删除项目', project_path(@project), data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right" diff --git a/app/views/projects/notes/_edit_form.zh.html.haml b/app/views/projects/notes/_edit_form.zh.html.haml new file mode 100644 index 00000000000..b9a571c9c46 --- /dev/null +++ b/app/views/projects/notes/_edit_form.zh.html.haml @@ -0,0 +1,15 @@ +.note-edit-form + = form_for note, url: namespace_project_note_path(@project.namespace, @project, note), method: :put, remote: true, authenticity_token: true do |f| + = note_target_fields(note) + = render layout: 'projects/md_preview', locals: { preview_class: "note-text" } do + = render 'projects/zen', f: f, attr: :note, + classes: 'note_text js-note-text' + + .comment-hints.clearfix + .pull-left 讨论内容通过 #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }} 解析 + .pull-right 拖放文件或 #{link_to "选择文件", '#', class: 'markdown-selector', tabindex: -1 }添加附件. + + .note-form-actions + .buttons + = f.submit '保存讨论', class: "btn btn-primary btn-save btn-grouped js-comment-button" + = link_to '取消', "#", class: "btn btn-cancel note-edit-cancel" \ No newline at end of file diff --git a/app/views/projects/notes/_form.zh.html.haml b/app/views/projects/notes/_form.zh.html.haml new file mode 100644 index 00000000000..48b83c6d699 --- /dev/null +++ b/app/views/projects/notes/_form.zh.html.haml @@ -0,0 +1,24 @@ += form_for [@project.namespace.becomes(Namespace), @project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new_note js-new-note-form common-note-form gfm-form" }, authenticity_token: true do |f| + = note_target_fields(@note) + = f.hidden_field :commit_id + = f.hidden_field :line_code + = f.hidden_field :noteable_id + = f.hidden_field :noteable_type + + = render layout: 'projects/md_preview', locals: { preview_class: "note-text" } do + = render 'projects/zen', f: f, attr: :note, + classes: 'note_text js-note-text' + + .comment-hints.clearfix + .pull-left 评论内容通过 #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }} 解析 + .pull-right 拖放文件或 #{link_to "选择文件", '#', class: 'markdown-selector', tabindex: -1 } 添加附件. + + + .note-form-actions + .buttons + = f.submit '添加附件', class: "btn comment-btn btn-grouped js-comment-button" + = yield(:note_actions) + %a.btn.grouped.js-close-discussion-note-form Cancel + +:javascript + window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}"; diff --git a/app/views/projects/notes/_note.zh.html.haml b/app/views/projects/notes/_note.zh.html.haml new file mode 100644 index 00000000000..27b9823d4f9 --- /dev/null +++ b/app/views/projects/notes/_note.zh.html.haml @@ -0,0 +1,69 @@ +%li.timeline-entry{ id: dom_id(note), class: [dom_class(note), "note-row-#{note.id}", ('system-note' if note.system)], data: { discussion: note.discussion_id } } + .timeline-entry-inner + .timeline-icon + - if note.system + %span.fa.fa-circle + - else + = image_tag avatar_icon(note.author_email), class: "avatar s40" + .timeline-content + .note-header + .note-actions + = link_to "##{dom_id(note)}", name: dom_id(note) do + %i.fa.fa-link + 链接到这里 +   + - if can?(current_user, :admin_note, note) && note.editable? + = link_to "#", title: "Edit comment", class: "js-note-edit" do + %i.fa.fa-pencil-square-o + 编辑 +   + = link_to namespace_project_note_path(@project.namespace, @project, note), title: "删除评论", method: :delete, data: { confirm: '您确定要删除此评论?' }, remote: true, class: "danger js-note-delete" do + %i.fa.fa-trash-o.cred + Remove + - if note.system + = image_tag avatar_icon(note.author_email), class: "avatar s16" + = link_to_member(@project, note.author, avatar: false) + %span.author-username + = '@' + note.author.username + %span.note-last-update + = note_timestamp(note) + + - if note.superceded?(@notes) + - if note.upvote? + %span.vote.upvote.label.label-gray.strikethrough + %i.fa.fa-thumbs-up + \+1 + - if note.downvote? + %span.vote.downvote.label.label-gray.strikethrough + %i.fa.fa-thumbs-down + \-1 + - else + - if note.upvote? + %span.vote.upvote.label.label-success + %i.fa.fa-thumbs-up + \+1 + - if note.downvote? + %span.vote.downvote.label.label-danger + %i.fa.fa-thumbs-down + \-1 + + + .note-body + .note-text + = preserve do + = markdown(note.note, {no_header_anchors: true}) + = render 'projects/notes/edit_form', note: note + + - if note.attachment.url + .note-attachment + - if note.attachment.image? + = link_to note.attachment.url, target: '_blank' do + = image_tag note.attachment.url, class: 'note-image-attach' + .attachment + = link_to note.attachment.url, target: "_blank" do + %i.fa.fa-paperclip + = note.attachment_identifier + = link_to delete_attachment_namespace_project_note_path(@project.namespace, @project, note), + title: "删除此附件", method: :delete, remote: true, data: { confirm: '您确定要删除此附件?' }, class: "danger js-note-attachment-delete" do + %i.fa.fa-trash-o.cred + .clear diff --git a/app/views/projects/notes/discussions/_active.zh.html.haml b/app/views/projects/notes/discussions/_active.zh.html.haml new file mode 100644 index 00000000000..67cef7f4ac8 --- /dev/null +++ b/app/views/projects/notes/discussions/_active.zh.html.haml @@ -0,0 +1,21 @@ +- note = discussion_notes.first +.discussion.js-toggle-container{ class: note.discussion_id } + .discussion-header + .discussion-actions + = link_to "#", class: "js-toggle-button" do + %i.fa.fa-chevron-up + 显示/隐藏 讨论 + %div + = link_to_member(@project, note.author, avatar: false) + started a discussion + 发起一场讨论 + = link_to diffs_namespace_project_merge_request_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code) do + %strong 对比 + .last-update.hide.js-toggle-content + - last_note = discussion_notes.last + 最新更新 + = link_to_member(@project, last_note.author, avatar: false) + %span.discussion-last-update + #{time_ago_with_tooltip(last_note.updated_at, 'bottom', 'discussion_updated_ago')} + .discussion-body.js-toggle-content + = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note diff --git a/app/views/projects/notes/discussions/_commit.zh.html.haml b/app/views/projects/notes/discussions/_commit.zh.html.haml new file mode 100644 index 00000000000..79b4632f7ef --- /dev/null +++ b/app/views/projects/notes/discussions/_commit.zh.html.haml @@ -0,0 +1,27 @@ +- note = discussion_notes.first +.discussion.js-toggle-container{ class: note.discussion_id } + .discussion-header + .discussion-actions + = link_to "#", class: "js-toggle-button" do + %i.fa.fa-chevron-up + 显示/隐藏讨论 + %div + = link_to_member(@project, note.author, avatar: false) + 发起一场关于提交的讨论 + = link_to(note.noteable.short_id, namespace_project_commit_path(note.project.namespace, note.project, note.noteable), class: 'monospace') + .last-update.hide.js-toggle-content + - last_note = discussion_notes.last + 最新更新 + = link_to_member(@project, last_note.author, avatar: false) + %span.discussion-last-update + #{time_ago_with_tooltip(last_note.updated_at, 'bottom', 'discussion_updated_ago')} + .discussion-body.js-toggle-content + - if note.for_diff_line? + = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note + - else + .panel.panel-default + .notes{ rel: discussion_notes.first.discussion_id } + = render discussion_notes + .discussion-reply-holder + = link_to_reply_diff(discussion_notes.first) + diff --git a/app/views/projects/notes/discussions/_outdated.zh.html.haml b/app/views/projects/notes/discussions/_outdated.zh.html.haml new file mode 100644 index 00000000000..f863913e81d --- /dev/null +++ b/app/views/projects/notes/discussions/_outdated.zh.html.haml @@ -0,0 +1,18 @@ +- note = discussion_notes.first +.discussion.js-toggle-container{ class: note.discussion_id } + .discussion-header + .discussion-actions + = link_to "#", class: "js-toggle-button" do + %i.fa.fa-chevron-down + 显示/隐藏讨论 + %div + = link_to_member(@project, note.author, avatar: false) + 发起一场关于 %strong 过期的对比 的讨论 + %div + - last_note = discussion_notes.last + 最新更新 + = link_to_member(@project, last_note.author, avatar: false) + %span.discussion-last-update + #{time_ago_with_tooltip(last_note.updated_at, 'bottom', 'discussion_updated_ago')} + .discussion-body.js-toggle-content.hide + = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note diff --git a/app/views/projects/project_members/_group_members.zh.html.haml b/app/views/projects/project_members/_group_members.zh.html.haml new file mode 100644 index 00000000000..59f4d47dc4d --- /dev/null +++ b/app/views/projects/project_members/_group_members.zh.html.haml @@ -0,0 +1,16 @@ +.panel.panel-default + .panel-heading + %strong #{@group.name} + 组成员 + %small + (#{members.count}) + .panel-head-actions + = link_to group_group_members_path(@group), class: 'btn btn-sm' do + %i.fa.fa-pencil-square-o + 编辑组成员 + %ul.well-list + - members.each do |member| + = render 'groups/group_members/group_member', member: member, show_controls: false + - if members.count > 20 + %li + 组成员数还有 #{members.count - 20} 个. 访问 #{link_to '组成员页面', group_group_members_path(@group)} 查看完整的列表 diff --git a/app/views/projects/project_members/_new_project_member.zh.html.haml b/app/views/projects/project_members/_new_project_member.zh.html.haml new file mode 100644 index 00000000000..3b1b629e8c4 --- /dev/null +++ b/app/views/projects/project_members/_new_project_member.zh.html.haml @@ -0,0 +1,16 @@ += form_for @project_member, as: :project_member, url: namespace_project_project_members_path(@project.namespace, @project), html: { class: 'form-horizontal users-project-form' } do |f| + .form-group + = f.label :user_ids, "People", class: 'control-label' + .col-sm-10= users_select_tag(:user_ids, multiple: true, class: 'input-large') + + .form-group + = f.label :access_level, "项目访问控制", class: 'control-label' + .col-sm-10 + = select_tag :access_level, options_for_select(ProjectMember.access_roles, @project_member.access_level), class: "project-access-select select2" + .help-block + 点 + %strong= link_to "此", help_page_path("permissions", "permissions"), class: "vlink" + 阅读更多关于角色权限的信息 + + .form-actions + = f.submit '添加用户到项目', class: "btn btn-create" diff --git a/app/views/projects/project_members/_project_member.zh.html.haml b/app/views/projects/project_members/_project_member.zh.html.haml new file mode 100644 index 00000000000..0f8880437e1 --- /dev/null +++ b/app/views/projects/project_members/_project_member.zh.html.haml @@ -0,0 +1,35 @@ +- user = member.user +- return unless user + +%li{class: "#{dom_class(member)} js-toggle-container project_member_row access-#{member.human_access.downcase}", id: dom_id(member)} + %span.list-item-name + = image_tag avatar_icon(user.email, 16), class: "avatar s16" + %strong= user.name + %span.cgray= user.username + - if user == current_user + %span.label.label-success It's you + - if user.blocked? + %label.label.label-danger + %strong 被屏蔽 + + - if current_user_can_admin_project + - unless @project.personal? && user == current_user + .pull-right + %strong= member.human_access + = button_tag class: "btn-xs btn js-toggle-button", + title: '编辑访问限制等级', type: 'button' do + %i.fa.fa-pencil-square-o + +   + - if current_user == user + = link_to leave_namespace_project_project_members_path(@project.namespace, @project), data: { confirm: "您确认要离开?"}, method: :delete, class: "btn-xs btn btn-remove", title: '离开项目' do + %i.fa.fa-minus.fa-inverse + - else + = link_to namespace_project_project_member_path(@project.namespace, @project, user), data: { confirm: remove_from_project_team_message(@project, user) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: '从团队中删除用户' do + %i.fa.fa-minus.fa-inverse + + .edit-member.hide.js-toggle-content + = form_for member, as: :project_member, url: namespace_project_project_member_path(@project.namespace, @project, member.user), remote: true do |f| + .alert.prepend-top-20 + = f.select :access_level, options_for_select(ProjectMember.access_roles, member.access_level) + = f.submit '保存', class: 'btn btn-save btn-sm' diff --git a/app/views/projects/project_members/_team.zh.html.haml b/app/views/projects/project_members/_team.zh.html.haml new file mode 100644 index 00000000000..bc5ac735f3c --- /dev/null +++ b/app/views/projects/project_members/_team.zh.html.haml @@ -0,0 +1,11 @@ +- can_admin_project = can?(current_user, :admin_project, @project) + +.panel.panel-default.prepend-top-20 + .panel-heading + %strong #{@project.name} + 项目成员 + %small + (#{members.count}) + %ul.well-list + - members.each do |project_member| + = render 'project_member', member: project_member, current_user_can_admin_project: can_admin_project diff --git a/app/views/projects/project_members/import.zh.html.haml b/app/views/projects/project_members/import.zh.html.haml new file mode 100644 index 00000000000..1092b77acd5 --- /dev/null +++ b/app/views/projects/project_members/import.zh.html.haml @@ -0,0 +1,14 @@ +%h3.page-title + 从其它项目导入成员 +%p.light + 只有项目成员会被导入. 组成员会跳过. +%hr += form_tag apply_import_namespace_project_project_members_path(@project.namespace, @project), method: 'post', class: 'form-horizontal' do + .form-group + = label_tag :source_project_id, "项目", class: 'control-label' + .col-sm-10= select_tag(:source_project_id, options_from_collection_for_select(current_user.authorized_projects, :id, :name_with_namespace), prompt: "选择项目", class: "select2 lg", required: true) + + .form-actions + = button_tag '导入项目成员', class: "btn btn-create" + = link_to "取消", namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-cancel" + diff --git a/app/views/projects/project_members/index.zh.html.haml b/app/views/projects/project_members/index.zh.html.haml new file mode 100644 index 00000000000..f2fcaa5aff3 --- /dev/null +++ b/app/views/projects/project_members/index.zh.html.haml @@ -0,0 +1,36 @@ +%h3.page-title + 有权限访问此项目的用户 + +%p.light + 点 + %strong= link_to "此", help_page_path("permissions", "permissions"), class: "vlink" + 查看更多关于项目权限的信息 + +%hr + +.clearfix.js-toggle-container + = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do + .form-group + = search_field_tag :search, params[:search], { placeholder: '按名字查找已有成员', class: 'form-control search-text-input input-mn-300' } + = button_tag '搜索', class: 'btn' + + - if can?(current_user, :admin_project_member, @project) + %span.pull-right + = button_tag class: 'btn btn-new btn-grouped js-toggle-button', type: 'button' do + 添加成员 + %i.fa.fa-chevron-down + = link_to import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-grouped", title: "从其它项目导入成员" do + 导入成员 + + .js-toggle-content.hide.new-group-member-holder + = render "new_project_member" + += render "team", members: @project_members + +- if @group + = render "group_members", members: @group_members + +:coffeescript + $('form.member-search-form').on 'submit', (event) -> + event.preventDefault() + Turbolinks.visit @.action + '?' + $(@).serialize() diff --git a/app/views/projects/protected_branches/_branches_list.zh.html.haml b/app/views/projects/protected_branches/_branches_list.zh.html.haml new file mode 100644 index 00000000000..c293f941861 --- /dev/null +++ b/app/views/projects/protected_branches/_branches_list.zh.html.haml @@ -0,0 +1,34 @@ +- unless @branches.empty? + %br + %h4 已经受保护: + %table.table.protected-branches-list + %thead + %tr.no-border + %th 分支 + %th 开发人员可以推送 + %th 最新提交 + %th + + %tbody + - @branches.each do |branch| + - @url = namespace_project_protected_branch_path(@project.namespace, @project, branch) + %tr + %td + = link_to namespace_project_commits_path(@project.namespace, @project, branch.name) do + %strong= branch.name + - if @project.root_ref?(branch.name) + %span.label.label-info 默认 + %td + = check_box_tag "developers_can_push", branch.id, branch.developers_can_push, "data-url" => @url + %td + - if commit = branch.commit + = link_to namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id' do + = commit.short_id + · + #{time_ago_with_tooltip(commit.committed_date)} + - else + (分支已经从项目中删除) + %td + .pull-right + - if can? current_user, :admin_project, @project + = link_to '取消保护', [@project.namespace.becomes(Namespace), @project, branch], data: { confirm: '开发人员将可以写分支. 您确定?' }, method: :delete, class: "btn btn-remove btn-sm" diff --git a/app/views/projects/protected_branches/index.zh.html.haml b/app/views/projects/protected_branches/index.zh.html.haml new file mode 100644 index 00000000000..d5b95844964 --- /dev/null +++ b/app/views/projects/protected_branches/index.zh.html.haml @@ -0,0 +1,35 @@ +%h3.page-title 受保护的分支 +%p.light 让稳定分支保持安全状态, 强制开发人员使用合并请求 +%hr + +.alert.alert-info + %p 受保护的分支设计用于 + %ul + %li 阻止除 #{link_to "masters", help_page_path("permissions", "permissions"), class: "vlink"} 外的任何人推送 + %li 阻止所有人强制推送到分支 + %li 阻止所有人删除分支 + %p 阅读更多关于 #{link_to "项目权限", help_page_path("permissions", "permissions"), class: "underlined-link"} 的信息 + +- if can? current_user, :admin_project, @project + = form_for [@project.namespace.becomes(Namespace), @project, @protected_branch], html: { class: 'form-horizontal' } do |f| + -if @protected_branch.errors.any? + .alert.alert-danger + %ul + - @protected_branch.errors.full_messages.each do |msg| + %li= msg + + .form-group + = f.label :name, "分支", class: 'control-label' + .col-sm-10 + = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "请选择分支"}, {class: "select2"}) + .form-group + = f.label :developers_can_push, class: 'control-label' do + 开发人员可以推送 + .col-sm-10 + .checkbox + = f.check_box :developers_can_push + %span.descr 允许开发人员推送到分支 + .form-actions + = f.submit '保护', class: "btn-create btn" += render 'branches_list' + diff --git a/app/views/projects/repositories/_download_archive.zh.html.haml b/app/views/projects/repositories/_download_archive.zh.html.haml new file mode 100644 index 00000000000..ff774326366 --- /dev/null +++ b/app/views/projects/repositories/_download_archive.zh.html.haml @@ -0,0 +1,37 @@ +- ref = ref || nil +- btn_class = btn_class || '' +- split_button = split_button || false +- if split_button == true + %span.btn-group{class: btn_class} + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn', rel: 'nofollow' do + %i.fa.fa-download + %span Download zip + %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } + %span.caret + %span.sr-only + 选择打包格式 + %ul.dropdown-menu{ role: 'menu' } + %li + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), rel: 'nofollow' do + %i.fa.fa-download + %span 下载zip包 + %li + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do + %i.fa.fa-download + %span 下载tar.gz包 + %li + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar.bz2'), rel: 'nofollow' do + %i.fa.fa-download + %span 下载tar.bz2包 + %li + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar'), rel: 'nofollow' do + %i.fa.fa-download + %span 下载tar包 +- else + %span.btn-group{class: btn_class} + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn', rel: 'nofollow' do + %i.fa.fa-download + %span zip + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar.gz'), class: 'btn', rel: 'nofollow' do + %i.fa.fa-download + %span tar.gz diff --git a/app/views/projects/repositories/_feed.zh.html.haml b/app/views/projects/repositories/_feed.zh.html.haml new file mode 100644 index 00000000000..b78768b1c1d --- /dev/null +++ b/app/views/projects/repositories/_feed.zh.html.haml @@ -0,0 +1,18 @@ +- commit = update +%tr + %td + = link_to namespace_project_commits_path(@project.namespace, @project, commit.head.name) do + %strong + = commit.head.name + - if @project.root_ref?(commit.head.name) + %span.label 默认 + + %td + %div + = link_to namespace_project_commits_path(@project.namespace, @project, commit.id) do + %code= commit.short_id + = image_tag avatar_icon(commit.author_email), class: "", width: 16, alt: '' + = gfm escape_once(truncate(commit.title, length: 40)) + %td + %span.pull-right.cgray + = time_ago_with_tooltip(commit.committed_date) diff --git a/app/views/projects/services/_form.zh.html.haml b/app/views/projects/services/_form.zh.html.haml new file mode 100644 index 00000000000..5d84ced3576 --- /dev/null +++ b/app/views/projects/services/_form.zh.html.haml @@ -0,0 +1,105 @@ +%h3.page-title + = @service.title + = boolean_to_icon @service.activated? + +%p= @service.description + +.back-link + = link_to namespace_project_services_path(@project.namespace, @project) do + ← 前往服务列表页 + +%hr + += form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |f| + - if @service.errors.any? + .alert.alert-danger + %ul + - @service.errors.full_messages.each do |msg| + %li= msg + + - if @service.help.present? + .alert.alert-info + = preserve do + = markdown @service.help + + .form-group + = f.label :active, "Active", class: "control-label" + .col-sm-10 + = f.check_box :active + + - if @service.supported_events.length > 1 + .form-group + = f.label :url, "Trigger", class: 'control-label' + .col-sm-10 + - if @service.supported_events.include?("push") + %div + = f.check_box :push_events, class: 'pull-left' + .prepend-left-20 + = f.label :push_events, class: 'list-label' do + %strong 推送事件 + %p.light + 此url会在推送到仓库的时候触发 + - if @service.supported_events.include?("tag_push") + %div + = f.check_box :tag_push_events, class: 'pull-left' + .prepend-left-20 + = f.label :tag_push_events, class: 'list-label' do + %strong 标签推送事件 + %p.light + 此url会在新标签推送到仓库的时候触发 + - if @service.supported_events.include?("note") + %div + = f.check_box :note_events, class: 'pull-left' + .prepend-left-20 + = f.label :note_events, class: 'list-label' do + %strong 评论 + %p.light + 此url会在添加评论的时候触发 + - if @service.supported_events.include?("issue") + %div + = f.check_box :issues_events, class: 'pull-left' + .prepend-left-20 + = f.label :issues_events, class: 'list-label' do + %strong 问题事件 + %p.light + 此url会在创建问题的时候触发 + - if @service.supported_events.include?("merge_request") + %div + = f.check_box :merge_requests_events, class: 'pull-left' + .prepend-left-20 + = f.label :merge_requests_events, class: 'list-label' do + %strong 合并请求事件 + %p.light + 此url会在创建合并请求的时候触发 + + - @service.fields.each do |field| + - name = field[:name] + - title = field[:title] || name.humanize + - value = service_field_value(field[:type], @service.send(name)) + - type = field[:type] + - placeholder = field[:placeholder] + - choices = field[:choices] + - default_choice = field[:default_choice] + - help = field[:help] + + .form-group + = f.label name, title, class: "control-label" + .col-sm-10 + - if type == 'text' + = f.text_field name, class: "form-control", placeholder: placeholder + - elsif type == 'textarea' + = f.text_area name, rows: 5, class: "form-control", placeholder: placeholder + - elsif type == 'checkbox' + = f.check_box name + - elsif type == 'select' + = f.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" } + - elsif type == 'password' + = f.password_field name, placeholder: value, class: 'form-control' + - if help + %span.help-block= help + + .form-actions + = f.submit '保存', class: 'btn btn-save' +   + - if @service.valid? && @service.activated? && @service.can_test? + = link_to '测试设置', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: 'btn' diff --git a/app/views/projects/services/index.zh.html.haml b/app/views/projects/services/index.zh.html.haml new file mode 100644 index 00000000000..5918523f1c8 --- /dev/null +++ b/app/views/projects/services/index.zh.html.haml @@ -0,0 +1,22 @@ +%h3.page-title 项目服务 +%p.light 项目服务允许您将GitLab与其它应用集成 + +%table.table + %thead + %tr + %th + %th 服务 + %th 描述 + %th 最后修改 + - @services.sort_by(&:title).each do |service| + %tr + %td + = boolean_to_icon service.activated? + %td + = link_to edit_namespace_project_service_path(@project.namespace, @project, service.to_param) do + %strong= service.title + %td + = service.description + %td.light + = time_ago_in_words service.updated_at + ago diff --git a/app/views/projects/show.zh.html.haml b/app/views/projects/show.zh.html.haml new file mode 100644 index 00000000000..95aa0d45411 --- /dev/null +++ b/app/views/projects/show.zh.html.haml @@ -0,0 +1,89 @@ +- if current_user && can?(current_user, :download_code, @project) + = render 'shared/no_ssh' + = render 'shared/no_password' + += render "home_panel" + +- readme = @repository.readme +%ul.nav.nav-tabs + %li.active + = link_to '#tab-activity', 'data-toggle' => 'tab' do + 活动 + - if readme + %li + = link_to '#tab-readme', 'data-toggle' => 'tab' do + Readme + .project-home-links + - unless @project.empty_repo? + = link_to pluralize(number_with_delimiter(@repository.commit_count), 'commit'), namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref) + = link_to pluralize(number_with_delimiter(@repository.branch_names.count), 'branch'), namespace_project_branches_path(@project.namespace, @project) + = link_to pluralize(number_with_delimiter(@repository.tag_names.count), 'tag'), namespace_project_tags_path(@project.namespace, @project) + %span.light.prepend-left-20= repository_size + +.tab-content + .tab-pane.active#tab-activity + .row + = link_to '#aside', class: 'show-aside' do + %i.fa.fa-angle-left + %section.col-md-9 + = render "events/event_last_push", event: @last_push + = render 'shared/event_filter' + .content_list + = spinner + %aside.col-md-3.project-side + .clearfix + - if @project.archived? + .alert.alert-warning + %h4 + %i.fa.fa-exclamation-triangle + 已打包的项目 + %p 仓库是只读状态 + + - if @project.forked_from_project + .well + %i.fa.fa-code-fork.project-fork-icon + Fork自: + %br + = link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project) + + - unless @project.empty_repo? + = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: @ref || @repository.root_ref), class: 'btn btn-block' do + 对比代码 + + - if @repository.version + - version = @repository.version + = link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, version.name)), class: 'btn btn-block' do + 版本: + %span.count + = @repository.blob_by_oid(version.id).data + + .prepend-top-10 + %p + %span.light 创建于 + #{@project.created_at.stamp('Aug 22, 2013')} + %p + %span.light 归属于 #{@project.group ? "the" : nil} + - if @project.group + #{link_to @project.group.name, @project.group} group + - else + #{link_to @project.owner_name, @project.owner} + + - @project.ci_services.each do |ci_service| + - if ci_service.active? && ci_service.respond_to?(:builds_path) + - 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" + - else + %span.light CI provided by + = link_to ci_service.title, ci_service.builds_path, :'data-no-turbolink' => 'data-no-turbolink' + + - if readme + .tab-pane#tab-readme + %article.readme-holder#README + = link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)) do + %h4.readme-file-title + %i.fa.fa-file + = readme.name + .wiki + = render_readme(readme) + diff --git a/app/views/projects/snippets/_snippet.zh.html.haml b/app/views/projects/snippets/_snippet.zh.html.haml new file mode 100644 index 00000000000..38024f2e582 --- /dev/null +++ b/app/views/projects/snippets/_snippet.zh.html.haml @@ -0,0 +1,15 @@ +%li + %h4.snippet-title + = link_to reliable_snippet_path(snippet) do + = truncate(snippet.title, length: 60) + %span.cgray.monospace.tiny.pull-right + = snippet.file_name + + .snippet-info + = "##{snippet.id}" + %span + 按 + = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16" + = snippet.author_name + %span.light + #{time_ago_with_tooltip(snippet.created_at)} diff --git a/app/views/projects/snippets/edit.zh.html.haml b/app/views/projects/snippets/edit.zh.html.haml new file mode 100644 index 00000000000..3d380a6d71d --- /dev/null +++ b/app/views/projects/snippets/edit.zh.html.haml @@ -0,0 +1,4 @@ +%h3.page-title + 编辑代码片段 +%hr += render "shared/snippets/form", url: namespace_project_snippet_path(@project.namespace, @project, @snippet) diff --git a/app/views/projects/snippets/index.zh.html.haml b/app/views/projects/snippets/index.zh.html.haml new file mode 100644 index 00000000000..5c9f73d5b04 --- /dev/null +++ b/app/views/projects/snippets/index.zh.html.haml @@ -0,0 +1,15 @@ +%h3.page-title + 代码片段 + - if can? current_user, :write_project_snippet, @project + = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new pull-right", title: "新建代码片段" do + 添加新的代码片段 + +%p.light + 在git仓库之外与其它人分享代码 + +%hr +%ul.bordered-list + = render partial: "projects/snippets/snippet", collection: @snippets + - if @snippets.empty? + %li + .nothing-here-block 这里什么也没有. diff --git a/app/views/projects/snippets/new.zh.html.haml b/app/views/projects/snippets/new.zh.html.haml new file mode 100644 index 00000000000..76050b53004 --- /dev/null +++ b/app/views/projects/snippets/new.zh.html.haml @@ -0,0 +1,4 @@ +%h3.page-title + 新建代码片段 +%hr += render "shared/snippets/form", url: namespace_project_snippets_path(@project.namespace, @project, @snippet) diff --git a/app/views/projects/snippets/show.zh.html.haml b/app/views/projects/snippets/show.zh.html.haml new file mode 100644 index 00000000000..de7455870b1 --- /dev/null +++ b/app/views/projects/snippets/show.zh.html.haml @@ -0,0 +1,37 @@ +%h3.page-title + = @snippet.title + + .pull-right + = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new", title: "新建代码片段" do + 添加新的代码片段 + +%hr + +.append-bottom-20 + .pull-right + = "##{@snippet.id}" + %span.light + 按 + = link_to user_path(@snippet.author) do + = image_tag avatar_icon(@snippet.author_email), class: "avatar avatar-inline s16" + = @snippet.author_name + + .back-link + = link_to namespace_project_snippets_path(@project.namespace, @project) do + ← 项目代码片段 + +.file-holder + .file-title + %i.fa.fa-file + %strong + = @snippet.file_name + .file-actions + .btn-group + - if can?(current_user, :modify_project_snippet, @snippet) + = link_to "编辑", edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", title: '编辑代码片段' + = link_to "raw", raw_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", target: "_blank" + - if can?(current_user, :admin_project_snippet, @snippet) + = link_to "删除", namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "您确定?" }, class: "btn btn-sm btn-remove", title: '删除代码片段' + = render 'shared/snippets/blob' + +%div#notes= render "projects/notes/notes_with_form" diff --git a/app/views/projects/tree/_spinner.zh.html.haml b/app/views/projects/tree/_spinner.zh.html.haml new file mode 100644 index 00000000000..310fab1e45b --- /dev/null +++ b/app/views/projects/tree/_spinner.zh.html.haml @@ -0,0 +1,3 @@ +%span.log_loading.hide + %i.fa.fa-spinner.fa-spin + 正在加载提交数据... diff --git a/app/views/projects/tree/_tree.zh.html.haml b/app/views/projects/tree/_tree.zh.html.haml new file mode 100644 index 00000000000..e2fe40aebd1 --- /dev/null +++ b/app/views/projects/tree/_tree.zh.html.haml @@ -0,0 +1,53 @@ +%ul.breadcrumb.repo-breadcrumb + %li + = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do + = @project.path + - tree_breadcrumbs(tree, 6) do |title, path| + %li + - if path + = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path) + - else + = link_to title, '#' + - if current_user && can_push_branch?(@project, @ref) + %li + = link_to namespace_project_new_blob_path(@project.namespace, @project, @id), title: 'New file', id: 'new-file-link' do + %small + %i.fa.fa-plus + +%div#tree-content-holder.tree-content-holder + %table#tree-slider{class: "table_#{@hex_path} tree-table" } + %thead + %tr + %th 名称 + %th 最近更新 + %th.hidden-xs + .pull-left 最近提交 + .last-commit.hidden-sm.pull-left +   + %i.fa.fa-angle-right +   + %small.light + = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit) + – + = truncate(@commit.title, length: 50) + = link_to '历史记录', namespace_project_commits_path(@project.namespace, @project, @id), class: 'pull-right' + + - if @path.present? + %tr.tree-item + %td.tree-item-file-name + = link_to "..", namespace_project_tree_path(@project.namespace, @project, up_dir_path), class: 'prepend-left-10' + %td + %td.hidden-xs + + = render_tree(tree) + + - if tree.readme + = render "projects/tree/readme", readme: tree.readme + +%div.tree_progress + +:javascript + // Load last commit log for each file in tree + $('#tree-slider').waitForImages(function() { + ajaxGet('#{@logs_path}'); + }); diff --git a/app/views/projects/wikis/_form.zh.html.haml b/app/views/projects/wikis/_form.zh.html.haml new file mode 100644 index 00000000000..b7ea5e4c89b --- /dev/null +++ b/app/views/projects/wikis/_form.zh.html.haml @@ -0,0 +1,46 @@ += form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal wiki-form gfm-form' } do |f| + -if @page.errors.any? + #error_explanation + .alert.alert-danger + - @page.errors.full_messages.each do |msg| + %p= msg + + = f.hidden_field :title, value: @page.title + .form-group + = f.label :format, class: 'control-label' + .col-sm-10 + = f.select :format, options_for_select(ProjectWiki::MARKUPS, {selected: @page.format}), {}, class: "form-control" + + .row + .col-sm-2 + .col-sm-10 + %p.cgray + 链接到(新)页面您可以输入 + %code [Link Title](page-slug) + \. + + .form-group.wiki-content + = f.label :content, class: 'control-label' + .col-sm-10 + = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do + = render 'projects/zen', f: f, attr: :content, classes: 'description form-control' + .col-sm-12.hint + .pull-left Wiki内容由 #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'} 解析 + .pull-right 拖放文件或 #{link_to "选择文件", '#', class: 'markdown-selector' } 添加附件. + + .clearfix + .error-alert + .form-group + = f.label :commit_message, class: 'control-label' + .col-sm-10= f.text_field :message, class: 'form-control', rows: 18 + + .form-actions + - if @page && @page.persisted? + = f.submit '保存修改', class: "btn-save btn" + = link_to "取消", namespace_project_wiki_path(@project.namespace, @project, @page), class: "btn btn-cancel" + - else + = f.submit '新建页面', class: "btn-create btn" + = link_to "取消", namespace_project_wiki_path(@project.namespace, @project, :home), class: "btn btn-cancel" + +:javascript + window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}"; diff --git a/app/views/projects/wikis/_main_links.zh.html.haml b/app/views/projects/wikis/_main_links.zh.html.haml new file mode 100644 index 00000000000..aa0a2e52e3f --- /dev/null +++ b/app/views/projects/wikis/_main_links.zh.html.haml @@ -0,0 +1,8 @@ +%span.pull-right + - if (@page && @page.persisted?) + = link_to history_namespace_project_wiki_path(@project.namespace, @project, @page), class: "btn btn-grouped" do + 页面历史 + - if can?(current_user, :write_wiki, @project) + = link_to edit_namespace_project_wiki_path(@project.namespace, @project, @page), class: "btn btn-grouped" do + %i.fa.fa-pencil-square-o + 编辑 diff --git a/app/views/projects/wikis/_nav.zh.html.haml b/app/views/projects/wikis/_nav.zh.html.haml new file mode 100644 index 00000000000..f9aa6c3fded --- /dev/null +++ b/app/views/projects/wikis/_nav.zh.html.haml @@ -0,0 +1,19 @@ +%ul.nav.nav-tabs + = nav_link(html_options: {class: params[:id] == 'home' ? 'active' : '' }) do + = link_to 'Home', namespace_project_wiki_path(@project.namespace, @project, :home) + + = nav_link(path: 'wikis#pages') do + = link_to 'Pages', pages_namespace_project_wikis_path(@project.namespace, @project) + + = nav_link(path: 'wikis#git_access') do + = link_to git_access_namespace_project_wikis_path(@project.namespace, @project) do + %i.fa.fa-download + Git访问控制 + + - if can?(current_user, :write_wiki, @project) + .pull-right + = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do + %i.fa.fa-plus + 新建页面 + += render 'projects/wikis/new' diff --git a/app/views/projects/wikis/_new.zh.html.haml b/app/views/projects/wikis/_new.zh.html.haml new file mode 100644 index 00000000000..d22d8da86d0 --- /dev/null +++ b/app/views/projects/wikis/_new.zh.html.haml @@ -0,0 +1,14 @@ +%div#modal-new-wiki.modal.hide + .modal-dialog + .modal-content + .modal-header + %a.close{href: "#", "data-dismiss" => "modal"} × + %h3.page-title 新建Wiki页面 + .modal-body + = label_tag :new_wiki_path do + %span Page slug + = text_field_tag :new_wiki_path, nil, placeholder: '如何设置', class: 'form-control', required: true, :'data-wikis-path' => namespace_project_wikis_path(@project.namespace, @project) + %p.hint + 请不要使用空格. + .modal-footer + = link_to '构建', '#', class: 'build-new-wiki btn btn-create' diff --git a/app/views/projects/wikis/edit.zh.html.haml b/app/views/projects/wikis/edit.zh.html.haml new file mode 100644 index 00000000000..6ddc6cdd609 --- /dev/null +++ b/app/views/projects/wikis/edit.zh.html.haml @@ -0,0 +1,13 @@ += render 'nav' +.pull-right + = render 'main_links' +%h3.page-title + 编辑中 - + %span.light #{@page.title} +%hr += render 'form' + +.pull-right + - if @page.persisted? && can?(current_user, :admin_wiki, @project) + = link_to namespace_project_wiki_path(@project.namespace, @project, @page), data: { confirm: "您确定要删除当前页?"}, method: :delete, class: "btn btn-sm btn-remove" do + 删除当前页 diff --git a/app/views/projects/wikis/empty.zh.html.haml b/app/views/projects/wikis/empty.zh.html.haml new file mode 100644 index 00000000000..f43592487ff --- /dev/null +++ b/app/views/projects/wikis/empty.zh.html.haml @@ -0,0 +1,4 @@ +%h3.page-title 空页面 +%hr +.error_message + 不允许您创建wiki页面 diff --git a/app/views/projects/wikis/git_access.zh.html.haml b/app/views/projects/wikis/git_access.zh.html.haml new file mode 100644 index 00000000000..a48b17319d2 --- /dev/null +++ b/app/views/projects/wikis/git_access.zh.html.haml @@ -0,0 +1,31 @@ += render 'nav' +.row + .col-sm-6 + %h3.page-title + Git access for + %strong= @project_wiki.path_with_namespace + + .col-sm-6 + = render "shared/clone_panel", project: @project_wiki + +.git-empty + %fieldset + %legend 安装Gollum: + %pre.dark + :preserve + gem install gollum + + %legend 克隆您的Wiki: + %pre.dark + :preserve + git clone #{ content_tag(:span, default_url_to_repo(@project_wiki), class: 'clone')} + cd #{@project_wiki.path} + + %legend 启动Gollum并在本地编辑: + %pre.dark + :preserve + gollum + == Sinatra/1.3.5 has taken the stage on 4567 for development with backup from Thin + >> Thin web server (v1.5.0 codename Knife) + >> Maximum connections set to 1024 + >> Listening on 0.0.0.0:4567, CTRL+C to stop diff --git a/app/views/projects/wikis/history.zh.html.haml b/app/views/projects/wikis/history.zh.html.haml new file mode 100644 index 00000000000..97462d5245b --- /dev/null +++ b/app/views/projects/wikis/history.zh.html.haml @@ -0,0 +1,30 @@ += render 'nav' +%h3.page-title + %span.light 历史记录 + = link_to @page.title, namespace_project_wiki_path(@project.namespace, @project, @page) + +%table.table + %thead + %tr + %th 页面版本 + %th 作者 + %th 提交信息 + %th 最近更新 + %th 格式 + %tbody + - @page.versions.each_with_index do |version, index| + - commit = version + %tr + %td + = link_to project_wiki_path_with_version(@project, @page, + commit.id, index == 0) do + = truncate_sha(commit.id) + %td + = commit.author.name + %td + = commit.message + %td + #{time_ago_with_tooltip(version.authored_date)} + %td + %strong + = @page.page.wiki.page(@page.page.name, commit.id).try(:format) diff --git a/app/views/projects/wikis/pages.zh.html.haml b/app/views/projects/wikis/pages.zh.html.haml new file mode 100644 index 00000000000..1e47dec4fe7 --- /dev/null +++ b/app/views/projects/wikis/pages.zh.html.haml @@ -0,0 +1,12 @@ += render 'nav' +%h3.page-title + 所有页面 +%ul.bordered-list + - @wiki_pages.each do |wiki_page| + %li + %h4 + = link_to wiki_page.title, namespace_project_wiki_path(@project.namespace, @project, wiki_page) + %small (#{wiki_page.format}) + .pull-right + %small 最近编辑时间 #{time_ago_with_tooltip(wiki_page.commit.authored_date)} += paginate @wiki_pages, theme: 'gitlab' diff --git a/app/views/projects/wikis/show.zh.html.haml b/app/views/projects/wikis/show.zh.html.haml new file mode 100644 index 00000000000..25b892f040f --- /dev/null +++ b/app/views/projects/wikis/show.zh.html.haml @@ -0,0 +1,20 @@ += render 'nav' +%h3.page-title + = @page.title + = render 'main_links' +- if @page.historical? + .warning_message + 这是页面的老版本. + 您可以查看 #{link_to "最新的版本", namespace_project_wiki_path(@project.namespace, @project, @page)} 或浏览 #{link_to "历史记录", history_namespace_project_wiki_path(@project.namespace, @project, @page)}. + +%hr + +.wiki-holder + .wiki + = preserve do + = render_wiki_content(@page) + +%hr + +.wiki-last-edit-by + 最近由 #{@page.commit.author.name} 编辑 #{time_ago_with_tooltip(@page.commit.authored_date)} diff --git a/app/views/search/_filter.zh.html.haml b/app/views/search/_filter.zh.html.haml new file mode 100644 index 00000000000..5458460bd26 --- /dev/null +++ b/app/views/search/_filter.zh.html.haml @@ -0,0 +1,35 @@ +.dropdown.inline + %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'} + %i.fa.fa-tags + %span.light 组: + - if @group.present? + %strong= @group.name + - else + 所有 + %b.caret + %ul.dropdown-menu + %li + = link_to search_filter_path(group_id: nil) do + 所有 + - current_user.authorized_groups.sort_by(&:name).each do |group| + %li + = link_to search_filter_path(group_id: group.id, project_id: nil) do + = group.name + +.dropdown.inline.prepend-left-10.project-filter + %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'} + %i.fa.fa-tags + %span.light 项目: + - if @project.present? + %strong= @project.name_with_namespace + - else + 所有 + %b.caret + %ul.dropdown-menu + %li + = link_to search_filter_path(project_id: nil) do + 所有 + - current_user.authorized_projects.sort_by(&:name_with_namespace).each do |project| + %li + = link_to search_filter_path(project_id: project.id, group_id: nil) do + = project.name_with_namespace diff --git a/app/views/search/_global_filter.zh.html.haml b/app/views/search/_global_filter.zh.html.haml new file mode 100644 index 00000000000..9ab09daeac5 --- /dev/null +++ b/app/views/search/_global_filter.zh.html.haml @@ -0,0 +1,16 @@ +%ul.nav.nav-pills.nav-stacked.search-filter + %li{class: ("active" if @scope == 'projects')} + = link_to search_filter_path(scope: 'projects') do + 项目 + .pull-right + = @search_results.projects_count + %li{class: ("active" if @scope == 'issues')} + = link_to search_filter_path(scope: 'issues') do + 问题 + .pull-right + = @search_results.issues_count + %li{class: ("active" if @scope == 'merge_requests')} + = link_to search_filter_path(scope: 'merge_requests') do + 合并请求 + .pull-right + = @search_results.merge_requests_count diff --git a/app/views/search/_project_filter.zh.html.haml b/app/views/search/_project_filter.zh.html.haml new file mode 100644 index 00000000000..e60a414ce63 --- /dev/null +++ b/app/views/search/_project_filter.zh.html.haml @@ -0,0 +1,32 @@ +%ul.nav.nav-pills.nav-stacked.search-filter + %li{class: ("active" if @scope == 'blobs')} + = link_to search_filter_path(scope: 'blobs') do + %i.fa.fa-code + 代码 + .pull-right + = @search_results.blobs_count + %li{class: ("active" if @scope == 'issues')} + = link_to search_filter_path(scope: 'issues') do + %i.fa.fa-exclamation-circle + 问题 + .pull-right + = @search_results.issues_count + %li{class: ("active" if @scope == 'merge_requests')} + = link_to search_filter_path(scope: 'merge_requests') do + %i.fa.fa-code-fork + 合并请求 + .pull-right + = @search_results.merge_requests_count + %li{class: ("active" if @scope == 'notes')} + = link_to search_filter_path(scope: 'notes') do + %i.fa.fa-comments + 评论 + .pull-right + = @search_results.notes_count + %li{class: ("active" if @scope == 'wiki_blobs')} + = link_to search_filter_path(scope: 'wiki_blobs') do + %i.fa.fa-book + Wiki + .pull-right + = @search_results.wiki_blobs_count + diff --git a/app/views/search/_snippet_filter.zh.html.haml b/app/views/search/_snippet_filter.zh.html.haml new file mode 100644 index 00000000000..836b7fdc70a --- /dev/null +++ b/app/views/search/_snippet_filter.zh.html.haml @@ -0,0 +1,13 @@ +%ul.nav.nav-pills.nav-stacked.search-filter + %li{class: ("active" if @scope == 'snippet_blobs')} + = link_to search_filter_path(scope: 'snippet_blobs', snippets: true, group_id: nil, project_id: nil) do + %i.fa.fa-code + 代码片段内容 + .pull-right + = @search_results.snippet_blobs_count + %li{class: ("active" if @scope == 'snippet_titles')} + = link_to search_filter_path(scope: 'snippet_titles', snippets: true, group_id: nil, project_id: nil) do + %i.fa.fa-book + 标题和文件名 + .pull-right + = @search_results.snippet_titles_count diff --git a/app/views/search/results/_note.zh.html.haml b/app/views/search/results/_note.zh.html.haml new file mode 100644 index 00000000000..4d968843f29 --- /dev/null +++ b/app/views/search/results/_note.zh.html.haml @@ -0,0 +1,26 @@ +- project = note.project +.search-result-row + %h5.note-search-caption.str-truncated + %i.fa.fa-comment + = link_to_member(project, note.author, avatar: false) + 评论 + + - if note.for_commit? + = link_to project do + = project.name_with_namespace + · + = link_to namespace_project_commit_path(project.namespace, project, note.commit_id, anchor: dom_id(note)) do + 提交 #{truncate_sha(note.commit_id)} + - else + = link_to project do + = project.name_with_namespace + · + %span #{note.noteable_type.titleize} ##{note.noteable.iid} + · + = link_to [project.namespace.becomes(Namespace), project, note.noteable, anchor: dom_id(note)] do + = note.noteable.title + + .note-search-result + .term + = preserve do + = search_md_sanitize(markdown(note.note, {no_header_anchors: true})) diff --git a/app/views/search/results/_snippet_blob.zh.html.haml b/app/views/search/results/_snippet_blob.zh.html.haml new file mode 100644 index 00000000000..10e7a512e39 --- /dev/null +++ b/app/views/search/results/_snippet_blob.zh.html.haml @@ -0,0 +1,59 @@ +.search-result-row + %span + = snippet_blob[:snippet_object].title + 由 + = link_to user_snippets_path(snippet_blob[:snippet_object].author) do + = image_tag avatar_icon(snippet_blob[:snippet_object].author_email), class: "avatar avatar-inline s16", alt: '' + = snippet_blob[:snippet_object].author_name + %span.light #{time_ago_with_tooltip(snippet_blob[:snippet_object].created_at)} + %h4.snippet-title + - snippet_path = reliable_snippet_path(snippet_blob[:snippet_object]) + = link_to snippet_path do + .file-holder + .file-title + %i.fa.fa-file + %strong= snippet_blob[:snippet_object].file_name + - if gitlab_markdown?(snippet_blob[:snippet_object].file_name) + .file-content.wiki + - snippet_blob[:snippet_chunks].each do |snippet| + - unless snippet[:data].empty? + = preserve do + = markdown(snippet[:data]) + - else + .file-content.code + .nothing-here-block 空文件 + - elsif markup?(snippet_blob[:snippet_object].file_name) + .file-content.wiki + - snippet_blob[:snippet_chunks].each do |snippet| + - unless snippet[:data].empty? + = render_markup(snippet_blob[:snippet_object].file_name, snippet[:data]) + - else + .file-content.code + .nothing-here-block 空文件 + - else + .file-content.code + %div.highlighted-data{class: user_color_scheme_class} + .line-numbers + - snippet_blob[:snippet_chunks].each do |snippet| + - unless snippet[:data].empty? + - snippet[:data].lines.to_a.size.times do |index| + - offset = defined?(snippet[:start_line]) ? snippet[:start_line] : 1 + - i = index + offset + = link_to snippet_path+"#L#{i}", id: "L#{i}", rel: "#L#{i}" do + %i.fa.fa-link + = i + - unless snippet == snippet_blob[:snippet_chunks].last + %a + = "." + .highlight.term + %pre + %code + - snippet_blob[:snippet_chunks].each do |snippet| + - unless snippet[:data].empty? + = snippet[:data] + - unless snippet == snippet_blob[:snippet_chunks].last + %a + = "..." + - else + .file-content.code + .nothing-here-block 空文件 diff --git a/app/views/search/results/_snippet_title.zh.html.haml b/app/views/search/results/_snippet_title.zh.html.haml new file mode 100644 index 00000000000..e905c594f90 --- /dev/null +++ b/app/views/search/results/_snippet_title.zh.html.haml @@ -0,0 +1,23 @@ +.search-result-row + %h4.snippet-title.term + = link_to reliable_snippet_path(snippet_title) do + = truncate(snippet_title.title, length: 60) + - if snippet_title.private? + %span.label.label-gray + %i.fa.fa-lock + 私有 + %span.cgray.monospace.tiny.pull-right.term + = snippet_title.file_name + + %small.pull-right.cgray + - if snippet_title.project_id? + = link_to snippet_title.project.name_with_namespace, namespace_project_path(snippet_title.project.namespace, snippet_title.project) + + .snippet-info + = "##{snippet_title.id}" + %span + 由 + = link_to user_snippets_path(snippet_title.author) do + = image_tag avatar_icon(snippet_title.author_email), class: "avatar avatar-inline s16", alt: '' + = snippet_title.author_name + %span.light #{time_ago_with_tooltip(snippet_title.created_at)} diff --git a/app/views/search/show.zh.html.haml b/app/views/search/show.zh.html.haml new file mode 100644 index 00000000000..137012fea4c --- /dev/null +++ b/app/views/search/show.zh.html.haml @@ -0,0 +1,22 @@ += form_tag search_path, method: :get, class: 'form-horizontal' do |f| + .search-holder.clearfix + .form-group + = label_tag :search, class: 'control-label' do + %span 查找 + .col-sm-6 + = search_field_tag :search, params[:search], placeholder: "问题 143", class: "form-control search-text-input", id: "dashboard_search" + .col-sm-4 + = button_tag '搜索', class: "btn btn-create" + .form-group + .col-sm-2 + - unless params[:snippets].eql? 'true' + .col-sm-10 + = render 'filter', f: f + = hidden_field_tag :project_id, params[:project_id] + = hidden_field_tag :group_id, params[:group_id] + = hidden_field_tag :snippets, params[:snippets] + = hidden_field_tag :scope, params[:scope] + + .results.prepend-top-10 + - if params[:search].present? + = render 'search/results' diff --git a/app/views/shared/_choose_group_avatar_button.zh.html.haml b/app/views/shared/_choose_group_avatar_button.zh.html.haml new file mode 100644 index 00000000000..bd6b10ce198 --- /dev/null +++ b/app/views/shared/_choose_group_avatar_button.zh.html.haml @@ -0,0 +1,7 @@ +%a.choose-btn.btn.btn-sm.js-choose-group-avatar-button + %i.fa.fa-paperclip + %span 选择文件 ... +  +%span.file_name.js-avatar-filename 文件名... += f.file_field :avatar, class: 'js-group-avatar-input hidden' +.light 允许的最大文件尺寸为200KB. diff --git a/app/views/shared/_clone_panel.zh.html.haml b/app/views/shared/_clone_panel.zh.html.haml new file mode 100644 index 00000000000..acf5288fbf6 --- /dev/null +++ b/app/views/shared/_clone_panel.zh.html.haml @@ -0,0 +1,23 @@ +- project = project || @project +.git-clone-holder.input-group + .input-group-btn + %button{ | + class: "btn #{ 'active' if default_clone_protocol == 'ssh' }#{ ' has_tooltip' if current_user && current_user.require_ssh_key? }", | + :"data-clone" => project.ssh_url_to_repo, | + :"data-title" => "添加SSH key 到您的个人资料中
通过SSH拉取或推送", + :"data-html" => "true", + :"data-container" => "body"} + SSH + %button{ | + class: "btn #{ 'active' if default_clone_protocol == 'http' }#{ ' has_tooltip' if current_user && current_user.require_password? }", | + :"data-clone" => project.http_url_to_repo, | + :"data-title" => "为您的帐号设置密码
或通过 #{gitlab_config.protocol.upcase} 推送或拉取", + :"data-html" => "true", + :"data-container" => "body"} + = gitlab_config.protocol.upcase + = text_field_tag :project_clone, default_url_to_repo(project), class: "one_click_select form-control", readonly: true + - if project.kind_of?(Project) + .input-group-addon + .visibility-level-label.has_tooltip{'data-title' => "#{visibility_level_label(project.visibility_level)} project" } + = visibility_level_icon(project.visibility_level) + = visibility_level_label(project.visibility_level).downcase diff --git a/app/views/shared/_commit_message_container.zh.html.haml b/app/views/shared/_commit_message_container.zh.html.haml new file mode 100644 index 00000000000..d71e24110a5 --- /dev/null +++ b/app/views/shared/_commit_message_container.zh.html.haml @@ -0,0 +1,14 @@ +.form-group.commit_message-group + = label_tag 'commit_message', class: 'control-label' do + 提交信息 + .col-sm-10 + .commit-message-container + .max-width-marker + = text_area_tag 'commit_message', + (params[:commit_message] || local_assigns[:text]), + class: 'form-control', placeholder: local_assigns[:placeholder], + required: true, rows: (local_assigns[:rows] || 3) + - if local_assigns[:hint] + %p.hint + 保持首行字数在52个字以下 + 其余各行在72个字以下 diff --git a/app/views/shared/_confirm_modal.zh.html.haml b/app/views/shared/_confirm_modal.zh.html.haml new file mode 100644 index 00000000000..79212d253b6 --- /dev/null +++ b/app/views/shared/_confirm_modal.zh.html.haml @@ -0,0 +1,22 @@ +#modal-confirm-danger.modal.hide{tabindex: -1} + .modal-dialog + .modal-content + .modal-header + %a.close{href: "#", "data-dismiss" => "modal"} × + %h4 请确认 + + .modal-body + %p.cred.lead.js-confirm-text + + %p + 此操作会导致数据丢失. + 为防止意外操作请确认这是你的真实要求. + %br + 请输入 + %code.js-confirm-danger-match #{phrase} + 继续或关闭窗口取消操作 + + .form-group + = text_field_tag 'confirm_name_input', '', class: 'form-control js-confirm-danger-input' + .form-group + = submit_tag '确认', class: "btn btn-danger js-confirm-danger-submit" diff --git a/app/views/shared/_event_filter.zh.html.haml b/app/views/shared/_event_filter.zh.html.haml new file mode 100644 index 00000000000..7231aa0d913 --- /dev/null +++ b/app/views/shared/_event_filter.zh.html.haml @@ -0,0 +1,19 @@ +%ul.nav.nav-pills.event_filter + = event_filter_link EventFilter.push, '推送事件' + = event_filter_link EventFilter.merged, '合并事件' + = event_filter_link EventFilter.comments, '评论' + = event_filter_link EventFilter.team, '团队' + + - if current_user + - if current_controller?(:dashboard) + %li.pull-right + = link_to dashboard_path(:atom, { private_token: current_user.private_token }), class: 'rss-btn' do + %i.fa.fa-rss + 新闻推送 + + - if current_controller?(:groups) + %li.pull-right + = link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed", class: 'rss-btn' do + %i.fa.fa-rss + 新闻推送 +%hr diff --git a/app/views/shared/_group_form.zh.html.haml b/app/views/shared/_group_form.zh.html.haml new file mode 100644 index 00000000000..d0b16970d27 --- /dev/null +++ b/app/views/shared/_group_form.zh.html.haml @@ -0,0 +1,29 @@ +- if @group.persisted? + .form-group + = f.label :name, class: 'control-label' do + 组名称 + .col-sm-10 + = f.text_field :name, placeholder: 'open-source', class: 'form-control' + +.form-group + = f.label :path, class: 'control-label' do + 组路径 + .col-sm-10 + .input-group + .input-group-addon + = root_url + = f.text_field :path, placeholder: 'open-source', class: 'form-control', + autofocus: local_assigns[:autofocus] || false + - if @group.persisted? + .alert.alert-warning.prepend-top-10 + %ul + %li 修改组路径会产生意外的副作用. + %li 重命名组路径会重命名所有相关项目的目录 + %li 访问组和组项目的地址会发生变化. + %li 该组下面的项目git路径会发生变化. + +.form-group.group-description-holder + = f.label :description, '详情', class: 'control-label' + .col-sm-10 + = f.text_area :description, maxlength: 250, + class: 'form-control js-gfm-input', rows: 4 diff --git a/app/views/shared/_group_tips.zh.html.haml b/app/views/shared/_group_tips.zh.html.haml new file mode 100644 index 00000000000..223e2684153 --- /dev/null +++ b/app/views/shared/_group_tips.zh.html.haml @@ -0,0 +1,6 @@ +%ul + %li 组是多个项目的集合 + %li 组默认是私有的 + %li 组内成员只能查看他有查看权限的项目 + %li 组项目的URL地址以组命名空间为前缀 + %li 已有项目可以移进组 diff --git a/app/views/shared/_issuable_filter.zh.html.haml b/app/views/shared/_issuable_filter.zh.html.haml new file mode 100644 index 00000000000..748fa36d370 --- /dev/null +++ b/app/views/shared/_issuable_filter.zh.html.haml @@ -0,0 +1,119 @@ +.issues-filters + .issues-state-filters + %ul.nav.nav-tabs + %li{class: ("active" if params[:state] == 'opened')} + = link_to page_filter_path(state: 'opened') do + %i.fa.fa-exclamation-circle + 打开 + %li{class: ("active" if params[:state] == 'closed')} + = link_to page_filter_path(state: 'closed') do + %i.fa.fa-check-circle + 已关闭 + %li{class: ("active" if params[:state] == 'all')} + = link_to page_filter_path(state: 'all') do + %i.fa.fa-compass + 所有 + + %div + - if controller.controller_name == 'issues' + .check-all-holder + = check_box_tag "check_all_issues", nil, false, + class: "check_all_issues left", + disabled: !can?(current_user, :modify_issue, @project) + .issues-other-filters + .dropdown.inline.assignee-filter + %button.dropdown-toggle.btn{type: 'button', "data-toggle" => "dropdown"} + %i.fa.fa-user + %span.light 指定给: + - if @assignee.present? + %strong= @assignee.name + - elsif params[:assignee_id] == "0" + 未指定 + - else + 任何人 + %b.caret + %ul.dropdown-menu + %li + = link_to page_filter_path(assignee_id: nil) do + 任何人 + = link_to page_filter_path(assignee_id: 0) do + 未指定 + - @assignees.sort_by(&:name).each do |user| + %li + = link_to page_filter_path(assignee_id: user.id) do + = image_tag avatar_icon(user.email), class: "avatar s16", alt: '' + = user.name + + .dropdown.inline.prepend-left-10.author-filter + %button.dropdown-toggle.btn{type: 'button', "data-toggle" => "dropdown"} + %i.fa.fa-user + %span.light 作者: + - if @author.present? + %strong= @author.name + - elsif params[:author_id] == "0" + 未指定 + - else + 任何人 + %b.caret + %ul.dropdown-menu + %li + = link_to page_filter_path(author_id: nil) do + 任何人 + = link_to page_filter_path(author_id: 0) do + 未指定 + - @authors.sort_by(&:name).each do |user| + %li + = link_to page_filter_path(author_id: user.id) do + = image_tag avatar_icon(user.email), class: "avatar s16", alt: '' + = user.name + + .dropdown.inline.prepend-left-10.milestone-filter + %button.dropdown-toggle.btn{type: 'button', "data-toggle" => "dropdown"} + %i.fa.fa-clock-o + %span.light 里程碑: + - if @milestone.present? + %strong= @milestone.title + - elsif params[:milestone_id] == "0" + 无 (backlog) + - else + 所有 + %b.caret + %ul.dropdown-menu + %li + = link_to page_filter_path(milestone_id: nil) do + 所有 + = link_to page_filter_path(milestone_id: 0) do + 无 (backlog) + - @milestones.each do |milestone| + %li + = link_to page_filter_path(milestone_id: milestone.id) do + %strong= milestone.title + %small.light= milestone.expires_at + + - if @project + .dropdown.inline.prepend-left-10.labels-filter + %button.dropdown-toggle.btn{type: 'button', "data-toggle" => "dropdown"} + %i.fa.fa-tags + %span.light 标签: + - if params[:label_name].present? + %strong= params[:label_name] + - else + 所有 + %b.caret + %ul.dropdown-menu + %li + = link_to page_filter_path(label_name: nil) do + 所有 + - if @project.labels.any? + - @project.labels.each do |label| + %li + = link_to page_filter_path(label_name: label.name) do + = render_colored_label(label) + - else + %li + = link_to generate_namespace_project_labels_path(@project.namespace, @project, redirect: request.original_url), method: :post do + %i.fa.fa-plus-circle + 创建默认标签 + + .pull-right + = render 'shared/sort_dropdown' diff --git a/app/views/shared/_issuable_search_form.zh.html.haml b/app/views/shared/_issuable_search_form.zh.html.haml new file mode 100644 index 00000000000..10279cd22f4 --- /dev/null +++ b/app/views/shared/_issuable_search_form.zh.html.haml @@ -0,0 +1,9 @@ += form_tag(path, method: :get, id: "issue_search_form", class: 'pull-left issue-search-form') do + .append-right-10.hidden-xs.hidden-sm + = search_field_tag :issue_search, params[:issue_search], { placeholder: '按标题或描述筛选', class: 'form-control issue_search search-text-input input-mn-300' } + = hidden_field_tag :state, params['state'] + = hidden_field_tag :scope, params['scope'] + = hidden_field_tag :assignee_id, params['assignee_id'] + = hidden_field_tag :author_id, params['author_id'] + = hidden_field_tag :milestone_id, params['milestone_id'] + = hidden_field_tag :label_id, params['label_id'] diff --git a/app/views/shared/_issues.zh.html.haml b/app/views/shared/_issues.zh.html.haml new file mode 100644 index 00000000000..2bf7e62a750 --- /dev/null +++ b/app/views/shared/_issues.zh.html.haml @@ -0,0 +1,15 @@ +- if @issues.any? + - @issues.group_by(&:project).each do |group| + .panel.panel-default.panel-small + - project = group[0] + .panel-heading + = link_to_project project + = link_to '显示所有', namespace_project_issues_path(project.namespace, project), class: 'pull-right' + + %ul.well-list.issues-list + - group[1].each do |issue| + = render 'projects/issues/issue', issue: issue + = paginate @issues, theme: "gitlab" +- else + .nothing-here-block 无问题可显示 + diff --git a/app/views/shared/_merge_requests.zh.html.haml b/app/views/shared/_merge_requests.zh.html.haml new file mode 100644 index 00000000000..f886afbd214 --- /dev/null +++ b/app/views/shared/_merge_requests.zh.html.haml @@ -0,0 +1,14 @@ +- if @merge_requests.any? + - @merge_requests.group_by(&:target_project).each do |group| + .panel.panel-default.panel-small + - project = group[0] + .panel-heading + = link_to_project project + = link_to '显示所有', namespace_project_merge_requests_path(project.namespace, project), class: 'pull-right' + %ul.well-list.mr-list + - group[1].each do |merge_request| + = render 'projects/merge_requests/merge_request', merge_request: merge_request + = paginate @merge_requests, theme: "gitlab" + +- else + .nothing-here-block 无合并请求可显示 diff --git a/app/views/shared/_milestones_filter.zh.html.haml b/app/views/shared/_milestones_filter.zh.html.haml new file mode 100644 index 00000000000..4f74fc3cd43 --- /dev/null +++ b/app/views/shared/_milestones_filter.zh.html.haml @@ -0,0 +1,14 @@ +.milestones-filters.append-bottom-10 + %ul.nav.nav-tabs + %li{class: ("active" if params[:state].blank? || params[:state] == 'opened')} + = link_to milestones_filter_path(state: 'opened') do + %i.fa.fa-exclamation-circle + 打开状态 + %li{class: ("active" if params[:state] == 'closed')} + = link_to milestones_filter_path(state: 'closed') do + %i.fa.fa-check-circle + 已关闭 + %li{class: ("active" if params[:state] == 'all')} + = link_to milestones_filter_path(state: 'all') do + %i.fa.fa-compass + 所有 diff --git a/app/views/shared/_no_password.zh.html.haml b/app/views/shared/_no_password.zh.html.haml new file mode 100644 index 00000000000..f39ea794403 --- /dev/null +++ b/app/views/shared/_no_password.zh.html.haml @@ -0,0 +1,8 @@ +- if cookies[:hide_no_password_message].blank? && !current_user.hide_no_password && current_user.require_password? + .no-password-message.alert.alert-warning.hidden-xs + 您必须给您帐号#{link_to '设置密码', edit_profile_password_path}之后才能通过#{gitlab_config.protocol.upcase}方式拉取或推送项目代码. + + .pull-right + = link_to "不再显示", profile_path(user: {hide_no_password: true}), method: :put + | + = link_to '以后再提示', '#', class: 'hide-no-password-message' diff --git a/app/views/shared/_no_ssh.zh.html.haml b/app/views/shared/_no_ssh.zh.html.haml new file mode 100644 index 00000000000..e4f409b3cd8 --- /dev/null +++ b/app/views/shared/_no_ssh.zh.html.haml @@ -0,0 +1,8 @@ +- if cookies[:hide_no_ssh_message].blank? && !current_user.hide_no_ssh_key && current_user.require_ssh_key? + .no-ssh-key-message.alert.alert-warning.hidden-xs + 在您#{link_to '添加SSH Key', new_profile_key_path, class: 'alert-link'}之前您将不能通过SSH拉取或推送项目代码. + + .pull-right + = link_to "不再显示", profile_path(user: {hide_no_ssh_key: true}), method: :put, class: 'alert-link' + | + = link_to '今后再提示', '#', class: 'hide-no-ssh-message alert-link' diff --git a/app/views/shared/_outdated_browser.zh.html.haml b/app/views/shared/_outdated_browser.zh.html.haml new file mode 100644 index 00000000000..890355f87ec --- /dev/null +++ b/app/views/shared/_outdated_browser.zh.html.haml @@ -0,0 +1,8 @@ +- if outdated_browser? + - link = "https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/requirements.md#supported-web-browsers" + .browser-alert + GitLab可能无法正常工作, 因为您正在使用过时的网页浏览器. + %br + Please install a + 为获取更佳的体验请安装一款 + = link_to '支持的网页浏览器.', link diff --git a/app/views/shared/_projects_list.zh.html.haml b/app/views/shared/_projects_list.zh.html.haml new file mode 100644 index 00000000000..27fccfd2923 --- /dev/null +++ b/app/views/shared/_projects_list.zh.html.haml @@ -0,0 +1,17 @@ +- projects_limit = 20 unless local_assigns[:projects_limit] +- avatar = true unless local_assigns[:avatar] == false +- stars = false unless local_assigns[:stars] == true +%ul.well-list.projects-list + - projects.each_with_index do |project, i| + %li{class: (i >= projects_limit) ? 'project-row hide' : 'project-row'} + = render "shared/project", project: project, avatar: avatar, stars: stars + - if projects.blank? + %li + .nothing-here-block 无项目. + - if projects.count > projects_limit + %li.bottom + %span.light + 显示了 #{projects_limit} / #{pluralize(projects.count, 'project')} 个项目. + %span + = link_to '#', class: 'js-expand' do + 显示所有 diff --git a/app/views/shared/_promo.zh.html.haml b/app/views/shared/_promo.zh.html.haml new file mode 100644 index 00000000000..e2f24dbfc67 --- /dev/null +++ b/app/views/shared/_promo.zh.html.haml @@ -0,0 +1,5 @@ +.gitlab-promo + = link_to '首页', promo_url + = link_to "博客", promo_url + '/blog/' + = link_to "@gitlab", "https://twitter.com/gitlab" + = link_to "Requests", "http://feedback.gitlab.com/" diff --git a/app/views/shared/_sort_dropdown.zh.html.haml b/app/views/shared/_sort_dropdown.zh.html.haml new file mode 100644 index 00000000000..072c0111130 --- /dev/null +++ b/app/views/shared/_sort_dropdown.zh.html.haml @@ -0,0 +1,22 @@ +.dropdown.inline.prepend-left-10 + %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} + %span.light 排序: + - if @sort.present? + = sort_options_hash[@sort] + - else + = sort_title_recently_created + %b.caret + %ul.dropdown-menu.dropdown-menu-align-right + %li + = link_to page_filter_path(sort: sort_value_recently_created) do + = sort_title_recently_created + = link_to page_filter_path(sort: sort_value_oldest_created) do + = sort_title_oldest_created + = link_to page_filter_path(sort: sort_value_recently_updated) do + = sort_title_recently_updated + = link_to page_filter_path(sort: sort_value_oldest_updated) do + = sort_title_oldest_updated + = link_to page_filter_path(sort: sort_value_milestone_soon) do + = sort_title_milestone_soon + = link_to page_filter_path(sort: sort_value_milestone_later) do + = sort_title_milestone_later diff --git a/app/views/snippets/_snippet.zh.html.haml b/app/views/snippets/_snippet.zh.html.haml new file mode 100644 index 00000000000..fba5081c449 --- /dev/null +++ b/app/views/snippets/_snippet.zh.html.haml @@ -0,0 +1,23 @@ +%li + %h4.snippet-title + = link_to reliable_snippet_path(snippet) do + = truncate(snippet.title, length: 60) + - if snippet.private? + %span.label.label-gray + %i.fa.fa-lock + 私有 + %span.cgray.monospace.tiny.pull-right + = snippet.file_name + + %small.pull-right.cgray + - if snippet.project_id? + = link_to snippet.project.name_with_namespace, namespace_project_path(snippet.project.namespace, snippet.project) + + .snippet-info + = "##{snippet.id}" + %span + 由 + = link_to user_snippets_path(snippet.author) do + = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16", alt: '' + = snippet.author_name + %span.light #{time_ago_with_tooltip(snippet.created_at)} diff --git a/app/views/snippets/_snippets.zh.html.haml b/app/views/snippets/_snippets.zh.html.haml new file mode 100644 index 00000000000..441f84a5a3d --- /dev/null +++ b/app/views/snippets/_snippets.zh.html.haml @@ -0,0 +1,7 @@ +%ul.bordered-list + = render partial: 'snippet', collection: @snippets + - if @snippets.empty? + %li + .nothing-here-block 这里什么也没有. + += paginate @snippets, theme: 'gitlab' diff --git a/app/views/snippets/current_user_index.zh.html.haml b/app/views/snippets/current_user_index.zh.html.haml new file mode 100644 index 00000000000..e311be9ccec --- /dev/null +++ b/app/views/snippets/current_user_index.zh.html.haml @@ -0,0 +1,39 @@ +%h3.page-title + 我的代码片段 + .pull-right + = link_to new_snippet_path, class: "btn btn-new btn-grouped", title: "New Snippet" do + 添加新的代码片段 + = link_to snippets_path, class: "btn btn-grouped" do + 发现代码片段 + +%p.light + 与其它人分享git仓库外的内容 +%hr + +.row + .col-md-3 + %ul.nav.nav-pills.nav-stacked + = nav_tab :scope, nil do + = link_to user_snippets_path(@user) do + 所有 + %span.pull-right + = @user.snippets.count + = nav_tab :scope, 'are_private' do + = link_to user_snippets_path(@user, scope: 'are_private') do + 私有 + %span.pull-right + = @user.snippets.are_private.count + = nav_tab :scope, 'are_internal' do + = link_to user_snippets_path(@user, scope: 'are_internal') do + 内部 + %span.pull-right + = @user.snippets.are_internal.count + = nav_tab :scope, 'are_public' do + = link_to user_snippets_path(@user, scope: 'are_public') do + 公开 + %span.pull-right + = @user.snippets.are_public.count + + .col-md-9.my-snippets + = render 'snippets' + diff --git a/app/views/snippets/edit.zh.html.haml b/app/views/snippets/edit.zh.html.haml new file mode 100644 index 00000000000..1df04d5f2af --- /dev/null +++ b/app/views/snippets/edit.zh.html.haml @@ -0,0 +1,4 @@ +%h3.page-title + 编辑代码片段 +%hr += render "shared/snippets/form", url: snippet_path(@snippet) diff --git a/app/views/snippets/index.zh.html.haml b/app/views/snippets/index.zh.html.haml new file mode 100644 index 00000000000..d47f169a11d --- /dev/null +++ b/app/views/snippets/index.zh.html.haml @@ -0,0 +1,17 @@ +%h3.page-title + 公开代码片段 + + .pull-right + + - if current_user + = link_to new_snippet_path, class: "btn btn-new btn-grouped", title: "New Snippet" do + 添加代码片段 + = link_to user_snippets_path(current_user), class: "btn btn-grouped" do + 我的代码片段 + +%p.light + 由您和其它用户创建的代码片段显示在这里 + +%hr += render 'snippets' + diff --git a/app/views/snippets/new.zh.html.haml b/app/views/snippets/new.zh.html.haml new file mode 100644 index 00000000000..2b30be39d90 --- /dev/null +++ b/app/views/snippets/new.zh.html.haml @@ -0,0 +1,4 @@ +%h3.page-title + 新建代码片段 +%hr += render "shared/snippets/form", url: snippets_path(@snippet) diff --git a/app/views/snippets/show.zh.html.haml b/app/views/snippets/show.zh.html.haml new file mode 100644 index 00000000000..1316696a95f --- /dev/null +++ b/app/views/snippets/show.zh.html.haml @@ -0,0 +1,43 @@ +%h3.page-title + = @snippet.title + + - if @snippet.private? + %span.label.label-success + %i.fa.fa-lock + 私有 + + .pull-right + = link_to new_snippet_path, class: "btn btn-new", title: "New Snippet" do + 添加代码片段 +%hr + +.append-bottom-20 + .pull-right + = "##{@snippet.id}" + %span.light + 由 + = link_to user_snippets_path(@snippet.author) do + = image_tag avatar_icon(@snippet.author_email), class: "avatar avatar-inline s16" + = @snippet.author_name + + .back-link + - if @snippet.author == current_user + = link_to user_snippets_path(current_user) do + ← 我的代码片段 + - else + = link_to snippets_path do + ← 发现代码片段 + +.file-holder + .file-title + %i.fa.fa-file + %strong + = @snippet.file_name + .file-actions + .btn-group + - if can?(current_user, :modify_personal_snippet, @snippet) + = link_to "编辑", edit_snippet_path(@snippet), class: "btn btn-sm", title: 'Edit Snippet' + = link_to "raw", raw_snippet_path(@snippet), class: "btn btn-sm", target: "_blank" + - if can?(current_user, :admin_personal_snippet, @snippet) + = link_to "删除", snippet_path(@snippet), method: :delete, data: { confirm: "您确定?" }, class: "btn btn-sm btn-remove", title: '删除代码片段' + = render 'shared/snippets/blob' diff --git a/app/views/snippets/user_index.zh.html.haml b/app/views/snippets/user_index.zh.html.haml new file mode 100644 index 00000000000..4859102fc43 --- /dev/null +++ b/app/views/snippets/user_index.zh.html.haml @@ -0,0 +1,13 @@ +%h3.page-title + = image_tag avatar_icon(@user.email), class: "avatar s24" + = @user.name + %span + \/ + 代码片段 + - if current_user + = link_to new_snippet_path, class: "btn btn-sm add_new pull-right", title: "新建代码片段" do + 添加代码片段 + +%hr + += render 'snippets' diff --git a/app/views/users/_profile.zh.html.haml b/app/views/users/_profile.zh.html.haml new file mode 100644 index 00000000000..79179a778f2 --- /dev/null +++ b/app/views/users/_profile.zh.html.haml @@ -0,0 +1,27 @@ +.panel.panel-default + .panel-heading + 用户资料 + %ul.well-list + %li + %span.light 用户注册于 + %strong= user.created_at.stamp("Aug 21, 2011") + - unless user.skype.blank? + %li + %span.light Skype: + %strong= link_to user.skype, "skype:#{user.skype}" + - unless user.linkedin.blank? + %li + %span.light LinkedIn: + %strong= link_to user.linkedin, "http://www.linkedin.com/in/#{user.linkedin}" + - unless user.twitter.blank? + %li + %span.light Twitter: + %strong= link_to user.twitter, "http://www.twitter.com/#{user.twitter}" + - unless user.website_url.blank? + %li + %span.light 网站: + %strong= link_to user.short_website_url, user.full_website_url + - unless user.bio.blank? + %li + %span.light 自传: + %span= user.bio diff --git a/app/views/users/_projects.zh.html.haml b/app/views/users/_projects.zh.html.haml new file mode 100644 index 00000000000..c7195e860f8 --- /dev/null +++ b/app/views/users/_projects.zh.html.haml @@ -0,0 +1,13 @@ +- if @contributed_projects.present? + .panel.panel-default + .panel-heading 贡献的项目 + = render 'shared/projects_list', + projects: @contributed_projects.sort_by(&:star_count).reverse, + projects_limit: 5, stars: true, avatar: false + +- if @projects.present? + .panel.panel-default + .panel-heading 个人项目 + = render 'shared/projects_list', + projects: @projects.sort_by(&:star_count).reverse, + projects_limit: 10, stars: true, avatar: false diff --git a/app/views/users/calendar.zh.html.haml b/app/views/users/calendar.zh.html.haml new file mode 100644 index 00000000000..0a40830862a --- /dev/null +++ b/app/views/users/calendar.zh.html.haml @@ -0,0 +1,8 @@ +%h4 提交日历 +#cal-heatmap.calendar + :javascript + new calendar( + #{@timestamps.to_json}, + #{@starting_year}, + #{@starting_month} + ); diff --git a/app/views/users/show.zh.html.haml b/app/views/users/show.zh.html.haml new file mode 100644 index 00000000000..b079f0c23e1 --- /dev/null +++ b/app/views/users/show.zh.html.haml @@ -0,0 +1,45 @@ +.row + = link_to '#aside', class: 'show-aside' do + %i.fa.fa-angle-left + %section.col-md-8 + %h3.page-title + = image_tag avatar_icon(@user.email, 90), class: "avatar avatar-tile s90", alt: '' + = @user.name + - if @user == current_user + .pull-right + = link_to profile_path, class: 'btn' do + %i.fa.fa-pencil-square-o + 编辑个人资料设置 + %br + %span.user-show-username #{@user.username} + %br + %small 会员注册于 #{@user.created_at.stamp("Nov 12, 2031")} + .clearfix + + - if @groups.any? + %h4 组 + = render 'groups', groups: @groups + %hr + + .hidden-xs + .user-calendar + %h4.center.light + %i.fa.fa-spinner.fa-spin + %hr + %h4 + 用户活动 + + - if current_user + %span.rss-icon.pull-right + = link_to user_path(@user, :atom, { private_token: current_user.private_token }) do + %strong + %i.fa.fa-rss + + = render @events + %aside.col-md-4 + = render 'profile', user: @user + = render 'projects' + +:coffeescript + $ -> + $(".user-calendar").load("#{user_calendar_path}") -- GitLab From 396b1f6779eae4d2dd07f7f6689eecb2d7d190aa Mon Sep 17 00:00:00 2001 From: King Jin Date: Sun, 5 Apr 2015 15:33:30 +0800 Subject: [PATCH 43/46] add i18-zh translation of app dir fixes #1 --- app/views/dashboard/groups/index.zh.html.haml | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 app/views/dashboard/groups/index.zh.html.haml diff --git a/app/views/dashboard/groups/index.zh.html.haml b/app/views/dashboard/groups/index.zh.html.haml new file mode 100644 index 00000000000..a2f2c5daf06 --- /dev/null +++ b/app/views/dashboard/groups/index.zh.html.haml @@ -0,0 +1,41 @@ +%h3.page-title + 组成员管理 + - if current_user.can_create_group? + %span.pull-right + = link_to new_group_path, class: "btn btn-new" do + %i.fa.fa-plus + 新建组 +%p.light + 组成员可以访问组的所有项目. + +%hr +.panel.panel-default + .panel-heading + %strong 组 + (#{@group_members.count}) + %ul.well-list + - @group_members.each do |group_member| + - group = group_member.group + %li + .pull-right + - if can?(current_user, :manage_group, group) + = link_to edit_group_path(group), class: "btn-sm btn btn-grouped" do + %i.fa.fa-cogs + 设置 + + - if can?(current_user, :destroy_group_member, group_member) + = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: '从组中删除用户' do + %i.fa.fa-sign-out + 离开 + + = image_tag group_icon(group), class: "avatar s40 avatar-tile" + = link_to group, class: 'group-name' do + %strong= group.name + + 作为 + %strong #{group_member.human_access} + + %div.light + #{group.projects.count}项目, #{group.users.count}用户 + += paginate @group_members -- GitLab From f8601cad704e122bf089c4d16558c07aa404b7d9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 1 Apr 2015 17:57:10 -0700 Subject: [PATCH 44/46] Version 7.9.2 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ac2f3747d99..e048e60ec11 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.9.1 \ No newline at end of file +7.9.2 \ No newline at end of file -- GitLab From 2bcef80d7c59fcdf973d0ba0de104f97d0dfa55e Mon Sep 17 00:00:00 2001 From: GitLab Date: Sun, 19 Apr 2015 18:18:48 +0800 Subject: [PATCH 45/46] fix translation typos Fixes #1 --- app/views/devise/sessions/_new_base.zh.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/devise/sessions/_new_base.zh.html.haml b/app/views/devise/sessions/_new_base.zh.html.haml index be637571c54..eec968dcad0 100644 --- a/app/views/devise/sessions/_new_base.zh.html.haml +++ b/app/views/devise/sessions/_new_base.zh.html.haml @@ -5,8 +5,8 @@ .remember-me.checkbox %label{for: "user_remember_me"} = f.check_box :remember_me - %span 记信我 + %span 记住我 .pull-right = link_to "忘记了您的密码?", new_password_path(resource_name) %div - = f.submit "注册", class: "btn btn-save" + = f.submit "登录", class: "btn btn-save" -- GitLab From f9e3f01a867ff7edbaaafa5da7a4b87d03055017 Mon Sep 17 00:00:00 2001 From: GitLab Date: Sun, 19 Apr 2015 18:35:31 +0800 Subject: [PATCH 46/46] translate sign up/in placeholder string --- app/views/devise/sessions/_new_base.zh.html.haml | 4 ++-- app/views/devise/shared/_signup_box.zh.html.haml | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/views/devise/sessions/_new_base.zh.html.haml b/app/views/devise/sessions/_new_base.zh.html.haml index eec968dcad0..9ff717936a1 100644 --- a/app/views/devise/sessions/_new_base.zh.html.haml +++ b/app/views/devise/sessions/_new_base.zh.html.haml @@ -1,6 +1,6 @@ = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| - = f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus" - = f.password_field :password, class: "form-control bottom", placeholder: "Password" + = f.text_field :login, class: "form-control top", placeholder: "用户名或邮箱", autofocus: "autofocus" + = f.password_field :password, class: "form-control bottom", placeholder: "密码" - if devise_mapping.rememberable? .remember-me.checkbox %label{for: "user_remember_me"} diff --git a/app/views/devise/shared/_signup_box.zh.html.haml b/app/views/devise/shared/_signup_box.zh.html.haml index 2a596392140..f8a0ea3455b 100644 --- a/app/views/devise/shared/_signup_box.zh.html.haml +++ b/app/views/devise/shared/_signup_box.zh.html.haml @@ -10,15 +10,15 @@ .devise-errors = devise_error_messages! %div - = f.text_field :name, class: "form-control top", placeholder: "Name", required: true + = f.text_field :name, class: "form-control top", placeholder: "名字", required: true %div - = f.text_field :username, class: "form-control middle", placeholder: "Username", required: true + = f.text_field :username, class: "form-control middle", placeholder: "用户名", required: true %div - = f.email_field :email, class: "form-control middle", placeholder: "Email", required: true + = f.email_field :email, class: "form-control middle", placeholder: "邮箱", required: true .form-group.append-bottom-20#password-strength - = f.password_field :password, class: "form-control bottom", id: "user_password_sign_up", placeholder: "Password", required: true + = f.password_field :password, class: "form-control bottom", id: "user_password_sign_up", placeholder: "密码", required: true %div - = f.submit "Sign up", class: "btn-create btn" + = f.submit "注册", class: "btn-create btn" .clearfix.prepend-top-20 %p -- GitLab