Commit e0b5e260357b4882e43863f61dcf337b120534b2

Authored by Dmitriy Zaporozhets
2 parents 55836973 e33debc2

Merge pull request #2153 from koenpunt/commit-diff-views

Added swipe view for image diff
app/assets/images/onion_skin_sprites.gif 0 → 100644

1.55 KB

app/assets/images/swipemode_sprites.gif 0 → 100644

1.5 KB

app/assets/javascripts/commit/file.js.coffee 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +class CommitFile
  2 +
  3 + constructor: (file) ->
  4 + if $('.image', file).length
  5 + new ImageFile(file)
  6 +
  7 +this.CommitFile = CommitFile
0 8 \ No newline at end of file
... ...
app/assets/javascripts/commit/image-file.js.coffee 0 → 100644
... ... @@ -0,0 +1,128 @@
  1 +class ImageFile
  2 +
  3 + # Width where images must fits in, for 2-up this gets divided by 2
  4 + @availWidth = 900
  5 + @viewModes = ['two-up', 'swipe']
  6 +
  7 + constructor: (@file) ->
  8 + # Determine if old and new file has same dimensions, if not show 'two-up' view
  9 + this.requestImageInfo $('.two-up.view .frame.deleted img', @file), (deletedWidth, deletedHeight) =>
  10 + this.requestImageInfo $('.two-up.view .frame.added img', @file), (width, height) =>
  11 + if width == deletedWidth && height == deletedHeight
  12 + this.initViewModes()
  13 + else
  14 + this.initView('two-up')
  15 +
  16 + initViewModes: ->
  17 + viewMode = ImageFile.viewModes[0]
  18 +
  19 + $('.view-modes', @file).removeClass 'hide'
  20 + $('.view-modes-menu', @file).on 'click', 'li', (event) =>
  21 + unless $(event.currentTarget).hasClass('active')
  22 + this.activateViewMode(event.currentTarget.className)
  23 +
  24 + this.activateViewMode(viewMode)
  25 +
  26 + activateViewMode: (viewMode) ->
  27 + $('.view-modes-menu li', @file)
  28 + .removeClass('active')
  29 + .filter(".#{viewMode}").addClass 'active'
  30 + $(".view:visible:not(.#{viewMode})", @file).fadeOut 200, =>
  31 + $(".view.#{viewMode}", @file).fadeIn(200)
  32 + this.initView viewMode
  33 +
  34 + initView: (viewMode) ->
  35 + this.views[viewMode].call(this)
  36 +
  37 + prepareFrames = (view) ->
  38 + maxWidth = 0
  39 + maxHeight = 0
  40 + $('.frame', view).each (index, frame) =>
  41 + width = $(frame).width()
  42 + height = $(frame).height()
  43 + maxWidth = if width > maxWidth then width else maxWidth
  44 + maxHeight = if height > maxHeight then height else maxHeight
  45 + .css
  46 + width: maxWidth
  47 + height: maxHeight
  48 +
  49 + [maxWidth, maxHeight]
  50 +
  51 + views:
  52 + 'two-up': ->
  53 + $('.two-up.view .wrap', @file).each (index, wrap) =>
  54 + $('img', wrap).each ->
  55 + currentWidth = $(this).width()
  56 + if currentWidth > ImageFile.availWidth / 2
  57 + $(this).width ImageFile.availWidth / 2
  58 +
  59 + this.requestImageInfo $('img', wrap), (width, height) ->
  60 + $('.image-info .meta-width', wrap).text "#{width}px"
  61 + $('.image-info .meta-height', wrap).text "#{height}px"
  62 + $('.image-info', wrap).removeClass('hide')
  63 +
  64 + 'swipe': ->
  65 + maxWidth = 0
  66 + maxHeight = 0
  67 +
  68 + $('.swipe.view', @file).each (index, view) =>
  69 +
  70 + [maxWidth, maxHeight] = prepareFrames(view)
  71 +
  72 + $('.swipe-frame', view).css
  73 + width: maxWidth + 16
  74 + height: maxHeight + 28
  75 +
  76 + $('.swipe-wrap', view).css
  77 + width: maxWidth + 1
  78 + height: maxHeight + 2
  79 +
  80 + $('.swipe-bar', view).css
  81 + left: 0
  82 + .draggable
  83 + axis: 'x'
  84 + containment: 'parent'
  85 + drag: (event) ->
  86 + $('.swipe-wrap', view).width (maxWidth + 1) - $(this).position().left
  87 + stop: (event) ->
  88 + $('.swipe-wrap', view).width (maxWidth + 1) - $(this).position().left
  89 +
  90 + 'onion-skin': ->
  91 + maxWidth = 0
  92 + maxHeight = 0
  93 +
  94 + dragTrackWidth = $('.drag-track', @file).width() - $('.dragger', @file).width()
  95 +
  96 + $('.onion-skin.view', @file).each (index, view) =>
  97 +
  98 + [maxWidth, maxHeight] = prepareFrames(view)
  99 +
  100 + $('.onion-skin-frame', view).css
  101 + width: maxWidth + 16
  102 + height: maxHeight + 28
  103 +
  104 + $('.swipe-wrap', view).css
  105 + width: maxWidth + 1
  106 + height: maxHeight + 2
  107 +
  108 + $('.dragger', view).css
  109 + left: dragTrackWidth
  110 + .draggable
  111 + axis: 'x'
  112 + containment: 'parent'
  113 + drag: (event) ->
  114 + $('.frame.added', view).css('opacity', $(this).position().left / dragTrackWidth)
  115 + stop: (event) ->
  116 + $('.frame.added', view).css('opacity', $(this).position().left / dragTrackWidth)
  117 +
  118 +
  119 +
  120 + requestImageInfo: (img, callback) ->
  121 + domImg = img.get(0)
  122 + if domImg.complete
  123 + callback.call(this, domImg.naturalWidth, domImg.naturalHeight)
  124 + else
  125 + img.on 'load', =>
  126 + callback.call(this, domImg.naturalWidth, domImg.naturalHeight)
  127 +
  128 +this.ImageFile = ImageFile
0 129 \ No newline at end of file
... ...
app/assets/javascripts/commits.js
... ... @@ -1,59 +0,0 @@
1   -var CommitsList = {
2   - ref:null,
3   - limit:0,
4   - offset:0,
5   - disable:false,
6   -
7   - init:
8   - function(ref, limit) {
9   - $(".day-commits-table li.commit").live('click', function(e){
10   - if(e.target.nodeName != "A") {
11   - location.href = $(this).attr("url");
12   - e.stopPropagation();
13   - return false;
14   - }
15   - });
16   -
17   - this.ref=ref;
18   - this.limit=limit;
19   - this.offset=limit;
20   - this.initLoadMore();
21   - $('.loading').show();
22   - },
23   -
24   - getOld:
25   - function() {
26   - $('.loading').show();
27   - $.ajax({
28   - type: "GET",
29   - url: location.href,
30   - data: "limit=" + this.limit + "&offset=" + this.offset + "&ref=" + this.ref,
31   - complete: function(){ $('.loading').hide()},
32   - dataType: "script"});
33   - },
34   -
35   - append:
36   - function(count, html) {
37   - $("#commits_list").append(html);
38   - if(count > 0) {
39   - this.offset += count;
40   - } else {
41   - this.disable = true;
42   - }
43   - },
44   -
45   - initLoadMore:
46   - function() {
47   - $(document).endlessScroll({
48   - bottomPixels: 400,
49   - fireDelay: 1000,
50   - fireOnce:true,
51   - ceaseFire: function() {
52   - return CommitsList.disable;
53   - },
54   - callback: function(i) {
55   - CommitsList.getOld();
56   - }
57   - });
58   - }
59   -}
app/assets/javascripts/commits.js.coffee 0 → 100644
... ... @@ -0,0 +1,54 @@
  1 +class CommitsList
  2 + @data =
  3 + ref: null
  4 + limit: 0
  5 + offset: 0
  6 + @disable = false
  7 +
  8 + @showProgress: ->
  9 + $('.loading').show()
  10 +
  11 + @hideProgress: ->
  12 + $('.loading').hide()
  13 +
  14 + @init: (ref, limit) ->
  15 + $(".day-commits-table li.commit").live 'click', (event) ->
  16 + if event.target.nodeName != "A"
  17 + location.href = $(this).attr("url")
  18 + e.stopPropagation()
  19 + return false
  20 +
  21 + @data.ref = ref
  22 + @data.limit = limit
  23 + @data.offset = limit
  24 +
  25 + this.initLoadMore()
  26 + this.showProgress();
  27 +
  28 + @getOld: ->
  29 + this.showProgress()
  30 + $.ajax
  31 + type: "GET"
  32 + url: location.href
  33 + data: @data
  34 + complete: this.hideProgress
  35 + dataType: "script"
  36 +
  37 + @append: (count, html) ->
  38 + $("#commits-list").append(html)
  39 + if count > 0
  40 + @data.offset += count
  41 + else
  42 + @disable = true
  43 +
  44 + @initLoadMore: ->
  45 + $(document).endlessScroll
  46 + bottomPixels: 400
  47 + fireDelay: 1000
  48 + fireOnce: true
  49 + ceaseFire: =>
  50 + @disable
  51 + callback: =>
  52 + this.getOld()
  53 +
  54 +this.CommitsList = CommitsList
0 55 \ No newline at end of file
... ...
app/assets/stylesheets/common.scss
... ... @@ -338,7 +338,7 @@ li.note {
338 338 li {
339 339 border-bottom:none !important;
340 340 }
341   - .file {
  341 + .attachment {
342 342 padding-left: 20px;
343 343 background:url("icon-attachment.png") no-repeat left center;
344 344 }
... ...
app/assets/stylesheets/gitlab_bootstrap/files.scss
... ... @@ -135,7 +135,7 @@
135 135 pre {
136 136 border: none;
137 137 border-radius: 0;
138   - font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
  138 + font-family: $monospace_font;
139 139 font-size: 12px !important;
140 140 line-height: 16px !important;
141 141 margin: 0;
... ...
app/assets/stylesheets/gitlab_bootstrap/fonts.scss
... ... @@ -4,4 +4,4 @@
4 4 }
5 5  
6 6 /** Typo **/
7   -$monospace: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
  7 +$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
... ...
app/assets/stylesheets/gitlab_bootstrap/typography.scss
... ... @@ -21,7 +21,7 @@ h6 {
21 21  
22 22 /** CODE **/
23 23 pre {
24   - font-family:'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
  24 + font-family: $monospace_font;
25 25  
26 26 &.dark {
27 27 background: #333;
... ... @@ -79,7 +79,7 @@ a:focus {
79 79 }
80 80  
81 81 .monospace {
82   - font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
  82 + font-family: $monospace_font;
83 83 }
84 84  
85 85 /**
... ...
app/assets/stylesheets/gitlab_bootstrap/variables.scss
1   -/** Colors **/
  1 +/**
  2 + * General Colors
  3 + */
2 4 $primary_color: #2FA0BB;
3 5 $link_color: #3A89A3;
4 6 $style_color: #474D57;
5 7 $hover: #D9EDF7;
  8 +
  9 +/**
  10 + * Commit Diff Colors
  11 + */
  12 +$added: #63c363;
  13 +$deleted: #f77;
... ...
app/assets/stylesheets/sections/commits.scss
1 1 /**
2   - *
3   - * COMMIT SHOw
4   - *
  2 + * Commit file
5 3 */
6 4 .commit-committer-link,
7 5 .commit-author-link {
... ... @@ -12,11 +10,11 @@
12 10 }
13 11 }
14 12  
15   -.diff_file {
  13 +.file {
16 14 border: 1px solid #CCC;
17 15 margin-bottom: 1em;
18 16  
19   - .diff_file_header {
  17 + .header {
20 18 @extend .clearfix;
21 19 padding: 5px 5px 5px 10px;
22 20 color: #555;
... ... @@ -28,32 +26,35 @@
28 26 background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
29 27 background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
30 28  
  29 + a{
  30 + color: $style_color;
  31 + }
  32 +
31 33 > span {
32   - font-family: $monospace;
  34 + font-family: $monospace_font;
33 35 font-size: 14px;
34 36 line-height: 30px;
35 37 }
36 38  
37   - a.view-commit{
  39 + a.view-file{
38 40 font-weight: bold;
39 41 }
40 42  
41 43 .commit-short-id{
42   - font-family: $monospace;
  44 + font-family: $monospace_font;
43 45 font-size: smaller;
44 46 }
45 47  
46 48 .file-mode{
47   - font-family: $monospace;
  49 + font-family: $monospace_font;
48 50 }
49 51 }
50   - .diff_file_content {
  52 + .content {
51 53 overflow: auto;
52 54 overflow-y: hidden;
53   - background: #fff;
  55 + background: #FFF;
54 56 color: #333;
55 57 font-size: 12px;
56   - font-family: $monospace;
57 58 .old{
58 59 span.idiff{
59 60 background-color: #FAA;
... ... @@ -66,114 +67,274 @@
66 67 }
67 68  
68 69 table {
  70 + font-family: $monospace_font;
  71 + border: none;
  72 + margin: 0px;
  73 + padding: 0px;
69 74 td {
70 75 line-height: 18px;
  76 + font-size: 12px;
  77 + }
  78 + }
  79 + .old_line, .new_line {
  80 + margin: 0px;
  81 + padding: 0px;
  82 + border: none;
  83 + background: #EEE;
  84 + color: #666;
  85 + padding: 0px 5px;
  86 + border-right: 1px solid #ccc;
  87 + text-align: right;
  88 + min-width: 35px;
  89 + max-width: 35px;
  90 + width: 35px;
  91 + @include user-select(none);
  92 + a {
  93 + float: left;
  94 + width: 35px;
  95 + font-weight: normal;
  96 + color: #666;
  97 + &:hover {
  98 + text-decoration: underline;
  99 + }
  100 + }
  101 + }
  102 + .line_content {
  103 + white-space: pre;
  104 + height: 14px;
  105 + margin: 0px;
  106 + padding: 0px;
  107 + border: none;
  108 + &.new {
  109 + background: #CFD;
  110 + }
  111 + &.old {
  112 + background: #FDD;
  113 + }
  114 + &.matched {
  115 + color: #ccc;
  116 + background: #fafafa;
71 117 }
72 118 }
73 119 }
74   - .diff_file_content_image {
75   - background: #eee;
  120 + .image {
  121 + background: #ddd;
76 122 text-align: center;
77   - .image {
  123 + padding: 30px;
  124 + .wrap{
78 125 display: inline-block;
79   - margin: 50px;
80   - max-width: 400px;
81   -
  126 + }
  127 +
  128 + .frame {
  129 + display: inline-block;
  130 + background-color: #fff;
  131 + line-height: 0;
82 132 img{
  133 + border: 1px solid #FFF;
83 134 background: url('trans_bg.gif');
84 135 }
  136 + &.deleted {
  137 + border: 1px solid $deleted;
  138 + }
85 139  
86   - &.diff_removed {
87   - img{
88   - border: 1px solid #C00;
89   - }
  140 + &.added {
  141 + border: 1px solid $added;
90 142 }
  143 + }
  144 + .image-info{
  145 + font-size: 12px;
  146 + margin: 5px 0 0 0;
  147 + color: grey;
  148 + }
91 149  
92   - &.diff_added {
93   - img{
94   - border: 1px solid #0C0;
  150 + .view.swipe{
  151 + position: relative;
  152 +
  153 + .swipe-frame{
  154 + display: block;
  155 + margin: auto;
  156 + position: relative;
  157 + }
  158 + .swipe-wrap{
  159 + overflow: hidden;
  160 + border-left: 1px solid #999;
  161 + position: absolute;
  162 + display: block;
  163 + top: 13px;
  164 + right: 7px;
  165 + }
  166 + .frame{
  167 + top: 0;
  168 + right: 0;
  169 + position: absolute;
  170 + &.deleted{
  171 + margin: 0;
  172 + display: block;
  173 + top: 13px;
  174 + right: 7px;
95 175 }
96 176 }
97   -
98   - .image-info{
99   - margin: 5px 0 0 0;
  177 + .swipe-bar{
  178 + display: block;
  179 + height: 100%;
  180 + width: 15px;
  181 + z-index: 100;
  182 + position: absolute;
  183 + cursor: pointer;
  184 + &:hover{
  185 + .top-handle{
  186 + background-position: -15px 3px;
  187 + }
  188 + .bottom-handle{
  189 + background-position: -15px -11px;
  190 + }
  191 + };
  192 + .top-handle{
  193 + display: block;
  194 + height: 14px;
  195 + width: 15px;
  196 + position: absolute;
  197 + top: 0px;
  198 + background: url('swipemode_sprites.gif') 0 3px no-repeat;
  199 + }
  200 + .bottom-handle{
  201 + display: block;
  202 + height: 14px;
  203 + width: 15px;
  204 + position: absolute;
  205 + bottom: 0px;
  206 + background: url('swipemode_sprites.gif') 0 -11px no-repeat;
  207 + }
100 208 }
101   - }
102   -
103   - &.img_compared {
104   - .image {
105   - max-width: 300px;
  209 + } //.view.swipe
  210 + .view.onion-skin{
  211 + .onion-skin-frame{
  212 + display: block;
  213 + margin: auto;
  214 + position: relative;
106 215 }
107   - }
  216 + .frame.added, .frame.deleted {
  217 + position: absolute;
  218 + display: block;
  219 + top: 0px;
  220 + left: 0px;
  221 + }
  222 + .controls{
  223 + display: block;
  224 + height: 14px;
  225 + width: 300px;
  226 + z-index: 100;
  227 + position: absolute;
  228 + bottom: 0px;
  229 + left: 50%;
  230 + margin-left: -150px;
  231 +
  232 + .drag-track{
  233 + display: block;
  234 + position: absolute;
  235 + left: 12px;
  236 + height: 10px;
  237 + width: 276px;
  238 + background: url('onion_skin_sprites.gif') -4px -20px repeat-x;
  239 + }
  240 +
  241 + .dragger {
  242 + display: block;
  243 + position: absolute;
  244 + left: 0px;
  245 + top: 0px;
  246 + height: 14px;
  247 + width: 14px;
  248 + background: url('onion_skin_sprites.gif') 0px -34px repeat-x;
  249 + cursor: pointer;
  250 + }
  251 +
  252 + .transparent {
  253 + display: block;
  254 + position: absolute;
  255 + top: 2px;
  256 + right: 0px;
  257 + height: 10px;
  258 + width: 10px;
  259 + background: url('onion_skin_sprites.gif') -2px 0px no-repeat;
  260 + }
  261 +
  262 + .opaque {
  263 + display: block;
  264 + position: absolute;
  265 + top: 2px;
  266 + left: 0px;
  267 + height: 10px;
  268 + width: 10px;
  269 + background: url('onion_skin_sprites.gif') -2px -10px no-repeat;
  270 + }
  271 + }
  272 + } //.view.onion-skin
108 273 }
109   -}
  274 + .view-modes{
110 275  
111   -.diff_file_content{
112   - table {
113   - border: none;
114   - margin: 0px;
115   - padding: 0px;
116   - tr {
117   - td {
118   - font-size: 12px;
119   - }
  276 + padding: 10px;
  277 + text-align: center;
  278 +
  279 + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
  280 + background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
  281 + background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
  282 + background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
  283 +
  284 + ul, li{
  285 + list-style: none;
  286 + margin: 0;
  287 + padding: 0;
  288 + display: inline-block;
120 289 }
121   - }
122   - .new_line,
123   - .old_line,
124   - .notes_line {
125   - margin:0px;
126   - padding:0px;
127   - border:none;
128   - background:#EEE;
129   - color:#666;
130   - padding: 0px 5px;
131   - border-right: 1px solid #ccc;
132   - text-align: right;
133   - min-width: 35px;
134   - max-width: 35px;
135   - width: 35px;
136   - moz-user-select: none;
137   - -khtml-user-select: none;
138   - user-select: none;
139   -
140   - a {
141   - float: left;
142   - width: 35px;
143   - font-weight: normal;
144   - color: #666;
145   - &:hover {
  290 +
  291 + li{
  292 + color: grey;
  293 + border-left: 1px solid #c1c1c1;
  294 + padding: 0 12px 0 16px;
  295 + cursor: pointer;
  296 + &:first-child{
  297 + border-left: none;
  298 + }
  299 + &:hover{
146 300 text-decoration: underline;
147 301 }
148   - }
149   - }
150   - .line_content {
151   - white-space: pre;
152   - height: 14px;
153   - margin: 0px;
154   - padding: 0px;
155   - border: none;
156   - &.new {
157   - background: #CFD;
158   - }
159   - &.old {
160   - background: #FDD;
161   - }
162   - &.matched {
163   - color: #ccc;
164   - background: #fafafa;
  302 + &.active{
  303 + &:hover{
  304 + text-decoration: none;
  305 + }
  306 + cursor: default;
  307 + color: #333;
  308 + }
  309 + &.disabled{
  310 + display: none;
  311 + }
165 312 }
166 313 }
167 314 }
168 315  
169 316 /** COMMIT BLOCK **/
170   -.commit-title{display: block;}
171   -.commit-title{margin-bottom: 10px}
172   -.commit-author, .commit-committer{display: block;color: #999; font-weight: normal; font-style: italic;}
173   -.commit-author strong, .commit-committer strong{font-weight: bold; font-style: normal;}
  317 +.commit-title{
  318 + display: block;
  319 +}
  320 +.commit-title{
  321 + margin-bottom: 10px;
  322 +}
  323 +.commit-author, .commit-committer{
  324 + display: block;
  325 + color: #999;
  326 + font-weight: normal;
  327 + font-style: italic;
  328 +}
  329 +.commit-author strong, .commit-committer strong{
  330 + font-weight: bold;
  331 + font-style: normal;
  332 +}
174 333  
175 334  
176   -/** COMMIT ROW **/
  335 +/**
  336 + * COMMIT ROW
  337 + */
177 338 .commit {
178 339 .browse_code_link_holder {
179 340 @extend .span2;
... ... @@ -199,11 +360,10 @@
199 360 float: left;
200 361 @extend .lined;
201 362 min-width: 65px;
202   - font-family: $monospace;
  363 + font-family: $monospace_font;
203 364 }
204 365 }
205 366  
206   -.diff_file_header a,
207 367 .file-stats a {
208 368 color: $style_color;
209 369 }
... ... @@ -237,7 +397,7 @@
237 397 font-size: 13px;
238 398 background: #474D57;
239 399 color: #fff;
240   - font-family: $monospace;
  400 + font-family: $monospace_font;
241 401 }
242 402  
243 403  
... ...
app/assets/stylesheets/sections/merge_requests.scss
... ... @@ -77,7 +77,7 @@ li.merge_request {
77 77 font-size: 14px;
78 78 background: #474D57;
79 79 color: #fff;
80   - font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
  80 + font-family: $monospace_font;
81 81 }
82 82  
83 83 .mr_source_commit,
... ...
app/assets/stylesheets/sections/notes.scss
... ... @@ -40,13 +40,13 @@ ul.notes {
40 40 .discussion-body {
41 41 margin-left: 50px;
42 42  
43   - .diff_file,
  43 + .file,
44 44 .discussion-hidden,
45 45 .notes {
46 46 @extend .borders;
47 47 background-color: #F9F9F9;
48 48 }
49   - .diff_file .notes {
  49 + .file .notes {
50 50 /* reset */
51 51 background: inherit;
52 52 border: none;
... ... @@ -109,7 +109,7 @@ ul.notes {
109 109 }
110 110 }
111 111  
112   -.diff_file .notes_holder {
  112 +.file .notes_holder {
113 113 font-family: $sansFontFamily;
114 114 font-size: 13px;
115 115 line-height: 18px;
... ... @@ -134,8 +134,6 @@ ul.notes {
134 134 }
135 135 }
136 136  
137   -
138   -
139 137 /**
140 138 * Actions for Discussions/Notes
141 139 */
... ... @@ -171,7 +169,7 @@ ul.notes {
171 169 }
172 170 }
173 171 }
174   -.diff_file .note .note-actions {
  172 +.file .note .note-actions {
175 173 right: 0;
176 174 top: 0;
177 175 }
... ... @@ -182,7 +180,7 @@ ul.notes {
182 180 * Line note button on the side of diffs
183 181 */
184 182  
185   -.diff_file tr.line_holder {
  183 +.file tr.line_holder {
186 184 .add-diff-note {
187 185 background: url("diff_note_add.png") no-repeat left 0;
188 186 height: 22px;
... ... @@ -212,8 +210,6 @@ ul.notes {
212 210 }
213 211 }
214 212  
215   -
216   -
217 213 /**
218 214 * Note Form
219 215 */
... ... @@ -222,7 +218,12 @@ ul.notes {
222 218 .reply-btn {
223 219 @extend .save-btn;
224 220 }
225   -.diff_file,
  221 +.file .content tr.line_holder:hover > td { background: $hover !important; }
  222 +.file .content tr.line_holder:hover > td .line_note_link {
  223 + opacity: 1.0;
  224 + filter: alpha(opacity=100);
  225 +}
  226 +.file,
226 227 .discussion {
227 228 .new_note {
228 229 margin: 8px 5px 8px 0;
... ...
app/helpers/commits_helper.rb
... ... @@ -59,9 +59,9 @@ module CommitsHelper
59 59  
60 60 def image_diff_class(diff)
61 61 if diff.deleted_file
62   - "diff_removed"
  62 + "deleted"
63 63 elsif diff.new_file
64   - "diff_added"
  64 + "added"
65 65 else
66 66 nil
67 67 end
... ...
app/views/commit/show.html.haml
... ... @@ -11,19 +11,7 @@
11 11  
12 12 :javascript
13 13 $(function(){
14   - var w, h;
15   - $('.diff_file').each(function(){
16   - $('.image.diff_removed img', this).on('load', $.proxy(function(event){
17   - var w = event.currentTarget.naturalWidth
18   - , h = event.currentTarget.naturalHeight;
19   - $('.image.diff_removed .image-info', this).append(' | <b>W:</b> ' + w + 'px | <b>H:</b> ' + h + 'px');
20   - }, this));
21   - $('.image.diff_added img', this).on('load', $.proxy(function(event){
22   - var w = event.currentTarget.naturalWidth
23   - , h = event.currentTarget.naturalHeight;
24   - $('.image.diff_added .image-info', this).append(' | <b>W:</b> ' + w + 'px | <b>H:</b> ' + h + 'px');
25   - }, this));
26   -
  14 + $('.files .file').each(function(){
  15 + new CommitFile(this);
27 16 });
28   -
29 17 });
... ...
app/views/commits/_diffs.html.haml
... ... @@ -12,50 +12,38 @@
12 12 .file-stats
13 13 = render "commits/diff_head", diffs: diffs
14 14  
15   -- unless @suppress_diff
16   - - diffs.each_with_index do |diff, i|
17   - - next if diff.diff.empty?
18   - - file = (@commit.tree / diff.new_path)
19   - - file = (@commit.prev_commit.tree / diff.old_path) unless file
20   - - next unless file
21   - .diff_file{id: "diff-#{i}"}
22   - .diff_file_header
23   - - if diff.deleted_file
24   - %span= diff.old_path
  15 +.files
  16 + - unless @suppress_diff
  17 + - diffs.each_with_index do |diff, i|
  18 + - next if diff.diff.empty?
  19 + - file = (@commit.tree / diff.new_path)
  20 + - file = (@commit.prev_commit.tree / diff.old_path) unless file
  21 + - next unless file
  22 + .file{id: "diff-#{i}"}
  23 + .header
  24 + - if diff.deleted_file
  25 + %span= diff.old_path
25 26  
26   - - if @commit.prev_commit
27   - = link_to project_tree_path(@project, tree_join(@commit.prev_commit_id, diff.new_path)), {:class => 'btn right view-commit'} do
  27 + - if @commit.prev_commit
  28 + = link_to project_tree_path(@project, tree_join(@commit.prev_commit_id, diff.new_path)), {:class => 'btn right view-file'} do
  29 + View file @
  30 + %span.commit-short-id= @commit.short_id(6)
  31 + - else
  32 + %span= diff.new_path
  33 + - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
  34 + %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
  35 +
  36 + = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn very_small right view-file'} do
28 37 View file @
29 38 %span.commit-short-id= @commit.short_id(6)
30   - - else
31   - %span= diff.new_path
32   - - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
33   - %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
34   -
35   - = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn very_small right view-commit'} do
36   - View file @
37   - %span.commit-short-id= @commit.short_id(6)
38 39  
39   - %br/
40   - .diff_file_content
41   - -# Skip all non-supported blobs
42   - - next unless file.respond_to?('text?')
43   - - if file.text?
44   - = render "commits/text_diff", diff: diff, index: i
45   - - elsif file.image?
46   - - old_file = (@commit.prev_commit.tree / diff.old_path) if !@commit.prev_commit.nil?
47   - - if diff.renamed_file || diff.new_file || diff.deleted_file
48   - .diff_file_content_image
49   - .image{class: image_diff_class(diff)}
50   - %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
51   - %div.image-info= "#{number_to_human_size file.size}"
  40 + .content
  41 + -# Skipp all non non-supported blobs
  42 + - next unless file.respond_to?('text?')
  43 + - if file.text?
  44 + = render "commits/text_file", diff: diff, index: i
  45 + - elsif file.image?
  46 + - old_file = (@commit.prev_commit.tree / diff.old_path) if !@commit.prev_commit.nil?
  47 + = render "commits/image", diff: diff, old_file: old_file, file: file, index: i
52 48 - else
53   - .diff_file_content_image.img_compared
54   - .image.diff_removed
55   - %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
56   - %div.image-info= "#{number_to_human_size file.size}"
57   - .image.diff_added
58   - %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
59   - %div.image-info= "#{number_to_human_size file.size}"
60   - - else
61   - %p.nothing_here_message No preview for this file type
  49 + %p.nothing_here_message No preview for this file type
... ...
app/views/commits/_image.html.haml 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +- if diff.renamed_file || diff.new_file || diff.deleted_file
  2 + .image
  3 + %span.wrap
  4 + .frame{class: image_diff_class(diff)}
  5 + %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
  6 + %p.image-info= "#{number_to_human_size file.size}"
  7 +- else
  8 + .image
  9 + %div.two-up.view
  10 + %span.wrap
  11 + .frame.deleted
  12 + %a{href: project_tree_path(@project, tree_join(@commit.id, diff.old_path))}
  13 + %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
  14 + %p.image-info.hide
  15 + %span.meta-filesize= "#{number_to_human_size old_file.size}"
  16 + |
  17 + %b W:
  18 + %span.meta-width
  19 + |
  20 + %b H:
  21 + %span.meta-height
  22 + %span.wrap
  23 + .frame.added
  24 + %a{href: project_tree_path(@project, tree_join(@commit.id, diff.new_path))}
  25 + %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
  26 + %p.image-info.hide
  27 + %span.meta-filesize= "#{number_to_human_size file.size}"
  28 + |
  29 + %b W:
  30 + %span.meta-width
  31 + |
  32 + %b H:
  33 + %span.meta-height
  34 +
  35 + %div.swipe.view.hide
  36 + .swipe-frame
  37 + .frame.deleted
  38 + %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
  39 + .swipe-wrap
  40 + .frame.added
  41 + %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
  42 + %span.swipe-bar
  43 + %span.top-handle
  44 + %span.bottom-handle
  45 +
  46 + %div.onion-skin.view.hide
  47 + .onion-skin-frame
  48 + .frame.deleted
  49 + %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
  50 + .frame.added
  51 + %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
  52 + .controls
  53 + .transparent
  54 + .drag-track
  55 + .dragger{:style => "left: 0px;"}
  56 + .opaque
  57 +
  58 +
  59 + .view-modes.hide
  60 + %ul.view-modes-menu
  61 + %li.two-up{data: {mode: 'two-up'}} 2-up
  62 + %li.swipe{data: {mode: 'swipe'}} Swipe
  63 + %li.onion-skin{data: {mode: 'onion-skin'}} Onion skin
0 64 \ No newline at end of file
... ...
app/views/commits/_text_diff.html.haml
... ... @@ -1,23 +0,0 @@
1   -- too_big = diff.diff.lines.count > 1000
2   -- if too_big
3   - %a.supp_diff_link Diff suppressed. Click to show
4   -
5   -%table{class: "#{'hide' if too_big}"}
6   - - each_diff_line(diff, index) do |line, type, line_code, line_new, line_old|
7   - %tr.line_holder{ id: line_code }
8   - - if type == "match"
9   - %td.old_line= "..."
10   - %td.new_line= "..."
11   - %td.line_content.matched= line
12   - - else
13   - %td.old_line
14   - = link_to raw(type == "new" ? "&nbsp;" : line_old), "##{line_code}", id: line_code
15   - - if @comments_allowed
16   - = render "notes/diff_note_link", line_code: line_code
17   - %td.new_line= link_to raw(type == "old" ? "&nbsp;" : line_new) , "##{line_code}", id: line_code
18   - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line)
19   -
20   - - if @reply_allowed
21   - - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at)
22   - - unless comments.empty?
23   - = render "notes/diff_notes_with_reply", notes: comments
app/views/commits/_text_file.html.haml 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +- too_big = diff.diff.lines.count > 1000
  2 +- if too_big
  3 + %a.supp_diff_link Diff suppressed. Click to show
  4 +
  5 +%table.text-file{class: "#{'hide' if too_big}"}
  6 + - each_diff_line(diff, index) do |line, type, line_code, line_new, line_old|
  7 + %tr.line_holder{ id: line_code }
  8 + - if type == "match"
  9 + %td.old_line= "..."
  10 + %td.new_line= "..."
  11 + %td.line_content.matched= line
  12 + - else
  13 + %td.old_line
  14 + = link_to raw(type == "new" ? "&nbsp;" : line_old), "##{line_code}", id: line_code
  15 + - if @comments_allowed
  16 + = render "notes/diff_note_link", line_code: line_code
  17 + %td.new_line= link_to raw(type == "old" ? "&nbsp;" : line_new) , "##{line_code}", id: line_code
  18 + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line)
  19 +
  20 + - if @reply_allowed
  21 + - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at)
  22 + - unless comments.empty?
  23 + = render "notes/diff_notes_with_reply", notes: comments
... ...
app/views/commits/show.html.haml
... ... @@ -5,7 +5,7 @@
5 5 = breadcrumbs
6 6  
7 7 %div{id: dom_id(@project)}
8   - #commits_list= render "commits"
  8 + #commits-list= render "commits"
9 9 .clear
10 10 .loading{ style: "display:none;"}
11 11  
... ...
app/views/notes/_discussion.html.haml
... ... @@ -38,7 +38,7 @@
38 38 - if note.for_diff_line?
39 39 - if note.diff
40 40 .content
41   - .diff_file= render "notes/discussion_diff", discussion_notes: discussion_notes, note: note
  41 + .file= render "notes/discussion_diff", discussion_notes: discussion_notes, note: note
42 42 - else
43 43 = link_to 'show outdated discussion', '#', class: 'js-show-outdated-discussion'
44 44 %div.hide.outdated-discussion
... ...
app/views/notes/_discussion_diff.html.haml
1 1 - diff = note.diff
2   -.diff_file_header
  2 +.header
3 3 - if diff.deleted_file
4 4 %span= diff.old_path
5 5 - else
... ... @@ -7,7 +7,7 @@
7 7 - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
8 8 %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
9 9 %br/
10   -.diff_file_content
  10 +.content
11 11 %table
12 12 - each_diff_line(diff, note.diff_file_index) do |line, type, line_code, line_new, line_old|
13 13 %tr.line_holder{ id: line_code }
... ...
features/steps/shared/diff_note.rb
... ... @@ -2,27 +2,27 @@ module SharedDiffNote
2 2 include Spinach::DSL
3 3  
4 4 Given 'I cancel the diff comment' do
5   - within(".diff_file") do
  5 + within(".file") do
6 6 find(".js-close-discussion-note-form").trigger("click")
7 7 end
8 8 end
9 9  
10 10 Given 'I delete a diff comment' do
11 11 sleep 1
12   - within(".diff_file") do
  12 + within(".file") do
13 13 first(".js-note-delete").trigger("click")
14 14 end
15 15 end
16 16  
17 17 Given 'I haven\'t written any diff comment text' do
18   - within(".diff_file") do
  18 + within(".file") do
19 19 fill_in "note[note]", with: ""
20 20 end
21 21 end
22 22  
23 23 Given 'I leave a diff comment like "Typo, please fix"' do
24 24 find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click")
25   - within(".diff_file") do
  25 + within(".file") do
26 26 fill_in "note[note]", with: "Typo, please fix"
27 27 #click_button("Add Comment")
28 28 find(".js-comment-button").trigger("click")
... ... @@ -32,7 +32,7 @@ module SharedDiffNote
32 32  
33 33 Given 'I preview a diff comment text like "Should fix it :smile:"' do
34 34 find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click")
35   - within(".diff_file") do
  35 + within(".file") do
36 36 fill_in "note[note]", with: "Should fix it :smile:"
37 37 find(".js-note-preview-button").trigger("click")
38 38 end
... ... @@ -40,7 +40,7 @@ module SharedDiffNote
40 40  
41 41 Given 'I preview another diff comment text like "DRY this up"' do
42 42 find("#586fb7c4e1add2d4d24e27566ed7064680098646_57_41.line_holder .js-add-diff-note-button").trigger("click")
43   - within(".diff_file") do
  43 + within(".file") do
44 44 fill_in "note[note]", with: "DRY this up"
45 45 find(".js-note-preview-button").trigger("click")
46 46 end
... ... @@ -55,13 +55,13 @@ module SharedDiffNote
55 55 end
56 56  
57 57 Given 'I write a diff comment like ":-1: I don\'t like this"' do
58   - within(".diff_file") do
  58 + within(".file") do
59 59 fill_in "note[note]", with: ":-1: I don\'t like this"
60 60 end
61 61 end
62 62  
63 63 Given 'I submit the diff comment' do
64   - within(".diff_file") do
  64 + within(".file") do
65 65 click_button("Add Comment")
66 66 end
67 67 end
... ... @@ -69,49 +69,49 @@ module SharedDiffNote
69 69  
70 70  
71 71 Then 'I should not see the diff comment form' do
72   - within(".diff_file") do
  72 + within(".file") do
73 73 page.should_not have_css("form.new_note")
74 74 end
75 75 end
76 76  
77 77 Then 'I should not see the diff comment preview button' do
78   - within(".diff_file") do
  78 + within(".file") do
79 79 page.should have_css(".js-note-preview-button", visible: false)
80 80 end
81 81 end
82 82  
83 83 Then 'I should not see the diff comment text field' do
84   - within(".diff_file") do
  84 + within(".file") do
85 85 page.should have_css(".js-note-text", visible: false)
86 86 end
87 87 end
88 88  
89 89 Then 'I should only see one diff form' do
90   - within(".diff_file") do
  90 + within(".file") do
91 91 page.should have_css("form.new_note", count: 1)
92 92 end
93 93 end
94 94  
95 95 Then 'I should see a diff comment form with ":-1: I don\'t like this"' do
96   - within(".diff_file") do
  96 + within(".file") do
97 97 page.should have_field("note[note]", with: ":-1: I don\'t like this")
98 98 end
99 99 end
100 100  
101 101 Then 'I should see a diff comment saying "Typo, please fix"' do
102   - within(".diff_file .note") do
  102 + within(".file .note") do
103 103 page.should have_content("Typo, please fix")
104 104 end
105 105 end
106 106  
107 107 Then 'I should see a discussion reply button' do
108   - within(".diff_file") do
  108 + within(".file") do
109 109 page.should have_link("Reply")
110 110 end
111 111 end
112 112  
113 113 Then 'I should see a temporary diff comment form' do
114   - within(".diff_file") do
  114 + within(".file") do
115 115 page.should have_css(".js-temp-notes-holder form.new_note")
116 116 end
117 117 end
... ... @@ -121,37 +121,37 @@ module SharedDiffNote
121 121 end
122 122  
123 123 Then 'I should see an empty diff comment form' do
124   - within(".diff_file") do
  124 + within(".file") do
125 125 page.should have_field("note[note]", with: "")
126 126 end
127 127 end
128 128  
129 129 Then 'I should see the cancel comment button' do
130   - within(".diff_file form") do
  130 + within(".file form") do
131 131 page.should have_css(".js-close-discussion-note-form", text: "Cancel")
132 132 end
133 133 end
134 134  
135 135 Then 'I should see the diff comment preview' do
136   - within(".diff_file form") do
  136 + within(".file form") do
137 137 page.should have_css(".js-note-preview", visible: false)
138 138 end
139 139 end
140 140  
141 141 Then 'I should see the diff comment edit button' do
142   - within(".diff_file") do
  142 + within(".file") do
143 143 page.should have_css(".js-note-edit-button", visible: true)
144 144 end
145 145 end
146 146  
147 147 Then 'I should see the diff comment preview button' do
148   - within(".diff_file") do
  148 + within(".file") do
149 149 page.should have_css(".js-note-preview-button", visible: true)
150 150 end
151 151 end
152 152  
153 153 Then 'I should see two separate previews' do
154   - within(".diff_file") do
  154 + within(".file") do
155 155 page.should have_css(".js-note-preview", visible: true, count: 2)
156 156 page.should have_content("Should fix it")
157 157 page.should have_content("DRY this up")
... ...