diff --git a/Gemfile b/Gemfile index f47bdcef5..c497001b2 100644 --- a/Gemfile +++ b/Gemfile @@ -21,7 +21,7 @@ gem 'rails-xmlrpc', '~> 0.3.6' # :git => 'git://github.com/chipiga/rails-xmlrpc. # gem 'rugged', '~> 0.16.0' gem 'grack', :git => 'git://github.com/rdblue/grack.git', :require => 'git_http' -gem "grit", :git => 'git://github.com/chipiga/grit.git' +gem "grit", :git => 'git://github.com/chipiga/grit.git' #, :path => '~/Sites/code/grit' gem 'charlock_holmes', '~> 0.6.8' #, :git => 'git://github.com/brianmario/charlock_holmes.git', :branch => 'bundle-icu' # Wiki diff --git a/app/assets/images/404.png b/app/assets/images/404.png index 0c6ce2f7b..9efbf38fa 100644 Binary files a/app/assets/images/404.png and b/app/assets/images/404.png differ diff --git a/app/assets/images/500.png b/app/assets/images/500.png new file mode 100644 index 000000000..ea507efc9 Binary files /dev/null and b/app/assets/images/500.png differ diff --git a/app/assets/images/503.png b/app/assets/images/503.png new file mode 100644 index 000000000..915e9c483 Binary files /dev/null and b/app/assets/images/503.png differ diff --git a/app/assets/javascripts/extra/admin-members.js b/app/assets/javascripts/extra/admin-members.js index 2138a07c0..c51de1ce5 100644 --- a/app/assets/javascripts/extra/admin-members.js +++ b/app/assets/javascripts/extra/admin-members.js @@ -24,3 +24,15 @@ function deleteAdminMember() { $('form#members_form').attr('action', delete_url); $('form#members_form').submit(); } + +function saveAdminGroup() { + $('#groups_method').attr('value', 'post'); + $('form#groups_form').submit(); +} + +function deleteAdminGroup() { + $('#groups_method').attr('value', 'delete'); + var delete_url = $('form#groups_form').attr('delete_url'); + $('form#groups_form').attr('action', delete_url); + $('form#groups_form').submit(); +} diff --git a/app/assets/stylesheets/design/custom.scss b/app/assets/stylesheets/design/custom.scss index c87731e50..b873ae386 100644 --- a/app/assets/stylesheets/design/custom.scss +++ b/app/assets/stylesheets/design/custom.scss @@ -621,3 +621,32 @@ div.right.bigpadding div.command_select div.rightlist textarea { div.rightlist textarea.resizable { resize: both; } + +table.tablesorter.list-users th.th1 { + width: 150px; +} + +table.tablesorter.list-users th.th2 { + width: 100px; +} + +table.tablesorter.list-users th.th3 { + width: 200px; +} + +table.tablesorter.list-users th.th4 { + width: 50px; +} + +div.admin-role { + padding-right: 10px; +} + +article a.right_floated { + float: right; +} + +/* TODO think, how to do it more beautiful */ +ul.ui-autocomplete { + z-index: 999 !important; +} diff --git a/app/assets/stylesheets/design/main.scss b/app/assets/stylesheets/design/main.scss index 4c84fd6d2..3bd65fb09 100644 --- a/app/assets/stylesheets/design/main.scss +++ b/app/assets/stylesheets/design/main.scss @@ -1,2244 +1,2413 @@ -html, body { - margin: 0; - padding: 0; - font-family: Tahoma, Geneva, Helvetica, sans-serif; - color: #292929; - background: #1f60a1 image-url("bg.png") repeat-x; - min-width: 940px; - min-height: 600px; - text-align: center; - height: 100%; -} - -header, section, footer, aside, nav, article, menu { - display: block; -} - -input[type="text"]:focus { outline: none; } - -input[type="password"]:focus { outline: none; } - -input:focus { outline: none; } - -select:focus { outline: none; } - -a img { border: none; } - -.wrap { - width: 940px; - margin: 0 auto; - text-align: center; - border: 1px solid #3f668c; - -webkit-box-shadow: 0px 0px 7px 0px rgba(0, 0, 0, 0.5); - -moz-box-shadow: 0px 0px 7px 0px rgba(0, 0, 0, 0.5); - box-shadow: 0px 0px 7px 0px rgba(0, 0, 0, 0.5); - background: #FFF; - min-height: 92%; -} - -.wrap.columns { - background: #FFF image-url("page-bg.png") repeat-y; -} - -.both { - clear: both; -} - -/* Top menu */ - -header { - -webkit-box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.4); - -moz-box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.4); - box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.4); - position: relative; - z-index: 1000; -} - -header div.left { - background: image-url("top-left.png"); - height: 46px; - width: 14px; - float: left; -} - -header div.middle { - background: image-url("top-middle.png"); - float: left; - height: 46px; - width: 912px; -} - -header div.right { - background: image-url("top-right.png"); - height: 46px; - width: 14px; - float: right; -} - -/* Left part of top menu*/ - -header menu { - float: left; - margin: 0; - padding: 0; -} - -header menu ul { - list-style: none; - margin: 0; - padding-top: 10px; -} - -header menu ul li { - display: inline; -} - -header menu ul li a { - font-size: 12px; - color: #FFF; - text-decoration: none; - height: 43px; - padding: 15px 10px 15px 10px; -} - -header menu ul li a:hover { - color: #cee7ff; -} - -header menu ul li a.first { -} - -header menu ul li a.active { - background: image-url("menu-hover.png") repeat-x; -} - -header div.logo { - float: left; - margin-top: 5px; - padding-left: 0px; - padding-right: 0px; -} - -/* Right part of top menu */ - -header div.information { - float: right; -} - -header div.search { - float: left; - margin: 10px 0px 0px 0px; - -moz-border-radius-topleft: 3px; - -moz-border-radius-topright: 3px; - -moz-border-radius-bottomright: 3px; - -moz-border-radius-bottomleft: 3px; - -webkit-border-radius: 3px 3px 3px 3px; - border-radius: 3px 3px 3px 3px; - background: #FFF; - border: 1px solid #7691aa; -} - -header div.search div.pic { - background: image-url("search-button.png"); - height: 22px; - width: 24px; - float: left; -} - -header div.search div.field { - float: left; - margin: -1px 0px 0px 0px; -} - -header div.search div.field input { - border: none; - height: 18px; - background: none; - width: 132px; - font-size: 12px; - font-family: Arial; - padding: 2px 0px 0px 0px; -} - -header div.search div.field input.gray { - color: #cfcfcf; -} - -header div.search div.field input.black { - color: #333333; -} - -header div.avatar { - float:left; - padding: 6px 10px 10px 10px; - -} - -header div.information div.active { - background: image-url("menu-hover.png") repeat-x; -} - -header div.information div.user { - float: left; - margin-left: 14px; -} - -header div.profile { - float: left; - text-align: right; - color: #FFF; - font-size: 12px; - padding-top: 12px; -} - -header div.profile a { - color: #FFF; - text-decoration: none; - padding-right: 10px; -} - -header div.profile a:hover { - text-decoration: underline; -} - - -header div.droplist-wrap { - margin: -4px 0px 0px 0px; - width: 151px; - float: right; -} - -header div.droplist { - background: image-url("bg-droplist.png") repeat-x; - height: 91px; - width: 151px; - -webkit-box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5); - -moz-box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5); - box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5); - position: absolute; - margin-top: 0px; - border-radius: 0px 0px 4px 4px; - display: none; - text-align: right; - z-index: 9999; -} - -header div.droplist-wrap div.a { - margin-top: 5px; -} - -header div.droplist a{ - position: relative; - padding-left: 15px; - font-size: 12px; - color: #447cae; - text-decoration: none; - padding-right: 15px; - margin-top: 10px; -} - -header div.droplist a:hover{ - text-decoration: underline; -} - - -/* Submenu */ - -.sub-menu { - height: 38px; - margin: -7px 0px 0px 0px; - padding: 0px 0px 0px 15px; - background: #ededed; - position: relative; - z-index: 100; - border-bottom: 1px solid #FFF; - -webkit-box-shadow: 0px 5px 3px -3px rgba(18, 86, 135, 0.2); - -moz-box-shadow: 0px 5px 3px -3px rgba(18, 86, 135, 0.2); - box-shadow: 0px 5px 3px -3px rgba(18, 86, 135, 0.2); -} - -.sub-menu div.left { - float: left; - width: 200px; - border-right: 1px solid #dcdcdc; - font-size: 12px; - text-align: left; - font-weight: 700; - padding: 10px 0px 0px 0px; - height: 21px; -} - -.sub-menu div.right { - float: left; -} - - -.sub-menu nav { - float: left; - margin: 0px 0px 0px 0px; -} - -.sub-menu nav ul { - list-style: none; - text-align: left; - padding: 0; - margin: 0; - padding-top: 4px; -} - -.sub-menu nav ul li { - display: inline; -} - -.sub-menu nav ul li a { - font-size: 12px; - color: #292929; - text-decoration: none; - height: 34px; - padding: 0px 20px 9px 20px; -} - -.sub-menu nav ul li a.active { - background: image-url("submenu-hover.png") repeat-x scroll 0 100% transparent; -} - -.sub-menu nav ul li a:hover { - color: #2b6daf; -} - -/* Page markup */ - -article { - font-size: 12px; -} - -aside { - float: left; - width: 215px; -} - -article div.right { - float: right; - width: 645px; - padding: 20px 40px 40px 40px; - text-align: left; -} - -article div.right.bigpadding { - width: 445px; - padding: 20px 140px 40px 140px; -} - -article div.right.middlepadding { - width: 510px; - padding: 20px 120px 40px 50px; -} - -article div.right.middlepadding div.rightlist{ - width: 300px; -} - -article div.right.middlepadding div.rightlist input{ - width: 300px; -} - -article div.right.middlepadding div.rightlist textarea{ - width: 300px; -} - -article div.all { - width: 855px; - padding: 20px 40px 20px 40px; - text-align: left; -} - -article div.all.bigpadding { - width: 605px; - padding: 0px 40px 20px 200px; - text-align: left; -} - -article div.all.verybigpadding { - width: 545px; - padding: 0px 40px 20px 200px; - text-align: left; -} - -article div.all.verybigpadding div.left { - float: left; -} - -article div.all.verybigpadding div.left img{ - padding-right: 40px; - margin-top: 20px; -} - -article div.all.verybigpadding div.left h3, article div.all.verybigpadding div.left h4, article div.all.verybigpadding div.left p{ - width: 420px; -} - -article div.all.verybigpadding div.left .tmargin5 { - padding-top: 5px; - position: relative; -} - - -/* Left part of page markup */ - -aside div.bordered { - border-bottom: 1px solid #dee5eb; - text-align: left; - padding: 20px 0px 30px 15px; -} - -aside div.block { - text-align: left; - padding: 10px 0px 30px 15px; -} - -/* Common page parts markups */ - -article h4 { - font-size: 12px; - margin-bottom: 0px; - padding-bottom: 2px; -} - -article p { - margin: 0; - padding: 0; -} - -div.expand-gray-down, div.expand-gray-up { - height: 10px; - width: 12px; - float: left; - margin: 3px 0px 0px 3px; - cursor: pointer; -} - -div.expand-gray-down { - background: image-url("expand-gray.png") no-repeat; -} - -div.expand-gray-up { - background: image-url("expand-gray2.png") no-repeat; -} - -article a.button { - display: inline-block; - white-space: nowrap; - background-color: #125687; - background-image: -webkit-gradient(linear, left top, left bottom, from(#68a3d8), to(#125687)); - background-image: -webkit-linear-gradient(top, #68a3d8, #125687); - background-image: -moz-linear-gradient(top, #68a3d8, #125687); - background-image: -ms-linear-gradient(top, #68a3d8, #125687); - background-image: -o-linear-gradient(top, #68a3d8, #125687); - background-image: linear-gradient(top, #68a3d8, #125687); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#68a3d8', EndColorStr='#125687'); - border: 1px solid #5084b4; - padding: 4px 20px 6px; - margin: 0; - font-size: 12px; - text-decoration: none; - color: #FFF; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; - text-align: center; -} - -article a.button:hover{ - background-color: #34719d; - background-image: -webkit-gradient(linear, left top, left bottom, from(#7fb3e1), to(#34719d)); - background-image: -webkit-linear-gradient(top, #7fb3e1, #34719d); - background-image: -moz-linear-gradient(top, #7fb3e1, #34719d); - background-image: -ms-linear-gradient(top, #7fb3e1, #34719d); - background-image: -o-linear-gradient(top, #7fb3e1, #34719d); - background-image: linear-gradient(top, #7fb3e1, #34719d); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#7fb3e1', EndColorStr='#34719d'); - text-decoration: none; -} - - - -article a.button:active{ - background-color: #125687; - background-image: -webkit-gradient(linear, left top, left bottom, from(#68a3d8), to(#125687)); - background-image: -webkit-linear-gradient(top, #68a3d8, #125687); - background-image: -moz-linear-gradient(top, #68a3d8, #125687); - background-image: -ms-linear-gradient(top, #68a3d8, #125687); - background-image: -o-linear-gradient(top, #68a3d8, #125687); - background-image: linear-gradient(top, #68a3d8, #125687); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#68a3d8', EndColorStr='#125687'); -} - -article a.disabled { - background-color: #888888; - background-image: -webkit-gradient(linear, left top, left bottom, from(#aaaaaa), to(#888888)); - background-image: -webkit-linear-gradient(top, #aaaaaa, #888888); - background-image: -moz-linear-gradient(top, #aaaaaa, #888888); - background-image: -ms-linear-gradient(top, #aaaaaa, #888888); - background-image: -o-linear-gradient(top, #aaaaaa, #888888); - background-image: linear-gradient(top, #aaaaaa, #888888); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#aaaaaa', EndColorStr='#888888'); - cursor: default; - color: #d8d8d8; - border: 1px solid #aaaaaa; - cursor: default; - text-align: center; -} - -article input[type="file"] { - - -} - -article input[type="submit"] { - display: inline-block; - white-space: nowrap; - background-color: #125687; - background-image: -webkit-gradient(linear, left top, left bottom, from(#68a3d8), to(#125687)); - background-image: -webkit-linear-gradient(top, #68a3d8, #125687); - background-image: -moz-linear-gradient(top, #68a3d8, #125687); - background-image: -ms-linear-gradient(top, #68a3d8, #125687); - background-image: -o-linear-gradient(top, #68a3d8, #125687); - background-image: linear-gradient(top, #68a3d8, #125687); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#68a3d8', EndColorStr='#125687'); - border: 1px solid #5084b4; - padding: 3px 20px 5px; - margin: 0; - font-size: 12px; - text-decoration: none; - color: #FFF; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; - text-align: center; - height: auto; - width: auto; - font-family: Tahoma; -} - -article input[type="submit"]:hover{ - background-color: #34719d; - background-image: -webkit-gradient(linear, left top, left bottom, from(#7fb3e1), to(#34719d)); - background-image: -webkit-linear-gradient(top, #7fb3e1, #34719d); - background-image: -moz-linear-gradient(top, #7fb3e1, #34719d); - background-image: -ms-linear-gradient(top, #7fb3e1, #34719d); - background-image: -o-linear-gradient(top, #7fb3e1, #34719d); - background-image: linear-gradient(top, #7fb3e1, #34719d); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#7fb3e1', EndColorStr='#34719d'); - text-decoration: none; - cursor: pointer; -} - - - -article input[type="submit"]:active{ - background-color: #125687; - background-image: -webkit-gradient(linear, left top, left bottom, from(#68a3d8), to(#125687)); - background-image: -webkit-linear-gradient(top, #68a3d8, #125687); - background-image: -moz-linear-gradient(top, #68a3d8, #125687); - background-image: -ms-linear-gradient(top, #68a3d8, #125687); - background-image: -o-linear-gradient(top, #68a3d8, #125687); - background-image: linear-gradient(top, #68a3d8, #125687); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#68a3d8', EndColorStr='#125687'); -} - -article input[type="submit"]:disabled { - background-color: #888888; - background-image: -webkit-gradient(linear, left top, left bottom, from(#aaaaaa), to(#888888)); - background-image: -webkit-linear-gradient(top, #aaaaaa, #888888); - background-image: -moz-linear-gradient(top, #aaaaaa, #888888); - background-image: -ms-linear-gradient(top, #aaaaaa, #888888); - background-image: -o-linear-gradient(top, #aaaaaa, #888888); - background-image: linear-gradient(top, #aaaaaa, #888888); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#aaaaaa', EndColorStr='#888888'); - cursor: default; - color: #d8d8d8; - border: 1px solid #aaaaaa; - cursor: default; - text-align: center; -} - - -article h3{ - font-size: 14px; - color: #292929; - margin-bottom: 0; - padding-bottom: 2px; -} - -article h3.fix { - margin-top: 0px; - padding-top: 0px; -} - -article a{ - color: #447cae; - font-size: 12px; - text-decoration: none; - padding: 0px 0px; -} - -article a:hover{ - text-decoration: underline; -} - -/* Right part of page markup */ - -article div.right div.hr { - border-bottom: 1px solid #dedede; - width: 100%; - padding-top: 30px; - margin-bottom: 30px; -} - -article div.right div.hr.bottom { - margin-bottom: 10px; - padding-top: 20px; -} - -article div.right div.hr.top { - padding-top: 7px; - margin-bottom: 20px; -} - -article div.leftside { - float: left; -} - -article div.rightside { - float: right; -} - -article div.all.bigpadding div.rightside { - margin-right: 40px; -} - -.lefter { - float: left; - margin-right: 5px; -} - -.lefter span.gap { - padding-right: 59px; -} - -.lefter.top { - margin-top: -6px; -} - -.w25 { - width: 25px; -} - -.w420 { - width: 420px; - padding-bottom: 20px; -} - -.padd25 { - padding-left: 25px; -} - -.width70 { - width: 70px; -} - -a.button.width81 { - width: 79px; - padding: 4px 0px; - text-align: center; -} - -/* Footer */ - -footer { - height: 32px; - padding-left: 15px; - width: 900px; - margin: 0 auto; - text-align: center; -} - -footer ul { - margin: 0; - padding: 0; - list-style: none; - font-size: 12px; - color: #FFF; - padding-top: 10px; - text-align: left; -} - -footer ul li { - display: inline; -} - -footer ul li a { - font-size: 12px; - color: #FFF; - text-decoration: none; -} - -footer ul li a:hover { - text-decoration: underline; -} - -/* Main page */ - -aside div.bordered table{ - padding: 0; - margin: 0; - padding-bottom: 0px; - margin-left: -10px; -} - -aside div.bordered table td{ - font-size: 12px; - padding: 1px 0px 0px 0px; -} - -aside div.block table td { - text-align: right; - padding: 2px 3px 1px 3px; -} - - -aside div.block table td.first{ - width: 150px; - text-align: left; -} - -article div.right div.messages { - background: #e9f4fb; - border: 1px solid #dfeefa; - border-radius: 5px; - width: 100%; - color: #477cae; - text-align: center; - font-size: 12px; - padding: 4px 0px 4px 0px; - cursor: pointer; - margin: 15px 0px 15px 0px; -} - -article div.right div.messages:hover { - background: #dceffa; -} - -article div.right div.messages p{ - margin: 0; - padding: 0; -} - -article div.activity { - border: 1px solid #d6d6d6; - /*width: 614px;*/ - border-radius: 5px; - padding: 6px; - margin-top: 15px; - color: #333; -} - -article div.activity div.top div.image { - float: left; -} - -article div.activity div.top div.text { - float: left; - padding-left: 10px; - font-size: 12px; -} - -article div.activity div.top div.text span.name { - font-weight: 700; -} - -article div.activity div.top div.text span.date { - font-size: 11px; -} - -article div.text span.subject { - float: left; -} - -article div.activity div.top div.text span.subject img { - cursor: pointer; -} - -article div.activity div.fulltext { - font-size: 12px; - padding-top: 10px; - display: none; -} - -article div.activity div.fulltext.view { - display: block; -} - -/* Admin page */ - -.admin-preferences ul { - list-style: none; - margin: 0; - padding: 0; - margin-top: 20px; - width: 215px; - text-align: left; -} - -.admin-preferences ul li{ - padding-top: 5px; - padding-bottom: 5px; - width: 215px; -} - -.admin-preferences ul li.active, .admin-preferences ul li:hover { - background: #dcecfa; -} - -.admin-preferences ul li a{ - color: #292929; - text-decoration: none; - padding-top: 5px; - padding-bottom: 5px; - padding-left: 15px; -} - -.right div.leftlist, .all div.leftlist { - float: left; - width: 200px; - margin: 0px 0px 10px 0px; -} - -.right div.rightlist, .all div.rightlist { - float: left; - width: 400px; - font-size: 12px; - color: #292929; - margin: 0px 0px 10px 0px; -} - -.right div.rightlist div.check { - float: left; -} - -.right div.rightlist div.forcheck { - float: left; - margin: 1px 0px 0px 5px; -} -div.rightlist textarea { - height: 110px; - width: 350px; - border: 1px solid #dedede; - border-radius: 4px; - padding: 5px; - font-family: Tahoma, Geneva, Helvetica, sans-serif; - font-size: 12px; -} - -div.rightlist input[type="text"], div.rightlist input[type="password"] { - height: 16px; - width: 350px; - border: 1px solid #dedede; - border-radius: 4px; - padding: 5px; - font-family: Tahoma, Geneva, Helvetica, sans-serif; - font-size: 12px; -} - -/* Admin-members page */ - -div.img { - float: left; -} - - table div.radio { - float: left; - margin: 5px 0px 0px 0px; -} - -div.forimg { - float: left; - margin: 5px 0px 0px 5px; -} - -table div.forradio { - float: left; - margin: 5px 0px 0px 5px; -} - -table span.niceCheck-main { - margin-top: 3px; -} - -div.admin-search { - float: left; -} - -.right div.admin-role { - float: left; -} - -.right div.admin-search input { - width: 300px; - margin-right: 5px; - height: 23px; - border: 1px solid #dedede; - border-radius: 3px; - margin-top: 1px; - font-size: 12px; - font-family: Tahoma, Geneva, Helvetica, sans-serif; - padding-left: 5px; -} - -article input.gray { - color: #cfcfcf; -} - -article input.black { - color: #333333; -} - -.right div.admin-add { - float: left; - padding-top: 1px; - margin-left: 5px; -} - -.right div.admin-add a { - width: 86px; - text-align: center; - padding-bottom: 5px; -} - -/* Input elements */ - -.niceRadio { - width: 17px; - height: 17px; - display: inline-block; - cursor: pointer; - background: image-url("radio.png"); - overflow: hidden; -} -.radioChecked { - background-position: 0 -17px; -} -.niceRadio input { - margin-left: -18px; -} - -.sel80 { - width: 200px; - padding-bottom: 4px; - text-align: left; -} - -.sel80.aside { - width: 185px; -} -.lineForm, -.lineForm3 { - margin-bottom: 0px; -} - -.niceCheck { - width: 17px; - height: 17px; - display: inline-block; - cursor: pointer; - background: image-url("checkbox.png"); -} -.niceCheck input { - display: none; -} - -.niceCheck-main { - width: 18px; - height: 18px; - display: inline-block; - cursor: pointer; - background: image-url("checkbox-main.png"); -} -.niceCheck-main input { - display: none; -} - -/* Admin build project */ - -section.left { - float: left; - text-align: left; - width: 230px; - margin-left: 250px; -} - -section.right { - float: right; - text-align: left; - width: 200px; - margin-right: 250px; -} - -section .left { - float: left; - margin-right: 4px; -} - -/* Commits history */ - - -article .date-block { - width: 100%; - margin-top: 17px; -} - -article .date-block div.date { - float: left; - background: #bedbf6; - color: #477cae; - border: 1px solid #98bede; - -moz-border-radius-topleft: 4px; - -moz-border-radius-topright: 0px; - -moz-border-radius-bottomright: 0px; - -moz-border-radius-bottomleft: 4px; - -webkit-border-radius: 4px 0px 0px 4px; - border-radius: 4px 0px 0px 4px; - width: 65px; - height: 55px; - padding: 10px; - padding-top: 20px; - -webkit-box-shadow: -1px 0px 0px 1px rgba(0, 0, 0, 0.1); - -moz-box-shadow: -1px 0px 0px 1px rgba(0, 0, 0, 0.1); - box-shadow: -1px 0px 0px 1px rgba(0, 0, 0, 0.1); - font-size: 14px; - text-align: center; -} - -article .date-block div.messages { - float: left; - border: 1px solid #cfdde7; - -moz-border-radius-topleft: 0px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; - -moz-border-radius-bottomleft: 4px; - -webkit-border-radius: 0px 4px 4px 4px; - border-radius: 0px 4px 4px 4px; - padding: 10px; - padding-bottom: 0px; - width: 746px; -} - -article .date-block div.message { - border: 1px solid #d6d6d6; - -moz-border-radius-topleft: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; - -moz-border-radius-bottomleft: 4px; - -webkit-border-radius: 4px 4px 4px 4px; - border-radius: 4px 4px 4px 4px; - padding: 6px; - margin-bottom: 10px; -} - -article .date-block div.message div.body { - float: left; - text-align: left; -} - -article .date-block div.message div.code { - float: right; - margin: -7px 0px 0px 640px; - position: absolute; -} - -article .date-block div.code div.top { - width: 90px; - height: 22px; - border: 1px solid #9dbcd5; - background: #cbdeef; -} - -article .date-block div.code div.bottom { - width: 90px; - text-align: right; -} - -article .date-block div.code div.left { - float: left; - width: 13px; - height: 13px; - padding-left: 2px; - padding-top: 4px; -} - -article .date-block div.code div.right { - float: right; - border: 1px solid #bcd5ea; - background: #FFF; - font-size: 12px; - width: 65px; - height: 14px; - margin: 2px; - padding: 0px 2px 2px 0px; - text-align: center; -} - -article .date-block div.image, .last-commit div.image { - float: left; -} - -article .date-block div.text, .last-commit div.text { - float: left; - padding-left: 10px; - font-size: 12px; -} - -article .date-block div.text span.name, .last-commit span.name { - font-weight: 700; -} - -article .date-block div.text span.date, .last-commit span.date { - font-size: 11px; -} - -article .date-block div.text span.subject img, .last-commit span.subject img { - cursor: pointer; -} - -article .date-block div.fulltext, .last-commit div.fulltext { - font-size: 12px; - padding-top: 10px; - display: none; - /*width: 640px;*/ -} - - -article div.year { - background: #e9f4fb; - border: 1px solid #dfeefa; - border-radius: 5px; - width: 760px; - color: 477cae; - text-align: center; - font-size: 12px; - padding: 4px; - margin-left: 87px; - margin-top: 30px; - margin-bottom: 30px; -} - -article div.year p{ - margin: 0; - padding: 0; - color: #477CAE; -} - -div.pagination.tmargin30 { - margin-top: 30px; -} - -/* Create issue */ - -.bordered.nopadding, .right.nopadding { - padding-top: 0px; -} - -p.tmargin5 { - margin-top: 5px; -} - -aside input { - height: 25px; - width: 170px; - border: 1px solid #dedede; - border-radius: 4px; - padding: 0px 5px; - font-family: Tahoma, Geneva, Helvetica, sans-serif; - font-size: 12px; - margin-bottom: 5px; - margin-top: 5px; -} - -aside input.gray { - color: #cfcfcf; -} - -aside input.black { - color: #333333; -} - -div.people { - width: 202px; - clear: both; - cursor: pointer; - margin-left: -15px; - padding: 5px; - padding-left: 10px; - padding-right: 0px; -} - -div.people div.avatar, div.avatar { - float: left; - padding-left: 5px; -} - -div.people div.name, div.name { - padding-top: 4px; - padding-left: 3px; - float: left; -} - -aside div.select, div.people:hover { - background: #dcecfa; -} - -div.label.selected, div.label { - width: 196px; - clear: both; - cursor: pointer; - margin-left: -15px; - padding: 5px; - padding-left: 15px; -} - -div.label.selected:hover, div.label:hover { - background: #dcecfa; -} - -div.labeltext.selected { - float: left; - margin-left: 2px; - font-size: 12px; - margin-top: 0px; - padding-left: 3px; - padding-right: 3px; - color: #FFF; - padding-top: 1px; - padding-bottom: 1px; - border-radius: 2px; -} - -div.label div.flag { - height: 11px; - width: 3px; - background: #39b54a; - float: left; - margin-top: 3px; - margin-right: 3px; - border-radius: 2px; -} - -.right span.small-text { - font-size: 11px; -} - -.right .bpadding10, .all .bpadding10 { - padding-bottom: 10px; -} - - -/* Issue page */ - -aside div.switcher, aside div.switcher-off { - height: 23px; - width: 194px; - background: image-url("switch-on.png"); - color: #FFF; - font-size: 12px; - cursor: pointer; -} - -aside div.switcher-off { - background: image-url("switch-off.png"); -} - -aside div.switcher div.swleft, aside div.switcher-off div.swleft { - float: left; - width: 96px; - text-align: center; - padding-top: 3px; -} - -aside div.switcher div.swright, aside div.switcher-off div.swright { - float: right; - width: 96px; - text-align: center; - padding-top: 3px; -} - -p.non-view { - display: none; -} - -div.non-view { - display: none; -} - -div.view { - display: block; -} - -div.nopointer { - cursor: default; -} - -div.nopointer:hover { - background: none; -} - -a.button.tmargin10, input[type="submit"].tmargin10 { - margin-top: 10px; -} - -h3.tmargin0 { - margin-top: 0px; -} - -h3.bmargin10 { - margin-bottom: 10px; -} - -.right div.comment { - text-align: left; - border: 1px solid #b3cce0; - -moz-border-radius-topleft: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; - -moz-border-radius-bottomleft: 4px; - -webkit-border-radius: 4px 4px 4px 4px; - border-radius: 4px 4px 4px 4px; - padding: 6px; - margin-bottom: 10px; - width: 631px; - background: #dcecfa; -} - -.right div.comment div.issue-left { - float: left; - font-size: 12px; - margin-top: 4px; -} - -.right div.comment div.issue-right { - float: right; -} - -.right div.comment textarea { - height: 110px; - width: 618px; - border: 1px solid #dedede; - border-radius: 4px; - padding: 5px; - font-family: Tahoma, Geneva, Helvetica, sans-serif; - font-size: 12px; - color: #292929; - margin: 10px 0px; -} - -.right div.comment-closed { - display: none; -} - -.right div.comment-closed div.state { - float: left; - padding: 2px 0px 2px 0px; - background: #bd4d40; - color: #FFF; - font-size: 12px; - border: 1px solid #924f52; - -moz-border-radius-topleft: 2px; - -moz-border-radius-topright: 0px; - -moz-border-radius-bottomright: 0px; - -moz-border-radius-bottomleft: 2px; - -webkit-border-radius: 2px 0px 0px 2px; - border-radius: 2px 0px 0px 2px; - width: 80px; - text-align: center; -} - -.right div.comment-closed div.text { - border: 1px solid #dce6ed; - -moz-border-radius-topleft: 2px; - -moz-border-radius-topright: 2px; - -moz-border-radius-bottomright: 2px; - -moz-border-radius-bottomleft: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; - float: left; - width: 561px; -} - -.right div.comment-closed div.avatar { - float: left; - padding: 5px; -} - -.right div.comment-closed div.name { - float: left; - font-size: 12px; - padding-top: 9px; -} - -div.description-top { - background: #dcecfa; - font-size: 12px; - color: #292929; - border: 1px solid #a9c6dd; - height: 38px; - width: 100%; - margin-bottom: 20px; -} - -div.description-top div.img { - float: left; - padding-left: 10px; - margin-top: 14px; -} - -div.description-top input.name { - float: left; - margin-top: 5px; - margin-left: 10px; - background: #FFF; - border: 1px solid #d1deeb; - height: 21px; - width: auto; - color: #292929; - font-size: 11px; - width: 415px; - padding: 2px 5px 3px; -} - -div.description-top div.role { - float: left; - margin-top: 11px; - margin-left: 10px; - font-size: 11px; -} - - div.fork { - float: right; - margin-top: 5px; -} - div.fork p { - float: right; - margin-top: 5px; - margin-right: 2px; -} - -div.description-top div.fork { - margin-right: 10px; -} - -.all div.description { - text-align: left; -} - -.all div.description h3{ - color: #292929; - font-weight: 700; - font-size: 14px; - margin-bottom: 5px; - margin-top: 5px; -} - -.all div.description p{ - font-size: 12px; - padding: 0; - margin: 0; - color: #292929; -} - -.all div.last-commit { - border: 1px solid #d6d6d6; - -moz-border-radius-topleft: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; - -moz-border-radius-bottomleft: 4px; - -webkit-border-radius: 4px 4px 4px 4px; - border-radius: 4px 4px 4px 4px; - padding: 6px; - margin: 10px 0px; -} - - -/* Project main page */ - -table.tablesorter.project .th1 { - width: 130px; - /*padding-left: 17px;*/ -} - -table.tablesorter.project .th2 { - width: 110px; - /*padding-left: 17px;*/ -} - -table.tablesorter.project .th3 { - width: 450px; -} - -table.tablesorter.project .th4 { - /*padding-left: 17px;*/ -} - -table.tablesorter.project div.name { - float: left; - margin-top: 0px; -} - -table.tablesorter.project div.pic { - float: left; - padding-right: 5px; -} - -a.files-see { - color: #565657; - text-decoration: underline; -} - -div.file { - border: 1px solid #dddddd; - margin-top: 10px; -} - -div.file div.top { - height: 28px; - background: #ededed; - -webkit-box-shadow: 0px 3px 3px -1px rgba(18, 86, 135, 0.2); - -moz-box-shadow: 0px 3px 3px -1px rgba(18, 86, 135, 0.2); - box-shadow: 0px 3px 3px -1px rgba(18, 86, 135, 0.2); - position: relative; - z-index: 99; -} - -div.file div.top div.l { - float: left; - margin: 6px 0px 0px 10px; -} - -div.file div.top div.r { - float: right; - margin: 6px 10px 0px 0px; -} - -div.files div.l { - float: left; - margin-bottom: 5px; -} - -div.files div.r { - float: right; - display: none; -} - -div.file { - margin-bottom: 10px; -} - -textarea.commit-message { - height: 60px; - width: 845px; - resize: none; - border: 1px solid #dedede; - border-radius: 4px; - padding: 5px; - font-family: Tahoma, Geneva, Helvetica, sans-serif; - font-size: 12px; - margin-top: 5px; -} - -div.files div.l p{ - padding: 0; - margin: 5px 0px 0px 0px; -} - - -/* Code */ - -div.gutter { - float: left; - border: 0 !important; - padding: 10px 5px 10px 0px; - font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; - background: #EDEDED; - width: 40px; - text-align: right; -} - - -/* Tracker */ - -table td.width18 { - width: 18px; -} - -table td.width135 { - width: 135px; -} - -table td.width145 { - width: 145px; -} - -.width125 { - width: 125px; -} - -table td.width30 { - width: 30px; -} - -table td.width30.right { - text-align: right; -} - -div.bordered.bpadding20 { - padding-bottom: 20px; -} - -table.tracker-lables td { - padding: 1px; -} - -table.tracker-lables div.label { - width: auto; - clear: both; - cursor: default; - margin-left: -15px; - padding: 5px; - padding-left: 15px; - text-align: left; -} - -table.tracker-lables div.label:hover { - background: none; -} - -div.blue-switcher { - height: 19px; - width: 258px; - border: 1px solid #a0a0a1; - border-radius: 3px; - background-color: #292929; - color: #FFF; - -webkit-box-shadow: inset 0px 2px 5px 0px rgba(0, 0, 0, 0.3); - -moz-box-shadow: inset 0px 2px 5px 0px rgba(0, 0, 0, 0.3); - box-shadow: inset 0px 2px 5px 0px rgba(0, 0, 0, 0.3); - float: right; -} - -div.blue-switcher div.open { - float: left; - padding: 1px 0px 2px 0px; - width: 128px; - text-align: center; - cursor: pointer; - position: relative; - z-index: 3; -} - -div.blue-switcher div.selected { - background-image: -webkit-gradient(linear, left top, left bottom, from(#619dd2), to(#125687)); - background-image: -webkit-linear-gradient(top, #619dd2, #125687); - background-image: -moz-linear-gradient(top, #619dd2, #125687); - background-image: -ms-linear-gradient(top, #619dd2, #125687); - background-image: -o-linear-gradient(top, #619dd2, #125687); - background-image: linear-gradient(top, #619dd2, #125687); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#619dd2', EndColorStr='#125687'); - border-radius: 2px; - height: 18px; - width: 128px; - -webkit-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.5); - -moz-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.5); - box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.5); - position: absolute; - margin: 0px; - z-index: 2; - -} - -div.blue-switcher div.closed { - float: right; - padding: 1px 0px 0px 0px; - width: 128px; - text-align: center; - cursor: pointer; - position: relative; - z-index: 3; -} - -table.tablesorter.tracker th.th1{ - width: 50px; -} - -table.tablesorter.tracker td.td0{ - width: 10px; - padding-right: 0px; -} - -table.tablesorter.tracker td.td3{ - width: 120px; - padding-top: 10px; -} - -table.tablesorter.tracker td.td3 div.code { - height: 19px; - width: 15px; - background: #FFF; - color: #009fe3; - border: 1px solid #83d1f2; - font-size: 16px; - padding: 1px 0px 0px 5px; - float: left; - margin-right: 5px; - cursor: pointer; -} - -table.tablesorter.tracker td.td3 div.avatar { - float: left; - margin-right: 5px; - cursor: pointer; -} - -table.tablesorter.tracker td.td3 div.answers { - height: 20px; - background: #FFF; - color: #009fe3; - border: 1px solid #83d1f2; - font-size: 16px; - float: left; - cursor: pointer; -} - -table.tablesorter.tracker td.td3 div.answers div.pic { - float: left; - margin: 2px; -} - -table.tablesorter.tracker td.td3 div.answers div.count { - float: left; - margin: 0px 5px 0px 2px; -} - -table.tablesorter.tracker div.smalltext { - font-size: 11px; - color: #b0b0b1; - float: left; - margin-top: 3px; -} - - -div.label.selected.tracker { - width: auto; - clear: both; - cursor: default; - margin-left: 0px; - padding: 5px; - float: right; - margin-top: -6px; -} - -div.label.selected.tracker:hover { - background: none; -} - - -div.label.edit { - width: 196px; - clear: both; - cursor: default; - margin-left: -15px; - padding: 5px; - padding-left: 15px; -} - -div.label.edit:hover{ - background: none; -} - -div.labeltext.edit { - float: left; - margin-left: 2px; - font-size: 12px; - margin-top: 0px; - margin-bottom: 5px; - padding-left: 3px; - padding-right: 3px; - color: #FFF; - padding-top: 1px; - padding-bottom: 1px; - border-radius: 2px; - width: 175px; - cursor: default; -} - -div.labeltext.edit div.text { - float: left; -} - -div.labeltext.edit div.delete { - float: right; - cursor: pointer; - margin-top: 1px; -} - -div.labeltext a { - text-decoration: none; - color: #292929; -} - -div.labeltext.edit a { - text-decoration: none; - color: #FFF; -} - -aside div.colors { - margin: 10px 0px; -} - -aside div.colors div.color { - float: left; - width: 22px; - height: 22px; - margin-right: 5px; - border-radius: 4px; - -webkit-box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.8); - -moz-box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.8); - box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.8); - cursor: pointer; -} - -aside div.colors div.choose { - height: 14px; - width: 14px; - padding: 4px; -} - -aside div.colors div.choose.selected, aside div.colors div.choose:hover { - background: image-url("choose.png") no-repeat 50% 50%; - height: 14px; - width: 14px; - padding: 4px; -} - -aside div.lefter { - float: left; -} - -aside div.righter { - float: right; - margin-right: 15px; -} - -tr.label-active { - background: #DDD; - border-radius: 3px; -} - -/* Wiki */ - -span.wiki-gray { - color: #b0b0b1; -} - -.right table.wiki { - border: 1px solid #e2e2e2; - border-bottom: none; - margin-top: 10px; -} - -.right table.wiki td { - border-bottom: 1px solid #e2e2e2; - padding: 8px; -} - -.right table.wiki tr.history td.td1{ - width: 5px; -} - -.right table.wiki tr.history td.td2{ - width: 180px; -} - -a.button.rigth { - float: right; -} - -div.r { - float: right; - margin-left: 10px; -} - -h3.wiki { - color: #477cae; - font-size: 16px; -} - -a.button.width100 { - width: 100px; -} - -.div-tracker-labels { - margin: 2px 13px 2px 0px; - cursor: pointer; - border-radius: 4px; -} - -.div-label-left { - float: left; - width: 150px; -} - -.div-label-right { - float: right; - width: 30px; - text-align: right; - padding-top: 4px; - padding-right: 3px; -} - -div.div-label-left div.label { - width: auto; - clear: both; - margin-left: -15px; - padding: 5px; - padding-left: 15px; - text-align: left; -} - -div.div-label-left div.label:hover { - background: none; -} - -/* Monitoring */ - -aside div.table { - margin-top: 5px; -} - -h3.small { - font-size: 12px; - margin: 0px; - padding: 3px 0px; -} - -table.tablesorter th.lpadding16 { - padding-left: 16px; -} - -div.right.slim { - padding: 5px 14px 40px; - width: 695px; -} - -img.delete-row { - cursor: pointer; -} - -table tbody tr.error td { - background: #fedede; -} - -table tbody tr.success td { - background: #e3edb7; -} - -table.tablesorter.width565 { - width: 565px; -} - -table.tablesorter thead th { - padding-left: 5px; -} - -/* Create group */ - -div.right-error { - float: left; - width: 369px; - height: 59px; - background: image-url("error-groups.png"); - margin: 0px 0px 5px -3px; - text-align: center; -} - -div.right-error p { - margin: 0; - padding: 27px 0px 0px 0px; -} - -div.rightlist.nomargin { - margin: 0; -} - -article div.rightlist input.error { - border: 1px solid #bd4d40; - -webkit-box-shadow: 0px 0px 2px 0px rgba(189, 77, 64, 1); - -moz-box-shadow: 0px 0px 2px 0px rgba(189, 77, 64, 1); - box-shadow: 0px 0px 2px 0px rgba(189, 77, 64, 1); -} - -/* Group pages */ - -article div.groups-profile { - float: left; -} - -article div.groups-profile a { - margin: 0px 0px 0px 5px; -} - -article div.groups-profile img { - margin: 2px 0px 0px 0px; -} - -table.tablesorter.group-list th.th2 { - width: 540px; -} - -/* Platform */ - -table.tablesorter.create-platform th.th1 { - /*padding-left: 17px;*/ - width: 120px; -} - -div.right div.left { - float: left; - margin-right: 5px; -} -table.tablesorter.platform-products th.th1 { - /*padding-left: 17px;*/ - width: 560px; -} - -table.tablesorter.platform-products td.td2 { - text-align: center; -} - -table.tablesorter.platform-repos th.th1 { - /*padding-left: 17px;*/ - width: 480px; -} - -table.tablesorter.platform-repos th.th2 { - /*padding-left: 17px;*/ - width: 80px; -} - -table.tablesorter.platform-repos td.td3 { - text-align: center; -} - -div.new-owner div.field { - float: left; - margin-right: 10px; -} - -div.new-owner div.field input { - width: 230px; -} - -div.new-owner div.search { - float: left; -} - -.tpadding10 { - padding-top: 10px; -} - -article div.all div.hr { - border-bottom: 1px solid #dedede; - width: 565px; - padding-top: 30px; - margin-bottom: 30px; -} - -table.tablesorter.platform-product-main th.th1 { - /*padding-left: 17px;*/ - width: 60px; -} - -table.tablesorter.platform-product-main th.th2 { - /*padding-left: 17px;*/ - width: 400px; -} - -table.tablesorter.platform-product-main th.th3 { - padding-left: 0px; -} - -table.tablesorter.platform-product-main th.th4 { - /*padding-left: 17px;*/ - width: 150px; -} - -div.right.rpadding0 { - padding-right: 0px; -} - -article div.loadFile div.btn { - float: left; -} - -article div.loadFile div.name { - float: left; - margin-left: 20px; - padding-top: 4px; -} - -/* Profile */ - -.bpadding10 { - padding-bottom: 10px; -} - -article div.rightlist div.load { - float: left; - margin-left: 40px; -} - -.notify { - border: 1px solid #c86b60; - background: #f4e1df; - border-radius: 4px; - width: 100%; - margin-top: 20px; -} - -.notify p { - padding: 5px 10px; -} - -.notify.blue { - border: 1px solid #a9c6dd; - background: #dcecfa; - border-radius: 1px; - width: 555px; - margin-top: 20px; - text-align: right; - padding: 5px; -} - -.notify.blue div.green { - border: 1px solid #bad099; - background: #d7e599; - float: left; -} - -/* Pagination */ - -div.pagination em { - font-style: normal; -} - -div.pagination em, div.pagination span, div.pagination a { - border: 1px solid #dddddd; - border-radius: 1px; - background: #ededed; - padding: 3px 7px; -} - -div.pagination em.current { - background: #d5e7f9; - border: 1px solid #c1daed; -} - -div.pagination a { - color: #4c90d0; -} - -/*404*/ - -article div.all.error404 { - background: image-url("404.png") no-repeat 59% 0; - height: 500px; - text-align: center; -} - -article div.all.error404 h1 { - margin: 0; - padding: 0; - margin-top: 165px; - font-size: 48px; - font-weight: normal; -} - -article div.all.error404 h1 span { - color: #4496d0; -} - -article div.all.error404 h2 { - margin: 0; - padding: 0; - margin-top: 5px; - font-size: 18px; - font-weight: normal; -} - -article div.all.error404 p { - margin: 0 auto; - padding: 0; - text-align: center; - font-size: 14px; -} - -article div.all.error404 p.pages { - margin-top: 72px; - width: 280px; -} - -article div.all.error404 p.search { - margin-top: 80px; - width: 230px; -} - -/*search*/ - -input.button.width100 { - width: 100px; -} - -input[type="text"].exsearch { - height: 16px; - border: 1px solid #dedede; - border-radius: 4px; - padding: 5px; - font-family: Tahoma, Geneva, Helvetica, sans-serif; - font-size: 12px; - width: 520px; - margin-right: 10px; -} - -div.lineForm.leftside.rmargin10 { - margin-right: 10px; -} - -table.tablesorter.bmargin5 { - margin-bottom: 1px; -} - -div.width400 { - width: 400px; - float: left; -} - -div.width400.rmargin55 { - margin-right: 55px; -} - -div.tmargin10 { - margin-top: 10px; -} - -/*My projects*/ - -article h3 a { - font-size: 14px; -} +html, body { + margin: 0; + padding: 0; + font-family: Tahoma, Geneva, Helvetica, sans-serif; + color: #292929; + background: #1f60a1 image-url("bg.png") repeat-x; + min-width: 940px; + min-height: 600px; + text-align: center; + height: 100%; +} + +header, section, footer, aside, nav, article, menu { + display: block; +} + +input[type="text"]:focus { outline: none; } + +input[type="password"]:focus { outline: none; } + +input:focus { outline: none; } + +select:focus { outline: none; } + +a img { border: none; } + +.wrap { + width: 940px; + margin: 0 auto; + text-align: center; + border: 1px solid #3f668c; + -webkit-box-shadow: 0px 0px 7px 0px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 0px 0px 7px 0px rgba(0, 0, 0, 0.5); + box-shadow: 0px 0px 7px 0px rgba(0, 0, 0, 0.5); + background: #FFF; + min-height: 92%; +} + +.wrap.columns { + background: #FFF image-url("page-bg.png") repeat-y; +} + +.both { + clear: both; +} + +/* Top menu */ + +header { + -webkit-box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.4); + -moz-box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.4); + box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.4); + position: relative; + z-index: 1000; +} + +header div.left { + background: image-url("top-left.png"); + height: 46px; + width: 14px; + float: left; +} + +header div.middle { + background: image-url("top-middle.png"); + float: left; + height: 46px; + width: 912px; +} + +header div.right { + background: image-url("top-right.png"); + height: 46px; + width: 14px; + float: right; +} + +/* Left part of top menu*/ + +header menu { + float: left; + margin: 0; + padding: 0; +} + +header menu ul { + list-style: none; + margin: 0; + padding-top: 10px; +} + +header menu ul li { + display: inline; +} + +header menu ul li a { + font-size: 12px; + color: #FFF; + text-decoration: none; + height: 43px; + padding: 15px 10px 15px 10px; +} + +header menu ul li a:hover { + color: #cee7ff; +} + +header menu ul li a.first { +} + +header menu ul li a.active { + background: image-url("menu-hover.png") repeat-x; +} + +header div.logo { + float: left; + margin-top: 5px; + padding-left: 0px; + padding-right: 0px; +} + +/* Right part of top menu */ + +header div.information { + float: right; +} + +header div.search { + float: left; + margin: 10px 0px 0px 0px; + -moz-border-radius-topleft: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-bottomright: 3px; + -moz-border-radius-bottomleft: 3px; + -webkit-border-radius: 3px 3px 3px 3px; + border-radius: 3px 3px 3px 3px; + background: #FFF; + border: 1px solid #7691aa; +} + +header div.search div.pic { + background: image-url("search-button.png"); + height: 22px; + width: 24px; + float: left; +} + +header div.search div.field { + float: left; + margin: -1px 0px 0px 0px; +} + +header div.search div.field input { + border: none; + height: 18px; + background: none; + width: 132px; + font-size: 12px; + font-family: Arial; + padding: 2px 0px 0px 0px; +} + +header div.search div.field input.gray { + color: #cfcfcf; +} + +header div.search div.field input.black { + color: #333333; +} + +header div.avatar { + float:left; + padding: 6px 10px 10px 10px; + +} + +header div.information div.active { + background: image-url("menu-hover.png") repeat-x; +} + +header div.information div.user { + float: left; + margin-left: 14px; +} + +header div.profile { + float: left; + text-align: right; + color: #FFF; + font-size: 12px; + padding-top: 12px; +} + +header div.profile a { + color: #FFF; + text-decoration: none; + padding-right: 10px; +} + +header div.profile a:hover { + text-decoration: underline; +} + + +header div.droplist-wrap { + margin: -4px 0px 0px 0px; + width: 151px; + float: right; +} + +header div.droplist { + background: image-url("bg-droplist.png") repeat-x; + height: 91px; + width: 151px; + -webkit-box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5); + box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5); + position: absolute; + margin-top: 0px; + border-radius: 0px 0px 4px 4px; + display: none; + text-align: right; + z-index: 9999; +} + +header div.droplist-wrap div.a { + margin-top: 5px; +} + +header div.droplist a{ + position: relative; + padding-left: 15px; + font-size: 12px; + color: #447cae; + text-decoration: none; + padding-right: 15px; + margin-top: 10px; +} + +header div.droplist a:hover{ + text-decoration: underline; +} + + +/* Submenu */ + +.sub-menu { + height: 38px; + margin: -7px 0px 0px 0px; + padding: 0px 0px 0px 15px; + background: #ededed; + position: relative; + z-index: 100; + border-bottom: 1px solid #FFF; + -webkit-box-shadow: 0px 5px 3px -3px rgba(18, 86, 135, 0.2); + -moz-box-shadow: 0px 5px 3px -3px rgba(18, 86, 135, 0.2); + box-shadow: 0px 5px 3px -3px rgba(18, 86, 135, 0.2); +} + +.sub-menu div.left { + float: left; + width: 200px; + border-right: 1px solid #dcdcdc; + font-size: 12px; + text-align: left; + font-weight: 700; + padding: 10px 0px 0px 0px; + height: 21px; +} + +.sub-menu div.right { + float: left; +} + + +.sub-menu nav { + float: left; + margin: 0px 0px 0px 0px; +} + +.sub-menu nav ul { + list-style: none; + text-align: left; + padding: 0; + margin: 0; + padding-top: 4px; +} + +.sub-menu nav ul li { + display: inline; +} + +.sub-menu nav ul li a { + font-size: 12px; + color: #292929; + text-decoration: none; + height: 34px; + padding: 0px 20px 9px 20px; +} + +.sub-menu nav ul li a.active { + background: image-url("submenu-hover.png") repeat-x scroll 0 100% transparent; +} + +.sub-menu nav ul li a:hover { + color: #2b6daf; +} + +/* Page markup */ + +article { + font-size: 12px; +} + +aside { + float: left; + width: 215px; +} + +article div.right { + float: right; + width: 645px; + padding: 20px 40px 40px 40px; + text-align: left; +} + +article div.right.bigpadding { + width: 445px; + padding: 20px 140px 40px 140px; +} + +article div.right.middlepadding { + width: 510px; + padding: 20px 120px 40px 50px; +} + +article div.right.middlepadding div.rightlist{ + width: 300px; +} + +article div.right.middlepadding div.rightlist input{ + width: 300px; +} + +article div.right.middlepadding div.rightlist textarea{ + width: 300px; +} + +article div.all { + width: 855px; + padding: 20px 40px 20px 40px; + text-align: left; +} + +article div.all.bigpadding { + width: 605px; + padding: 0px 40px 20px 200px; + text-align: left; +} + +article div.all.verybigpadding { + width: 545px; + padding: 0px 40px 20px 200px; + text-align: left; +} + +article div.all.verybigpadding div.left { + float: left; +} + +article div.all.verybigpadding div.left img{ + padding-right: 40px; + margin-top: 20px; +} + +article div.all.verybigpadding div.left h3, article div.all.verybigpadding div.left h4, article div.all.verybigpadding div.left p{ + width: 420px; +} + +article div.all.verybigpadding div.left .tmargin5 { + padding-top: 5px; + position: relative; +} + + +/* Left part of page markup */ + +aside div.bordered { + border-bottom: 1px solid #dee5eb; + text-align: left; + padding: 20px 0px 30px 15px; +} + +aside div.block { + text-align: left; + padding: 10px 0px 30px 15px; +} + +/* Common page parts markups */ + +article h4 { + font-size: 12px; + margin-bottom: 0px; + padding-bottom: 2px; +} + +article h4.nomargin { + margin: 0px; +} + +article p { + margin: 0; + padding: 0; +} + +div.expand-gray-down, div.expand-gray-up { + height: 10px; + width: 12px; + float: left; + margin: 3px 0px 0px 3px; + cursor: pointer; +} + +div.expand-gray-down { + background: image-url("expand-gray.png") no-repeat; +} + +div.expand-gray-up { + background: image-url("expand-gray2.png") no-repeat; +} + +article a.button { + display: inline-block; + white-space: nowrap; + background-color: #125687; + background-image: -webkit-gradient(linear, left top, left bottom, from(#68a3d8), to(#125687)); + background-image: -webkit-linear-gradient(top, #68a3d8, #125687); + background-image: -moz-linear-gradient(top, #68a3d8, #125687); + background-image: -ms-linear-gradient(top, #68a3d8, #125687); + background-image: -o-linear-gradient(top, #68a3d8, #125687); + background-image: linear-gradient(top, #68a3d8, #125687); + filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#68a3d8', EndColorStr='#125687'); + border: 1px solid #5084b4; + padding: 4px 20px 6px; + margin: 0; + font-size: 12px; + text-decoration: none; + color: #FFF; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + text-align: center; +} + +article a.button:hover{ + background-color: #34719d; + background-image: -webkit-gradient(linear, left top, left bottom, from(#7fb3e1), to(#34719d)); + background-image: -webkit-linear-gradient(top, #7fb3e1, #34719d); + background-image: -moz-linear-gradient(top, #7fb3e1, #34719d); + background-image: -ms-linear-gradient(top, #7fb3e1, #34719d); + background-image: -o-linear-gradient(top, #7fb3e1, #34719d); + background-image: linear-gradient(top, #7fb3e1, #34719d); + filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#7fb3e1', EndColorStr='#34719d'); + text-decoration: none; +} + + + +article a.button:active{ + background-color: #125687; + background-image: -webkit-gradient(linear, left top, left bottom, from(#68a3d8), to(#125687)); + background-image: -webkit-linear-gradient(top, #68a3d8, #125687); + background-image: -moz-linear-gradient(top, #68a3d8, #125687); + background-image: -ms-linear-gradient(top, #68a3d8, #125687); + background-image: -o-linear-gradient(top, #68a3d8, #125687); + background-image: linear-gradient(top, #68a3d8, #125687); + filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#68a3d8', EndColorStr='#125687'); +} + +article a.disabled { + background-color: #888888; + background-image: -webkit-gradient(linear, left top, left bottom, from(#aaaaaa), to(#888888)); + background-image: -webkit-linear-gradient(top, #aaaaaa, #888888); + background-image: -moz-linear-gradient(top, #aaaaaa, #888888); + background-image: -ms-linear-gradient(top, #aaaaaa, #888888); + background-image: -o-linear-gradient(top, #aaaaaa, #888888); + background-image: linear-gradient(top, #aaaaaa, #888888); + filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#aaaaaa', EndColorStr='#888888'); + cursor: default; + color: #d8d8d8; + border: 1px solid #aaaaaa; + cursor: default; + text-align: center; +} + +article input[type="file"] { + + +} + +article input[type="submit"] { + display: inline-block; + white-space: nowrap; + background-color: #125687; + background-image: -webkit-gradient(linear, left top, left bottom, from(#68a3d8), to(#125687)); + background-image: -webkit-linear-gradient(top, #68a3d8, #125687); + background-image: -moz-linear-gradient(top, #68a3d8, #125687); + background-image: -ms-linear-gradient(top, #68a3d8, #125687); + background-image: -o-linear-gradient(top, #68a3d8, #125687); + background-image: linear-gradient(top, #68a3d8, #125687); + filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#68a3d8', EndColorStr='#125687'); + border: 1px solid #5084b4; + padding: 3px 20px 5px; + margin: 0; + font-size: 12px; + text-decoration: none; + color: #FFF; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + text-align: center; + height: auto; + width: auto; + font-family: Tahoma; +} + +article input[type="submit"]:hover{ + background-color: #34719d; + background-image: -webkit-gradient(linear, left top, left bottom, from(#7fb3e1), to(#34719d)); + background-image: -webkit-linear-gradient(top, #7fb3e1, #34719d); + background-image: -moz-linear-gradient(top, #7fb3e1, #34719d); + background-image: -ms-linear-gradient(top, #7fb3e1, #34719d); + background-image: -o-linear-gradient(top, #7fb3e1, #34719d); + background-image: linear-gradient(top, #7fb3e1, #34719d); + filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#7fb3e1', EndColorStr='#34719d'); + text-decoration: none; + cursor: pointer; +} + + + +article input[type="submit"]:active{ + background-color: #125687; + background-image: -webkit-gradient(linear, left top, left bottom, from(#68a3d8), to(#125687)); + background-image: -webkit-linear-gradient(top, #68a3d8, #125687); + background-image: -moz-linear-gradient(top, #68a3d8, #125687); + background-image: -ms-linear-gradient(top, #68a3d8, #125687); + background-image: -o-linear-gradient(top, #68a3d8, #125687); + background-image: linear-gradient(top, #68a3d8, #125687); + filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#68a3d8', EndColorStr='#125687'); +} + +article input[type="submit"]:disabled { + background-color: #888888; + background-image: -webkit-gradient(linear, left top, left bottom, from(#aaaaaa), to(#888888)); + background-image: -webkit-linear-gradient(top, #aaaaaa, #888888); + background-image: -moz-linear-gradient(top, #aaaaaa, #888888); + background-image: -ms-linear-gradient(top, #aaaaaa, #888888); + background-image: -o-linear-gradient(top, #aaaaaa, #888888); + background-image: linear-gradient(top, #aaaaaa, #888888); + filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#aaaaaa', EndColorStr='#888888'); + cursor: default; + color: #d8d8d8; + border: 1px solid #aaaaaa; + cursor: default; + text-align: center; +} + + +article h3{ + font-size: 14px; + color: #292929; + margin-bottom: 0; + padding-bottom: 2px; +} + +article h3.fix { + margin-top: 0px; + padding-top: 0px; +} + +article a{ + color: #447cae; + font-size: 12px; + text-decoration: none; + padding: 0px 0px; +} + +article a:hover{ + text-decoration: underline; +} + +/* Right part of page markup */ + +article div.right div.hr { + border-bottom: 1px solid #dedede; + width: 100%; + padding-top: 30px; + margin-bottom: 30px; +} + +article div.right div.hr.bottom { + margin-bottom: 10px; + padding-top: 20px; +} + +article div.right div.hr.top { + padding-top: 7px; + margin-bottom: 20px; +} + +article div.leftside { + float: left; +} + +article div.rightside { + float: right; +} + +article div.all.bigpadding div.rightside { + margin-right: 40px; +} + +.lefter { + float: left; + margin-right: 5px; +} + +.lefter span.gap { + padding-right: 59px; +} + +.lefter.top { + margin-top: -6px; +} + +.w25 { + width: 25px; +} + +.w420 { + width: 420px; + padding-bottom: 20px; +} + +.padd25 { + padding-left: 25px; +} + +.width70 { + width: 70px; +} + +a.button.width81 { + width: 79px; + padding: 4px 0px; + text-align: center; + +} + + +/* Footer */ + +footer { + height: 32px; + padding-left: 15px; + width: 900px; + margin: 0 auto; + text-align: center; +} + +footer ul { + margin: 0; + padding: 0; + list-style: none; + font-size: 12px; + color: #FFF; + padding-top: 10px; + text-align: left; +} + +footer ul li { + display: inline; +} + +footer ul li a { + font-size: 12px; + color: #FFF; + text-decoration: none; +} + +footer ul li a:hover { + text-decoration: underline; +} + +/* Main page */ + +aside div.bordered table{ + padding: 0; + margin: 0; + padding-bottom: 0px; + margin-left: -10px; +} + +aside div.bordered table td{ + font-size: 12px; + padding: 1px 0px 0px 0px; +} + +aside div.block table td { + text-align: right; + padding: 2px 3px 1px 3px; +} + + +aside div.block table td.first{ + width: 150px; + text-align: left; +} + +article div.right div.messages { + background: #e9f4fb; + border: 1px solid #dfeefa; + border-radius: 5px; + width: 100%; + color: #477cae; + text-align: center; + font-size: 12px; + padding: 4px 0px 4px 0px; + cursor: pointer; + margin: 15px 0px 15px 0px; +} + +article div.right div.messages:hover { + background: #dceffa; +} + +article div.right div.messages p{ + margin: 0; + padding: 0; +} + +article div.activity { + border: 1px solid #d6d6d6; + /*width: 614px;*/ + border-radius: 5px; + padding: 6px; + margin-top: 15px; + color: #333; +} + +article div.activity div.top div.image { + float: left; +} + +article div.activity div.top div.text { + float: left; + padding-left: 10px; + font-size: 12px; +} + +article div.activity div.top div.text span.name { + font-weight: 700; +} + +article div.activity div.top div.text span.date { + font-size: 11px; +} + +article div.text span.subject { + float: left; +} + +article div.activity div.top div.text span.subject img { + cursor: pointer; +} + +article div.activity div.fulltext { + font-size: 12px; + padding-top: 10px; + display: none; +} + +article div.activity div.fulltext.view { + display: block; +} + +/* Admin page */ + +.admin-preferences ul { + list-style: none; + margin: 0; + padding: 0; + margin-top: 20px; + width: 215px; + text-align: left; +} + +.admin-preferences ul li{ + padding-top: 5px; + padding-bottom: 5px; + width: 215px; +} + +.admin-preferences ul li.active, .admin-preferences ul li:hover { + background: #dcecfa; +} + +.admin-preferences ul li a{ + color: #292929; + text-decoration: none; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 15px; +} + +.right div.leftlist, .all div.leftlist { + float: left; + width: 200px; + margin: 0px 0px 10px 0px; +} + +.right div.rightlist, .all div.rightlist { + float: left; + width: 400px; + font-size: 12px; + color: #292929; + margin: 0px 0px 10px 0px; +} + +.right div.rightlist div.check { + float: left; +} + +.right div.rightlist div.forcheck { + float: left; + margin: 1px 0px 0px 5px; +} +div.rightlist textarea { + height: 110px; + width: 350px; + border: 1px solid #dedede; + border-radius: 4px; + padding: 5px; + font-family: Tahoma, Geneva, Helvetica, sans-serif; + font-size: 12px; +} + +div.rightlist input[type="text"], div.rightlist input[type="password"] { + height: 16px; + width: 350px; + border: 1px solid #dedede; + border-radius: 4px; + padding: 5px; + font-family: Tahoma, Geneva, Helvetica, sans-serif; + font-size: 12px; +} + +/* Admin-members page */ + +div.img { + float: left; +} + + table div.radio { + float: left; + margin: 5px 0px 0px 0px; +} + +div.forimg { + float: left; + margin: 5px 0px 0px 5px; +} + +table div.forradio { + float: left; + margin: 5px 0px 0px 5px; +} + +table span.niceCheck-main { + margin-top: 3px; +} + +div.admin-search { + float: left; +} + +.right div.admin-role { + float: left; +} + +.right div.admin-search input { + width: 300px; + margin-right: 5px; + height: 23px; + border: 1px solid #dedede; + border-radius: 3px; + margin-top: 1px; + font-size: 12px; + font-family: Tahoma, Geneva, Helvetica, sans-serif; + padding-left: 5px; +} + +article input.gray { + color: #cfcfcf; +} + +article input.black { + color: #333333; +} + +.right div.admin-add { + float: left; + padding-top: 1px; + margin-left: 5px; +} + +.right div.admin-add a { + width: 86px; + text-align: center; + padding-bottom: 5px; +} + +/* Input elements */ + +.niceRadio { + width: 17px; + height: 17px; + display: inline-block; + cursor: pointer; + background: image-url("radio.png"); + overflow: hidden; +} +.radioChecked { + background-position: 0 -17px; +} +.niceRadio input { + margin-left: -18px; +} + +.sel80 { + width: 200px; + padding-bottom: 4px; + text-align: left; +} + +.sel80.aside { + width: 185px; +} +.lineForm, +.lineForm3 { + margin-bottom: 0px; +} + +.niceCheck { + width: 17px; + height: 17px; + display: inline-block; + cursor: pointer; + background: image-url("checkbox.png"); +} +.niceCheck input { + display: none; +} + +.niceCheck-main { + width: 18px; + height: 18px; + display: inline-block; + cursor: pointer; + background: image-url("checkbox-main.png"); +} +.niceCheck-main input { + display: none; +} + +/* Admin build project */ + +section.left { + float: left; + text-align: left; + width: 230px; + margin-left: 250px; +} + +section.right { + float: right; + text-align: left; + width: 200px; + margin-right: 250px; +} + +section .left { + float: left; + margin-right: 4px; +} + +/* Commits history */ + + +article .date-block { + width: 100%; + margin-top: 17px; +} + +article .date-block div.date { + float: left; + background: #bedbf6; + color: #477cae; + border: 1px solid #98bede; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 0px; + -moz-border-radius-bottomright: 0px; + -moz-border-radius-bottomleft: 4px; + -webkit-border-radius: 4px 0px 0px 4px; + border-radius: 4px 0px 0px 4px; + width: 65px; + height: 55px; + padding: 10px; + padding-top: 20px; + -webkit-box-shadow: -1px 0px 0px 1px rgba(0, 0, 0, 0.1); + -moz-box-shadow: -1px 0px 0px 1px rgba(0, 0, 0, 0.1); + box-shadow: -1px 0px 0px 1px rgba(0, 0, 0, 0.1); + font-size: 14px; + text-align: center; +} + +article .date-block div.messages { + float: left; + border: 1px solid #cfdde7; + -moz-border-radius-topleft: 0px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px; + -webkit-border-radius: 0px 4px 4px 4px; + border-radius: 0px 4px 4px 4px; + padding: 10px; + padding-bottom: 0px; + width: 746px; +} + +article .date-block div.message { + border: 1px solid #d6d6d6; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px; + -webkit-border-radius: 4px 4px 4px 4px; + border-radius: 4px 4px 4px 4px; + padding: 6px; + margin-bottom: 10px; +} + +article .date-block div.message div.body { + float: left; + text-align: left; +} + +article .date-block div.message div.code { + float: right; + margin: -7px 0px 0px 640px; + position: absolute; +} + +article .date-block div.code div.top { + width: 90px; + height: 22px; + border: 1px solid #9dbcd5; + background: #cbdeef; +} + +article .date-block div.code div.bottom { + width: 90px; + text-align: right; +} + +article .date-block div.code div.left { + float: left; + width: 13px; + height: 13px; + padding-left: 2px; + padding-top: 4px; +} + +article .date-block div.code div.right { + float: right; + border: 1px solid #bcd5ea; + background: #FFF; + font-size: 12px; + width: 65px; + height: 14px; + margin: 2px; + padding: 0px 2px 2px 0px; + text-align: center; +} + +article .date-block div.image, .last-commit div.image { + float: left; +} + +article .date-block div.text, .last-commit div.text { + float: left; + padding-left: 10px; + font-size: 12px; +} + +article .date-block div.text span.name, .last-commit span.name { + font-weight: 700; +} + +article .date-block div.text span.date, .last-commit span.date { + font-size: 11px; +} + +article .date-block div.text span.subject img, .last-commit span.subject img { + cursor: pointer; +} + +article .date-block div.fulltext, .last-commit div.fulltext { + font-size: 12px; + padding-top: 10px; + display: none; + /*width: 640px;*/ +} + + +article div.year { + background: #e9f4fb; + border: 1px solid #dfeefa; + border-radius: 5px; + width: 760px; + color: 477cae; + text-align: center; + font-size: 12px; + padding: 4px; + margin-left: 87px; + margin-top: 30px; + margin-bottom: 30px; +} + +article div.year p{ + margin: 0; + padding: 0; + color: #477CAE; +} + +div.pagination.tmargin30 { + margin-top: 30px; +} + +/* Create issue */ + +.bordered.nopadding, .right.nopadding { + padding-top: 0px; +} + +p.tmargin5 { + margin-top: 5px; +} + +aside input { + height: 25px; + width: 170px; + border: 1px solid #dedede; + border-radius: 4px; + padding: 0px 5px; + font-family: Tahoma, Geneva, Helvetica, sans-serif; + font-size: 12px; + margin-bottom: 5px; + margin-top: 5px; +} + +aside input.gray { + color: #cfcfcf; +} + +aside input.black { + color: #333333; +} + +div.people { + width: 202px; + clear: both; + cursor: pointer; + margin-left: -15px; + padding: 5px; + padding-left: 10px; + padding-right: 0px; +} + +div.people div.avatar, div.avatar { + float: left; + padding-left: 5px; +} + +div.people div.name, div.name { + padding-top: 4px; + padding-left: 3px; + float: left; +} + +aside div.select, div.people:hover { + background: #dcecfa; +} + +div.label.selected, div.label { + width: 196px; + clear: both; + cursor: pointer; + margin-left: -15px; + padding: 5px; + padding-left: 15px; +} + +div.label.selected:hover, div.label:hover { + background: #dcecfa; +} + +div.labeltext.selected { + float: left; + margin-left: 2px; + font-size: 12px; + margin-top: 0px; + padding-left: 3px; + padding-right: 3px; + color: #FFF; + padding-top: 1px; + padding-bottom: 1px; + border-radius: 2px; +} + +div.label div.flag { + height: 11px; + width: 3px; + background: #39b54a; + float: left; + margin-top: 3px; + margin-right: 3px; + border-radius: 2px; +} + +.right span.small-text { + font-size: 11px; +} + +.right .bpadding10, .all .bpadding10 { + padding-bottom: 10px; +} + + +/* Issue page */ + +aside div.switcher, aside div.switcher-off { + height: 23px; + width: 194px; + background: image-url("switch-on.png"); + color: #FFF; + font-size: 12px; + cursor: pointer; +} + +aside div.switcher-off { + background: image-url("switch-off.png"); +} + +aside div.switcher div.swleft, aside div.switcher-off div.swleft { + float: left; + width: 96px; + text-align: center; + padding-top: 3px; +} + +aside div.switcher div.swright, aside div.switcher-off div.swright { + float: right; + width: 96px; + text-align: center; + padding-top: 3px; +} + +p.non-view { + display: none; +} + +div.non-view { + display: none; +} + +div.view { + display: block; +} + +div.nopointer { + cursor: default; +} + +div.nopointer:hover { + background: none; +} + +a.button.tmargin10, input[type="submit"].tmargin10 { + margin-top: 10px; +} + +h3.tmargin0 { + margin-top: 0px; +} + +h3.bmargin10 { + margin-bottom: 10px; +} + +.right div.comment { + text-align: left; + border: 1px solid #b3cce0; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px; + -webkit-border-radius: 4px 4px 4px 4px; + border-radius: 4px 4px 4px 4px; + padding: 6px; + margin-bottom: 10px; + width: 631px; + background: #dcecfa; +} + +.right div.comment div.issue-left { + float: left; + font-size: 12px; + margin-top: 4px; +} + +.right div.comment div.issue-right { + float: right; +} + +.right div.comment textarea { + height: 110px; + width: 618px; + border: 1px solid #dedede; + border-radius: 4px; + padding: 5px; + font-family: Tahoma, Geneva, Helvetica, sans-serif; + font-size: 12px; + color: #292929; + margin: 10px 0px; +} + +.right div.comment-closed { + display: none; +} + +.right div.comment-closed div.state { + float: left; + padding: 2px 0px 2px 0px; + background: #bd4d40; + color: #FFF; + font-size: 12px; + border: 1px solid #924f52; + -moz-border-radius-topleft: 2px; + -moz-border-radius-topright: 0px; + -moz-border-radius-bottomright: 0px; + -moz-border-radius-bottomleft: 2px; + -webkit-border-radius: 2px 0px 0px 2px; + border-radius: 2px 0px 0px 2px; + width: 80px; + text-align: center; +} + +.right div.comment-closed div.text { + border: 1px solid #dce6ed; + -moz-border-radius-topleft: 2px; + -moz-border-radius-topright: 2px; + -moz-border-radius-bottomright: 2px; + -moz-border-radius-bottomleft: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + float: left; + width: 561px; +} + +.right div.comment-closed div.avatar { + float: left; + padding: 5px; +} + +.right div.comment-closed div.name { + float: left; + font-size: 12px; + padding-top: 9px; +} + +div.description-top { + background: #dcecfa; + font-size: 12px; + color: #292929; + border: 1px solid #a9c6dd; + height: 38px; + width: 100%; + margin-bottom: 20px; +} + +div.description-top div.img { + float: left; + padding-left: 10px; + margin-top: 14px; +} + +div.description-top input.name { + float: left; + margin-top: 5px; + margin-left: 10px; + background: #FFF; + border: 1px solid #d1deeb; + height: 21px; + width: auto; + color: #292929; + font-size: 11px; + width: 415px; + padding: 2px 5px 3px; +} + +div.description-top div.role { + float: left; + margin-top: 11px; + margin-left: 10px; + font-size: 11px; +} + + div.fork { + float: right; + margin-top: 5px; +} + div.fork p { + float: right; + margin-top: 5px; + margin-right: 2px; +} + +div.description-top div.fork { + margin-right: 10px; +} + +.all div.description { + text-align: left; +} + +.all div.description h3{ + color: #292929; + font-weight: 700; + font-size: 14px; + margin-bottom: 5px; + margin-top: 5px; +} + +.all div.description p{ + font-size: 12px; + padding: 0; + margin: 0; + color: #292929; +} + +.all div.last-commit { + border: 1px solid #d6d6d6; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px; + -webkit-border-radius: 4px 4px 4px 4px; + border-radius: 4px 4px 4px 4px; + padding: 6px; + margin: 10px 0px; +} + + +/* Project main page */ + +table.tablesorter.project .th1 { + width: 130px; + /*padding-left: 17px;*/ +} + +table.tablesorter.project .th2 { + width: 110px; + /*padding-left: 17px;*/ +} + +table.tablesorter.project .th3 { + width: 450px; +} + +table.tablesorter.project .th4 { + /*padding-left: 17px;*/ +} + +table.tablesorter.project div.name { + float: left; + margin-top: 0px; +} + +table.tablesorter.project div.pic { + float: left; + padding-right: 5px; +} + +a.files-see { + color: #292929; + text-decoration: underline; +} + +div.file { + border: 1px solid #dddddd; + margin-top: 10px; +} + +div.file div.top { + height: 28px; + background: #ededed; + -webkit-box-shadow: 0px 3px 3px -1px rgba(18, 86, 135, 0.2); + -moz-box-shadow: 0px 3px 3px -1px rgba(18, 86, 135, 0.2); + box-shadow: 0px 3px 3px -1px rgba(18, 86, 135, 0.2); + position: relative; + z-index: 99; +} + +div.file div.top div.l { + float: left; + margin: 6px 0px 0px 10px; +} + +div.file div.top div.r { + float: right; + margin: 6px 10px 0px 0px; +} + +div.files div.l { + float: left; + margin-bottom: 5px; +} + +div.files div.r { + float: right; + display: none; +} + +div.file { + margin-bottom: 10px; +} + +textarea.commit-message { + height: 60px; + width: 845px; + resize: none; + border: 1px solid #dedede; + border-radius: 4px; + padding: 5px; + font-family: Tahoma, Geneva, Helvetica, sans-serif; + font-size: 12px; + margin-top: 5px; +} + +div.files div.l p{ + padding: 0; + margin: 5px 0px 0px 0px; +} + + +/* Code */ + +div.gutter { + float: left; + border: 0 !important; + padding: 10px 5px 10px 0px; + font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; + background: #EDEDED; + width: 40px; + text-align: right; +} + + +/* Tracker */ + +table td.width18 { + width: 18px; +} + +table td.width135 { + width: 135px; +} + +table td.width145 { + width: 145px; +} + +.width125 { + width: 125px; +} + +table td.width30 { + width: 30px; +} + +table td.width30.right { + text-align: right; +} + +div.bordered.bpadding20 { + padding-bottom: 20px; +} + +table.tracker-lables td { + padding: 1px; +} + +table.tracker-lables div.label { + width: auto; + clear: both; + cursor: default; + margin-left: -15px; + padding: 5px; + padding-left: 15px; + text-align: left; +} + +table.tracker-lables div.label:hover { + background: none; +} + +div.blue-switcher { + height: 19px; + width: 258px; + border: 1px solid #a0a0a1; + border-radius: 3px; + background-color: #292929; + color: #FFF; + -webkit-box-shadow: inset 0px 2px 5px 0px rgba(0, 0, 0, 0.3); + -moz-box-shadow: inset 0px 2px 5px 0px rgba(0, 0, 0, 0.3); + box-shadow: inset 0px 2px 5px 0px rgba(0, 0, 0, 0.3); + float: right; +} + +div.blue-switcher div.open { + float: left; + padding: 1px 0px 2px 0px; + width: 128px; + text-align: center; + cursor: pointer; + position: relative; + z-index: 3; +} + +div.blue-switcher div.selected { + background-image: -webkit-gradient(linear, left top, left bottom, from(#619dd2), to(#125687)); + background-image: -webkit-linear-gradient(top, #619dd2, #125687); + background-image: -moz-linear-gradient(top, #619dd2, #125687); + background-image: -ms-linear-gradient(top, #619dd2, #125687); + background-image: -o-linear-gradient(top, #619dd2, #125687); + background-image: linear-gradient(top, #619dd2, #125687); + filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#619dd2', EndColorStr='#125687'); + border-radius: 2px; + height: 18px; + width: 128px; + -webkit-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.5); + box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.5); + position: absolute; + margin: 0px; + z-index: 2; + +} + +div.blue-switcher div.closed { + float: right; + padding: 1px 0px 0px 0px; + width: 128px; + text-align: center; + cursor: pointer; + position: relative; + z-index: 3; +} + +table.tablesorter.tracker th.th1{ + width: 50px; +} + +table.tablesorter.tracker td.td0{ + width: 10px; + padding-right: 0px; +} + +table.tablesorter.tracker td.td3{ + min-width: 110px; + padding-top: 10px; +} + +table.tablesorter.tracker td.td3 div.code { + height: 23px; + width: 15px; + background: #FFF; + color: #009fe3; + border: 1px solid #83d1f2; + font-size: 16px; + padding: 5px 0px 0px 5px; + float: left; + margin-right: 3px; + cursor: pointer; +} + +table.tablesorter.tracker td.td3 div.avatar { + float: left; + margin-right: 8px; + cursor: pointer; +} + +table.tablesorter.tracker td.td3 div.answers { + height: 28px; + background: #FFF; + color: #009fe3; + border: 1px solid #83d1f2; + font-size: 16px; + float: left; + cursor: pointer; +} + +table.tablesorter.tracker td.td3 div.answers div.pic { + float: left; + margin: 2px; + margin-top: 6px; +} + +table.tablesorter.tracker td.td3 div.answers div.count { + float: left; + margin: 4px 5px 0px 2px; +} + +table.tablesorter.tracker div.smalltext { + font-size: 11px; + color: #b0b0b1; + float: left; + margin-top: 3px; +} + + +div.label.selected.tracker { + width: auto; + clear: both; + cursor: default; + margin-left: 0px; + padding: 0px 0px 0px 2px; + float: left; + margin-top: 3px; +} + +div.right div.left.nomargin { + margin: 0px; + padding: 0px; +} + +div.label.selected.tracker:hover { + background: none; +} + + +div.label.edit { + width: 196px; + clear: both; + cursor: default; + margin-left: -15px; + padding: 5px; + padding-left: 15px; +} + +div.label.edit:hover{ + background: none; +} + +div.labeltext.edit { + float: left; + margin-left: 2px; + font-size: 12px; + margin-top: 0px; + margin-bottom: 5px; + padding-left: 3px; + padding-right: 3px; + color: #FFF; + padding-top: 1px; + padding-bottom: 1px; + border-radius: 2px; + width: 175px; + cursor: default; +} + +div.labeltext.edit div.text { + float: left; +} + +div.labeltext.edit div.delete { + float: right; + cursor: pointer; + margin-top: 1px; +} + +div.labeltext a { + text-decoration: none; + color: #292929; +} + +div.labeltext.edit a { + text-decoration: none; + color: #FFF; +} + +aside div.colors { + margin: 10px 0px; +} + +aside div.colors div.color { + float: left; + width: 22px; + height: 22px; + margin-right: 5px; + border-radius: 4px; + -webkit-box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.8); + -moz-box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.8); + box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.8); + cursor: pointer; +} + +aside div.colors div.choose { + height: 14px; + width: 14px; + padding: 4px; +} + +aside div.colors div.choose.selected, aside div.colors div.choose:hover { + background: image-url("choose.png") no-repeat 50% 50%; + height: 14px; + width: 14px; + padding: 4px; +} + +aside div.lefter { + float: left; +} + +aside div.righter { + float: right; + margin-right: 15px; +} + +tr.label-active { + background: #DDD; + border-radius: 3px; +} + +/* Wiki */ + +span.wiki-gray { + color: #b0b0b1; +} + +.right table.wiki { + border: 1px solid #e2e2e2; + border-bottom: none; + margin-top: 10px; +} + +.right table.wiki td { + border-bottom: 1px solid #e2e2e2; + padding: 8px; +} + +.right table.wiki tr.history td.td1{ + width: 5px; +} + +.right table.wiki tr.history td.td2{ + width: 180px; +} + +a.button.rigth { + float: right; +} + +div.r { + float: right; + margin-left: 10px; +} + +h3.wiki { + color: #477cae; + font-size: 16px; +} + +a.button.width100 { + width: 100px; +} + +.div-tracker-labels { + margin: 2px 13px 2px 0px; + cursor: pointer; + border-radius: 4px; +} + +.div-label-left { + float: left; + width: 150px; +} + +.div-label-right { + float: right; + width: 30px; + text-align: right; + padding-top: 4px; + padding-right: 3px; +} + +div.div-label-left div.label { + width: auto; + clear: both; + margin-left: -15px; + padding: 5px; + padding-left: 15px; + text-align: left; +} + +div.div-label-left div.label:hover { + background: none; +} + +/* Monitoring */ + +aside div.table { + margin-top: 5px; +} + +h3.small { + font-size: 12px; + margin: 0px; + padding: 3px 0px; +} + +table.tablesorter th.lpadding16 { + padding-left: 16px; +} + +div.right.slim { + padding: 5px 14px 40px; + width: 695px; +} + +img.delete-row { + cursor: pointer; +} + +table tbody tr.error td { + background: #fedede; +} + +table tbody tr.success td { + background: #e3edb7; +} + +/* Create group */ + +div.right-error { + float: left; + width: 369px; + height: 59px; + background: image-url("error-groups.png"); + margin: 0px 0px 5px -3px; + text-align: center; +} + +div.right-error p { + margin: 0; + padding: 27px 0px 0px 0px; +} + +div.rightlist.nomargin { + margin: 0; +} + +article div.rightlist input.error { + border: 1px solid #bd4d40; + -webkit-box-shadow: 0px 0px 2px 0px rgba(189, 77, 64, 1); + -moz-box-shadow: 0px 0px 2px 0px rgba(189, 77, 64, 1); + box-shadow: 0px 0px 2px 0px rgba(189, 77, 64, 1); +} + +/* Group pages */ + +article div.groups-profile { + float: left; +} + +article div.groups-profile a { + margin: 0px 0px 0px 5px; +} + +article div.groups-profile img { + margin: 2px 0px 0px 0px; +} + +table.tablesorter.group-list th.th2 { + width: 540px; +} + +/* Platform */ + +table.tablesorter.create-platform th.th1 { + /*padding-left: 17px;*/ + width: 120px; +} + +div.right div.left { + float: left; + margin-right: 5px; +} +table.tablesorter.platform-products th.th1 { + /*padding-left: 17px;*/ + width: 560px; +} + +table.tablesorter.platform-products td.td2 { + text-align: center; +} + +table.tablesorter.platform-repos th.th1 { + /*padding-left: 17px;*/ + width: 480px; +} + +table.tablesorter.platform-repos th.th2 { + /*padding-left: 17px;*/ + width: 80px; +} + +table.tablesorter.platform-repos td.td3 { + text-align: center; +} + +div.new-owner div.field { + float: left; + margin-right: 10px; +} + +div.new-owner div.field input { + width: 230px; +} + +div.new-owner div.search { + float: left; +} + +.tpadding10 { + padding-top: 10px; +} + +article div.all div.hr { + border-bottom: 1px solid #dedede; + width: 565px; + padding-top: 30px; + margin-bottom: 30px; +} + +table.tablesorter.platform-product-main th.th1 { + /*padding-left: 17px;*/ + width: 60px; +} + +table.tablesorter.platform-product-main th.th2 { + /*padding-left: 17px;*/ + width: 400px; +} + +table.tablesorter.platform-product-main th.th3 { + padding-left: 0px; +} + +table.tablesorter.platform-product-main th.th4 { + /*padding-left: 17px;*/ + width: 150px; +} + +div.right.rpadding0 { + padding-right: 0px; +} + +article div.loadFile div.btn { + float: left; +} + +article div.loadFile div.name { + float: left; + margin-left: 20px; + padding-top: 4px; +} + +/* Profile */ + +.bpadding10 { + padding-bottom: 10px; +} + +article div.rightlist div.load { + float: left; + margin-left: 40px; +} + +.notify { + border: 1px solid #c86b60; + background: #f4e1df; + border-radius: 4px; + width: 100%; + margin-top: 20px; +} + +.notify p { + padding: 5px 10px; +} + +.notify.blue { + border: 1px solid #a9c6dd; + background: #dcecfa; + border-radius: 1px; + width: 555px; + margin-top: 20px; + text-align: right; + padding: 5px; +} + +.notify.blue div.green { + border: 1px solid #bad099; + background: #d7e599; + float: left; +} + +/* Pagination */ + +div.pagination em { + font-style: normal; +} + +div.pagination em, div.pagination span, div.pagination a { + border: 1px solid #dddddd; + border-radius: 1px; + background: #ededed; + padding: 3px 7px; +} + +div.pagination em.current { + background: #d5e7f9; + border: 1px solid #c1daed; +} + +div.pagination a { + color: #4c90d0; +} + +/*404*/ + +article div.all.error404 { + background: image-url("404.png") no-repeat 49% 0; + height: 500px; + text-align: center; +} + +article div.all.error404 h1 { + margin: 0; + padding: 0; + margin-top: 165px; + font-size: 48px; + font-weight: normal; +} + +article div.all.error404 h1 span { + color: #4496d0; +} + +article div.all.error404 h2 { + margin: 0; + padding: 0; + margin-top: 5px; + font-size: 18px; + font-weight: normal; +} + +article div.all.error404 p { + margin: 0 auto; + padding: 0; + text-align: center; + font-size: 14px; +} + +article div.all.error404 p.pages { + margin-top: 72px; + width: 280px; +} + +article div.all.error404 p.search { + margin-top: 80px; + width: 230px; +} + +/*500*/ + +article div.all.error500 { + background: image-url("500.png") no-repeat 49% 0; + height: 500px; + text-align: center; +} + +article div.all.error500 h1 { + margin: 0; + padding: 0; + margin-top: 135px; + font-size: 48px; + font-weight: normal; +} + +article div.all.error500 h1 span { + color: #4496d0; +} + +article div.all.error500 h2 { + margin: 0; + padding: 0; + margin-top: 5px; + font-size: 18px; + font-weight: normal; + text-align: left; + margin-left: 298px; +} + +article div.all.error500 p { + margin: 0 auto; + padding: 0; + text-align: center; + font-size: 14px; +} + +article div.all.error500 p.pages { + margin-top: 55px; + width: 280px; +} + +article div.all.error500 p.search { + margin-top: 80px; + width: 230px; +} + +/*503*/ + +article div.all.error503 { + background: image-url("503.png") no-repeat 50% 0; + height: 500px; + text-align: center; +} + +article div.all.error503 h1 { + margin: 0; + padding: 0; + margin-top: 395px; + font-size: 38px; + font-weight: normal; + text-align: center; + +} + +article div.all.error503 h1 span { + color: #4496d0; +} + +article div.all.error503 h2 { + margin: 0; + padding: 0; + margin-top: 25px; + font-size: 18px; + font-weight: normal; + text-align: left; + margin-left: 215px; +} + +article div.all.error503 { + min-height: 630px; +} + +article div.all.error503 h2 span { + color: #4496d0; +} + +div.wrap.tmargin30 { + margin-top: 30px; + min-height: 91%; +} + +/*search*/ + +input.button.width100 { + width: 100px; +} + +input[type="text"].exsearch { + height: 16px; + border: 1px solid #dedede; + border-radius: 4px; + padding: 5px; + font-family: Tahoma, Geneva, Helvetica, sans-serif; + font-size: 12px; + width: 520px; + margin-right: 10px; +} + +div.lineForm.leftside.rmargin10 { + margin-right: 10px; +} + +table.tablesorter.bmargin5 { + margin-bottom: 1px; +} + +div.width400 { + width: 400px; + float: left; +} + +div.width400.rmargin55 { + margin-right: 55px; +} + +div.tmargin10 { + margin-top: 10px; +} + +.tmargin10 { + margin-top: 10px; +} + +a.lmargin7 { + margin-left: 7px; +} + +a.lmargin5 { + margin-left: 5px; +} + +/*My projects*/ + +table.tablesorter tr.search td { + background: #dcecfa; +} + +table.tablesorter tr.search td input[type="text"] { + height: 16px; + width: 830px; + border: 1px solid #cdcdcd; + border-radius: 4px; + padding: 5px; + font-family: Tahoma, Geneva, Helvetica, sans-serif; + font-size: 12px; + margin-top: 2px; +} + + +table.tablesorter.width565 { + width: 565px; +} + +article h3 a { + font-size: 14px; +} + +/*Wiki*/ + +div#wiki-content div.wrap { + width: 100%; + text-align: left; + border: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + background: #FFF; + margin-top: 20px; +} + +div#wiki-content div#wiki-body { + float: left; + width: 410px; + margin: 0px 0px 20px; +} + +div#wiki-content div#wiki-rightbar { + float: right; + width: 170px; +} + +div#wiki-content div#wiki-footer { + clear: both; + margin: 20px 0px; +} + +div#wiki-content div#wiki-rightbar, div#wiki-content div#wiki-footer { + background-color: #f7f7f7; + border: 1px solid #DDDDDD; + border-radius: 3px; + line-height: 1.5em; + padding: 10px 20px; +} + +div#gollum-footer { + color: #727272; +} diff --git a/app/controllers/activity_feeds_controller.rb b/app/controllers/activity_feeds_controller.rb index ccdf38127..24ab280ab 100644 --- a/app/controllers/activity_feeds_controller.rb +++ b/app/controllers/activity_feeds_controller.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class ActivityFeedsController < ApplicationController before_filter :authenticate_user! diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb new file mode 100644 index 000000000..c7e901668 --- /dev/null +++ b/app/controllers/admin/users_controller.rb @@ -0,0 +1,68 @@ +# -*- encoding : utf-8 -*- +class Admin::UsersController < ApplicationController + before_filter :authenticate_user! + load_and_authorize_resource + + def index + @filter = params[:filter] || 'all' + end + + def new + end + + def create + @user.role = params[:role] + if @user.save + flash[:notice] = t('flash.user.saved') + redirect_to users_path + else + flash[:error] = t('flash.user.save_error') + flash[:warning] = @user.errors.full_messages.join('. ') + render :action => :new + end + end + + def profile + end + + def update + @user.role = params[:role] + if @user.update_without_password(params[:user]) + if @user.avatar && params[:delete_avatar] == '1' + @user.avatar = nil + @user.save + end + flash[:notice] = t('flash.user.saved') + redirect_to users_path#edit_user_path(@user) + else + flash[:error] = t('flash.user.save_error') + flash[:warning] = @user.errors.full_messages.join('. ') + render(:action => :profile) + end + end + + def destroy + @user.destroy + flash[:notice] = t("flash.user.destroyed") + redirect_to users_path + end + + def list + colName = ['users.name', 'users.uname', 'users.email'] + sort_col = params[:iSortCol_0] || 0 + sort_dir = params[:sSortDir_0]=="asc" ? 'asc' : 'desc' + order = "#{colName[sort_col.to_i]} #{sort_dir}" + + @users = @users.paginate(:page => (params[:iDisplayStart].to_i/params[:iDisplayLength].to_i).to_i + 1, :per_page => params[:iDisplayLength]) + @total_users = @users.count + if !params[:sSearch].blank? && search = "%#{params[:sSearch]}%" + @users = @users.where('users.name ILIKE ? or users.uname ILIKE ? or users.email ILIKE ?', search, search, search) + end + @filter = params[:filter] || 'all' + @users = @users.send(@filter) if ['real', 'admin', 'banned'].include? @filter + @total_user = @users.count + @users = @users.order(order) + + render :partial =>'users_ajax', :layout => false + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3fde610e6..9170ab957 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -12,7 +12,7 @@ class ApplicationController < ActionController::Base helper_method :get_owner rescue_from CanCan::AccessDenied do |exception| - redirect_to forbidden_url, :alert => t('flash.exception_message')#:alert => exception.message + redirect_to forbidden_url, :alert => t("flash.exception_message") end protected diff --git a/app/controllers/build_lists_controller.rb b/app/controllers/build_lists_controller.rb index 2ae18691c..7b64ebf9d 100644 --- a/app/controllers/build_lists_controller.rb +++ b/app/controllers/build_lists_controller.rb @@ -45,6 +45,7 @@ class BuildListsController < ApplicationController @build_list.commit_hash = @project.git_repository.commits(@build_list.project_version.match(/^latest_(.+)/).to_a.last || @build_list.project_version).first.id if @build_list.project_version @build_list.bpl = bpl; @build_list.arch = arch; @build_list.user = current_user @build_list.include_repos = @build_list.include_repos.select { |ir| @build_list.bpl.repository_ids.include? ir.to_i } + @build_list.priority = 100 # User builds more priority than mass rebuild with zero priority flash_options = {:project_version => @build_list.project_version, :arch => arch.name, :bpl => bpl.name, :pl => @build_list.pl} if @build_list.save notices << t("flash.build_list.saved", flash_options) @@ -60,7 +61,7 @@ class BuildListsController < ApplicationController render :action => :new else flash[:notice] = notices.join('
').html_safe - redirect_to @project + redirect_to project_build_lists_path(@project) end end diff --git a/app/controllers/collaborators_controller.rb b/app/controllers/collaborators_controller.rb index bf24d77da..a149b06b9 100644 --- a/app/controllers/collaborators_controller.rb +++ b/app/controllers/collaborators_controller.rb @@ -37,7 +37,7 @@ class CollaboratorsController < ApplicationController relation.update_attribute(:role, role) else relation = @project.relations.build(:object_id => user_id, :object_type => 'User', :role => role) - relation.save! + relation.save end } if params['user'] @@ -47,7 +47,7 @@ class CollaboratorsController < ApplicationController relation.update_attribute(:role, role) else relation = @project.relations.build(:object_id => user_id, :object_type => 'Group', :role => role) - relation.save! + relation.save end } if params['group'] @@ -62,7 +62,7 @@ class CollaboratorsController < ApplicationController def remove all_user_ids = [] - all_groups_ids = [] + all_group_ids = [] params['user_remove'].keys.each { |user_id| all_user_ids << user_id if params['user_remove'][user_id] == ["1"] @@ -75,12 +75,12 @@ class CollaboratorsController < ApplicationController u = User.find(user_id) Relation.by_object(u).by_target(@project).each {|r| r.destroy} end - all_groups_ids.each do |group_id| + all_group_ids.each do |group_id| g = Group.find(group_id) Relation.by_object(g).by_target(@project).each {|r| r.destroy} end - redirect_to edit_project_collaborators_path(@project) + redirect_to edit_project_collaborators_path(@project) + "##{params['user_remove'].present? ? 'users' : 'groups'}" end def add @@ -114,7 +114,8 @@ class CollaboratorsController < ApplicationController end end - redirect_to(edit_project_collaborators_path(@project)) + # if add an anchor, adding will be more pleasant, but flash message wouldn't be shown. + redirect_to edit_project_collaborators_path(@project) # + "##{(params['member_id'].present?) ? 'users' : 'groups'}" end protected @@ -124,11 +125,11 @@ class CollaboratorsController < ApplicationController end def find_users - @users = @project.collaborators#User.all + @users = @project.collaborators.order('uname')#User.all end def find_groups - @groups = @project.groups#Group.all + @groups = @project.groups.order('uname')#Group.all end def authorize_collaborators diff --git a/app/controllers/git/blobs_controller.rb b/app/controllers/git/blobs_controller.rb index 0ad168508..4be95c11c 100644 --- a/app/controllers/git/blobs_controller.rb +++ b/app/controllers/git/blobs_controller.rb @@ -37,7 +37,7 @@ class Git::BlobsController < Git::BaseController end def blame - @blame = Grit::Blob.blame(@git_repository.repo, @commit.try(:id), @path) + @blame = Grit::Blob.blame(@git_repository.repo, @commit.id, @path) end def raw @@ -55,10 +55,10 @@ class Git::BlobsController < Git::BaseController def set_path_blob @path = params[:path] @blob = @tree / @path + @commit = @git_repository.log(@treeish, @path, :max_count => 1).first end def find_tree @tree = @git_repository.tree(@treeish) - @commit = @git_repository.log(@treeish, @path, :max_count => 1).first # TODO WTF nil ? end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 3bd7ed95a..01a0d8ddf 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -5,7 +5,6 @@ class ProjectsController < ApplicationController def index @projects = current_user.projects.paginate(:page => params[:page]) - #@projects = @projects.search(params[:query]).search_order if params[:query] end def new diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index af1911ef3..c4bf6b275 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,57 +2,27 @@ class UsersController < ApplicationController before_filter :authenticate_user! - load_and_authorize_resource + load_and_authorize_resource :only => :show + before_filter :set_current_user, :only => [:profile, :update, :private] autocomplete :user, :uname - def index - @user = User.scoped - if !params[:filter].blank? && !params[:filter][:email].blank? - @users = @users.where(:email => params[:filter][:email]) - @email = params[:filter][:email] - end - @users = @users.paginate(:page => params[:user_page]) - @action_url = users_path - end - def show @groups = @user.groups.uniq - @platforms = @user.platforms.paginate(:page => params[:platform_page], :per_page => 10) + @platforms = @user.platforms.paginate(:page => params[:platform_page], :per_page => 10) @projects = @user.projects.paginate(:page => params[:project_page], :per_page => 10) end - def new - @user = User.new - end - def profile - @user ||= current_user - end - - def create - @user = User.new params[:user] - if @user.save - flash[:notice] = t('flash.user.saved') - redirect_to users_path - else - flash[:error] = t('flash.user.save_error') - render :action => :new - end end def update - if params[:user][:role] && current_user.admin? - @user.role = params[:user][:role] - params[:user].delete(:role) - end - @user ||= current_user if @user.update_without_password(params[:user]) if @user.avatar && params[:delete_avatar] == '1' @user.avatar = nil @user.save end flash[:notice] = t('flash.user.saved') - redirect_to @user == current_user ? edit_profile_path : edit_user_path(@user) + redirect_to edit_profile_path else flash[:error] = t('flash.user.save_error') flash[:warning] = @user.errors.full_messages.join('. ') @@ -73,10 +43,10 @@ class UsersController < ApplicationController end end - def destroy - @user.destroy - flash[:notice] = t("flash.user.destroyed") - redirect_to users_path + protected + + def set_current_user + @user = current_user end end diff --git a/app/helpers/activity_feeds_helper.rb b/app/helpers/activity_feeds_helper.rb index 8880830d7..8680fcbac 100644 --- a/app/helpers/activity_feeds_helper.rb +++ b/app/helpers/activity_feeds_helper.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- module ActivityFeedsHelper def render_activity_feed(activity_feed) render :partial => activity_feed.partial, :locals => activity_feed.data.merge(:activity_feed => activity_feed) diff --git a/app/helpers/build_lists_helper.rb b/app/helpers/build_lists_helper.rb index ec670a549..fc2a5e9cd 100644 --- a/app/helpers/build_lists_helper.rb +++ b/app/helpers/build_lists_helper.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- module BuildListsHelper def build_list_status_color(status) if [BuildList::BUILD_PUBLISHED, BuildServer::SUCCESS].include? status diff --git a/app/models/ability.rb b/app/models/ability.rb index c122a37d0..17bbf6f11 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -14,12 +14,9 @@ class Ability # Shared rights between guests and registered users can :forbidden, Platform - # TODO remove because auth callbacks skipped - can :auto_build, Project can [:publish_build, :status_build, :pre_build, :post_build, :circle_build, :new_bbdt], BuildList if user.guest? # Guest rights - can :create, User can [:create, :show_message], RegisterRequest else # Registered user rights if user.admin? diff --git a/app/models/activity_feed.rb b/app/models/activity_feed.rb index 3bd57217c..3b2b74e3e 100644 --- a/app/models/activity_feed.rb +++ b/app/models/activity_feed.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class ActivityFeed < ActiveRecord::Base CODE = ['git_delete_branch_notification', 'git_new_push_notification', 'new_comment_commit_notification'] diff --git a/app/models/activity_feed_observer.rb b/app/models/activity_feed_observer.rb index b97d90450..dbbe8a189 100644 --- a/app/models/activity_feed_observer.rb +++ b/app/models/activity_feed_observer.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class ActivityFeedObserver < ActiveRecord::Observer observe :issue, :comment, :user, :build_list @@ -70,7 +71,7 @@ class ActivityFeedObserver < ActiveRecord::Observer when 'GitHook' change_type = record.change_type - branch_name = record.refname.match(/\/([\w\d]+)$/)[1] + branch_name = record.refname.split('/').last last_commits = record.project.git_repository.repo.log(branch_name, nil).first(3) first_commiter = User.find_by_email(last_commits[0].author.email) unless last_commits.blank? diff --git a/app/models/build_list/filter.rb b/app/models/build_list/filter.rb index bc76ee73e..5e39ec5b1 100644 --- a/app/models/build_list/filter.rb +++ b/app/models/build_list/filter.rb @@ -56,7 +56,7 @@ class BuildList::Filter :project_name => nil })) - @options[:ownership] = @options[:ownership].presence || 'owned' + @options[:ownership] = @options[:ownership].presence || (@project ? 'index' : 'owned') @options[:status] = @options[:status].present? ? @options[:status].to_i : nil @options[:created_at_start] = build_date_from_params(:created_at_start, @options) @options[:created_at_end] = build_date_from_params(:created_at_end, @options) diff --git a/app/models/group.rb b/app/models/group.rb index 69d839a49..fd541923c 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -25,7 +25,7 @@ class Group < ActiveRecord::Base attr_accessible :description attr_readonly :own_projects_count - delegate :ssh_key, :email, :to => :owner + delegate :email, :to => :owner after_create :add_owner_to_members diff --git a/app/models/label.rb b/app/models/label.rb index cc031d15a..e5fe686f2 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class Label < ActiveRecord::Base has_many :labelings, :dependent => :destroy has_many :issues, :through => :labelings diff --git a/app/models/labeling.rb b/app/models/labeling.rb index d03b0c6b3..acc688f68 100644 --- a/app/models/labeling.rb +++ b/app/models/labeling.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class Labeling < ActiveRecord::Base belongs_to :issue belongs_to :label diff --git a/app/models/platform.rb b/app/models/platform.rb index 43705fa03..3975b6a73 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -153,13 +153,15 @@ class Platform < ActiveRecord::Base end def build_all(user) - repositories.find_by_name('main').projects.find_in_batches(:batch_size => 5) do |group| + repositories.find_by_name('main').projects.find_in_batches(:batch_size => 2) do |group| sleep 1 group.each do |p| - begin - p.build_for(self, user) - rescue RuntimeError, Exception - p.delay.build_for(self, user) + %w(i586 x86_64).each do |arch| + begin + p.build_for(self, user, arch) + rescue RuntimeError, Exception + p.delay.build_for(self, user, arch) + end end end end diff --git a/app/models/project.rb b/app/models/project.rb index 4f1bc02c1..8e343a172 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -65,7 +65,7 @@ class Project < ActiveRecord::Base end end - def build_for(platform, user, arch = 'x86_64') # Return i586 after mass rebuild + def build_for(platform, user, arch = 'i586') # Return i586 after mass rebuild arch = Arch.find_by_name(arch) if arch.acts_like?(:string) build_lists.create do |bl| bl.pl = platform diff --git a/app/models/user.rb b/app/models/user.rb index bed92640a..bdb66f0c5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,6 +1,6 @@ # -*- encoding : utf-8 -*- class User < ActiveRecord::Base - ROLES = ['admin'] + ROLES = ['', 'admin', 'banned'] LANGUAGES_FOR_SELECT = [['Russian', 'ru'], ['English', 'en']] LANGUAGES = LANGUAGES_FOR_SELECT.map(&:last) MAX_AVATAR_SIZE = 5.megabyte @@ -42,14 +42,16 @@ class User < ActiveRecord::Base validates :role, :inclusion => {:in => ROLES}, :allow_blank => true validates :language, :inclusion => {:in => LANGUAGES}, :allow_blank => true - attr_accessible :email, :password, :password_confirmation, :current_password, :remember_me, :login, :name, :ssh_key, :uname, :language, + attr_accessible :email, :password, :password_confirmation, :current_password, :remember_me, :login, :name, :uname, :language, :site, :company, :professional_experience, :location, :avatar attr_readonly :uname, :own_projects_count - attr_readonly :uname attr_accessor :login scope :search_order, order("CHAR_LENGTH(uname) ASC") scope :search, lambda {|q| where("uname ILIKE ?", "%#{q}%")} + scope :banned, where(:role => 'banned') + scope :admin, where(:role => 'admin') + scope :real, where(:role => ['', nil]) after_create lambda { self.create_notifier } @@ -65,6 +67,10 @@ class User < ActiveRecord::Base new_record? end + def access_locked? + role == 'banned' + end + def fullname return "#{uname} (#{name})" end diff --git a/app/views/admins/_submenu.html.haml b/app/views/admin/_submenu.html.haml similarity index 100% rename from app/views/admins/_submenu.html.haml rename to app/views/admin/_submenu.html.haml diff --git a/app/views/admin/users/_sidebar.html.haml b/app/views/admin/users/_sidebar.html.haml new file mode 100644 index 000000000..2a8d51566 --- /dev/null +++ b/app/views/admin/users/_sidebar.html.haml @@ -0,0 +1,11 @@ +- content_for :sidebar do + .bordered + - if can? :create, User.new + = link_to t("layout.users.new"), new_user_path, :class => 'button' + %h3= t("layout.users.filter_header") + %table + - t('layout.users.users_filter').each_key do |base| + %tr + %td.width18=radio_button_tag :myradio, base, @filter.to_sym == base, {:id => 'users_filter', :class => 'niceRadio', :name => 'filter'} + %td.width135=t("layout.users.users_filter.#{base}") + .both diff --git a/app/views/admin/users/_users_ajax.js.erb b/app/views/admin/users/_users_ajax.js.erb new file mode 100644 index 000000000..433991b04 --- /dev/null +++ b/app/views/admin/users/_users_ajax.js.erb @@ -0,0 +1,19 @@ +{ + "sEcho": <%=h params[:sEcho].to_i || -1 %>, + "iTotalRecords": <%= @total_users %>, + "iTotalDisplayRecords": <%= @total_user %>, + "aaData": [ + <% @users.each do |user| %> + [ + "<%= user.name %>", + "<%= user.uname %>", + "<%= user.email %>", + "'><%= user.role %>", + "<%= j raw [(link_to t('layout.show'), user_path(user) if can? :read, user), + (link_to t('layout.edit'), edit_user_path(user) if can? :edit, user), + (link_to t('layout.delete'), delete_user_path(user), :method => :delete, :confirm => t('layout.users.confirm_delete') if can? :destroy, user) + ].compact.join(' | ') %>" + ]<%= user == @users.last ? '' : ',' %> + <% end %> + ] +} diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml new file mode 100644 index 000000000..b8690fe55 --- /dev/null +++ b/app/views/admin/users/index.html.haml @@ -0,0 +1,32 @@ +%h3.fix= t("layout.users.list_header") + +- columns = [{:type => 'html'}, {:type => 'html'}, {:type => 'html'}, {:type => 'html', :sortable => false, :searchable => false}, {:type => nil, :sortable => false, :searchable => false, :class => 'buttons'}] += raw datatable(columns, {:sort_by => "[0, 'asc']", :processing => t("layout.processing"), :search_label => t("layout.search.header"), + :pagination_labels => {:previous => t("datatables.previous_label"), :next => t("datatables.next_label")}, + :empty_label => t("datatables.empty_label"), + :info_label => t("datatables.info_label"), + :info_empty_label => t("datatables.info_empty_label"), + :filtered_label => t("datatables.filtered_label"), + :table_dom_id => 'datatable', + :auto_width => 'false', + :ajax_source => "#{url_for :controller => 'admin/users', :action => :list}", + :additional_data => {:filter => "' + $('#users_filter[type=\"radio\"]:checked').val() + '"} }) + +%table#datatable.tablesorter.list-users{:cellspacing => 0, :cellpadding => 0} + %thead + %tr + %th.th1= t("activerecord.attributes.user.name") + %th.th2= t("activerecord.attributes.user.uname") + %th.th3= t("activerecord.attributes.user.email") + %th.th4= t("activerecord.attributes.user.role") + %th.last   + %tbody +%br + += render :partial => 'admin/users/sidebar' += render 'admin/submenu' + +:javascript + $('#users_filter[type="radio"]').live('change', function(){ + $('#datatable').dataTable().fnDraw(); + }); diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/users/new.html.haml new file mode 100644 index 000000000..340f067ff --- /dev/null +++ b/app/views/admin/users/new.html.haml @@ -0,0 +1,11 @@ +.block + .content + %h2.title= t("layout.users.new_header") + .inner + = form_for @user, :url => create_user_path, :html => { :class => :form } do |f| + = render :partial => "users/form", :locals => {:f => f} + +- content_for :sidebar do + .bordered.nopadding + += render 'admin/submenu' diff --git a/app/views/admin/users/profile.html.haml b/app/views/admin/users/profile.html.haml new file mode 100644 index 000000000..e2ae8fda6 --- /dev/null +++ b/app/views/admin/users/profile.html.haml @@ -0,0 +1,16 @@ +%h3.fix.bpadding10= @user.uname + += form_for @user, :url => update_user_path(@user), :html => { :class => :form } do |f| + = render :partial => "users/form", :locals => {:f => f} + +.notify + %p= t('layout.users.public_data_edit_warning') +.notify + %p= t('layout.users.avatar_notice') + +:javascript + $('article .right').addClass('middlepadding'); + += render 'admin/submenu' +- content_for :sidebar do + .bordered.nopadding diff --git a/app/views/build_lists/_filter.html.haml b/app/views/build_lists/_filter.html.haml index 2a6ee9f6e..8d967dcc5 100644 --- a/app/views/build_lists/_filter.html.haml +++ b/app/views/build_lists/_filter.html.haml @@ -24,10 +24,11 @@ .lefter= f.radio_button :ownership, 'owned', :class => 'niceRadio', :id => 'myradio1' .lefter= t("layout.build_lists.ownership.owned") .both - .table - .lefter= f.radio_button :ownership, 'related', :class => 'niceRadio', :id => 'myradio2' - .lefter= t("layout.build_lists.ownership.related") - .both + - unless @project + .table + .lefter= f.radio_button :ownership, 'related', :class => 'niceRadio', :id => 'myradio2' + .lefter= t("layout.build_lists.ownership.related") + .both .table .lefter= f.radio_button :ownership, 'index', :class => 'niceRadio', :id => 'myradio3' .lefter= t("layout.build_lists.ownership.index") diff --git a/app/views/collaborators/edit.html.haml b/app/views/collaborators/edit.html.haml index 82c56a244..c075b3440 100644 --- a/app/views/collaborators/edit.html.haml +++ b/app/views/collaborators/edit.html.haml @@ -1,5 +1,19 @@ += render :partial => 'projects/sidebar' = render :partial => 'projects/submenu' +%a{:name => 'users'} +%h3= t("layout.users.list_header") + += form_tag add_project_collaborators_path(@project) do + .admin-search + = autocomplete_field_tag 'member_id', params[:member_id], autocomplete_user_uname_users_path, :id_element => '#member_id_field' + .admin-role + .lineForm + = select_tag 'role', options_for_collaborators_roles_select + = hidden_field_tag 'member_id', nil, :id => 'member_id_field' + = submit_tag t("layout.add"), :class => 'button' + .both + = form_tag project_collaborators_path(@project), :id => 'members_form', :delete_url => remove_project_collaborators_path(@project) do = hidden_field_tag "_method", "post" %table.tablesorter{:cellpadding => "0", :cellspacing => "0"} @@ -12,8 +26,8 @@ %th{:colspan => "3"} = t("layout.collaborators.roles") %tbody - - @users.each do |user| - %tr#admin-table-members-row1 + - @users.each_with_index do |user, num| + %tr{:id => "admin-table-members-row#{num}"} %td %span#niceCheckbox1.niceCheck-main{ :style => "background-position: 0px 0px; "} = check_box_tag "user_remove[#{user.id}][]" @@ -25,31 +39,54 @@ %td .radio = radio_button_tag "user[#{user.id}]", role, ((@project.relations.exists? :object_id => user.id, :object_type => 'User', :role => role) ? :checked : nil), :class => 'niceRadio' - -# f.radio_button "group[#{role}][#{group.id}]", '1', ((@project.relations.exists? :object_id => group.id, :object_type => 'Group', :role => role) ? :checked : nil) - -#%span.niceRadio.radioChecked - -# %input#myradio1{:checked => "checked", :name => "myradio", :tabindex => "1", :type => "radio", :value => "on"}/ .forradio= t("layout.collaborators.role_names.#{ role }") - = link_to_function t("layout.delete"), "deleteAdminMember();", :class => 'button' + = link_to_function t("layout.delete_selected"), "deleteAdminMember();", :class => 'button' + = link_to_function t("layout.save"), "saveAdminMember();", :class => 'button right_floated' .both -.hr.top - -= form_tag add_project_collaborators_path(@project) do - .admin-search - = autocomplete_field_tag 'member_id', params[:member_id], autocomplete_user_uname_users_path, :id_element => '#member_id_field' - .admin-role - .lineForm - = select_tag 'role', options_for_collaborators_roles_select - .both - -#.admin-search - -# = label_tag "group_uname", t("layout.collaborators.input_groupname") - -# = autocomplete_field_tag 'group_id', params[:group_id], autocomplete_group_uname_groups_path, :id_element => '#group_id_field' - = hidden_field_tag 'member_id', nil, :id => 'member_id_field' - =# hidden_field_tag 'group_id', nil, :id => 'group_id_field' - %br - = submit_tag t("layout.add"), :class => 'button' +%br .hr.bottom .both -= link_to_function t("layout.save"), "saveAdminMember();", :class => 'button' -- content_for :sidebar, render('projects/sidebar') +%a{:name => 'groups'} +%h3= t("layout.groups.list_header") + += form_tag add_project_collaborators_path(@project) do + .admin-search + = autocomplete_field_tag 'group_id', params[:group_id], autocomplete_group_uname_groups_path, :id_element => '#group_id_field' + .admin-role + .lineForm + = select_tag 'role', options_for_collaborators_roles_select, :id => 'group_role' + = hidden_field_tag 'group_id', nil, :id => 'group_id_field' + = submit_tag t("layout.add"), :class => 'button' + .both + += form_tag project_collaborators_path(@project), :id => 'groups_form', :delete_url => remove_project_collaborators_path(@project) do + = hidden_field_tag "_method", "post", :id => 'groups_method' + %table.tablesorter{:cellpadding => "0", :cellspacing => "0"} + %thead + %tr + %th + \  + %th + = t("layout.collaborators.members") + %th{:colspan => "3"} + = t("layout.collaborators.roles") + %tbody + - @groups.each_with_index do |group, num| + %tr{:id => "admin-table-members-row#{num + @users.size + 1}"} + %td + %span#niceCheckbox1.niceCheck-main{ :style => "background-position: 0px 0px; "} + = check_box_tag "group_remove[#{group.id}][]" + %td + .forimg= link_to "#{group.uname}", group_path(group) + - Relation::ROLES.each_with_index do |role, i| + %td + .radio + = radio_button_tag "group[#{group.id}]", role, ((@project.relations.exists? :object_id => group.id, :object_type => 'Group', :role => role) ? :checked : nil), :class => 'niceRadio' + .forradio= t("layout.collaborators.role_names.#{ role }") + = link_to_function t("layout.delete_selected"), "deleteAdminGroup();", :class => 'button' + = link_to_function t("layout.save"), "saveAdminGroup();", :class => 'button right_floated' + .both +.both + diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index ec003cdad..31aa496e9 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -7,15 +7,17 @@ .logo / Page %article - - is_error = (flash.try(:first).try(:first) == :alert && flash.try(:first).try(:last) == t('devise.failure.invalid')) # Trash + - if flash.try(:first).try(:first) == :alert && [t('devise.failure.invalid'), t('devise.failure.locked')].include?(flash.try(:first).try(:last)) + - error = flash.first.last + - error ||= false - login = t('devise.sessions.login'); password = t('devise.sessions.password') =hidden_field_tag :login_default, login =hidden_field_tag :password_default, password = form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "form login" }) do |f| %h1= title t("layout.sessions.sign_in_header") - = f.text_field :login, :class => "registartion-input #{is_error ? "registartion-input-error" : ''}", :value => login + = f.text_field :login, :class => "registartion-input #{error ? "registartion-input-error" : ''}", :value => login %br/ - = f.password_field :password, :class => "registartion-input #{is_error ? "registartion-input-error" : ''}", :value => password + = f.password_field :password, :class => "registartion-input #{error ? "registartion-input-error" : ''}", :value => password %br/ .registration .remember @@ -30,4 +32,4 @@ .forgot .password %p= link_to t("layout.devise.shared_links.forgot_password"), new_password_path(resource_name) - =showDeviseHintError(:login_error, is_error ? t('devise.failure.invalid') : false) + =showDeviseHintError(:login_error, error) diff --git a/app/views/event_logs/index.html.haml b/app/views/event_logs/index.html.haml index 51e2f4d42..d2d3360fa 100644 --- a/app/views/event_logs/index.html.haml +++ b/app/views/event_logs/index.html.haml @@ -18,4 +18,4 @@ .actions-bar.wat-cf .actions= will_paginate -= render 'admins/submenu' += render 'admin/submenu' diff --git a/app/views/git/blobs/_editor.html.haml b/app/views/git/blobs/_editor.html.haml index d4f727877..a02d5e229 100644 --- a/app/views/git/blobs/_editor.html.haml +++ b/app/views/git/blobs/_editor.html.haml @@ -19,5 +19,8 @@ :javascript $(function() { - var editor = CodeMirror.fromTextArea(document.getElementById('code'), {lineNumbers: true, mode: '#{@blob.raw_mime_type.content_type}', theme: 'eclipse'}); - }); \ No newline at end of file + var editor = CodeMirror.fromTextArea(document.getElementById('code'), { + lineNumbers: true, + mode: '#{@blob.raw_mime_type.content_type}' + }); + }); diff --git a/app/views/git/blobs/blame.html.haml b/app/views/git/blobs/blame.html.haml index 1eb9109f4..27e748ee4 100644 --- a/app/views/git/blobs/blame.html.haml +++ b/app/views/git/blobs/blame.html.haml @@ -22,4 +22,4 @@ - render_way = choose_render_way(@blob) .file .top= render 'top', :render_way => render_way - .blame_data= render 'blame_table' + .blame_data= render 'blame_table' if @blame.first.first.present? diff --git a/app/views/groups/_sidebar.html.haml b/app/views/groups/_sidebar.html.haml index 24c862edf..abe3e44b0 100644 --- a/app/views/groups/_sidebar.html.haml +++ b/app/views/groups/_sidebar.html.haml @@ -5,7 +5,7 @@ %aside .admin-preferences %ul - - if can? :edit, @project + - if can? :edit, @group %li{:class => (act == :edit && contr == :groups) ? 'active' : ''} = link_to t("layout.groups.edit"), edit_group_path(@group) - if can? :manage_members, @group diff --git a/app/views/issues/_issue.html.haml b/app/views/issues/_issue.html.haml index 471653db9..67a1fc873 100644 --- a/app/views/issues/_issue.html.haml +++ b/app/views/issues/_issue.html.haml @@ -9,10 +9,10 @@ =issue.created_at.to_s(:long) =t("layout.by") if issue.creator =link_to(issue.creator.uname, user_path(issue.creator)) if issue.creator - .label.selected.tracker - -issue.labels.each do |label| + -issue.labels.each do |label| + .left.nomargin + .label.selected.tracker.left .labeltext.selected{:style => "background: ##{label.color};"}=label.name - .both %td.td3 .avatar =link_to image_tag(avatar_url(issue.user), :alt => 'avatar'), user_path(issue.user) if issue.user diff --git a/app/views/layouts/menu/_top.html.haml b/app/views/layouts/menu/_top.html.haml index d7635c682..97688685e 100644 --- a/app/views/layouts/menu/_top.html.haml +++ b/app/views/layouts/menu/_top.html.haml @@ -1,6 +1,6 @@ %ul - (collection = t which_menu).each do |base, title| - if can? :index, base.to_s.classify.constantize - %li= link_to title, send(:"#{base}_path"), :class => [].tap{|c| c << 'active' if params[:controller] == base.to_s}.join(' ') + %li= link_to title, send(:"#{base}_path"), :class => controller_name == base.to_s ? 'active' : '' - if current_user.admin? && which_menu == 'top_menu' - %li= link_to 'Admin', users_path, :class => t('admins_menu').has_key?(params[:controller].to_sym) ? 'active' : '' + %li= link_to t('admins_menu_header'), users_path, :class => t('admins_menu').has_key?(controller_name.to_sym) ? 'active' : '' diff --git a/app/views/product_build_lists/_product_build_list.html.haml b/app/views/product_build_lists/_product_build_list.html.haml index e3979204c..a39f7ea7d 100644 --- a/app/views/product_build_lists/_product_build_list.html.haml +++ b/app/views/product_build_lists/_product_build_list.html.haml @@ -2,4 +2,5 @@ %td= product_build_list.id %td= product_build_list.human_status %td= link_to nil, product_build_list.container_path + %td= link_to image_tag('x.png'), platform_product_product_build_list_path(product_build_list.product.platform, product_build_list.product, product_build_list), :method => :delete, :confirm => t("layout.confirm") if can? :destroy, product_build_list %td= l(product_build_list.notified_at, :format => :long) diff --git a/app/views/products/show.html.haml b/app/views/products/show.html.haml index dd705cdc1..01b827878 100644 --- a/app/views/products/show.html.haml +++ b/app/views/products/show.html.haml @@ -1,7 +1,7 @@ = render :partial => 'platforms/submenu' = render :partial => 'platforms/sidebar' -%h3= "#{t("layout.products.about")} #{@product.name}" +%h3 #{t("layout.products.about")} #{@product.name} %p= @product.description @@ -20,59 +20,9 @@ %table#myTable.tablesorter.platform-product-main{:cellspacing => "0", :cellpadding => "0"} %thead %tr - %th.th1= t("activerecord.attributes.product_build_list.id") - %th.th2= t("activerecord.attributes.product_build_list.status") - %th.th3= t("layout.product_build_lists.action") - %th.th4= t("activerecord.attributes.product_build_list.notified_at") - %tbody - = render @product.product_build_lists.default_order --#.block - .secondary-navigation - %ul.wat-cf - %li.first= link_to @platform.name, platform_path(@platform) + "#products" - %li.active= link_to @product.name, platform_product_path(@platform, @product) - - .content - .inner - %p - %b - = t("activerecord.attributes.product.name") - \: - = @product.name - - %p - %b - = t("activerecord.attributes.product.is_template") - \: - = t("layout.#{@product.is_template?}_") - - - content_for :commented do - %p - %b - = t("activerecord.attributes.product.system_wide") - \: - = t("layout.#{@product.system_wide?}_") - - .wat-cf - - if can? :update, @product - = link_to image_tag("code.png", :alt => t("layout.edit")) + " " + t("layout.edit"), edit_platform_product_path(@platform, @product), :class => "button" - - if can? :destroy, @product - = link_to image_tag("x.png", :alt => t("layout.delete")) + " " + t("layout.delete"), platform_product_path(@platform, @product), :method => "delete", :class => "button", :confirm => t("layout.products.confirm_delete") - - if @product.can_clone? - =# link_to t("layout.products.clone"), clone_platform_product_path(@platform, @product), :class => "button" - - if can?(:create, @product => ProductBuildList) - = link_to t("layout.products.build"), platform_product_product_build_lists_path(@platform, @product), :class => "button", :method => 'post', :confirm => t("layout.confirm") - --#.block - .content - .inner - %table.table - %tr - %th.first= t("activerecord.attributes.product_build_list.id") - %th= t("activerecord.attributes.product_build_list.product") - %th= t("activerecord.attributes.product_build_list.container_path") - %th= t("activerecord.attributes.product_build_list.status") - %th= t("layout.product_build_lists.action") - %th.last= t("activerecord.attributes.product_build_list.notified_at") - = render @product.product_build_lists.default_order - / = will_paginate build_lists + %th= t("activerecord.attributes.product_build_list.id") + %th= t("activerecord.attributes.product_build_list.status") + %th= t("activerecord.attributes.product_build_list.container_path") + %th= t("layout.product_build_lists.action") + %th= t("activerecord.attributes.product_build_list.notified_at") + %tbody= render @product.product_build_lists.default_order diff --git a/app/views/projects/_sidebar.html.haml b/app/views/projects/_sidebar.html.haml index 0f5b9be4f..a3265dcb5 100644 --- a/app/views/projects/_sidebar.html.haml +++ b/app/views/projects/_sidebar.html.haml @@ -1,14 +1,16 @@ -- act = action_name.to_sym -- contr = controller_name.to_sym +- content_for :sidebar do -%aside - .admin-preferences - %ul - - if can? :edit, @project - %li{:class => (act == :edit && contr == :projects) ? 'active' : ''} - = link_to t("layout.projects.edit"), edit_project_path(@project) - %li{:class => (act == :sections && contr == :projects) ? 'active' : ''} - = link_to t("layout.projects.sections"), sections_project_path(@project) - - if can? :manage_collaborators, @project - %li{:class => (act == :edit && contr == :collaborators) ? 'active' : ''} - = link_to t("layout.projects.edit_collaborators"), edit_project_collaborators_path(@project) \ No newline at end of file + - act = action_name.to_sym + - contr = controller_name.to_sym + + %aside + .admin-preferences + %ul + - if can? :edit, @project + %li{:class => (act == :edit && contr == :projects) ? 'active' : ''} + = link_to t("layout.projects.edit"), edit_project_path(@project) + %li{:class => (act == :sections && contr == :projects) ? 'active' : ''} + = link_to t("layout.projects.sections"), sections_project_path(@project) + - if can? :manage_collaborators, @project + %li{:class => (act == :edit && contr == :collaborators) ? 'active' : ''} + = link_to t("layout.projects.edit_collaborators"), edit_project_collaborators_path(@project) diff --git a/app/views/projects/_submenu.html.haml b/app/views/projects/_submenu.html.haml index eac17b005..5b15e6679 100644 --- a/app/views/projects/_submenu.html.haml +++ b/app/views/projects/_submenu.html.haml @@ -1,6 +1,8 @@ - content_for :submenu do - act = action_name.to_sym; contr = controller_name.to_sym - .left= @project.name + .left + .table-sort-left=image_tag visibility_icon(@project.visibility) + .table-sort-right=@project.name %nav %ul %li= link_to t("project_menu.project"), project_path(@project), :class => (act.in?([:show, :edit]) && contr.in?([:trees, :blobs]) ? 'active' : nil) diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 755de5ab5..92fbbcb56 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -1,4 +1,5 @@ = render :partial => 'projects/submenu' += render :partial => 'projects/sidebar' = form_for @project, :html => { :class => :form, :multipart => true } do |f| = render :partial => "form", :locals => {:f => f} @@ -8,4 +9,3 @@ .rightside= link_to t("layout.delete"), project_path(@project), :method => :delete, :confirm => t("layout.projects.confirm_delete"), :class => 'button' if can? :destroy, @project .both -- content_for :sidebar, render('sidebar') diff --git a/app/views/projects/sections.html.haml b/app/views/projects/sections.html.haml index 0b154c058..caa737d38 100644 --- a/app/views/projects/sections.html.haml +++ b/app/views/projects/sections.html.haml @@ -1,4 +1,5 @@ = render :partial => 'projects/submenu' += render :partial => 'projects/sidebar' = form_for @project, :url => sections_project_path(@project), :method => :post, :html => { :class => :form, :multipart => true } do |f| .leftside.w25 @@ -18,8 +19,6 @@ .padd25= submit_tag t("layout.save"), :class => 'button' .both -- content_for :sidebar, render('sidebar') - :javascript // TODO: Replace this temporary hack by something more true $('.right').addClass('bigpadding'); diff --git a/app/views/repositories/_proj_ajax.js.erb b/app/views/repositories/_proj_ajax.js.erb index ff7e5ff00..9fd8431d4 100644 --- a/app/views/repositories/_proj_ajax.js.erb +++ b/app/views/repositories/_proj_ajax.js.erb @@ -6,7 +6,7 @@ <% @projects.each do |project| %> [ "<%=j link_to("#{project.owner.respond_to?(:uname) ? project.owner.uname : project.owner.name} / #{project.name}", project) %>", - "<%= truncate(project.description || '', :length => 60).gsub("\n", ' ') %>", + "<%= truncate(project.description || '', :length => 60).gsub("\n", ' ').gsub("\r", ' ') %>", "<%=j link_to t("layout.add"), url_for(:controller => :repositories, :action => :add_project, :project_id => project.id) %>" ]<%= project == @projects.last ? '' : ',' %> <% end %> diff --git a/app/views/repositories/_project.js.erb b/app/views/repositories/_project.js.erb index 91050c158..11e30ec45 100644 --- a/app/views/repositories/_project.js.erb +++ b/app/views/repositories/_project.js.erb @@ -13,7 +13,7 @@ j(link_to("#{project.owner.respond_to?(:uname) ? project.owner.uname : project.owner.name} / #{project.name}", project)) + "").html_safe %>", - "<%= truncate(project.description || '', :length => 60).gsub("\n", ' ') %>", + "<%= truncate(project.description || '', :length => 60).gsub("\n", ' ').gsub("\r", ' ') %>", "<%= if can? :remove_project, @repository j(link_to(' '.html_safe, diff --git a/app/views/users/_form.html.haml b/app/views/users/_form.html.haml index ff52c8865..39fa3ffd8 100644 --- a/app/views/users/_form.html.haml +++ b/app/views/users/_form.html.haml @@ -1,3 +1,23 @@ +- if current_user.admin? + .leftlist + = f.label :role, t("activerecord.attributes.user.role"), :class => :label + .rightlist + = f.select :role, User::ROLES, {}, {:name => 'role'} + - if @user.new_record? + .leftlist + = f.label :uname, t("activerecord.attributes.user.uname") + .rightlist + = f.text_field :uname + .leftlist + = f.label :password, t("activerecord.attributes.user.password") + .rightlist + = f.password_field :password + .both + .leftlist + = f.label :password_confirmation, t("activerecord.attributes.user.password_confirm") + .rightlist + = f.password_field :password_confirmation + .both .leftlist = f.label :name, t("activerecord.attributes.user.name") .rightlist diff --git a/app/views/users/_sidebar.html.haml b/app/views/users/_sidebar.html.haml index 72beffd9d..9b8259f79 100644 --- a/app/views/users/_sidebar.html.haml +++ b/app/views/users/_sidebar.html.haml @@ -5,7 +5,7 @@ .admin-preferences %ul - if can? :edit, @user - %li{:class => (act == :edit && :users == contr) ? 'active' : ''} + %li{:class => (act == :profile && :users == contr) ? 'active' : ''} = link_to t("layout.users.profile"), @user == current_user ? edit_profile_path : edit_user_path(@user) - if can? :private, @user %li{:class => (act == :private && contr == :users) ? 'active' : ''} diff --git a/app/views/users/index.html.haml b/app/views/users/index.html.haml deleted file mode 100644 index 5174e43c7..000000000 --- a/app/views/users/index.html.haml +++ /dev/null @@ -1,39 +0,0 @@ -.block - .secondary-navigation - %ul.wat-cf - %li.first.active= link_to t("layout.users.list"), users_path - %li= link_to t("layout.users.new"), new_user_path - %li= link_to t("layout.users.register_requests"), register_requests_path if can? :read, RegisterRequest - .content - %h2.title - = t("layout.users.list_header") - .inner - = render :partial => "users/filter", :action_url => @action_url - .inner - %table.table - %tr - %th.first ID - %th= t("activerecord.attributes.user.name") - %th= t("activerecord.attributes.user.uname") - %th= t("activerecord.attributes.user.email") - %th= t("activerecord.attributes.user.role") - %th.last   - - @users.each do |user| - %tr{:class => cycle("odd", "even")} - %td= user.id - %td= link_to user.name, user_path(user) - %td= link_to user.uname, user_path(user) - %td= user.email - %td= user.role - %td.last - - if can? :read, user - = link_to t("layout.show"), user_path(user) - \| - - if can? :edit, user - #{link_to t("layout.edit"), edit_user_path(user)} - \| - - if can? :destroy, user - #{link_to t("layout.delete"), user_path(user), :method => :delete, :confirm => t("layout.users.confirm_delete")} - .actions-bar.wat-cf - .actions= will_paginate @users, :param_name => :user_page -= render 'admins/submenu' diff --git a/app/views/users/new.html.haml b/app/views/users/new.html.haml deleted file mode 100644 index 7fe4cfe4e..000000000 --- a/app/views/users/new.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -.block - .secondary-navigation - %ul.wat-cf - %li.first= link_to t("layout.users.list"), users_path - %li.active= link_to t("layout.users.new"), new_user_path - .content - %h2.title= t("layout.users.new_header") - .inner - = form_for @user, :url => users_path, :html => { :class => :form } do |f| - = render :partial => "form", :locals => {:f => f} - -- content_for :sidebar, render('sidebar') diff --git a/app/views/users/profile.html.haml b/app/views/users/profile.html.haml index 4c82d7b8b..7c723128b 100644 --- a/app/views/users/profile.html.haml +++ b/app/views/users/profile.html.haml @@ -1,12 +1,7 @@ %h3.fix.bpadding10= @user.uname = form_for @user, :url => user_path(@user), :html => { :class => :form } do |f| - - if current_user.admin? - .leftlist - = f.label :role, t("activerecord.attributes.user.role"), :class => :label - .rightlist - = f.select :role, User::ROLES, :include_blank => true - = render :partial => "form", :locals => {:f => f} + = render :partial => "users/form", :locals => {:f => f} .notify %p= t('layout.users.public_data_edit_warning') diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index b1df08bef..d1ea445fc 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -1,7 +1,7 @@ .left = image_tag avatar_url(@user, :big) %br - = link_to t("layout.users.settings"), edit_user_path(@user), :class => 'button width81' if can? :edit, @user + = link_to t("layout.users.settings"), current_user == @user ? edit_profile_path : edit_user_path(@user), :class => 'button width81' if can? :edit, @user .left %h3= @user.uname = @user.name diff --git a/app/views/wiki/_page.html.haml b/app/views/wiki/_page.html.haml index cb200c328..e7b51c2e0 100644 --- a/app/views/wiki/_page.html.haml +++ b/app/views/wiki/_page.html.haml @@ -7,6 +7,7 @@ - if has_footer? #wiki-footer{:class => "gollum-#{footer_format}-content"} #footer-content= raw footer_content +.both #gollum-footer %p#last-edit = t("wiki.last_edited_by") @@ -15,5 +16,5 @@ = t("layout.time.ago") - unless action_name == 'preview' or cannot? :write, @project %p#delete-link - = link_to project_wiki_path(@project, escaped_name), :method => :delete, :confirm => t("layout.confirm"), :class => 'button width100' do + = link_to project_wiki_path(@project, escaped_name), :method => :delete, :confirm => t("layout.confirm") do %span= t("wiki.delete_page") \ No newline at end of file diff --git a/app/views/wiki/edit.html.haml b/app/views/wiki/edit.html.haml index ae0745da1..e73511a0a 100644 --- a/app/views/wiki/edit.html.haml +++ b/app/views/wiki/edit.html.haml @@ -1,18 +1,14 @@ = render 'gollum_includes' / = render 'project_short' = render 'projects/submenu' - -%h3.wiki - = t("wiki.editing_page") - %strong= @page.name +.left + %h3 + = t("wiki.editing_page") + %strong= @page.name - if can? :read, @project - .r= link_to t("wiki.view_page"), view_path(@project, escaped_name), :class => 'action-view-page button width100' - .r= link_to t("wiki.page_history"), history_project_wiki_path(@project, escaped_name), :class => 'aciton-view-history button width100' - -%br -%br -%br - + .r= link_to t("wiki.view_page"), view_path(@project, escaped_name), :class => 'action-view-page button' + .r= link_to t("wiki.page_history"), history_project_wiki_path(@project, escaped_name), :class => 'aciton-view-history button' +.both #wiki-content= render "editor" :javascript diff --git a/app/views/wiki/show.html.haml b/app/views/wiki/show.html.haml index a3d93ccb8..e8c83b2ba 100644 --- a/app/views/wiki/show.html.haml +++ b/app/views/wiki/show.html.haml @@ -1,23 +1,19 @@ / = render 'gollum_includes' / = render 'project_short' = render 'projects/submenu' - -%h3.wiki - = @page.name - = "(#{t("wiki.preview")})" if action_name == 'preview' +.left + %h3 + = @page.name + = "(#{t("wiki.preview")})" if action_name == 'preview' - unless action_name == 'preview' .r - = link_to t("wiki.page_history"), history_project_wiki_path(@project, escaped_name), :class => 'button width100' + = link_to t("wiki.page_history"), history_project_wiki_path(@project, escaped_name), :class => 'button' .r - if @editable - = link_to t("wiki.edit_page"), edit_project_wiki_path(@project, escaped_name), :class => "button width100" + = link_to t("wiki.edit_page"), edit_project_wiki_path(@project, escaped_name), :class => 'button' .r - if can? :write, @project - = link_to t("wiki.new_page"), '#', :'data-url' => project_wiki_index_path(@project), :id => 'minibutton-new-page', :class => 'button width100' - -%br -%br -%br + = link_to t("wiki.new_page"), '#', :'data-url' => project_wiki_index_path(@project), :id => 'minibutton-new-page', :class => 'button' .both / = render 'searchbar' = render "page" diff --git a/config/deploy.rb b/config/deploy.rb index d6b03af8a..bc6d7931b 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -3,12 +3,17 @@ $:.unshift File.expand_path('.') $:.unshift(File.expand_path('./lib', ENV['rvm_path'])) set :rvm_type, :user +set :default_environment, { + 'LANG' => 'en_US.UTF-8' +} + +#set :rake, "#{rake} --trace" + require 'rvm/capistrano' require 'bundler/capistrano' require 'delayed/recipes' require 'airbrake/capistrano' - set :whenever_command, "bundle exec whenever" # require "whenever/capistrano" @@ -61,6 +66,19 @@ namespace :deploy do task :symlink_pids, :roles => :app do run "cd #{fetch :shared_path}/tmp && ln -nfs ../pids pids" end + + # Speed up precompile (http://www.bencurtis.com/2011/12/skipping-asset-compilation-with-capistrano ) + namespace :assets do + task :precompile, :roles => :web, :except => { :no_release => true } do + from = source.next_revision(current_revision) + if capture("cd #{latest_release} && #{source.local.log(from)} app/assets/ lib/assets/ vendor/assets/ | wc -l").to_i > 0 + run %Q{cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile} + else + logger.info "Skipping asset pre-compilation because there were no asset changes" + end + end + end + end after "deploy:finalize_update", "deploy:symlink_all" diff --git a/config/deploy/application.pingwinsoft.yml b/config/deploy/application.pingwinsoft.yml new file mode 100644 index 000000000..ab00cdbb7 --- /dev/null +++ b/config/deploy/application.pingwinsoft.yml @@ -0,0 +1,22 @@ +common: &common + project_name: ABF + repo_project_name: ABF + distr_types: ['mdv', 'nau5', 'suse', 'deb'] + wiki_formats: + markdown: "Markdown" + textile: "Textile" + org: "Org-mode" + +production: + <<: *common + root_path: /share + nginx_log: /srv/rosa_build/shared/log/nginx.access.log + do-not-reply-email: do-not-reply@rosalab.ru + build_server_ip: 127.0.0.1 + build_server_port: 12555 + build_server_path: /xmlrpc + product_builder_ip: + mdv: 192.168.122.19 + nau5: 192.168.122.203 + product_builder_port: 12554 + product_builder_path: /xmlrpc \ No newline at end of file diff --git a/config/deploy/pingwinsoft.rb b/config/deploy/pingwinsoft.rb index 088b5b27d..83e0f8f1b 100644 --- a/config/deploy/pingwinsoft.rb +++ b/config/deploy/pingwinsoft.rb @@ -1,16 +1,14 @@ # -*- encoding : utf-8 -*- -set :branch, "pingwinsoft" +#require "whenever/capistrano" +set :branch, "master" -set :domain, "b.pingwinsoft.ru" # "195.19.76.12" -set :port, 1822 +set :domain, "89.248.225.78" # "195.19.76.12" +set :port, 16922 role :app, domain role :web, domain role :db, domain, :primary => true -set :application, "rosa_build_#{stage}" -set :deploy_to, "/srv/#{application}" - -# set :unicorn_port, 8081 - -before "deploy:restart", "deploy:stub_xml_rpc" +#set :application, "rosa_build_#{stage}" +#set :deploy_to, "/srv/#{application}" +#before "deploy:restart", "deploy:stub_xml_rpc" diff --git a/config/initializers/core.rb b/config/initializers/core.rb deleted file mode 100644 index 683f5b02f..000000000 --- a/config/initializers/core.rb +++ /dev/null @@ -1,2 +0,0 @@ -# -*- encoding : utf-8 -*- -require './lib/ext/core/string' diff --git a/config/locales/en.yml b/config/locales/en.yml index e226eebed..eefa2d4e0 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -24,6 +24,7 @@ en: create: Create update: Update delete: Erase + delete_selected: Remove selected save: Save clone: Clone search_by_name: Filter by name diff --git a/config/locales/menu.en.yml b/config/locales/menu.en.yml index bbea1cb51..bbc0e0bb9 100644 --- a/config/locales/menu.en.yml +++ b/config/locales/menu.en.yml @@ -33,6 +33,7 @@ en: wiki: Wiki platform_menu: settings: Settings + admins_menu_header: Admin admins_menu: users: Пользователи event_logs: Лог событий diff --git a/config/locales/menu.ru.yml b/config/locales/menu.ru.yml index 753772780..946f68e56 100644 --- a/config/locales/menu.ru.yml +++ b/config/locales/menu.ru.yml @@ -33,6 +33,7 @@ ru: wiki: Вики platform_menu: settings: Настройки + admins_menu_header: Центр управления admins_menu: users: Пользователи event_logs: Лог событий diff --git a/config/locales/models/activity_feed.en.yml b/config/locales/models/activity_feed.en.yml index 8b3c5cad6..3dcdf747d 100644 --- a/config/locales/models/activity_feed.en.yml +++ b/config/locales/models/activity_feed.en.yml @@ -7,7 +7,7 @@ en: all_my_builds: All my builds my_builds_by_day: My today builds new_project: Create project - load_messages: Load messages + load_messages: show previous messages notifications: subjects: diff --git a/config/locales/models/activity_feed.ru.yml b/config/locales/models/activity_feed.ru.yml index 052e4c5c5..bf78dc7d5 100644 --- a/config/locales/models/activity_feed.ru.yml +++ b/config/locales/models/activity_feed.ru.yml @@ -7,7 +7,7 @@ ru: all_my_builds: Все мои сборки my_builds_by_day: Мои сборки за день new_project: Создать проект - load_messages: Загрузить сообщения + load_messages: показать предыдущие сообщения notifications: subjects: diff --git a/config/locales/models/group.en.yml b/config/locales/models/group.en.yml index 139645c8f..6c09e295a 100644 --- a/config/locales/models/group.en.yml +++ b/config/locales/models/group.en.yml @@ -3,7 +3,7 @@ en: groups: list: List new: Create - edit: Edit + edit: Settings members: Members new_header: New group edit_header: Edit @@ -11,7 +11,7 @@ en: show: Group back_to_the_list: ⇐ List of groups confirm_delete: Are you sure to remove this group? - edit_members: Edit members + edit_members: Members group: Group description: Descripton leave_group: Leave group diff --git a/config/locales/models/group.ru.yml b/config/locales/models/group.ru.yml index 231f95c53..01c5aaf7a 100644 --- a/config/locales/models/group.ru.yml +++ b/config/locales/models/group.ru.yml @@ -3,7 +3,7 @@ ru: groups: list: Список new: Создать группу - edit: Редактировать + edit: Настройки members: Участники new_header: Новая группа edit_header: Редактировать @@ -11,7 +11,7 @@ ru: show: Группа back_to_the_list: ⇐ К списку групп confirm_delete: Вы уверены, что хотите удалить эту группу? - edit_members: Изменить список участников + edit_members: Участники group: Группа description: Описание leave_group: Покинуть группу diff --git a/config/locales/models/project.en.yml b/config/locales/models/project.en.yml index 7d840959a..4e1a50f05 100644 --- a/config/locales/models/project.en.yml +++ b/config/locales/models/project.en.yml @@ -2,7 +2,7 @@ en: layout: projects: add: Add - edit: Edit + edit: Settings fork_and_edit: Fork and Edit list: List list_header: Projects @@ -17,11 +17,10 @@ en: current_project_header: Current project current_build_lists: Current builds build_button: Start build - add_collaborators: Add collaborators + add_collaborators: Add members members: Members - collaborators: Collaborators groups: Groups - edit_collaborators: Edit collaborators + edit_collaborators: Members role: Project role remove_user: Leave project issues: Issues diff --git a/config/locales/models/project.ru.yml b/config/locales/models/project.ru.yml index dcc54cb96..abc61082a 100644 --- a/config/locales/models/project.ru.yml +++ b/config/locales/models/project.ru.yml @@ -2,7 +2,7 @@ ru: layout: projects: add: Добавить - edit: Редактировать + edit: Настройки fork_and_edit: Клонировать и редактировать list: Список list_header: Проекты @@ -17,11 +17,10 @@ ru: current_project_header: Текущий проект current_build_lists: Текущие сборки build_button: Начать сборку - add_collaborators: Добавить коллабораторов + add_collaborators: Добавить участников members: Участники - collaborators: Коллабораторы groups: Группы - edit_collaborators: Изменить список участников + edit_collaborators: Участники role: Роль в проекте remove_user: Покинуть проект issues: Задачи diff --git a/config/locales/ru.yml b/config/locales/ru.yml index ec5375701..8989582d7 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -24,6 +24,7 @@ ru: create: Создать update: Обновить delete: Удалить + delete_selected: Удалить выбранное save: Сохранить clone: Клонировать search_by_name: Фильтр по имени diff --git a/config/locales/users.en.yml b/config/locales/users.en.yml index 868058331..8dafa0915 100644 --- a/config/locales/users.en.yml +++ b/config/locales/users.en.yml @@ -25,6 +25,11 @@ en: avatar_notice: Without uploaded avatar will be used avatar from gravar web service. delete_avatar: Delete avatar avatar_with_size: Avatar (less than %{max}) + users_filter: + all: All + admin: Admins + real: Real + banned: Banned activerecord: attributes: diff --git a/config/locales/users.ru.yml b/config/locales/users.ru.yml index 33f5fa400..8c5317bc4 100644 --- a/config/locales/users.ru.yml +++ b/config/locales/users.ru.yml @@ -22,9 +22,14 @@ ru: delete_header: Удалить аккаунт delete_warning: Внимание! Удаленный аккаунт восстановлению не подлежит. private_settings_header: Изменение пароля - avatar_notice: При отсутствии загруженной аватарки будет использована Ваша аватарка на сервисе gravatar. + avatar_notice: При отсутствии загруженного аватара будет использован Ваш аватар на сервисе gravatar. delete_avatar: Удалить аватар avatar_with_size: Аватар (менее %{max}) + users_filter: + all: Все + admin: Админы + real: Обычные + banned: Забаненные activerecord: attributes: diff --git a/config/routes.rb b/config/routes.rb index c9173eb76..44906e335 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,14 +5,19 @@ Rosa::Application.routes.draw do devise_scope :user do get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru' - get '/user' => 'users#profile', :as => 'edit_profile' - put '/user' => 'users#update', :as => 'update_profile' - get '/users/:id/edit' => 'users#profile', :as => 'edit_user' - put '/users/:id/edit' => 'users#update', :as => 'update_user' + get '/user' => 'users#profile', :as => :edit_profile + put '/user' => 'users#update', :as => :update_profile + get '/users' => 'admin/users#index', :as => :users + get '/users/new' => 'admin/users#new', :as => :new_user + get '/users/list' => 'admin/users#list', :as => :users_list + post '/users/create' => 'admin/users#create', :as => :create_user + get '/users/:id/edit' => 'admin/users#profile', :as => :edit_user + put '/users/:id/edit' => 'admin/users#update', :as => :update_user + delete '/users/:id/delete' => 'admin/users#destroy', :as => :delete_user end devise_for :users, :controllers => {:omniauth_callbacks => 'users/omniauth_callbacks'} - resources :users do + resources :users, :only => [:show, :profile, :update] do resources :groups, :only => [:new, :create, :index] collection do resources :register_requests, :only => [:index, :new, :create, :show_message, :approve, :reject] do @@ -27,6 +32,7 @@ Rosa::Application.routes.draw do namespace :settings do resource :notifier, :only => [:show, :update] end + resources :platforms, :only => [:new, :create] end match 'users/:id/settings/private' => 'users#private', :as => :user_private_settings, :via => :get match 'users/:id/settings/private' => 'users#private', :as => :user_private_settings, :via => :put @@ -182,14 +188,14 @@ Rosa::Application.routes.draw do delete :remove end end - end - - resources :users, :groups do resources :platforms, :only => [:new, :create] - -# resources :repositories, :only => [:new, :create] end +# resources :users, :groups do +# resources :platforms, :only => [:new, :create] +# resources :repositories, :only => [:new, :create] +# end + resources :activity_feeds, :only => [:index] resources :search, :only => [:index] diff --git a/db/migrate/20120124065207_create_activity_feeds.rb b/db/migrate/20120124065207_create_activity_feeds.rb index d5b13fc3a..6037a0d14 100644 --- a/db/migrate/20120124065207_create_activity_feeds.rb +++ b/db/migrate/20120124065207_create_activity_feeds.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class CreateActivityFeeds < ActiveRecord::Migration def self.up create_table :activity_feeds do |t| diff --git a/db/migrate/20120219161749_add_creator_to_issue.rb b/db/migrate/20120219161749_add_creator_to_issue.rb index 54a3ba492..ccf0a1ef8 100644 --- a/db/migrate/20120219161749_add_creator_to_issue.rb +++ b/db/migrate/20120219161749_add_creator_to_issue.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddCreatorToIssue < ActiveRecord::Migration def change add_column :issues, :creator_id, :integer diff --git a/db/migrate/20120220175615_create_labels.rb b/db/migrate/20120220175615_create_labels.rb index b10b80ea7..ea91650c6 100644 --- a/db/migrate/20120220175615_create_labels.rb +++ b/db/migrate/20120220175615_create_labels.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class CreateLabels < ActiveRecord::Migration def change create_table :labels do |t| diff --git a/db/migrate/20120220185458_remove_repositories_owner.rb b/db/migrate/20120220185458_remove_repositories_owner.rb index 88c85a855..79d0d3e58 100644 --- a/db/migrate/20120220185458_remove_repositories_owner.rb +++ b/db/migrate/20120220185458_remove_repositories_owner.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class RemoveRepositoriesOwner < ActiveRecord::Migration def self.up remove_column :repositories, :owner_id diff --git a/db/migrate/20120228094721_add_closed_at_to_issue.rb b/db/migrate/20120228094721_add_closed_at_to_issue.rb index 91948e2af..e0fe478a4 100644 --- a/db/migrate/20120228094721_add_closed_at_to_issue.rb +++ b/db/migrate/20120228094721_add_closed_at_to_issue.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddClosedAtToIssue < ActiveRecord::Migration def change add_column :issues, :closed_at, :datetime diff --git a/db/migrate/20120228100121_add_closed_by_to_issue.rb b/db/migrate/20120228100121_add_closed_by_to_issue.rb index 9da79b29b..d0f815d70 100644 --- a/db/migrate/20120228100121_add_closed_by_to_issue.rb +++ b/db/migrate/20120228100121_add_closed_by_to_issue.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddClosedByToIssue < ActiveRecord::Migration def change add_column :issues, :closed_by, :integer diff --git a/db/migrate/20120229163054_add_description_to_groups.rb b/db/migrate/20120229163054_add_description_to_groups.rb index 16662758f..481c855c5 100644 --- a/db/migrate/20120229163054_add_description_to_groups.rb +++ b/db/migrate/20120229163054_add_description_to_groups.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddDescriptionToGroups < ActiveRecord::Migration def change add_column :groups, :description, :text diff --git a/db/migrate/20120229182356_add_default_values_to_is_rpm_for_projects.rb b/db/migrate/20120229182356_add_default_values_to_is_rpm_for_projects.rb index 4c223d2db..46fc6a7f4 100644 --- a/db/migrate/20120229182356_add_default_values_to_is_rpm_for_projects.rb +++ b/db/migrate/20120229182356_add_default_values_to_is_rpm_for_projects.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddDefaultValuesToIsRpmForProjects < ActiveRecord::Migration def change Project.update_all(:is_rpm => true) diff --git a/db/migrate/20120302102734_remove_name_from_groups.rb b/db/migrate/20120302102734_remove_name_from_groups.rb index f7f33ae48..2740878a9 100644 --- a/db/migrate/20120302102734_remove_name_from_groups.rb +++ b/db/migrate/20120302102734_remove_name_from_groups.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class RemoveNameFromGroups < ActiveRecord::Migration def up remove_column :groups, :name diff --git a/db/migrate/20120302114735_add_professional_experience_to_users.rb b/db/migrate/20120302114735_add_professional_experience_to_users.rb index 69ba2d342..1c3828533 100644 --- a/db/migrate/20120302114735_add_professional_experience_to_users.rb +++ b/db/migrate/20120302114735_add_professional_experience_to_users.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddProfessionalExperienceToUsers < ActiveRecord::Migration def change add_column :users, :professional_experience, :text diff --git a/db/migrate/20120303062601_add_site_company_and_location_to_users.rb b/db/migrate/20120303062601_add_site_company_and_location_to_users.rb index cb8f608db..8fc2939fe 100644 --- a/db/migrate/20120303062601_add_site_company_and_location_to_users.rb +++ b/db/migrate/20120303062601_add_site_company_and_location_to_users.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddSiteCompanyAndLocationToUsers < ActiveRecord::Migration def change add_column :users, :site, :string diff --git a/db/migrate/20120303171802_add_avatar_to_users.rb b/db/migrate/20120303171802_add_avatar_to_users.rb index 19ba567c7..a237076b3 100644 --- a/db/migrate/20120303171802_add_avatar_to_users.rb +++ b/db/migrate/20120303171802_add_avatar_to_users.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddAvatarToUsers < ActiveRecord::Migration def change change_table :users do |t| diff --git a/db/migrate/20120306212914_add_project_to_comment.rb b/db/migrate/20120306212914_add_project_to_comment.rb index 4ae6f4b64..94b6f8361 100644 --- a/db/migrate/20120306212914_add_project_to_comment.rb +++ b/db/migrate/20120306212914_add_project_to_comment.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddProjectToComment < ActiveRecord::Migration def up add_column :comments, :project_id, :integer diff --git a/db/migrate/20120313130930_delete_dublicate_subscribes.rb b/db/migrate/20120313130930_delete_dublicate_subscribes.rb index 7f1fcc6b9..2ec50ad80 100644 --- a/db/migrate/20120313130930_delete_dublicate_subscribes.rb +++ b/db/migrate/20120313130930_delete_dublicate_subscribes.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class DeleteDublicateSubscribes < ActiveRecord::Migration def up execute <<-SQL diff --git a/db/migrate/20120314151558_truncate_activity_feed.rb b/db/migrate/20120314151558_truncate_activity_feed.rb index aea3a87fd..5484c71bf 100644 --- a/db/migrate/20120314151558_truncate_activity_feed.rb +++ b/db/migrate/20120314151558_truncate_activity_feed.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class TruncateActivityFeed < ActiveRecord::Migration def up ActivityFeed.destroy_all diff --git a/db/migrate/20120314162313_add_description_to_products.rb b/db/migrate/20120314162313_add_description_to_products.rb index 3a54c661a..68d22d552 100644 --- a/db/migrate/20120314162313_add_description_to_products.rb +++ b/db/migrate/20120314162313_add_description_to_products.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddDescriptionToProducts < ActiveRecord::Migration def self.up add_column :products, :description, :text diff --git a/db/migrate/20120314223151_remove_is_template_from_products.rb b/db/migrate/20120314223151_remove_is_template_from_products.rb index b130c4f1a..c29ba1d01 100644 --- a/db/migrate/20120314223151_remove_is_template_from_products.rb +++ b/db/migrate/20120314223151_remove_is_template_from_products.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class RemoveIsTemplateFromProducts < ActiveRecord::Migration def up remove_column :products, :is_template diff --git a/db/migrate/20120320102912_add_build_list_priority.rb b/db/migrate/20120320102912_add_build_list_priority.rb index a1b08d66d..55e5fd81a 100644 --- a/db/migrate/20120320102912_add_build_list_priority.rb +++ b/db/migrate/20120320102912_add_build_list_priority.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddBuildListPriority < ActiveRecord::Migration def self.up add_column :build_lists, :priority, :integer, :null => false, :default => 0 @@ -6,4 +7,4 @@ class AddBuildListPriority < ActiveRecord::Migration def self.down remove_column :build_lists, :priority end -end \ No newline at end of file +end diff --git a/db/migrate/20120321130436_add_devise_lockable.rb b/db/migrate/20120321130436_add_devise_lockable.rb index 0d242536d..2a82c94a6 100644 --- a/db/migrate/20120321130436_add_devise_lockable.rb +++ b/db/migrate/20120321130436_add_devise_lockable.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class AddDeviseLockable < ActiveRecord::Migration def change add_column :users, :failed_attempts, :integer, :default => 0 # Only if lock strategy is :failed_attempts diff --git a/db/schema.rb b/db/schema.rb index fe45f84a7..cb386ec97 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,4 +1,4 @@ -# encoding: UTF-8 +# -*- encoding : utf-8 -*- # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. diff --git a/doc/README_FOR_APP b/doc/README_FOR_APP index 5fcb0c1f8..8458ee4f1 100644 --- a/doc/README_FOR_APP +++ b/doc/README_FOR_APP @@ -18,5 +18,7 @@ Add to /etc/rc.d/rc.sysinit fi === Tips -gem install charlock_holmes -- --with-icu-dir=/opt/local +sudo urpmi lib64icu-devel # mandriva +gem install charlock_holmes -- --with-icu-dir=/opt/local # macports + git config --global core.quotepath false diff --git a/doc/design/abf-404.html b/doc/design/abf-404.html index eb56cd7ed..9bfac5f12 100644 --- a/doc/design/abf-404.html +++ b/doc/design/abf-404.html @@ -17,9 +17,12 @@
+ -
diff --git a/doc/design/abf-500.html b/doc/design/abf-500.html new file mode 100644 index 000000000..fc5d9ea3d --- /dev/null +++ b/doc/design/abf-500.html @@ -0,0 +1,138 @@ + + + + + Сборочная среда + + + + + + +
+ +
+
+
+
+ + + + + + +
+ + + +
+
+ avatar +
+ +
+ +
+
+ + + +
+ +
+
+
+
+
+
+ +
+
+ + +
+ +
+ +

Ошибка 500

+

Что-то пошло не так.
+Мы были уведомлены об этом
+и скоро посмотрим что случилось.

+

+ Попробуйте открыть другие страницы. +

+ +
+ +
+ +
+
+
+ +
+ + + + \ No newline at end of file diff --git a/doc/design/abf-503.html b/doc/design/abf-503.html new file mode 100644 index 000000000..2fd2a65e9 --- /dev/null +++ b/doc/design/abf-503.html @@ -0,0 +1,62 @@ + + + + + Сборочная среда + + + + + + +
+ + +
+ +
+ +

Ведутся работы

+

Мы обновляем сайт, это займет еще некоторое время.
+Нажмите F5, если это не помогло, значит,
+нужно еще чуточку подождать.
+
+Мы правда пытаемся сделать это быстро и
+приносим свои извинения за возможные неудобства.

+
+ +
+ +
+
+
+ +
+ + + + \ No newline at end of file diff --git a/doc/design/abf-tracker.html b/doc/design/abf-tracker.html index 84147a9b2..c65e8de99 100644 --- a/doc/design/abf-tracker.html +++ b/doc/design/abf-tracker.html @@ -21,9 +21,12 @@
+ -
@@ -374,17 +374,33 @@
assets do not update if fingerprinting is turned on in development 3.2.0
2012-01-19 10:10 UTC by nathanhumber - -
+
+
+
2-3 stable
+
+
+ +
+
+
+ 3-0 stable +
+
+
+
+
+ 2-3 stable +
- +
+
@@ -414,8 +430,8 @@
date_select with both discard_day and include_blank may be broken in 3.2
-
2012-01-18 21:12 UTC by railsaholic - +
2012-01-18 21:12 UTC by railsaholic
+
3-0 stable @@ -423,8 +439,9 @@
+
+ -
@@ -511,7 +528,9 @@
assets do not update if fingerprinting is turned on in development 3.1.0
2012-01-19 10:10 UTC by nathanhumber +
+
2-3 stable @@ -519,8 +538,9 @@
-
+ + @@ -551,7 +571,9 @@
date_select with both discard_day and include_blank may be broken in 3.1
-
2012-01-18 21:12 UTC by railsaholic +
2012-01-18 21:12 UTC by railsaholic
+ +
@@ -561,6 +583,7 @@
+
diff --git a/doc/design/pics/404.png b/doc/design/pics/404.png index 0c6ce2f7b..9efbf38fa 100644 Binary files a/doc/design/pics/404.png and b/doc/design/pics/404.png differ diff --git a/doc/design/pics/500.png b/doc/design/pics/500.png new file mode 100644 index 000000000..ea507efc9 Binary files /dev/null and b/doc/design/pics/500.png differ diff --git a/doc/design/pics/503.png b/doc/design/pics/503.png new file mode 100644 index 000000000..915e9c483 Binary files /dev/null and b/doc/design/pics/503.png differ diff --git a/doc/design/styles/main.css b/doc/design/styles/main.css index 5f992cdd5..59d94275b 100644 --- a/doc/design/styles/main.css +++ b/doc/design/styles/main.css @@ -1394,7 +1394,7 @@ h3.bmargin10 { padding-top: 9px; } -div.desription-top { +div.description-top { background: #dcecfa; font-size: 12px; color: #292929; @@ -1404,13 +1404,13 @@ div.desription-top { margin-bottom: 20px; } -div.desription-top div.img { +div.description-top div.img { float: left; padding-left: 10px; margin-top: 14px; } -div.desription-top input.name { +div.description-top input.name { float: left; margin-top: 5px; margin-left: 10px; @@ -1424,7 +1424,7 @@ div.desription-top input.name { padding: 2px 5px 3px; } -div.desription-top div.role { +div.description-top div.role { float: left; margin-top: 11px; margin-left: 10px; @@ -1441,7 +1441,7 @@ div.desription-top div.role { margin-right: 2px; } -div.desription-top div.fork { +div.description-top div.fork { margin-right: 10px; } @@ -1693,31 +1693,31 @@ table.tablesorter.tracker td.td0{ } table.tablesorter.tracker td.td3{ - width: 120px; + min-width: 110px; padding-top: 10px; } table.tablesorter.tracker td.td3 div.code { - height: 19px; + height: 23px; width: 15px; background: #FFF; color: #009fe3; border: 1px solid #83d1f2; font-size: 16px; - padding: 1px 0px 0px 5px; + padding: 5px 0px 0px 5px; float: left; - margin-right: 5px; + margin-right: 3px; cursor: pointer; } table.tablesorter.tracker td.td3 div.avatar { float: left; - margin-right: 5px; + margin-right: 8px; cursor: pointer; } table.tablesorter.tracker td.td3 div.answers { - height: 20px; + height: 28px; background: #FFF; color: #009fe3; border: 1px solid #83d1f2; @@ -1729,11 +1729,12 @@ table.tablesorter.tracker td.td3 div.answers { table.tablesorter.tracker td.td3 div.answers div.pic { float: left; margin: 2px; + margin-top: 6px; } table.tablesorter.tracker td.td3 div.answers div.count { float: left; - margin: 0px 5px 0px 2px; + margin: 4px 5px 0px 2px; } table.tablesorter.tracker div.smalltext { @@ -1749,9 +1750,14 @@ div.label.selected.tracker { clear: both; cursor: default; margin-left: 0px; - padding: 5px; - float: right; - margin-top: -6px; + padding: 0px 0px 0px 2px; + float: left; + margin-top: 3px; +} + +div.right div.left.nomargin { + margin: 0px; + padding: 0px; } div.label.selected.tracker:hover { @@ -2367,4 +2373,46 @@ table.tablesorter.width565 { article h3 a { font-size: 14px; +} + + +/*Wiki*/ + +div#wiki-content div.wrap { + width: 100%; + text-align: left; + border: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + background: #FFF; + margin-top: 20px; +} + +div#wiki-content div#wiki-body { + float: left; + width: 410px; + margin: 0px 0px 20px; +} + +div#wiki-content div#wiki-rightbar { + float: right; + width: 170px; +} + +div#wiki-content div#wiki-footer { + clear: both; + margin: 20px 0px; +} + +div#wiki-content div#wiki-rightbar, div#wiki-content div#wiki-footer { + background-color: #f7f7f7; + border: 1px solid #DDDDDD; + border-radius: 3px; + line-height: 1.5em; + padding: 10px 20px; +} + +div#gollum-footer { + color: #727272; } \ No newline at end of file diff --git a/lib/ext/core/object.rb b/lib/ext/core/object.rb index d2856a51c..cdd331d93 100644 --- a/lib/ext/core/object.rb +++ b/lib/ext/core/object.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- class Object def with_skip begin diff --git a/lib/ext/gollum.rb b/lib/ext/gollum.rb index 8109242e9..817aa5f30 100644 --- a/lib/ext/gollum.rb +++ b/lib/ext/gollum.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- # # -*- encoding : utf-8 -*- module Gollum class Wiki diff --git a/lib/ext/grit.rb b/lib/ext/grit.rb index 043553435..d0cf5590f 100644 --- a/lib/ext/grit.rb +++ b/lib/ext/grit.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- # -*- ruby encoding: utf-8 -*- module Grit diff --git a/lib/grack/auth.rb b/lib/grack/auth.rb index 0b2c93ad5..598dd11a1 100644 --- a/lib/grack/auth.rb +++ b/lib/grack/auth.rb @@ -12,7 +12,7 @@ module Grack return render_not_found if project.blank? return ::Rack::Auth::Basic.new(@app) do |u, p| - user = User.find_for_database_authentication(:login => u) and user.valid_password?(p) and + user = User.find_for_database_authentication(:login => u) and !user.access_locked? and user.valid_password?(p) and ability = ::Ability.new(user) and ability.can?(action, project) # project.members.include?(user) end.call(env) unless project.public? and read? # need auth end diff --git a/lib/tasks/add_branch.rake b/lib/tasks/add_branch.rake index 1a7b96bd5..c8d7cf48d 100644 --- a/lib/tasks/add_branch.rake +++ b/lib/tasks/add_branch.rake @@ -9,12 +9,12 @@ task :add_branch => :environment do Platform.find_by_name(dst_branch).repositories.each do |r| say "=== Process #{r.name} repo" r.projects.find_each do |p| + next if p.branches.map(&:name).include?(dst_branch) say "===== Process #{p.name} project" tmp_path = Rails.root.join('tmp', p.name) system("git clone #{p.path} #{tmp_path}") - system("cd #{tmp_path} && git checkout remotes/origin/#{src_branch}") or system("cd #{tmp_path} && git checkout master") - system("cd #{tmp_path} && git checkout -b #{dst_branch}") - system("cd #{tmp_path} && git push origin HEAD") + system("cd #{tmp_path} && git checkout remotes/origin/#{src_branch} || git checkout master") + system("cd #{tmp_path} && git checkout -b #{dst_branch} && git push origin HEAD") FileUtils.rm_rf tmp_path end end diff --git a/public/404.html b/public/404.html index b5ea1ac4e..1b6717f14 100644 --- a/public/404.html +++ b/public/404.html @@ -1,22 +1,104 @@ - -not found + + + 404 + + + +
+ +
+
+
+
+ + + + + +
+ +
+ +
+
+
+
+
+
- +
+
+ + +
+ +
+ +

Error 404

+

Page not found

+

+ Try to open other pages. +

+ +
+ +
+ +
+
+
+
+ + - - -
-

Not found

-

:(

-
\ No newline at end of file + diff --git a/public/500.html b/public/500.html index b80307fc1..f4a948b0a 100644 --- a/public/500.html +++ b/public/500.html @@ -1,26 +1,106 @@ - - - - We're sorry, but something went wrong (500) - + + + 500 + - - -
-

We're sorry, but something went wrong.

-

We've been notified about this issue and we'll take a look at it shortly.

+
+ +
+
+
+
+ + + + + +
+ +
+ +
+
+
+
+
+
+ +
+
+ + +
+ +
+ +

Error 500

+

Something went wrong.
+ We've been notified about this issue
+ and we'll take a look at it shortly.

+

+ Try to open other pages. +

+ +
+ +
+ +
+
+
+
- - + + + + diff --git a/public/503.html b/public/503.html new file mode 100644 index 000000000..e82e44265 --- /dev/null +++ b/public/503.html @@ -0,0 +1,57 @@ + + + 503 + + + +
+ + +
+ +
+ +

Work is underway

+

We update the site, it will take some time.
+Press F5, if this does not help, it means,
+need to wait a little bit more.
+
+We are really trying to do it fast.
+We apologize for any inconvenience.

+
+ +
+ +
+
+
+ +
+ + + + diff --git a/public/pics/logo-mini.png b/public/pics/logo-mini.png new file mode 100644 index 000000000..3175f3b21 Binary files /dev/null and b/public/pics/logo-mini.png differ diff --git a/spec/controllers/activity_feeds_controller_spec.rb b/spec/controllers/activity_feeds_controller_spec.rb index 54ce3026a..8c9773ab7 100644 --- a/spec/controllers/activity_feeds_controller_spec.rb +++ b/spec/controllers/activity_feeds_controller_spec.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- require 'spec_helper' describe ActivityFeedsController do diff --git a/spec/controllers/collaborators_controller_spec.rb b/spec/controllers/collaborators_controller_spec.rb index 858bd3c05..02383d998 100644 --- a/spec/controllers/collaborators_controller_spec.rb +++ b/spec/controllers/collaborators_controller_spec.rb @@ -9,7 +9,7 @@ shared_examples_for 'project admin user' do it 'should be able to perform update action' do post :update, {:project_id => @project.id}.merge(@update_params) - response.should redirect_to(project_path(@project)) + response.should redirect_to(edit_project_collaborators_path(@project)) end it 'should be able to set reader role for any user' do @@ -26,7 +26,7 @@ shared_examples_for 'user with no rights for this project' do it 'should not be able to perform update action' do post :update, {:project_id => @project.id}.merge(@update_params) - response.should redirect_to(project_path(@project)) + response.should redirect_to(edit_project_collaborators_path(@project)) end it 'should not be able to set reader role for any user' do @@ -40,7 +40,7 @@ describe CollaboratorsController do stub_rsync_methods @project = Factory(:project) @another_user = Factory(:user) - @update_params = {:user => {:read => {@another_user.id => '1'}}} + @update_params = {:user => {@another_user.id => :reader}} end context 'for guest' do diff --git a/spec/controllers/personal_repositories_controller_spec.rb b/spec/controllers/personal_repositories_controller_spec.rb index 6e020d61e..b413f28fd 100644 --- a/spec/controllers/personal_repositories_controller_spec.rb +++ b/spec/controllers/personal_repositories_controller_spec.rb @@ -11,19 +11,19 @@ end shared_examples_for 'personal repository owner' do it_should_behave_like 'personal repository viewer' - it 'should be able to perform add_project action' do + it 'should not be able to perform add_project action' do get :add_project, :id => @repository.id - response.should render_template(:projects_list) + response.should redirect_to(forbidden_path) end - it 'should be able to add project personal repository with project_id param' do + it 'should not be able to add project personal repository with project_id param' do get :add_project, :id => @repository.id, :project_id => @project.id - response.should redirect_to(personal_repository_path(@repository)) + response.should redirect_to(forbidden_path) end - it 'should be able to perform remove_project action' do + it 'should not be able to perform remove_project action' do get :remove_project, :id => @repository.id, :project_id => @project.id - response.should redirect_to(personal_repository_path(@repository)) + response.should redirect_to(forbidden_path) end @@ -64,12 +64,11 @@ describe PersonalRepositoriesController do end end - context 'for admin' do + context 'for global admin' do before(:each) do @admin = Factory(:admin) - set_session_for(@admin) - @project.update_attribute(:owner, @admin) + set_session_for(@admin) end it_should_behave_like 'personal repository owner' @@ -77,7 +76,7 @@ describe PersonalRepositoriesController do it_should_behave_like 'repository user with remove project rights' end - context 'for anyone except admin' do + pending 'for anyone except admin' do before(:each) do @user = Factory(:user) set_session_for(@user) @@ -88,12 +87,13 @@ describe PersonalRepositoriesController do context 'for owner user' do before(:each) do @user = Factory(:user) - set_session_for(@user) @project.update_attribute(:owner, @user) @repository.platform.update_attribute(:owner, @user) @repository.platform.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'admin') + + set_session_for(@user) end it_should_behave_like 'personal repository owner' @@ -104,8 +104,8 @@ describe PersonalRepositoriesController do context 'for reader user' do before(:each) do @user = Factory(:user) - set_session_for(@user) @repository.platform.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'reader') + set_session_for(@user) end it_should_behave_like 'personal repository viewer' diff --git a/spec/controllers/platforms_controller_spec.rb b/spec/controllers/platforms_controller_spec.rb index 1f42bcdc1..2514fe136 100644 --- a/spec/controllers/platforms_controller_spec.rb +++ b/spec/controllers/platforms_controller_spec.rb @@ -15,7 +15,7 @@ shared_examples_for 'platform owner' do it 'should be able to perform destroy action' do delete :destroy, :id => @platform.id - response.should redirect_to(root_path) + response.should redirect_to(platforms_path) end end @@ -61,7 +61,7 @@ describe PlatformsController do end end - [:show, :new, :edit, :freeze, :unfreeze, :clone, :destroy].each do |action| + [:show, :new, :edit, :clone, :destroy].each do |action| it "should not be able to perform #{ action } action" do get action, :id => @platform response.should redirect_to(new_user_session_path) diff --git a/spec/controllers/products_controller_spec.rb b/spec/controllers/products_controller_spec.rb index 7184e039c..6f57b2b45 100644 --- a/spec/controllers/products_controller_spec.rb +++ b/spec/controllers/products_controller_spec.rb @@ -36,7 +36,7 @@ describe ProductsController do it 'should be able to perform create action' do post :create, @create_params - response.should redirect_to(platform_path( Product.last.platform.id )) + response.should redirect_to(platform_product_path( Product.last.platform.id, Product.last )) end it 'should change objects count on create' do @@ -54,7 +54,7 @@ describe ProductsController do it 'should be able to perform destroy action' do delete :destroy, :platform_id => @platform.id, :id => @product.id - response.should redirect_to(platform_path(@platform)) + response.should redirect_to(platform_products_path(@platform)) end end @@ -67,7 +67,7 @@ describe ProductsController do it 'should be able to perform create action' do post :create, @create_params - response.should redirect_to(platform_path( Product.last.platform.id )) + response.should redirect_to(platform_product_path( Product.last.platform.id, Product.last )) end it 'should change objects count on create' do @@ -85,7 +85,7 @@ describe ProductsController do it 'should be able to perform destroy action' do delete :destroy, :platform_id => @platform.id, :id => @product.id - response.should redirect_to(platform_path(@platform)) + response.should redirect_to(platform_products_path(@platform)) end end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 497c08695..6598ee7e6 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -76,12 +76,6 @@ describe ProjectsController do end it_should_behave_like 'projects user with reader rights' - - pending 'should be able to perform show action' do - get :show, :id => @project.id - response.should render_template(:show) - end - end context 'for writer user' do diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index a5a714873..7a15ae171 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -1,52 +1,30 @@ # -*- encoding : utf-8 -*- require 'spec_helper' -shared_examples_for 'user with users list viewer rights' do - it 'should be able to perform index action' do - get :index - response.should render_template(:index) - end - - it 'should assigns 5 users without filter params' do - get :index - assigns[:users].count.should == 5 - end - - it 'should find one user' do - get :index, :filter => {:email => "user1@nonexistanceserver.com"} - assigns[:users].size == 1 - end - - it 'should find user with searchable email' do - get :index, :filter => {:email => "user1@nonexistanceserver.com"} - assigns[:users].first.email.should == "user1@nonexistanceserver.com" - end -end - describe UsersController do before(:each) do stub_rsync_methods @simple_user = Factory(:user) + @other_user = Factory(:user) @admin = Factory(:admin) %w[user1 user2 user3].each do |uname| Factory(:user, :uname => uname, :email => "#{ uname }@nonexistanceserver.com") end - end - - context 'for global admin' do - before(:each) do - set_session_for(@admin) - end - - it_should_behave_like 'user with users list viewer rights' + @update_params = {:email => 'new_email@test.com'} end context 'for guest' do - it 'should not be able to perform index action' do - get :index + it 'should not be able to view profile' do + get :profile response.should redirect_to(new_user_session_path) end + + it 'should not be able to update other profile' do + get :update, {:id => @other_user.id}.merge(@update_params) + response.should redirect_to(new_user_session_path) + @other_user.reload.email.should_not == @update_params[:email] + end end context 'for simple user' do @@ -54,9 +32,23 @@ describe UsersController do set_session_for(@simple_user) end - it 'should not be able to perform index action' do - get :index - response.should redirect_to(forbidden_path) + it 'should be able to view profile' do + get :profile + response.code.should eq('200') + end + + context 'with mass assignment' do + it 'should not be able to update uname' do + @simple_user.should_not allow_mass_assignment_of :uname + end + + it 'should not be able to update role' do + @simple_user.should_not allow_mass_assignment_of :role + end + + it 'should not be able to update other user' do + @simple_user.should_not allow_mass_assignment_of :id + end end end end diff --git a/spec/factories/activity_feeds.rb b/spec/factories/activity_feeds.rb index d0e1984cc..a1d3273a1 100644 --- a/spec/factories/activity_feeds.rb +++ b/spec/factories/activity_feeds.rb @@ -1,6 +1,7 @@ +# -*- encoding : utf-8 -*- # Read about factories at http://github.com/thoughtbot/factory_girl FactoryGirl.define do factory :activity_feed do end -end \ No newline at end of file +end diff --git a/spec/factories/issues.rb b/spec/factories/issues.rb index 63a0c6682..dba0b93ab 100644 --- a/spec/factories/issues.rb +++ b/spec/factories/issues.rb @@ -4,5 +4,6 @@ Factory.define(:issue) do |p| p.body { Factory.next(:string) } p.association :project, :factory => :project p.association :user, :factory => :user + p.association :creator, :factory => :user p.status "open" end diff --git a/spec/helpers/activity_feeds_helper_spec.rb b/spec/helpers/activity_feeds_helper_spec.rb index 623c526ec..ce14e82ce 100644 --- a/spec/helpers/activity_feeds_helper_spec.rb +++ b/spec/helpers/activity_feeds_helper_spec.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- require 'spec_helper' # Specs in this file have access to a helper object that includes diff --git a/spec/helpers/build_lists_helper_spec.rb b/spec/helpers/build_lists_helper_spec.rb index bda7a8ffb..ceea3a40f 100644 --- a/spec/helpers/build_lists_helper_spec.rb +++ b/spec/helpers/build_lists_helper_spec.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- require 'spec_helper' # Specs in this file have access to a helper object that includes diff --git a/spec/models/activity_feed_observer_spec.rb b/spec/models/activity_feed_observer_spec.rb index 378ee2377..f008468e9 100644 --- a/spec/models/activity_feed_observer_spec.rb +++ b/spec/models/activity_feed_observer_spec.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- require 'spec_helper' describe ActivityFeedObserver do diff --git a/spec/models/activity_feed_spec.rb b/spec/models/activity_feed_spec.rb index c77e1d83a..cc55d6c65 100644 --- a/spec/models/activity_feed_spec.rb +++ b/spec/models/activity_feed_spec.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- require 'spec_helper' describe ActivityFeed do diff --git a/spec/models/cancan_spec.rb b/spec/models/cancan_spec.rb index 248a502d6..5928659d4 100644 --- a/spec/models/cancan_spec.rb +++ b/spec/models/cancan_spec.rb @@ -253,7 +253,7 @@ describe CanCan do @platform.update_attribute(:owner, @user) end - [:read, :update, :destroy, :freeze, :unfreeze].each do |action| + [:read, :update, :destroy].each do |action| it "should be able to #{action} platform" do @ability.should be_able_to(action, @platform) end diff --git a/spec/models/comment_for_commit_spec.rb b/spec/models/comment_for_commit_spec.rb index d2b6a61da..66c17ec05 100644 --- a/spec/models/comment_for_commit_spec.rb +++ b/spec/models/comment_for_commit_spec.rb @@ -9,8 +9,13 @@ def set_comments_data_for_commit %x(cp -Rf #{Rails.root}/spec/tests.git/* #{@project.git_repository.path}) # maybe FIXME ? @commit = @project.git_repository.commits.first - @comment = Factory(:comment, :user => @user) - @comment.update_attributes(:commentable_type => @commit.class.name, :commentable_id => @commit.id) + #@comment = Factory(:comment, :user => @user, :commentable_type => @commit.class.name, :commentable_id => @commit.id, :project => @project) + @comment = Factory.build(:comment, :user => @user, :project => @project) + @comment.commentable_type = @commit.class.name + @comment.commentable_id = @commit.id.hex + puts @comment.inspect + @comment.save + #@comment.update_attributes(:commentable_type => @commit.class.name, :commentable_id => @commit.id) @stranger_comment = Factory(:comment, :user => @stranger) @stranger_comment.update_attributes(:commentable_type => @commit.class.name, :commentable_id => @commit.id, :project => @project) diff --git a/spec/models/labels_spec.rb b/spec/models/labels_spec.rb index dd72c1f9f..8bfa08304 100644 --- a/spec/models/labels_spec.rb +++ b/spec/models/labels_spec.rb @@ -1,3 +1,4 @@ +# -*- encoding : utf-8 -*- require 'spec_helper' describe Label do diff --git a/spec/support/shared_examples/personal_repositories_controller.rb b/spec/support/shared_examples/personal_repositories_controller.rb index 7830abab2..d3aa5c969 100644 --- a/spec/support/shared_examples/personal_repositories_controller.rb +++ b/spec/support/shared_examples/personal_repositories_controller.rb @@ -9,6 +9,6 @@ end shared_examples_for 'destroy personal repository' do it 'should be able to perform destroy action' do delete :destroy, :id => @repository.id - response.should redirect_to(platform_path(@repository.platform.id)) + response.should redirect_to(platform_repositories_path(@repository.platform.id)) end end diff --git a/spec/support/shared_examples/repositories_controller.rb b/spec/support/shared_examples/repositories_controller.rb index 5debef465..adb222544 100644 --- a/spec/support/shared_examples/repositories_controller.rb +++ b/spec/support/shared_examples/repositories_controller.rb @@ -19,21 +19,21 @@ shared_examples_for 'repository user with owner rights' do it 'should be able to perform add_project action with project_id param' do get :add_project, :id => @repository.id, :project_id => @project.id - response.should redirect_to(repository_path(@repository)) + response.should redirect_to(platform_repository_path(@repository.platform, @repository)) end it_should_behave_like 'repository user with add project rights' it 'should be able to perform remove_project action' do get :remove_project, :id => @repository.id, :project_id => @project.id - response.should redirect_to(repository_path(@repository)) + response.should redirect_to(platform_repository_path(@repository.platform, @repository)) end it_should_behave_like 'repository user with remove project rights' it 'should be able to perform destroy action' do delete :destroy, :id => @repository.id - response.should redirect_to(platform_path(@repository.platform.id)) + response.should redirect_to(platform_repositories_path(@repository.platform)) end it 'should change objects count after destroy action' do diff --git a/vendor/assets/javascripts/codemirror.js b/vendor/assets/javascripts/codemirror.js index 9c6e65e41..7bd580f4a 100644 --- a/vendor/assets/javascripts/codemirror.js +++ b/vendor/assets/javascripts/codemirror.js @@ -1,5 +1,3 @@ -// CodeMirror version 2.22 -// // All functions that need access to the editor's state live inside // the CodeMirror function. Below that, at the bottom of the file, // some utilities are defined. @@ -15,9 +13,8 @@ var CodeMirror = (function() { if (defaults.hasOwnProperty(opt)) options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt]; - var targetDocument = options["document"]; // The element in which the editor lives. - var wrapper = targetDocument.createElement("div"); + var wrapper = document.createElement("div"); wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : ""); // This mess creates the base DOM structure for the editor. wrapper.innerHTML = @@ -48,7 +45,10 @@ var CodeMirror = (function() { if (!webkit) lineSpace.draggable = true; lineSpace.style.outline = "none"; if (options.tabindex != null) input.tabIndex = options.tabindex; + if (options.autofocus) focusInput(); if (!options.gutter && !options.lineNumbers) gutter.style.display = "none"; + // Needed to handle Tab key in KHTML + if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute"; // Check for problem with IE innerHTML not working when we have a // P (or similar) parent node. @@ -81,12 +81,13 @@ var CodeMirror = (function() { gutterDirty, callbacks; // Current visible range (may be bigger than the view window). var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0; - // bracketHighlighted is used to remember that a backet has been + // bracketHighlighted is used to remember that a bracket has been // marked. var bracketHighlighted; // Tracks the maximum line length so that the horizontal scrollbar // can be kept static when scrolling. var maxLine = "", maxWidth; + var tabCache = {}; // Initialize the content. operation(function(){setValue(options.value || ""); updateInput = false;})(); @@ -124,10 +125,16 @@ var CodeMirror = (function() { if (!options.readOnly) replaceSelection(""); })); + // Needed to handle Tab key in KHTML + if (khtml) connect(code, "mouseup", function() { + if (document.activeElement == input) input.blur(); + focusInput(); + }); + // IE throws unspecified error in certain cases, when // trying to access activeElement before onload - var hasFocus; try { hasFocus = (targetDocument.activeElement == input); } catch(e) { } - if (hasFocus) setTimeout(onFocus, 20); + var hasFocus; try { hasFocus = (document.activeElement == input); } catch(e) { } + if (hasFocus || options.autofocus) setTimeout(onFocus, 20); else onBlur(); function isLine(l) {return l >= 0 && l < doc.size;} @@ -178,17 +185,23 @@ var CodeMirror = (function() { line = clipLine(line == null ? doc.size - 1: line); return getStateBefore(line + 1); }, - cursorCoords: function(start){ + cursorCoords: function(start, mode) { if (start == null) start = sel.inverted; - return pageCoords(start ? sel.from : sel.to); + return this.charCoords(start ? sel.from : sel.to, mode); + }, + charCoords: function(pos, mode) { + pos = clipPos(pos); + if (mode == "local") return localCoords(pos, false); + if (mode == "div") return localCoords(pos, true); + return pageCoords(pos); }, - charCoords: function(pos){return pageCoords(clipPos(pos));}, coordsChar: function(coords) { var off = eltOffset(lineSpace); return coordsChar(coords.x - off.left, coords.y - off.top); }, markText: operation(markText), setBookmark: setBookmark, + findMarksAt: findMarksAt, setMarker: operation(addGutterMarker), clearMarker: operation(removeGutterMarker), setLineClass: operation(setLineClass), @@ -256,6 +269,7 @@ var CodeMirror = (function() { replaceRange: operation(replaceRange), getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));}, + triggerOnKeyDown: operation(onKeyDown), execCommand: function(cmd) {return commands[cmd](instance);}, // Stuff used by commands, probably not much use to outside code. moveH: operation(moveH), @@ -373,7 +387,7 @@ var CodeMirror = (function() { !posLess(start, sel.from) && !posLess(sel.to, start)) { // Let the drag handler handle this. if (webkit) lineSpace.draggable = true; - var up = connect(targetDocument, "mouseup", operation(function(e2) { + var up = connect(document, "mouseup", operation(function(e2) { if (webkit) lineSpace.draggable = false; draggingText = false; up(); @@ -384,6 +398,8 @@ var CodeMirror = (function() { } }), true); draggingText = true; + // IE's approach to draggable + if (lineSpace.dragDrop) lineSpace.dragDrop(); return; } e_preventDefault(e); @@ -402,12 +418,7 @@ var CodeMirror = (function() { } } - var move = connect(targetDocument, "mousemove", operation(function(e) { - clearTimeout(going); - e_preventDefault(e); - extend(e); - }), true); - var up = connect(targetDocument, "mouseup", operation(function(e) { + function done(e) { clearTimeout(going); var cur = posFromMouse(e); if (cur) setSelectionUser(start, cur); @@ -415,7 +426,14 @@ var CodeMirror = (function() { focusInput(); updateInput = true; move(); up(); + } + var move = connect(document, "mousemove", operation(function(e) { + clearTimeout(going); + e_preventDefault(e); + if (!ie && !e_button(e)) done(e); + else extend(e); }), true); + var up = connect(document, "mouseup", operation(done), true); } function onDoubleClick(e) { for (var n = e_target(e); n != wrapper; n = n.parentNode) @@ -464,11 +482,14 @@ var CodeMirror = (function() { } function onDragStart(e) { var txt = getSelection(); - // Disabled until further notice. Doesn't work on most browsers, - // and crashes Safari (issue #332). - //htmlEscape(txt); - //e.dataTransfer.setDragImage(escapeElement, 0, 0); e.dataTransfer.setData("Text", txt); + + // Use dummy image instead of default browsers image. + if (gecko || chrome) { + var img = document.createElement('img'); + img.scr = 'data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs='; //1x1 image + e.dataTransfer.setDragImage(img, 0, 0); + } } function doHandleBinding(bound, dropShift) { @@ -506,13 +527,19 @@ var CodeMirror = (function() { if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name; if (e_prop(e, "metaKey")) name = "Cmd-" + name; - if (e_prop(e, "shiftKey")) + if (e_prop(e, "shiftKey")) { handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap, - function(b) {return doHandleBinding(b, true);}); - if (!handled) + function(b) {return doHandleBinding(b, true);}) + || lookupKey(name, options.extraKeys, options.keyMap, function(b) { + if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(b); + }); + } else { handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding); - - if (handled) e_preventDefault(e); + } + if (handled) { + e_preventDefault(e); + if (ie) { e.oldKeyCode = e.keyCode; e.keyCode = 0; } + } return handled; } function handleCharBinding(e, ch) { @@ -545,7 +572,7 @@ var CodeMirror = (function() { if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode"); if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} - if (window.opera && !e.which && handleKeyBinding(e)) return; + if (((window.opera && !e.which) || khtml) && handleKeyBinding(e)) return; var ch = String.fromCharCode(charCode == null ? keyCode : charCode); if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) { if (mode.electricChars.indexOf(ch) > -1) @@ -837,11 +864,11 @@ var CodeMirror = (function() { return scrollIntoView(x, cursor.y, x, cursor.yBot); } function scrollIntoView(x1, y1, x2, y2) { - var pl = paddingLeft(), pt = paddingTop(), lh = textHeight(); + var pl = paddingLeft(), pt = paddingTop(); y1 += pt; y2 += pt; x1 += pl; x2 += pl; var screen = scroller.clientHeight, screentop = scroller.scrollTop, scrolled = false, result = true; - if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1 - 2*lh); scrolled = true;} - else if (y2 > screentop + screen) {scroller.scrollTop = y2 + lh - screen; scrolled = true;} + if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1); scrolled = true;} + else if (y2 > screentop + screen) {scroller.scrollTop = y2 - screen; scrolled = true;} var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft; var gutterw = options.fixedGutter ? gutter.clientWidth : 0; @@ -996,16 +1023,17 @@ var CodeMirror = (function() { } // This pass fills in the lines that actually changed. var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from; - var scratch = targetDocument.createElement("div"), newElt; + var scratch = document.createElement("div"); doc.iter(from, to, function(line) { if (nextIntact && nextIntact.to == j) nextIntact = intact.shift(); if (!nextIntact || nextIntact.from > j) { if (line.hidden) var html = scratch.innerHTML = "
";
           else {
-            var html = '
' + line.getHTML(makeTab) + '
'; + var html = '' + + line.getHTML(makeTab) + ''; // Kludge to make sure the styled element lies behind the selection (by z-index) - if (line.className) - html = '
 
' + html + "
"; } scratch.innerHTML = html; @@ -1021,7 +1049,7 @@ var CodeMirror = (function() { if (!options.gutter && !options.lineNumbers) return; var hText = mover.offsetHeight, hEditor = scroller.clientHeight; gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px"; - var html = [], i = showingFrom; + var html = [], i = showingFrom, normalNode; doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) { if (line.hidden) { html.push("
");
@@ -1035,14 +1063,19 @@ var CodeMirror = (function() {
           html.push((marker && marker.style ? '
' : "
"), text);
           for (var j = 1; j < line.height; ++j) html.push("
 "); html.push("
"); + if (!marker) normalNode = i; } ++i; }); gutter.style.display = "none"; gutterText.innerHTML = html.join(""); - var minwidth = String(doc.size).length, firstNode = gutterText.firstChild, val = eltText(firstNode), pad = ""; - while (val.length + pad.length < minwidth) pad += "\u00a0"; - if (pad) firstNode.insertBefore(targetDocument.createTextNode(pad), firstNode.firstChild); + // Make sure scrolling doesn't cause number gutter size to pop + if (normalNode != null) { + var node = gutterText.childNodes[normalNode - showingFrom]; + var minwidth = String(doc.size).length, val = eltText(node), pad = ""; + while (val.length + pad.length < minwidth) pad += "\u00a0"; + if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild); + } gutter.style.display = ""; lineSpace.style.marginLeft = gutter.offsetWidth + "px"; gutterDirty = false; @@ -1066,16 +1099,18 @@ var CodeMirror = (function() { html += '
'; } + var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth; + var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight; if (sel.from.ch && fromPos.y >= 0) { - var right = sameLine ? lineSpace.clientWidth - toPos.x : 0; + var right = sameLine ? clientWidth - toPos.x : 0; add(fromPos.x, fromPos.y, right, th); } var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0)); - var middleHeight = Math.min(toPos.y, lineSpace.clientHeight) - middleStart; + var middleHeight = Math.min(toPos.y, clientHeight) - middleStart; if (middleHeight > 0.2 * th) add(0, middleStart, 0, middleHeight); - if ((!sameLine || !sel.from.ch) && toPos.y < lineSpace.clientHeight - .5 * th) - add(0, toPos.y, lineSpace.clientWidth - toPos.x, th); + if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th) + add(0, toPos.y, clientWidth - toPos.x, th); selectionDiv.innerHTML = html; cursor.style.display = "none"; selectionDiv.style.display = ""; @@ -1105,7 +1140,12 @@ var CodeMirror = (function() { if (posLess(to, from)) {var tmp = to; to = from; from = tmp;} // Skip over hidden lines. - if (from.line != oldFrom) from = skipHidden(from, oldFrom, sel.from.ch); + if (from.line != oldFrom) { + var from1 = skipHidden(from, oldFrom, sel.from.ch); + // If there is no non-hidden line left, force visibility on current line + if (!from1) setLineHidden(from.line, false); + else from = from1; + } if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch); if (posEq(from, to)) sel.inverted = false; @@ -1114,7 +1154,7 @@ var CodeMirror = (function() { if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) { var head = sel.inverted ? from : to; - if (head.line != sel.from.line) { + if (head.line != sel.from.line && sel.from.line < doc.size) { var oldLine = getLine(sel.from.line); if (/^\s+$/.test(oldLine.text)) setTimeout(operation(function() { @@ -1209,6 +1249,7 @@ var CodeMirror = (function() { if (unit == "page") dist = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight); else if (unit == "line") dist = textHeight(); var target = coordsChar(pos.x, pos.y + dist * dir + 2); + if (unit == "page") scroller.scrollTop += localCoords(target, true).y - pos.y; setCursor(target.line, target.ch, true); goalColumn = pos.x; } @@ -1295,9 +1336,10 @@ var CodeMirror = (function() { changes.push({from: 0, to: doc.size}); } function makeTab(col) { - var w = options.tabSize - col % options.tabSize; + var w = options.tabSize - col % options.tabSize, cached = tabCache[w]; + if (cached) return cached; for (var str = '', i = 0; i < w; ++i) str += " "; - return {html: str + "", width: w}; + return (tabCache[w] = {html: str + "", width: w}); } function themeChanged() { scroller.className = scroller.className.replace(/\s*cm-s-\w+/g, "") + @@ -1313,7 +1355,7 @@ var CodeMirror = (function() { var lineN = lineNo(line); min = Math.min(min, lineN); max = Math.max(max, lineN); for (var j = 0; j < mk.length; ++j) - if (mk[j].set == this.set) mk.splice(j--, 1); + if (mk[j].marker == this) mk.splice(j--, 1); } if (min != Infinity) changes.push({from: min, to: max + 1}); @@ -1324,7 +1366,7 @@ var CodeMirror = (function() { var line = this.set[i], mk = line.marked; for (var j = 0; j < mk.length; ++j) { var mark = mk[j]; - if (mark.set == this.set) { + if (mark.marker == this) { if (mark.from != null || mark.to != null) { var found = lineNo(line); if (found != null) { @@ -1341,8 +1383,9 @@ var CodeMirror = (function() { function markText(from, to, className) { from = clipPos(from); to = clipPos(to); var tm = new TextMarker(); + if (!posLess(from, to)) return tm; function add(line, from, to, className) { - getLine(line).addMark(new MarkedText(from, to, className, tm.set)); + getLine(line).addMark(new MarkedText(from, to, className, tm)); } if (from.line == to.line) add(from.line, from.ch, to.ch, className); else { @@ -1362,6 +1405,19 @@ var CodeMirror = (function() { return bm; } + function findMarksAt(pos) { + pos = clipPos(pos); + var markers = [], marked = getLine(pos.line).marked; + if (!marked) return markers; + for (var i = 0, e = marked.length; i < e; ++i) { + var m = marked[i]; + if ((m.from == null || m.from <= pos.ch) && + (m.to == null || m.to >= pos.ch)) + markers.push(m.marker || m); + } + return markers; + } + function addGutterMarker(line, text, className) { if (typeof line == "number") line = getLine(clipLine(line)); line.gutterMarker = {text: text, style: className}; @@ -1383,10 +1439,11 @@ var CodeMirror = (function() { else return null; return line; } - function setLineClass(handle, className) { + function setLineClass(handle, className, bgClassName) { return changeLine(handle, function(line) { - if (line.className != className) { + if (line.className != className || line.bgClassName != bgClassName) { line.className = className; + line.bgClassName = bgClassName; return true; } }); @@ -1400,6 +1457,8 @@ var CodeMirror = (function() { if (hidden && (fline == no || tline == no)) { var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from; var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to; + // Can't hide the last visible line, we'd have no place to put the cursor + if (!to) return; setSelection(from, to); } return (gutterDirty = true); @@ -1420,7 +1479,7 @@ var CodeMirror = (function() { } var marker = line.gutterMarker; return {line: n, handle: line, text: line.text, markerText: marker && marker.text, - markerClass: marker && marker.style, lineClass: line.className}; + markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName}; } function stringWidth(str) { @@ -1464,7 +1523,7 @@ var CodeMirror = (function() { var extra = ""; // Include extra text at the end to make sure the measured line is wrapped in the right way. if (options.lineWrapping) { - var end = line.text.indexOf(" ", ch + 2); + var end = line.text.indexOf(" ", ch + 6); extra = htmlEscape(line.text.slice(ch + 1, end < 0 ? line.text.length : end + (ie ? 5 : 0))); } measure.innerHTML = "
" + line.getHTML(makeTab, ch) +
@@ -1823,7 +1882,7 @@ var CodeMirror = (function() {
     pollInterval: 100,
     undoDepth: 40,
     tabindex: null,
-    document: window.document
+    autofocus: null
   };
 
   var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
@@ -1831,7 +1890,7 @@ var CodeMirror = (function() {
   var win = /Win/.test(navigator.platform);
 
   // Known modes, by name and by MIME
-  var modes = {}, mimeModes = {};
+  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
   CodeMirror.defineMode = function(name, mode) {
     if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
     modes[name] = mode;
@@ -1842,6 +1901,8 @@ var CodeMirror = (function() {
   CodeMirror.resolveMode = function(spec) {
     if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
       spec = mimeModes[spec];
+    else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec))
+      return CodeMirror.resolveMode("application/xml");
     if (typeof spec == "string") return {name: spec};
     else return spec || {name: "null"};
   };
@@ -1926,7 +1987,7 @@ var CodeMirror = (function() {
   keyMap.basic = {
     "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
     "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
-    "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "indentMore", "Shift-Tab": "indentLess",
+    "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "insertTab", "Shift-Tab": "indentAuto",
     "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
   };
   // Note that the save and find-related commands aren't defined by
@@ -1937,6 +1998,7 @@ var CodeMirror = (function() {
     "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
     "Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find",
     "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
+    "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
     fallthrough: "basic"
   };
   keyMap.macDefault = {
@@ -1945,6 +2007,7 @@ var CodeMirror = (function() {
     "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft",
     "Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find",
     "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
+    "Cmd-[": "indentLess", "Cmd-]": "indentMore",
     fallthrough: ["basic", "emacsy"]
   };
   keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
@@ -1987,6 +2050,8 @@ var CodeMirror = (function() {
     options.value = textarea.value;
     if (!options.tabindex && textarea.tabindex)
       options.tabindex = textarea.tabindex;
+    if (options.autofocus == null && textarea.getAttribute("autofocus") != null)
+      options.autofocus = true;
 
     function save() {textarea.value = instance.getValue();}
     if (textarea.form) {
@@ -2098,34 +2163,34 @@ var CodeMirror = (function() {
   };
   CodeMirror.StringStream = StringStream;
 
-  function MarkedText(from, to, className, set) {
-    this.from = from; this.to = to; this.style = className; this.set = set;
+  function MarkedText(from, to, className, marker) {
+    this.from = from; this.to = to; this.style = className; this.marker = marker;
   }
   MarkedText.prototype = {
-    attach: function(line) { this.set.push(line); },
+    attach: function(line) { this.marker.set.push(line); },
     detach: function(line) {
-      var ix = indexOf(this.set, line);
-      if (ix > -1) this.set.splice(ix, 1);
+      var ix = indexOf(this.marker.set, line);
+      if (ix > -1) this.marker.set.splice(ix, 1);
     },
     split: function(pos, lenBefore) {
       if (this.to <= pos && this.to != null) return null;
       var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;
       var to = this.to == null ? null : this.to - pos + lenBefore;
-      return new MarkedText(from, to, this.style, this.set);
+      return new MarkedText(from, to, this.style, this.marker);
     },
-    dup: function() { return new MarkedText(null, null, this.style, this.set); },
+    dup: function() { return new MarkedText(null, null, this.style, this.marker); },
     clipTo: function(fromOpen, from, toOpen, to, diff) {
-      if (this.from != null && this.from >= from)
-        this.from = Math.max(to, this.from) + diff;
-      if (this.to != null && this.to > from)
-        this.to = to < this.to ? this.to + diff : from;
       if (fromOpen && to > this.from && (to < this.to || this.to == null))
         this.from = null;
+      else if (this.from != null && this.from >= from)
+        this.from = Math.max(to, this.from) + diff;
       if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))
         this.to = null;
+      else if (this.to != null && this.to > from)
+        this.to = to < this.to ? this.to + diff : from;
     },
     isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },
-    sameSet: function(x) { return this.set == x.set; }
+    sameSet: function(x) { return this.marker == x.marker; }
   };
 
   function Bookmark(pos) {
@@ -2168,7 +2233,7 @@ var CodeMirror = (function() {
     this.styles = styles || [text, null];
     this.text = text;
     this.height = 1;
-    this.marked = this.gutterMarker = this.className = this.handlers = null;
+    this.marked = this.gutterMarker = this.className = this.bgClassName = this.handlers = null;
     this.stateAfter = this.parent = this.hidden = null;
   }
   Line.inheritMarks = function(text, orig) {
@@ -2214,6 +2279,7 @@ var CodeMirror = (function() {
           if (newmark) {
             if (!taken.marked) taken.marked = [];
             taken.marked.push(newmark); newmark.attach(taken);
+            if (newmark == mark) mk.splice(i--, 1);
           }
         }
       }
@@ -2637,10 +2703,10 @@ var CodeMirror = (function() {
         if (start < last.start) {
           for (var i = last.start - start - 1; i >= 0; --i)
             last.old.unshift(old[i]);
-          last.added += last.start - start;
+          oldoff = Math.min(0, added - old.length);
+          last.added += last.start - start + oldoff;
           last.start = start;
-        }
-        else if (last.start < start) {
+        } else if (last.start < start) {
           oldoff = start - last.start;
           added += oldoff;
         }
@@ -2707,19 +2773,21 @@ var CodeMirror = (function() {
 
   var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
 
-  // Detect drag-and-drop
-  var dragAndDrop = function() {
-    // IE8 has ondragstart and ondrop properties, but doesn't seem to
-    // actually support ondragstart the way it's supposed to work.
-    if (/MSIE [1-8]\b/.test(navigator.userAgent)) return false;
-    var div = document.createElement('div');
-    return "draggable" in div;
-  }();
-
   var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
   var ie = /MSIE \d/.test(navigator.userAgent);
   var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
   var webkit = /WebKit\//.test(navigator.userAgent);
+  var chrome = /Chrome\//.test(navigator.userAgent);
+  var khtml = /KHTML\//.test(navigator.userAgent);
+
+  // Detect drag-and-drop
+  var dragAndDrop = function() {
+    // There is *some* kind of drag-and-drop support in IE6-8, but I
+    // couldn't get it to work yet.
+    if (ie_lt9) return false;
+    var div = document.createElement('div');
+    return "draggable" in div || "dragDrop" in div;
+  }();
 
   var lineSep = "\n";
   // Feature-detect whether newlines in textareas are converted to \r\n
@@ -2873,7 +2941,7 @@ var CodeMirror = (function() {
   var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
                   19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
                   36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
-                  46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 186: ";", 187: "=", 188: ",",
+                  46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 127: "Delete", 186: ";", 187: "=", 188: ",",
                   189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'", 63276: "PageUp",
                   63277: "PageDown", 63275: "End", 63273: "Home", 63234: "Left", 63232: "Up", 63235: "Right",
                   63233: "Down", 63302: "Insert", 63272: "Delete"};
diff --git a/vendor/assets/stylesheets/gollum/gollum.scss b/vendor/assets/stylesheets/gollum/gollum.scss
index 46b3ae862..f23528363 100755
--- a/vendor/assets/stylesheets/gollum/gollum.scss
+++ b/vendor/assets/stylesheets/gollum/gollum.scss
@@ -152,20 +152,7 @@
     .has-rightbar #wiki-footer {
       width: 70%;
     }
-    
-    #wiki-footer #footer-content {
-      background-color: #f7f7f7;
-      border: 1px solid #ddd;
-      font-size: 1.2em;
-      line-height: 1.5em;
-      margin-top: 1.5em;
-      padding: 1em;
-      
-      border-radius: 0.5em;
-      -moz-border-radius: 0.5em;
-      -webkit-border-radius: 0.5em;
-    }
-    
+
     #wiki-footer #footer-content h3 {
       font-size: 1.2em;
       color: #333;
@@ -213,18 +200,6 @@
     border-top: 1px solid #ccc;
     margin: 1em 0 7em;
   }
-  
-  #gollum-footer p#last-edit {
-    font-size: 1.2em;
-    line-height: 1.6em;
-    color: #999;
-    margin: 0.9em 0;
-  }
-  
-    #gollum-footer p#last-edit span.username {
-      font-weight: bold;
-    }
-
 
 /* @section history */
 .history h1 {