├── .gitignore ├── plugins └── redmine_dashboard │ ├── app │ ├── views │ │ └── rdb_dashboard │ │ │ ├── configure.html.slim │ │ │ ├── issues │ │ │ ├── _parent.html.slim │ │ │ ├── _issue.html.slim │ │ │ ├── _card.html.slim │ │ │ ├── _compact.html.slim │ │ │ ├── _issue_properties.html.slim │ │ │ └── _issue_menu.html.slim │ │ │ ├── error.js.erb │ │ │ ├── taskboard │ │ │ ├── column_dialog.js.erb │ │ │ ├── _overall_progress.html.slim │ │ │ ├── _group.html.slim │ │ │ ├── _column_names.html.slim │ │ │ ├── _columns.html.slim │ │ │ ├── _groups.html.slim │ │ │ ├── _column.html.slim │ │ │ ├── _column_dialog.html.slim │ │ │ └── _header.html.slim │ │ │ ├── index.js.erb │ │ │ ├── _taskboard.html.slim │ │ │ ├── _footer.html.slim │ │ │ └── index.html.slim │ ├── models │ │ ├── rdb_column.rb │ │ ├── rdb_filter.rb │ │ ├── rdb_tracker_filter.rb │ │ ├── rdb_group.rb │ │ ├── rdb_category_filter.rb │ │ ├── rdb_assignee_filter.rb │ │ └── rdb_version_filter.rb │ ├── controllers │ │ ├── rdb_taskboard_controller.rb │ │ └── rdb_dashboard_controller.rb │ └── helpers │ │ └── rdb_dashboard_helper.rb │ ├── assets │ ├── stylesheets │ │ └── img │ │ │ ├── cog.png │ │ │ ├── brick.png │ │ │ ├── menu.gif │ │ │ ├── time.png │ │ │ ├── user.png │ │ │ ├── package.png │ │ │ ├── ticket.png │ │ │ └── disabled_true.png │ └── javascripts │ │ ├── dashboard.ui.js │ │ ├── dashboard.taskboard.js │ │ ├── dashboard.js │ │ └── jquery.total-storage.js │ ├── config │ ├── routes.rb │ ├── default.yml │ └── locales │ │ ├── bg.yml │ │ ├── ko.yml │ │ ├── zh.yml │ │ ├── zh-TW.yml │ │ ├── ja.yml │ │ ├── en.yml │ │ ├── tr.yml │ │ ├── mn.yml │ │ ├── ru.yml │ │ ├── es.yml │ │ ├── uk.yml │ │ ├── pt-BR.yml │ │ ├── de.yml │ │ ├── cs.yml │ │ ├── ca.yml │ │ ├── nl.yml │ │ ├── it.yml │ │ ├── fr.yml │ │ └── pl.yml │ ├── init.rb │ ├── Gemfile │ ├── Rakefile │ └── README.md ├── themes └── PurpleMine2-master │ ├── src │ ├── sass │ │ ├── plugins │ │ │ └── redmine_backlogs │ │ │ │ ├── _common.scss │ │ │ │ ├── jquery │ │ │ │ ├── jquery.qtip.scss │ │ │ │ └── jquery.multiselect.scss │ │ │ │ └── statistics.scss │ │ ├── _functions.scss │ │ ├── mixins │ │ │ ├── _center-block.scss │ │ │ ├── _text-overflow.scss │ │ │ ├── _clearfix.scss │ │ │ ├── _image.scss │ │ │ ├── _link-variant.scss │ │ │ ├── _shadows.scss │ │ │ ├── _issues.scss │ │ │ ├── _buttons.scss │ │ │ └── _forms.scss │ │ ├── lib │ │ │ ├── _font-awesome.scss │ │ │ └── font-awesome │ │ │ │ ├── _mixins.scss │ │ │ │ └── _path.scss │ │ ├── _mixins.scss │ │ ├── components │ │ │ ├── _image-base64.scss │ │ │ ├── _gravatar.scss │ │ │ ├── _badges.scss │ │ │ ├── _context-menu.scss │ │ │ ├── _print.scss │ │ │ ├── _progress.scss │ │ │ ├── _pagination.scss │ │ │ ├── _calendar.scss │ │ │ ├── _flash.scss │ │ │ ├── _login.scss │ │ │ ├── _admin.scss │ │ │ ├── _simple-list.scss │ │ │ ├── _dropdown.scss │ │ │ └── _base.scss │ │ ├── functions │ │ │ └── _parse-length.scss │ │ ├── application.scss │ │ └── javascripts │ │ │ └── _sidebar-toggler.scss │ └── javascripts │ │ ├── theme.js │ │ └── modules │ │ ├── HistoryTabs.js │ │ ├── MenuCollapse.js │ │ ├── SidebarToggler.js │ │ └── RevisionGraph.js │ ├── favicon │ └── favicon.ico │ ├── images │ └── preloader.gif │ ├── svg │ ├── minus.svg │ ├── plus.svg │ ├── priority-medium.svg │ ├── priority-low.svg │ ├── chevron-left.svg │ ├── priority-high.svg │ ├── priority-trivial.svg │ ├── chevron-right.svg │ ├── priority-blocker.svg │ ├── diff-deleted.svg │ ├── diff-renamed.svg │ ├── priority-major.svg │ ├── priority-minor.svg │ ├── diff-added.svg │ ├── priority-critical.svg │ ├── diff-copied.svg │ ├── diff-modified.svg │ ├── priority-lowest.svg │ ├── icon-star.svg │ ├── icon-tag.svg │ ├── priority-highest.svg │ └── calendar.svg │ ├── fonts │ ├── FontAwesome.otf │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ └── fontawesome-webfont.woff2 │ ├── screenshots │ ├── issues.png │ ├── calendar.png │ ├── new-issue.png │ ├── issue-page.png │ └── redmine-backlogs.png │ ├── .gitignore │ ├── .editorconfig │ ├── .eslintrc.js │ ├── .lintstagedrc.js │ ├── plugins │ └── redmine_backlogs │ │ ├── jquery │ │ ├── jquery.qtip.css │ │ └── jquery.multiselect.css │ │ └── statistics.css │ ├── LICENSE │ ├── .github │ └── workflows │ │ └── lint.yml │ ├── package.json │ ├── Gruntfile.js │ └── README.md ├── conf.d └── database.yml ├── README.md └── docker-compose.yml /.gitignore: -------------------------------------------------------------------------------- 1 | postgres_data/ -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/configure.html.slim: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/issues/_parent.html.slim: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/plugins/redmine_backlogs/_common.scss: -------------------------------------------------------------------------------- 1 | @import "../../variables"; 2 | @import "../../mixins"; 3 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/favicon/favicon.ico -------------------------------------------------------------------------------- /themes/PurpleMine2-master/images/preloader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/images/preloader.gif -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/minus.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /conf.d/database.yml: -------------------------------------------------------------------------------- 1 | production: 2 | adapter: postgresql 3 | database: redmine 4 | host: db 5 | username: redmine 6 | password: "redmine" 7 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /themes/PurpleMine2-master/screenshots/issues.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/screenshots/issues.png -------------------------------------------------------------------------------- /themes/PurpleMine2-master/screenshots/calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/screenshots/calendar.png -------------------------------------------------------------------------------- /themes/PurpleMine2-master/screenshots/new-issue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/screenshots/new-issue.png -------------------------------------------------------------------------------- /themes/PurpleMine2-master/screenshots/issue-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/screenshots/issue-page.png -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/stylesheets/img/cog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/plugins/redmine_dashboard/assets/stylesheets/img/cog.png -------------------------------------------------------------------------------- /themes/PurpleMine2-master/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /themes/PurpleMine2-master/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /themes/PurpleMine2-master/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/_functions.scss: -------------------------------------------------------------------------------- 1 | // Functions 2 | // -------------------------------------------------- 3 | 4 | @import "functions/parse-length"; 5 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/stylesheets/img/brick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/plugins/redmine_dashboard/assets/stylesheets/img/brick.png -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/stylesheets/img/menu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/plugins/redmine_dashboard/assets/stylesheets/img/menu.gif -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/stylesheets/img/time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/plugins/redmine_dashboard/assets/stylesheets/img/time.png -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/stylesheets/img/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/plugins/redmine_dashboard/assets/stylesheets/img/user.png -------------------------------------------------------------------------------- /themes/PurpleMine2-master/.gitignore: -------------------------------------------------------------------------------- 1 | /.sass-cache 2 | /node_modules 3 | /src/sass/_custom-variables.scss 4 | /.sublime-grunt.cache 5 | /images/logo 6 | /.stylelintcache 7 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /themes/PurpleMine2-master/screenshots/redmine-backlogs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/themes/PurpleMine2-master/screenshots/redmine-backlogs.png -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/stylesheets/img/package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/plugins/redmine_dashboard/assets/stylesheets/img/package.png -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/stylesheets/img/ticket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/plugins/redmine_dashboard/assets/stylesheets/img/ticket.png -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/stylesheets/img/disabled_true.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UsmanovTimur/redmine/HEAD/plugins/redmine_dashboard/assets/stylesheets/img/disabled_true.png -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/error.js.erb: -------------------------------------------------------------------------------- 1 | <% if flash[:rdb_error] %> 2 | Rdb.rdbError("<%= escape_javascript(flash[:rdb_error]) %>"); 3 | <% end %> 4 | Rdb.rdbDADShowIssue(); 5 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/mixins/_center-block.scss: -------------------------------------------------------------------------------- 1 | // Center-align a block level element 2 | 3 | @mixin center-block() { 4 | display: block; 5 | margin-right: auto; 6 | margin-left: auto; 7 | } 8 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/priority-medium.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 2 10 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/taskboard/column_dialog.js.erb: -------------------------------------------------------------------------------- 1 | $().rdbDialog("<%= escape_javascript t(:rdb_dialog_update_issue_title) %>", "<%= escape_javascript(render :partial => 'rdb_dashboard/taskboard/column_dialog') %>"); 2 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/priority-low.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "standard", 3 | "globals": { 4 | "$": "readonly", 5 | "localStorage": "readonly", 6 | }, 7 | "ignorePatterns": [ 8 | "/javascripts/", 9 | ], 10 | }; 11 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/chevron-left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/mixins/_text-overflow.scss: -------------------------------------------------------------------------------- 1 | // Text overflow 2 | // Requires inline-block or block for proper styling 3 | 4 | @mixin text-overflow() { 5 | overflow: hidden; 6 | text-overflow: ellipsis; 7 | white-space: nowrap; 8 | } 9 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/priority-high.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/taskboard/_overall_progress.html.slim: -------------------------------------------------------------------------------- 1 | div.rdb-overall-progress 2 | - @board.column_list[0..-2].each do |column| 3 | a.rdb-overall-progress class="rdb-column-#{column.id}" style="width: #{column.percentage}%" 4 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/priority-trivial.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/index.js.erb: -------------------------------------------------------------------------------- 1 | $('#rdb-wrapper').html("<%= escape_javascript(render partial: @board.id.to_s) %>"); 2 | Rdb.rdbInit(); 3 | <% if flash[:rdb_error] %> 4 | Rdb.rdbError("<%= escape_javascript(flash[:rdb_error]) %>"); 5 | <% end %> 6 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/priority-blocker.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/javascripts/theme.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | /* global PurpleMine */ 3 | 'use strict' 4 | 5 | /* eslint-disable no-new */ 6 | new PurpleMine.SidebarToggler() 7 | new PurpleMine.HistoryTabs() 8 | new PurpleMine.MenuCollapse() 9 | }) 10 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/diff-deleted.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/diff-renamed.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/priority-major.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/priority-minor.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/diff-added.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/priority-critical.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/diff-copied.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/diff-modified.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/taskboard/_group.html.slim: -------------------------------------------------------------------------------- 1 | .rdb-group data-rdb-group-id=group.id 2 | .rdb-group-header 3 | a.rdb-evt-group-toggle 4 | h4 = group.title 5 | span = t(:rdb_x_issues, count: group.issue_count) 6 | = render partial: 'rdb_dashboard/taskboard/columns', locals: {group: group} 7 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/mixins/_clearfix.scss: -------------------------------------------------------------------------------- 1 | // Clearfix 2 | // 3 | // Source: http://cssmojo.com/the-very-latest-clearfix-reloaded/ 4 | 5 | @mixin clearfix() { 6 | &::after { 7 | content: ""; 8 | display: block; 9 | clear: both; 10 | } 11 | } 12 | 13 | %clearfix { 14 | @include clearfix; 15 | } 16 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/lib/_font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "font-awesome/variables"; 7 | @import "font-awesome/mixins"; 8 | @import "font-awesome/path"; 9 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/.lintstagedrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "src/**/*.js": files => [ 3 | `eslint "${files.join('" "')}"`, 4 | 'grunt js', 5 | 'git add javascripts/' 6 | ], 7 | "src/**/*.scss": files => [ 8 | `stylelint "${files.join('" "')}"`, 9 | 'grunt css', 10 | 'git add stylesheets/ plugins/' 11 | ], 12 | } 13 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/taskboard/_column_names.html.slim: -------------------------------------------------------------------------------- 1 | ul.rdb-headers 2 | - @board.column_list.each do |column| 3 | - if column.visible? 4 | li.rdb-column class=(column.compact? ? 'rdb-column-compact' : '') 5 | h3 = column.title 6 | - if column.issues.count > 0 7 | span = t :rdb_x_issues, count: column.issues.count 8 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/priority-lowest.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/icon-star.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/icon-tag.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------------------------------- 3 | 4 | @import "mixins/buttons"; 5 | @import "mixins/center-block"; 6 | @import "mixins/clearfix"; 7 | @import "mixins/forms"; 8 | @import "mixins/image"; 9 | @import "mixins/text-overflow"; 10 | 11 | @import "mixins/issues"; 12 | @import "mixins/link-variant"; 13 | @import "mixins/shadows"; 14 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/lib/font-awesome/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal 14px/1 FontAwesome; // shortening font declaration 7 | text-rendering: auto; // optimizelegibility throws things off #1094 8 | -webkit-font-smoothing: antialiased; 9 | -moz-osx-font-smoothing: grayscale; 10 | } 11 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/priority-highest.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/_taskboard.html.slim: -------------------------------------------------------------------------------- 1 | #rdb-taskboard 2 | header#rdb-header 3 | = render partial: 'rdb_dashboard/taskboard/header' 4 | .rdb-clear 5 | 6 | #rdb-board 7 | #rdb-board-container 8 | = render partial: 'rdb_dashboard/taskboard/column_names' 9 | = render partial: 'rdb_dashboard/taskboard/overall_progress' 10 | = render partial: 'rdb_dashboard/taskboard/groups' 11 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/issues/_issue.html.slim: -------------------------------------------------------------------------------- 1 | .rdb-issue( 2 | class="rdb-issue-#{@board.issue_view} #{@board.editable?('rdb-issue-drag')} #{issue.overdue? ? 'rdb-overdue' : ''}" 3 | data={'rdb-drop-on': @board.drop_on(issue), 'rdb-drop-group': group.id, 'rdb-issue-id': issue.id, 'rdb-lock-version': issue.lock_version} 4 | ) 5 | = render partial: "rdb_dashboard/issues/#{@board.issue_view}", locals: {issue: issue} 6 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_image-base64.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Base64 encoded images 3 | // -------------------------------------------------- 4 | 5 | // ACI = AutoComplete Indicator 6 | %image-aci { 7 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAKBAMAAAAnY0GXAAAAD1BMVEUAAACzs7Ozs7Ozs7Ozs7NJvZFvAAAABHRSTlMA5kpJG2qUMwAAABtJREFUCNdjIBMYCkMRDIg4QhBuAUUhKCIPAAAlaQNk5qF21gAAAABJRU5ErkJggg=="); 8 | } 9 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/taskboard/_columns.html.slim: -------------------------------------------------------------------------------- 1 | ul.rdb-columns 2 | - @board.visible_columns.each do |column| 3 | li.rdb-column class=(column.compact? ? 'rdb-column-compact' : '') data={'rdb-column-id': column.id, 'rdb-drop-group': group.id} 4 | - unless column.compact? 5 | = render partial: 'rdb_dashboard/taskboard/column', locals: {column: column, issues: group.filter(column.issues), group: group} 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Сборка проекта Redmine 2 | Оригинальный проект: https://www.redmine.org/ 3 | Образ: https://hub.docker.com/_/redmine 4 | В redmine установлены: 5 | - https://github.com/mrliptontea/PurpleMine2 симпатичная тема для работы 6 | - https://github.com/jgraichen/redmine_dashboard - канбан доска. 7 | 8 | ### Старт проекта 9 | ``` 10 | docker-compose up -d 11 | ``` 12 | Переходим на http://127.0.0.1:3000/ 13 | 14 | ``` 15 | Логин: admin 16 | Пароль: admin 17 | ``` 18 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/taskboard/_groups.html.slim: -------------------------------------------------------------------------------- 1 | .rdb-groups 2 | - if @board.groups.count == 1 3 | .rdb-group data-rdb-group-id=@board.group_list.first.id 4 | = render partial: 'rdb_dashboard/taskboard/columns', locals: {group: @board.group_list.first} 5 | - else 6 | - show_all = @board.group_list.select(&:visible?).none? 7 | - @board.group_list.each do |group| 8 | - if show_all || group.visible? 9 | = render partial: 'rdb_dashboard/taskboard/group', locals: {group: group} 10 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/plugins/redmine_backlogs/jquery/jquery.qtip.css: -------------------------------------------------------------------------------- 1 | .qtip{position:absolute;top:-31000px;left:-31000px;width:auto;max-width:500px;outline:none}.ui-tooltip-content{box-shadow:0 5px 8px -2px rgba(0,0,0,.25),0 1px 2px rgba(0,0,0,.3);position:relative;padding:10px;overflow:hidden;border:1px solid #d1d3e0;background-color:#fff;color:#3e4359;font-size:.92em;text-align:left;word-wrap:break-word}.ui-tooltip-tip{position:absolute;z-index:10;margin:0 auto;overflow:hidden;border:0 none;border-color:#d1d3e0;background:transparent;background-color:#fff} -------------------------------------------------------------------------------- /themes/PurpleMine2-master/plugins/redmine_backlogs/statistics.css: -------------------------------------------------------------------------------- 1 | table th,table td{padding:5px 8px}.ui-widget{margin-bottom:20px}.score{display:inline-block;width:1.5em;font-size:large;text-align:center}.score_0{background-color:red}.score_1{background-color:#ff5300}.score_2{background-color:#ff8100}.score_3{background-color:#ffa100}.score_4{background-color:#fb0}.score_5{background-color:#ffd300}.score_6{background-color:#ffec00}.score_7{background-color:#e9fb00}.score_8{background-color:#b1f100}.score_9{background-color:#74e600}.score_10{background-color:#0c0} -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/mixins/_image.scss: -------------------------------------------------------------------------------- 1 | // Retina image 2 | // 3 | 4 | @mixin img-retina($file-2x, $width-1x, $height-1x) { 5 | @media 6 | only screen and (-webkit-min-device-pixel-ratio: 2), 7 | only screen and (min--moz-device-pixel-ratio: 2), 8 | only screen and (-o-min-device-pixel-ratio: 2 / 1), 9 | only screen and (min-device-pixel-ratio: 2), 10 | only screen and (min-resolution: 192dpi), 11 | only screen and (min-resolution: 2dppx) { 12 | background-image: url("#{$file-2x}"); 13 | background-size: $width-1x $height-1x; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/issues/_card.html.slim: -------------------------------------------------------------------------------- 1 | / ISSUE CARD 2 | .rdb-card 3 | div class="rdb-priority rdb-priority-#{issue.priority.position}" 4 | header.rdb-card-header 5 | .rdb-card-title 6 | = render partial: 'rdb_dashboard/issues/issue_menu', locals: {issue: issue} 7 | div 8 | 9 | .rdb-card-progress 10 | .rdb-card-progress-bar style="width: #{issue.done_ratio}%" 11 | 12 | .rdb-card-content 13 | .rdb-card-subject.rdb-property-subject = issue.subject 14 | = render partial: 'rdb_dashboard/issues/issue_properties', locals: {issue: issue} 15 | / ISSUE CARD END 16 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/_footer.html.slim: -------------------------------------------------------------------------------- 1 | #rdb-footer 2 | #rdb-copyright 3 | a href="https://github.com/jgraichen/redmine_dashboard" 4 | | Redmine Dashboard 2 5 | = " - v#{Redmine::Plugin.find(:redmine_dashboard).version}" 6 | 7 | #rdb-legend 8 | div 9 | p = t :rdb_legend_priorities 10 | - IssuePriority.all.sort_by(&:position).each do |priority| 11 | span class="rdb-priority rdb-priority-#{priority.position}" 12 | = priority 13 | 14 | div 15 | p = t :rdb_legend_warnings 16 | span.rdb-overdue 17 | span   18 | = t :rdb_issue_overdue 19 | .rdb-clear 20 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/mixins/_link-variant.scss: -------------------------------------------------------------------------------- 1 | // Link variant 2 | 3 | @mixin link-variant($variant, $focus-hover: true) { 4 | $colors: map-get($icon-color-map, $variant); 5 | 6 | color: map-get($colors, normal); 7 | 8 | @if $focus-hover { 9 | &:focus, 10 | &:hover { 11 | color: map-get($colors, hover); 12 | } 13 | } 14 | } 15 | 16 | @mixin icon-variant($variant) { 17 | $colors: map-get($icon-color-map, $variant); 18 | 19 | &::before { 20 | color: map-get($colors, normal); 21 | } 22 | 23 | &:focus, 24 | &:hover { 25 | &::before { 26 | color: map-get($colors, hover); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/issues/_compact.html.slim: -------------------------------------------------------------------------------- 1 | / ISSUE COMPACT 2 | .rdb-compact 3 | .rdb-priority class="rdb-priority-#{issue.priority.position}" 4 | 5 | .rdb-compact-progress 6 | .rdb-compact-progress-bar style="width: #{issue.done_ratio}%" 7 | header.rdb-compact-header 8 | .rdb-compact-title 9 | = render partial: 'rdb_dashboard/issues/issue_menu', locals: {issue: issue} 10 | .rdb-compact-header-data 11 | = render partial: 'rdb_dashboard/issues/issue_properties', locals: {issue: issue} 12 | 13 | .rdb-compact-content 14 | .rdb-compact-subject.rdb-property-subject = issue.subject 15 | / ISSUE COMPACT END 16 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_gravatar.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Gravatars 3 | // -------------------------------------------------- 4 | 5 | img.gravatar { 6 | position: relative; 7 | top: -.15em; 8 | overflow: hidden; 9 | border-radius: $border-radius-large; 10 | line-height: 1; 11 | vertical-align: middle; 12 | 13 | h2 &, 14 | h3 &, 15 | h4 & { 16 | margin-right: 5px; 17 | } 18 | } 19 | 20 | 21 | //== Administration -> /users 22 | // 23 | 24 | .username img.gravatar { 25 | margin-right: .5em; 26 | } 27 | 28 | //== Gravatar 29 | // Used on 12px Gravatar img tags without the icon background 30 | 31 | .icon-gravatar { 32 | margin-right: 5px; 33 | float: left; 34 | } 35 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/mixins/_shadows.scss: -------------------------------------------------------------------------------- 1 | // Some really nice looking shadows 2 | 3 | @mixin nice-shadow($depth: 1) { 4 | $shadow: none; 5 | 6 | @if ($depth == 1) { 7 | $shadow: 0 1px 2px rgba(#000, .25); 8 | } @else if ($depth == 2) { 9 | $shadow: 0 5px 8px -2px rgba(#000, .25), 0 1px 2px rgba(#000, .3); 10 | } @else if ($depth == 3) { 11 | $shadow: 0 8px 16px -3px rgba(#000, .25), 0 2px 4px rgba(#000, .3); 12 | } @else if ($depth == 4) { 13 | $shadow: 0 14px 24px -4px rgba(#000, .25), 0 3px 10px rgba(#000, .3); 14 | } @else if ($depth == 5) { 15 | $shadow: 0 20px 32px -2px rgba(#000, .25), 0 4px 12px rgba(#000, .3); 16 | } 17 | 18 | box-shadow: $shadow; 19 | } 20 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/taskboard/_column.html.slim: -------------------------------------------------------------------------------- 1 | - if issues.any? && @board.groups.count > 1 2 | .rdb-column-head = t(:rdb_x_issues, count: issues.count) 3 | div class="rdb-grid-#{@board.issue_view}" 4 | - grouped_issues = issues.group_by {|i| i.priority.position } 5 | - grouped_issues.keys.sort.reverse.each do |priority| 6 | - grouped_issues[priority].sort_by(&:id).each do |issue| 7 | = render partial: 'rdb_dashboard/issues/issue', locals: {issue: issue, group: group} 8 | 9 | / Render multple empty diff to fill-up the "grid" if 10 | / very few issues are present in a column. Otherwise 11 | / the column will not add CSS grid columns in the group 12 | / if the overall column gets wide enought. 13 | - 5.times do 14 | div 15 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/taskboard/_column_dialog.html.slim: -------------------------------------------------------------------------------- 1 | div 2 | .rdb-card.rdb-card-dialog 3 | .rdb-priority class="rdb-priority-#{@issue.priority.position}" 4 | header.rdb-card-header 5 | span.rdb-card-title 6 | = link_to "#{@board.abbreviation(@issue.project_id)}#{@issue.id}", @issue 7 | 8 | .rdb-card-progress 9 | .rdb-card-progress-bar style="width: #{@issue.done_ratio}%" 10 | 11 | .rdb-card-content 12 | .rdb-card-subject.rdb-property-subject = @issue.subject 13 | 14 | .rdb-card-dialog-box.rdb-async 15 | label = t(:rdb_dialog_update_issue_status) 16 | ul 17 | - @statuses.each do |status| 18 | li = link_to status.name, rdb_update_path(@issue, status: status.id) 19 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/lib/font-awesome/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: "FontAwesome"; 6 | src: url("#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}"); 7 | src: url("#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}") format("embedded-opentype"), 8 | url("#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}") format("woff2"), 9 | url("#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}") format("woff"), 10 | url("#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}") format("truetype"), 11 | url("#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular") format("svg"); 12 | font-weight: normal; 13 | font-style: normal; 14 | } 15 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/svg/calendar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | 3 | services: 4 | redmine: 5 | image: redmine 6 | restart: always 7 | ports: 8 | - 3000:3000 9 | environment: 10 | REDMINE_DB_MYSQL: db 11 | REDMINE_DB_PASSWORD: example 12 | REDMINE_SECRET_KEY_BASE: supersecretkey 13 | TZ: Asia/Yekaterinburg 14 | volumes: 15 | - ./conf.d/database.yml:/usr/src/redmine/config/database.yml 16 | - ./themes:/usr/src/redmine/public/themes 17 | - ./plugins:/usr/src/redmine/plugins 18 | - ./redmine_files:/usr/src/redmine/files 19 | 20 | db: 21 | image: postgres:12.3 22 | environment: 23 | - POSTGRES_DB=redmine 24 | - POSTGRES_USER=redmine 25 | - POSTGRES_PASSWORD=redmine 26 | volumes: 27 | - ./postgres_data:/var/lib/postgresql/data 28 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/routes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Plugin's routes 4 | # See: http://guides.rubyonrails.org/routing.html 5 | 6 | match 'projects/:id/rdb/taskboard' => 'rdb_taskboard#index', :as => :rdb_taskboard, via: %i[get post] 7 | match 'projects/:id/rdb/taskboard/move' => 'rdb_taskboard#move', :as => :rdb_taskboard_move, via: %i[get post] 8 | match 'projects/:id/rdb/taskboard/update' => 'rdb_taskboard#update', :as => :rdb_taskboard_update, via: %i[get post] 9 | match 'projects/:id/rdb/taskboard/filter' => 'rdb_taskboard#filter', :as => :rdb_taskboard_filter, via: %i[get post] 10 | 11 | match 'projects/:id/rdb(/:board)' => 'rdb_dashboard#index', :as => :rdb, via: %i[get post] 12 | match 'projects/:id/dashboard' => 'rdb_dashboard#index', via: %i[get post] 13 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/plugins/redmine_backlogs/jquery/jquery.qtip.scss: -------------------------------------------------------------------------------- 1 | @import "../common"; 2 | 3 | .qtip { 4 | position: absolute; 5 | top: -31000px; 6 | left: -31000px; 7 | width: auto; 8 | max-width: 500px; 9 | outline: none; 10 | } 11 | 12 | .ui-tooltip-content { 13 | @include nice-shadow(2); 14 | position: relative; 15 | padding: 10px; 16 | overflow: hidden; 17 | border: 1px solid $tooltip-border; 18 | background-color: $tooltip-bg; 19 | color: $tooltip-text; 20 | font-size: $font-size-list; 21 | text-align: left; 22 | word-wrap: break-word; 23 | } 24 | 25 | .ui-tooltip-tip { 26 | position: absolute; 27 | z-index: 10; 28 | margin: 0 auto; 29 | overflow: hidden; 30 | border: 0 none; 31 | border-color: $tooltip-border; 32 | background: transparent; 33 | background-color: $tooltip-bg; 34 | } 35 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/init.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'redmine' 4 | 5 | Redmine::Plugin.register :redmine_dashboard do 6 | name 'Redmine Dashboard plugin' 7 | author 'Jan Graichen' 8 | description 'Add a task board and a planning board to Redmine' 9 | version '2.14.0' 10 | url 'https://github.com/jgraichen/redmine_dashboard' 11 | author_url 'mailto:jgraichen@altimos.de' 12 | 13 | requires_redmine '4.2' 14 | 15 | project_module :dashboard do 16 | permission :view_dashboards, { 17 | rdb_dashboard: [:index], 18 | rdb_taskboard: %i[index filter move update] 19 | } 20 | permission :configure_dashboards, {rdb_dashboard: [:configure]} 21 | end 22 | menu :project_menu, :dashboard, {controller: 'rdb_dashboard', action: 'index'}, 23 | caption: :menu_label_dashboard, after: :new_issue 24 | end 25 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/models/rdb_column.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RdbColumn 4 | attr_accessor :board 5 | attr_reader :name, :options, :id, :statuses 6 | 7 | def initialize(id, name, statuses, options = {}) 8 | @id = id.to_s 9 | @name = name 10 | @statuses = statuses.is_a?(Array) ? statuses : [statuses] 11 | @options = options 12 | end 13 | 14 | def scope(issue_scope) 15 | issue_scope.where status_id: statuses.map(&:id) 16 | end 17 | 18 | def issues 19 | @issues ||= board.issues_for(self) 20 | end 21 | 22 | def percentage 23 | all_issue_count = board.issues.count 24 | all_issue_count > 0 ? ((issues.count.to_f / all_issue_count) * 100).round(4) : 0 25 | end 26 | 27 | def title 28 | name.is_a?(Symbol) ? I18n.translate(name) : name.to_s 29 | end 30 | 31 | def compact? 32 | !!options[:compact] 33 | end 34 | 35 | def visible? 36 | !options[:hide] 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/default.yml: -------------------------------------------------------------------------------- 1 | # Configure default settings for dashboards here. They 2 | # apply to every dashboard on all projects. 3 | # 4 | # Remember to restart redmine to apply changed settings. 5 | # Also logout and login again as dashboard options are 6 | # also stored in the user session (cookie). 7 | 8 | # Default view mode. 9 | # Allowed values are: `card` or `compact`. 10 | view: card 11 | 12 | # Should subproject be included by default. 13 | # Allowed values are: `false` or `true`. 14 | include_subprojects: false 15 | 16 | # Default setting for assignee filter. 17 | # Allowed values are: `me` or `all`. 18 | assignee: me 19 | 20 | # Default setting for version filter. 21 | # Allowed values are: `latest` or `all`. 22 | version: latest 23 | 24 | # Should done issues be hidden by default 25 | # Allowed values are: `false` or `true`. 26 | hide_done: false 27 | 28 | # Should "Change assignee" option be enabled by default 29 | # Allowed values are: `false` or `true` 30 | change_assignee: false 31 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/index.html.slim: -------------------------------------------------------------------------------- 1 | - content_for :header_tags do 2 | - plugin = Rails.env.development? ? 'redmine_dashboard_linked' : 'redmine_dashboard' 3 | = stylesheet_link_tag 'dashboard.css', plugin: plugin 4 | = stylesheet_link_tag 'dashboard.ui.css', plugin: plugin 5 | = stylesheet_link_tag 'dashboard.issues.css', plugin: plugin 6 | = stylesheet_link_tag 'dashboard.taskboard.css', plugin: plugin 7 | = javascript_include_tag 'jquery.autoellipsis.js', plugin: plugin 8 | = javascript_include_tag 'jquery.total-storage.js', plugin: plugin 9 | = javascript_include_tag 'dashboard.js', plugin: plugin 10 | = javascript_include_tag 'dashboard.ui.js', plugin: plugin 11 | = javascript_include_tag 'dashboard.taskboard.js', plugin: plugin 12 | = javascript_include_tag 'jquery.ui.js', plugin: plugin 13 | 14 | #rdb data={'rdb-base': rdb_board_path} 15 | #rdb-wrapper 16 | #rdb-header 17 | #rdb-board 18 | #rdb-loading 19 | 20 | #rdb-errors 21 | #rdb-dialogs 22 | = render partial: 'footer' 23 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | # Gems required by redmine_dashboard 5 | 6 | send :ruby, RUBY_VERSION if ENV['CI'] 7 | 8 | gem 'rake' 9 | gem 'slim-rails' 10 | 11 | group :test do 12 | gem 'database_cleaner-active_record', '~> 2.0' 13 | gem 'rspec', '~> 3.10' 14 | gem 'rspec-rails' 15 | 16 | # Webrick is no longer bundled with Ruby 3.0+ but required by 17 | # capybara. If Redmine does not already include it in it's own 18 | # Gemfile, we need to add it here. 19 | if @dependencies.none? {|d| d.name == 'webrick' } 20 | gem 'webrick' 21 | end 22 | end 23 | 24 | # If rubocop is already defined, the Gemfile is loaded through Redmins own 25 | # Gemfile as a plugin Gemfile. In that case our local development gems are not 26 | # needed (and actually conflicting), therefore we skip them. 27 | if @dependencies.none? {|d| d.name == 'rubocop' } 28 | group :development, :test do 29 | gem 'rubocop', '~> 1.51.0' 30 | gem 'slim_lint', '~> 0.24.0' 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/plugins/redmine_backlogs/statistics.scss: -------------------------------------------------------------------------------- 1 | @import "common"; 2 | 3 | table { 4 | th, 5 | td { 6 | padding: $table-condensed-cell-padding $table-cell-padding; 7 | } 8 | } 9 | 10 | .ui-widget { 11 | margin-bottom: $line-height-computed; 12 | } 13 | 14 | .score { 15 | display: inline-block; 16 | width: 1.5em; 17 | font-size: large; 18 | text-align: center; 19 | } 20 | 21 | .score_0 { 22 | background-color: #f00; 23 | } 24 | 25 | .score_1 { 26 | background-color: #ff5300; 27 | } 28 | 29 | .score_2 { 30 | background-color: #ff8100; 31 | } 32 | 33 | .score_3 { 34 | background-color: #ffa100; 35 | } 36 | 37 | .score_4 { 38 | background-color: #fb0; 39 | } 40 | 41 | .score_5 { 42 | background-color: #ffd300; 43 | } 44 | 45 | .score_6 { 46 | background-color: #ffec00; 47 | } 48 | 49 | .score_7 { 50 | background-color: #e9fb00; 51 | } 52 | 53 | .score_8 { 54 | background-color: #b1f100; 55 | } 56 | 57 | .score_9 { 58 | background-color: #74e600; 59 | } 60 | 61 | .score_10 { 62 | background-color: #0c0; 63 | } 64 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/issues/_issue_properties.html.slim: -------------------------------------------------------------------------------- 1 | .rdb-property.rdb-property-tracker = issue.tracker 2 | - if @board.versions.any? 3 | - if issue.fixed_version 4 | .rdb-property.rdb-property-version = issue.fixed_version.name 5 | - else 6 | .rdb-property.rdb-property-version.rdb-disabled = t(:rdb_filter_version_unassigned) 7 | - if issue.assigned_to 8 | .rdb-property.rdb-property-assignee = issue.assigned_to.name 9 | - else 10 | .rdb-property.rdb-property-assignee.rdb-disabled = t(:rdb_unassigned) 11 | - if @board.issue_categories.any? 12 | - if issue.category 13 | .rdb-property.rdb-property-category = issue.category.name 14 | - else 15 | .rdb-property.rdb-property-category.rdb-disabled = t(:rdb_unassigned) 16 | - if User.current.allowed_to?(:view_time_entries, @project) 17 | .rdb-property.rdb-property-time class=(issue.estimated_hours.nil? && issue.time_entries.empty? ? 'rdb-disabled' : '') 18 | = t(:rdb_property_time, estimated: issue.estimated_hours.to_f.round(2), actual: issue.time_entries.map(&:hours).reduce(&:+).to_f.round(2)).html_safe 19 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/bg.yml: -------------------------------------------------------------------------------- 1 | --- 2 | bg: 3 | project_module_dashboard: Табло 4 | permission_view_dashboards: Преглед на таблата 5 | permission_configure_dashboards: Конфигурация на таблата 6 | menu_label_dashboard: Табло 7 | rdb_filter_version_all: Всички версии 8 | rdb_filter_assignee_none: Неназначен 9 | rdb_filter_assignee_others: Други 10 | rdb_options: Настройки 11 | rdb_options_hide_done: Скрий завършените задачи 12 | rdb_options_reset: Премахни филтър 13 | rdb_options_configure: Настройки 14 | rdb_options_group: Групиране на задачи 15 | rdb_group_category: Категория 16 | rdb_group_assignee: Назначен на 17 | rdb_group_tracker: Тракер 18 | rdb_group_priority: Приоритет 19 | rdb_group_version: Версия 20 | rdb_group_parent: Родителска задача 21 | rdb_group_project: Проект 22 | rdb_options_fullscreen: Цял екран 23 | rdb_legend_priorities: Приоритети 24 | rdb_column_done: Готово 25 | rdb_others: Други 26 | rdb_all_issues: Всички задачи 27 | rdb_no_parent: Без родителски задачи 28 | rdb_issue_menu_redmine_issue: Redmine задача 29 | rdb_issue_menu_edit: Редакция 30 | rdb_flash_invalid_request: "

Невалидна заявка.

" 31 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Grzegorz Rajchman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/models/rdb_filter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RdbFilter 4 | attr_accessor :board 5 | attr_reader :id 6 | 7 | def initialize(id) 8 | @id = id.to_sym 9 | end 10 | 11 | def default_options 12 | {} 13 | end 14 | 15 | def values 16 | @values ||= default_values 17 | end 18 | 19 | def default_values 20 | [] 21 | end 22 | 23 | def value 24 | values.first 25 | end 26 | 27 | def value=(value) 28 | self.values = value ? [value] : [] 29 | end 30 | 31 | def values=(values) 32 | values = [values] unless values.is_a?(Array) 33 | @values = values.select {|value| valid_value? value } 34 | @values = default_values if @values.empty? && !allow_no_values? 35 | end 36 | 37 | def valid_value?(_value) 38 | true 39 | end 40 | 41 | def allow_no_values? 42 | false 43 | end 44 | 45 | def title 46 | values.join 47 | end 48 | 49 | def to_options 50 | [] 51 | end 52 | 53 | def scope(scope) 54 | scope 55 | end 56 | 57 | def filter(issues) 58 | issues 59 | end 60 | 61 | def apply_to_child_issues? 62 | false 63 | end 64 | 65 | def update(params); end 66 | end 67 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Run linters 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'master' 7 | - 'v*.*' 8 | pull_request: 9 | 10 | jobs: 11 | lint: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v3 17 | 18 | - name: Use Node.js 16.x 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: 16.x 22 | 23 | - name: Install npm dependencies 24 | run: npm ci 25 | 26 | - name: Eslint 27 | run: npm run lint:js 28 | 29 | - name: Stylelint 30 | run: npm run lint:sass 31 | 32 | build: 33 | runs-on: ubuntu-latest 34 | 35 | strategy: 36 | matrix: 37 | node-version: [16.x, 18.x, 19.x] 38 | 39 | steps: 40 | - name: Checkout 41 | uses: actions/checkout@v3 42 | 43 | - name: Use Node.js ${{ matrix.node-version }} 44 | uses: actions/setup-node@v3 45 | with: 46 | node-version: ${{ matrix.node-version }} 47 | 48 | - name: Install npm dependencies 49 | run: npm ci --production 50 | 51 | - name: Check build 52 | run: npm run build 53 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/models/rdb_tracker_filter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RdbTrackerFilter < RdbFilter 4 | def initialize 5 | super :tracker 6 | end 7 | 8 | def scope(scope) 9 | return scope if all? 10 | 11 | scope.where tracker_id: values 12 | end 13 | 14 | def all? 15 | values.count == board.trackers.count 16 | end 17 | 18 | def apply_to_child_issues? 19 | true 20 | end 21 | 22 | def default_values 23 | board.trackers.pluck(:id) 24 | end 25 | 26 | def update(params) 27 | return unless (tracker = params[:tracker]) 28 | 29 | if tracker == 'all' 30 | self.values = board.trackers.pluck(:id) 31 | return 32 | end 33 | 34 | id = tracker.to_i 35 | return if board.trackers.where(id: id).empty? 36 | 37 | if params[:only] 38 | self.value = id 39 | elsif values.include? id 40 | values.delete id if values.count > 2 41 | else 42 | values << id 43 | end 44 | end 45 | 46 | def title 47 | return I18n.t(:rdb_filter_tracker_all) if all? 48 | return I18n.t(:rdb_filter_tracker_multiple) if values.count > 1 49 | 50 | board.trackers.find(value).name 51 | end 52 | 53 | def enabled?(id) 54 | return true if value == :all 55 | 56 | values.include? id 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/models/rdb_group.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RdbGroup 4 | attr_accessor :board 5 | attr_reader :name, :options, :id 6 | 7 | def initialize(id, name, options = {}) 8 | @id = id.to_s 9 | @name = name 10 | 11 | @options = default_options 12 | @options[:accept] = options[:accept] if options[:accept].respond_to? :call 13 | end 14 | 15 | def default_options 16 | {} 17 | end 18 | 19 | def accept?(issue) 20 | return true if options[:accept].nil? 21 | 22 | options[:accept].call(issue) 23 | end 24 | 25 | def title 26 | name.is_a?(Symbol) ? I18n.translate(name) : name.to_s 27 | end 28 | 29 | def accepted_issues(source = nil) 30 | @accepted_issues ||= filter((source || board).issues) 31 | end 32 | 33 | def accepted_issue_ids 34 | @accepted_issue_ids ||= accepted_issues.map(&:id) 35 | end 36 | 37 | def filter(issues) 38 | issues.select {|i| accept? i } 39 | end 40 | 41 | def visible? 42 | @visible ||= catch(:visible) do 43 | board.columns.each_value do |column| 44 | next if !column.visible? || column.compact? 45 | 46 | throw :visible, true if filter(column.issues).count > 0 47 | end 48 | false 49 | end 50 | end 51 | 52 | def issue_count 53 | filter(@board.issues).count.to_i 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/models/rdb_category_filter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RdbCategoryFilter < RdbFilter 4 | def initialize 5 | super :category 6 | end 7 | 8 | def scope(scope) 9 | return scope if all? 10 | 11 | scope.where category_id: values 12 | end 13 | 14 | def all? 15 | values.count >= board.issue_categories.count or board.issue_categories.empty? 16 | end 17 | 18 | def default_values 19 | board.issue_categories.pluck(:id) 20 | end 21 | 22 | def valid_value?(value) 23 | default_values.include? value.to_i 24 | end 25 | 26 | def update(params) 27 | return unless (category = params[:category]) 28 | 29 | if category == 'all' 30 | self.values = board.issue_categories.pluck(:id) 31 | else 32 | id = category.to_i 33 | 34 | if params[:only] 35 | self.value = id 36 | elsif values.include?(id) && values.count > 2 37 | values.delete id 38 | elsif valid_value?(id) 39 | values << id 40 | end 41 | end 42 | end 43 | 44 | def title 45 | return I18n.t(:rdb_filter_category_all) if all? 46 | return I18n.t(:rdb_filter_category_multiple) if values.count > 1 47 | 48 | board.issue_categories.find_by_id(value).try(:name) 49 | end 50 | 51 | def enabled?(id) 52 | return true if value == :all 53 | 54 | values.include? id 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/functions/_parse-length.scss: -------------------------------------------------------------------------------- 1 | // Extract the length of margin/padding/border 2 | // for given side from a shorthand syntax. 3 | // 4 | // Examples: 5 | // parse-length(1px, top) -> 1px 6 | // parse-length(1px 2px, right) -> 2px 7 | // parse-length(1px 2px 3px 4px, bottom) -> 3px 8 | // parse-length(1px 2px 3px 4px, left) -> 4px 9 | // 10 | @function parse-length($value, $side) { 11 | $index: 1; 12 | 13 | // Top values are always at index 1. The same for when the list has only one item 14 | @if ($side == top or length($value) == 1) { 15 | $index: 1; 16 | } 17 | // Covers "vertical horizontal" style 18 | @else if (length($value) == 2) { 19 | @if ($side == left or $side == right) { 20 | $index: 2; 21 | } 22 | @if ($side == bottom) { 23 | $index: 1; 24 | } 25 | } 26 | // Covers "top horizontal bottom" style 27 | @else if (length($value) == 3) { 28 | @if ($side == left or $side == right) { 29 | $index: 2; 30 | } 31 | @if ($side == bottom) { 32 | $index: 3; 33 | } 34 | } 35 | // Covers "top right bottom left" style 36 | @else if (length($value) == 4) { 37 | @if ($side == right) { 38 | $index: 2; 39 | } 40 | @if ($side == bottom) { 41 | $index: 3; 42 | } 43 | @if ($side == left) { 44 | $index: 4; 45 | } 46 | } 47 | 48 | @return nth($value, $index); 49 | } 50 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/issues/_issue_menu.html.slim: -------------------------------------------------------------------------------- 1 | - render_rdb_menu :issue, @board.issue_id(issue), small: true do 2 | - render_rdb_menu_list title: t(:rdb_issue_menu_redmine_issue) do 3 | - render_rdb_menu_list_item do 4 | = link_to t(:rdb_issue_menu_show), issue_path(issue) 5 | - if @board.editable? 6 | - render_rdb_menu_list_item do 7 | = link_to t(:rdb_issue_menu_edit), edit_issue_path(issue) 8 | - if issue.assigned_to_id == User.current.id 9 | - render_rdb_menu_list_item async: true do 10 | = link_to t(:rdb_issue_menu_unassign_me), rdb_update_path(issue, unassigne_me: true) 11 | - else 12 | - render_rdb_menu_list_item async: true do 13 | = link_to t(:rdb_issue_menu_assign_me), rdb_update_path(issue, assigne_me: true) 14 | 15 | - if @board.editable? && (issue.assigned_to_id == User.current.id || User.current.admin?) 16 | - render_rdb_menu_list title: t(:rdb_issue_menu_progress_title), async: true, list_tag: :div do 17 | ul.rdb-issue-menu-progress 18 | - [0, 20, 40].each do |value| 19 | li = link_to t(:rdb_issue_menu_progress, count: value), rdb_update_path(issue, done_ratio: value) 20 | ul.rdb-issue-menu-progress 21 | - [60, 80, 100].each do |value| 22 | li = link_to t(:rdb_issue_menu_progress, count: value), rdb_update_path(issue, done_ratio: value) 23 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_badges.scss: -------------------------------------------------------------------------------- 1 | tr.group .count, 2 | span.private, 3 | .badge { 4 | display: inline-block; 5 | position: relative; 6 | top: -1px; 7 | box-sizing: border-box; 8 | min-width: 1em; 9 | margin-right: $badge-space; 10 | margin-left: $badge-space; 11 | padding: $badge-padding-v $badge-padding-h; 12 | border: 1px solid; 13 | border-radius: $badge-border-radius; 14 | font-size: $badge-font-size; 15 | font-weight: $badge-font-weight; 16 | text-align: center; 17 | text-decoration: none; 18 | text-transform: uppercase; 19 | } 20 | 21 | span.private, 22 | .badge-private { 23 | padding: ($badge-padding-v + 1px) ($badge-padding-h + 1px); 24 | border: 0; 25 | background: $brand-warning; 26 | color: $brand-text; 27 | 28 | h3 & { 29 | font-size: $font-size-small-px; 30 | } 31 | } 32 | 33 | tr.group .count, 34 | .badge-count { 35 | padding: ($badge-padding-v + 1px) ($badge-padding-h + 1px); 36 | border: 0; 37 | background: $brand-primary; 38 | color: $brand-text; 39 | } 40 | 41 | .badge-status-open { 42 | border-color: $blue; 43 | color: $blue; 44 | } 45 | 46 | .badge-status-locked { 47 | border-color: $gray-600; 48 | color: $gray-600; 49 | } 50 | 51 | .badge-status-closed { 52 | border-color: $green; 53 | color: $green; 54 | } 55 | 56 | .badge-issues-count { 57 | border-color: $gray-400; 58 | background-color: $gray-100; 59 | } 60 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/models/rdb_assignee_filter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RdbAssigneeFilter < RdbFilter 4 | def initialize 5 | super :assignee 6 | end 7 | 8 | def scope(scope) 9 | case value 10 | when :me then scope.where(assigned_to_id: User.current.id) 11 | when :none then scope.where(assigned_to_id: nil) 12 | when :all then scope 13 | else scope.where(assigned_to_id: value) 14 | end 15 | end 16 | 17 | def apply_to_child_issues? 18 | true 19 | end 20 | 21 | def default_values 22 | [RdbDashboard.defaults[:assignee] || :me] 23 | end 24 | 25 | def update(params) 26 | return unless (assignee = params[:assignee]) 27 | 28 | Rails.logger.warn "CHANGE ASSIGNE: #{assignee}" 29 | 30 | if (assignee == 'all') || (assignee == 'me') || (assignee == 'none') 31 | self.value = assignee.to_sym 32 | elsif board.assignees.where(id: assignee.to_i).any? 33 | self.value = assignee.to_i 34 | end 35 | 36 | Rails.logger.warn "CHANGE ASSIGNE: #{assignee} => #{values.inspect}" 37 | end 38 | 39 | def title 40 | case value 41 | when :all then I18n.t(:rdb_filter_assignee_all) 42 | when :me then I18n.t(:rdb_filter_assignee_me) 43 | when :none then I18n.t(:rdb_filter_assignee_none) 44 | else 45 | values.map {|id| board.assignees.find(id) }.map(&:name).join(', ') 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/application.scss: -------------------------------------------------------------------------------- 1 | @import "variables"; 2 | @import "functions"; 3 | @import "mixins"; 4 | 5 | @import "lib/normalize"; 6 | @import "lib/font-awesome"; 7 | 8 | 9 | //== Redmine's core elements 10 | // 11 | 12 | @import "components/base"; 13 | @import "components/badges"; 14 | @import "components/buttons"; 15 | @import "components/forms"; 16 | @import "components/tabs"; 17 | @import "components/pagination"; 18 | @import "components/content"; 19 | @import "components/context-menu"; 20 | @import "components/gravatar"; 21 | @import "components/list"; 22 | @import "components/simple-list"; 23 | @import "components/issue"; 24 | @import "components/login"; 25 | @import "components/admin"; 26 | @import "components/coderay"; 27 | @import "components/rouge"; 28 | @import "components/gantt"; 29 | @import "components/calendar"; 30 | @import "components/progress"; 31 | @import "components/wiki"; 32 | @import "components/elements"; 33 | @import "components/jquery-ui"; 34 | @import "components/icons"; 35 | @import "components/dropdown"; 36 | @import "components/top"; 37 | @import "components/jstoolbar"; 38 | @import "components/flash"; 39 | @import "components/image-base64"; 40 | @import "components/responsive"; 41 | @import "components/print"; 42 | 43 | 44 | //== Tweaks for plugins 45 | // 46 | 47 | @import "components/plugins"; 48 | 49 | 50 | //== Built-in JavaScript plugins 51 | // 52 | 53 | @import "javascripts/sidebar-toggler"; 54 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_context-menu.scss: -------------------------------------------------------------------------------- 1 | #wrapper { 2 | .context-menu-selection { 3 | &, 4 | > td { 5 | background-color: $brand-primary !important; // stylelint-disable-line declaration-no-important 6 | color: $brand-text !important; // stylelint-disable-line declaration-no-important 7 | } 8 | } 9 | 10 | #context-menu { 11 | > ul, 12 | > ul > li > ul { 13 | @include nice-shadow(2); 14 | border: 0 none !important; // stylelint-disable-line declaration-no-important 15 | } 16 | 17 | ul { 18 | padding: 3px; 19 | } 20 | 21 | li { 22 | padding: 0; 23 | border: 0 none; 24 | border-radius: $border-radius-small; 25 | background: transparent; 26 | 27 | &:hover { 28 | background-color: $pagination-hover-bg; 29 | } 30 | } 31 | 32 | a:not(.easy-mindmup__icon) { 33 | @extend %fa-icon; 34 | padding: 3px 10px 3px 20px; 35 | border-radius: $border-radius-small; 36 | 37 | &::before { 38 | margin-top: 2px; 39 | margin-left: -16px; 40 | float: left; 41 | } 42 | 43 | &:hover { 44 | border-color: $pagination-hover-border; 45 | background-color: $pagination-hover-bg; 46 | } 47 | 48 | &.disabled { 49 | color: rgba($pagination-color, .5); 50 | } 51 | 52 | &.icon-checked { 53 | background: transparent; 54 | } 55 | 56 | &.submenu { 57 | background-image: inline-svg("chevron-right.svg", (path: (fill: $btn-default-icon-color))); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_print.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Media print specific styles 3 | // -------------------------------------------------- 4 | 5 | @media print { 6 | #top-menu, 7 | #header, 8 | #main-menu, 9 | #sidebar, 10 | #footer, 11 | #wiki_add_attachment, 12 | .hide-when-print, 13 | .contextual, 14 | .other-formats { 15 | display: none; 16 | } 17 | 18 | .pagination { 19 | .pages, 20 | .per-page { 21 | display: none; 22 | } 23 | } 24 | 25 | #main { 26 | display: block; 27 | overflow: visible !important; // stylelint-disable-line declaration-no-important 28 | background: $white; 29 | } 30 | 31 | #content { 32 | width: 100%; 33 | margin: 0; 34 | padding: 0; 35 | overflow: visible !important; // stylelint-disable-line declaration-no-important 36 | border: 0; 37 | background: $white; 38 | } 39 | 40 | .autoscroll { 41 | overflow-x: visible; 42 | } 43 | 44 | a { 45 | // stylelint-disable declaration-no-important 46 | padding: 0 !important; 47 | background-color: transparent !important; 48 | color: $black !important; 49 | 50 | &::before, 51 | &::after { 52 | display: none !important; 53 | } 54 | 55 | &.issue.closed { 56 | text-decoration: line-through; 57 | } 58 | } 59 | 60 | table.list { 61 | tr { 62 | background-color: transparent; 63 | } 64 | 65 | th, 66 | td { 67 | border: 1px solid $gray-500; 68 | background-color: transparent; 69 | 70 | &.buttons { 71 | padding: 0; 72 | 73 | a { 74 | display: none; 75 | } 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/plugins/redmine_backlogs/jquery/jquery.multiselect.css: -------------------------------------------------------------------------------- 1 | .ui-multiselect{padding:2px 0 2px 4px;text-align:left}.ui-multiselect span.ui-icon{float:right}.ui-multiselect-single .ui-multiselect-checkboxes input{position:absolute !important;top:auto !important;left:-9999px}.ui-multiselect-single .ui-multiselect-checkboxes label{padding:5px !important}.ui-multiselect-header{margin-bottom:3px;padding:3px}.ui-multiselect-header ul{font-size:.92em}.ui-multiselect-header ul li{padding:0 10px 0 0;float:left}.ui-multiselect-header a{text-decoration:none}.ui-multiselect-header a:hover{text-decoration:underline}.ui-multiselect-header span.ui-icon{float:left}.ui-multiselect-header li.ui-multiselect-close{padding-right:0;float:right;text-align:right}.ui-multiselect-menu{box-shadow:0 5px 8px -2px rgba(0,0,0,.25),0 1px 2px rgba(0,0,0,.3);display:none;position:absolute;z-index:10000;padding:3px;text-align:left}.ui-multiselect-checkboxes{position:relative;padding-right:2px;overflow-y:scroll}.ui-multiselect-checkboxes input[type=checkbox]{top:0;margin:3px 0 0 -20px;float:left}.ui-multiselect-checkboxes label{display:block;padding:3px 1px;padding-left:26px;border:1px solid transparent;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ui-multiselect-checkboxes label input{position:relative;top:1px}.ui-multiselect-checkboxes li{clear:both;font-size:.92em}.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label{margin-bottom:2px;border-bottom:1px solid #dadce6;font-weight:600;text-align:center}.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label a{display:block;margin:1px 0;padding:3px;text-decoration:none}* html .ui-multiselect-checkboxes label{border:0 none} -------------------------------------------------------------------------------- /themes/PurpleMine2-master/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "purplemine", 3 | "description": "A free Redmine 3.0+ theme written in SCSS", 4 | "keywords": [ 5 | "redmine", 6 | "theme", 7 | "sass", 8 | "scss" 9 | ], 10 | "author": "mrliptontea", 11 | "repository": { 12 | "type": "git", 13 | "url": "git@github.com:mrliptontea/PurpleMine2.git" 14 | }, 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/mrliptontea/PurpleMine2/issues" 18 | }, 19 | "homepage": "https://github.com/mrliptontea/PurpleMine2", 20 | "scripts": { 21 | "build": "grunt", 22 | "watch": "grunt watch", 23 | "lint:js": "eslint src/javascripts/", 24 | "lint:sass": "stylelint src/sass/**/*.scss", 25 | "lint": "npm run -S lint:js && npm run -S lint:sass" 26 | }, 27 | "dependencies": { 28 | "@liquid-js/sass-inline-svg": "^2.0.0", 29 | "autoprefixer": "^9.8.6", 30 | "grunt": "^1.4.0", 31 | "grunt-contrib-uglify": "^5.0.1", 32 | "grunt-contrib-watch": "^1.1.0", 33 | "grunt-postcss": "^0.9.0", 34 | "grunt-sass": "^3.1.0", 35 | "sass": "^1.34.0" 36 | }, 37 | "devDependencies": { 38 | "eslint": "^7.27.0", 39 | "eslint-config-standard": "^14.1.1", 40 | "eslint-plugin-import": "^2.23.3", 41 | "eslint-plugin-node": "^11.1.0", 42 | "eslint-plugin-promise": "^4.3.1", 43 | "eslint-plugin-standard": "^4.1.0", 44 | "husky": "^4.3.8", 45 | "lint-staged": "^10.5.4", 46 | "stylelint": "^13.13.1", 47 | "stylelint-order": "^4.1.0", 48 | "stylelint-scss": "^3.19.0" 49 | }, 50 | "browserslist": [ 51 | "last 2 versions", 52 | "> 1%", 53 | "not dead" 54 | ], 55 | "husky": { 56 | "hooks": { 57 | "pre-commit": "lint-staged --relative" 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/mixins/_issues.scss: -------------------------------------------------------------------------------- 1 | // Priority icon 2 | 3 | @mixin priority-icon-base() { 4 | &::before { 5 | content: "\00a0"; 6 | display: inline-block; 7 | width: $priority-icon-size; 8 | margin-right: $priority-icon-space; 9 | background-repeat: no-repeat; 10 | background-position: center center; 11 | background-size: $priority-icon-size; 12 | } 13 | } 14 | 15 | @mixin priority-icon($parent, $color, $icon) { 16 | table.list tbody tr#{$parent} .priority, 17 | .issue.details#{$parent} .attributes td.priority, 18 | .issue.details#{$parent} .attribute.priority .value { 19 | &::before { 20 | background-image: inline-svg($icon, (path: (fill: $color))); 21 | } 22 | } 23 | } 24 | 25 | 26 | // Tracker highlight 27 | 28 | @mixin tracker($parent, $background, $color) { 29 | tr#{$parent} .id > a, 30 | tr#{$parent} .issue_id > a, 31 | a#{$parent}.issue, 32 | a#{$parent}, 33 | .relations > span > a#{$parent}, 34 | .parent > a#{$parent} { 35 | background-color: $background; 36 | color: $color; 37 | 38 | &:hover { 39 | @if hue($background) > 15deg and hue($background) < 40deg { 40 | background-color: darken(adjust-hue($background, -8deg), 8%); 41 | } @else { 42 | background-color: darken($background, 10%); 43 | } 44 | color: $color; 45 | } 46 | } 47 | 48 | a#{$parent} { 49 | &.closed { 50 | color: mix($color, $background, 75%); 51 | 52 | &::after { 53 | border-top-color: rgba($color, .95); 54 | } 55 | 56 | &:hover::after { 57 | border-top-color: rgba($color, .25); 58 | } 59 | } 60 | } 61 | 62 | tr#{$parent} .id > a { 63 | &::before { 64 | color: mix($color, $background, 50%); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_progress.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Progress bar 3 | // -------------------------------------------------- 4 | 5 | table.progress { 6 | width: 80px; 7 | margin-top: 3px; 8 | margin-right: 5px; 9 | float: left; 10 | empty-cells: show; 11 | border: 0 none; 12 | 13 | .version-overview & { 14 | width: 40em; 15 | } 16 | 17 | td.done_ratio & { 18 | margin-right: auto; 19 | margin-left: auto; 20 | float: none; 21 | } 22 | 23 | tr { 24 | background: transparent !important; // stylelint-disable-line declaration-no-important 25 | } 26 | 27 | td { 28 | height: $progress-height; 29 | padding: 0; 30 | border: 0 none; 31 | 32 | &:first-child { 33 | border-top-left-radius: $progress-height * .5; 34 | border-bottom-left-radius: $progress-height * .5; 35 | } 36 | 37 | &:last-child { 38 | border-top-right-radius: $progress-height * .5; 39 | border-bottom-right-radius: $progress-height * .5; 40 | } 41 | 42 | &.done { 43 | background-color: $progress-bar-bg !important; // stylelint-disable-line declaration-no-important 44 | } 45 | 46 | &.closed { 47 | background-color: $progress-bar-success-bg !important; // stylelint-disable-line declaration-no-important 48 | } 49 | 50 | &.todo { 51 | background-color: $progress-bg !important; // stylelint-disable-line declaration-no-important 52 | mix-blend-mode: multiply; 53 | } 54 | } 55 | 56 | .issue & td { 57 | padding: 0; 58 | } 59 | 60 | .context-menu-selection & td.todo { 61 | mix-blend-mode: screen; 62 | } 63 | } 64 | 65 | p { 66 | &.percent { 67 | margin-bottom: 0; 68 | font-size: $font-size-small; 69 | } 70 | 71 | &.progress-info { 72 | clear: left; 73 | color: $gray-700; 74 | font-size: 80%; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/mixins/_buttons.scss: -------------------------------------------------------------------------------- 1 | // Button sizes 2 | @mixin button-size($padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) { 3 | padding: $padding-vertical $padding-horizontal; 4 | border-radius: $border-radius; 5 | font-size: $font-size; 6 | line-height: $line-height; 7 | } 8 | 9 | @mixin button-variant($color, $bg, $border) { 10 | $correction: 1; 11 | @if hue($bg) > 120 and hue($bg) < 160 or lightness($bg) > 90 { 12 | $correction: .5; 13 | } 14 | $normal-shadow: darken($border, 12% * $correction); 15 | $focus-bg: darken($bg, 12% * $correction); 16 | $focus-border: darken($border, 12% * $correction); 17 | $focus-shadow: darken($focus-border, 12% * $correction); 18 | $active-bg: darken($bg, 12% * $correction); 19 | $active-border: darken($border, 15% * $correction); 20 | $active-shadow: inset 0 3px 4px -2px $active-border; 21 | 22 | @if lightness($bg) > 98 { 23 | $focus-bg: darken($bg, 5%); 24 | $focus-border: darken($border, 5%); 25 | $normal-shadow: none; 26 | $focus-shadow: none; 27 | } 28 | 29 | background-color: $bg; 30 | color: $color; 31 | @if $normal-shadow == "none" { 32 | border-color: $border; 33 | box-shadow: none; 34 | } @else { 35 | border-color: $border $border $normal-shadow; 36 | box-shadow: 0 1px 0 $normal-shadow; 37 | } 38 | 39 | &:hover, 40 | &:focus { 41 | background-color: $focus-bg; 42 | color: $color; 43 | @if $focus-shadow == "none" { 44 | border-color: $focus-border; 45 | box-shadow: none; 46 | } @else { 47 | border-color: $focus-border $focus-border $focus-shadow; 48 | box-shadow: 0 1px 0 $focus-shadow; 49 | } 50 | } 51 | 52 | &:active { 53 | transform: translate(0, 1px); 54 | border-color: $active-border; 55 | background-color: $active-bg; 56 | box-shadow: $active-shadow; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/models/rdb_version_filter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RdbVersionFilter < RdbFilter 4 | def initialize 5 | super :version 6 | end 7 | 8 | def scope(issues) 9 | case value 10 | when :all then issues 11 | when :unassigned then issues.where fixed_version_id: nil 12 | else issues.where fixed_version_id: value 13 | end 14 | end 15 | 16 | def valid_value?(value) 17 | return true if (value == :all) || value.nil? 18 | return false unless value.respond_to?(:to_i) 19 | 20 | board.versions.where(id: value.to_i).any? 21 | end 22 | 23 | def default_values 24 | if RdbDashboard.defaults[:version] == :latest 25 | version = board.versions 26 | .where(status: %i[open locked]) 27 | .where('effective_date IS NOT NULL') 28 | .order('effective_date ASC') 29 | .first 30 | return [version.id] unless version.nil? 31 | 32 | version = board.versions 33 | .where(status: %i[open locked]) 34 | .order('name ASC') 35 | .first 36 | return [version.id] unless version.nil? 37 | end 38 | 39 | [:all] 40 | end 41 | 42 | def update(params) 43 | return unless (version = params[:version]) 44 | 45 | case version 46 | when 'all' 47 | self.value = :all 48 | when 'unassigned' 49 | self.values = [nil] 50 | else 51 | self.value = version.to_i 52 | end 53 | end 54 | 55 | def title 56 | if value == :all 57 | I18n.t(:rdb_filter_version_all) 58 | elsif value.nil? 59 | I18n.t(:rdb_filter_version_unassigned) 60 | else 61 | values.map {|id| board.versions.find(id) }.map(&:name).join(', ') 62 | end 63 | end 64 | 65 | def versions 66 | board.versions.where(status: %i[open locked]) 67 | end 68 | 69 | def done_versions 70 | board.versions.where(status: :closed) 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_pagination.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Pagination (multiple pages) 3 | // -------------------------------------------------- 4 | .pagination { 5 | .pages { 6 | display: inline-block; 7 | margin: 0; 8 | padding: 0; 9 | } 10 | 11 | li { 12 | display: inline-block; 13 | margin-right: .3em; 14 | list-style: none; 15 | } 16 | 17 | li > a, 18 | li > span, 19 | > .previous, 20 | > .next, 21 | > .page { 22 | display: inline-block; 23 | padding: $pagination-padding-vertical $pagination-padding-horizontal; 24 | border: 1px solid $pagination-border; 25 | border-radius: $border-radius-base; 26 | background-color: $pagination-bg; 27 | color: $pagination-color; 28 | text-decoration: none; 29 | white-space: nowrap; 30 | } 31 | 32 | li > span { 33 | border-color: $pagination-inactive-border; 34 | background-color: $pagination-inactive-bg; 35 | color: $pagination-inactive-color; 36 | cursor: default; 37 | } 38 | 39 | .spacer > span { 40 | padding: 0; 41 | border: 0 none; 42 | background: transparent; 43 | color: $text-color; 44 | } 45 | 46 | a { 47 | &:hover, 48 | &:focus { 49 | border-color: $pagination-hover-border; 50 | background-color: $pagination-hover-bg; 51 | color: $pagination-hover-color; 52 | } 53 | } 54 | 55 | .page.current, 56 | .current > span { 57 | z-index: 2; 58 | border-color: $pagination-active-border; 59 | background-color: $pagination-active-bg; 60 | color: $pagination-active-color; 61 | cursor: default; 62 | } 63 | 64 | .items, 65 | .per-page { 66 | display: inline-block; 67 | margin: ($pagination-padding-vertical + 1px) 0 ($pagination-padding-vertical + 1px) $pagination-padding-vertical; 68 | } 69 | } 70 | 71 | p.pagination { 72 | margin-bottom: 0; 73 | float: left; 74 | 75 | + h1, 76 | + h2, 77 | + h3, 78 | + h4, 79 | + h5, 80 | + h6 { 81 | clear: both; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_calendar.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Calendar 3 | // -------------------------------------------------- 4 | 5 | 6 | table.cal { 7 | width: 100%; 8 | margin-bottom: $line-height-computed; 9 | border: 1px solid $table-border-color; 10 | 11 | thead th { 12 | width: 14%; 13 | padding: $table-condensed-cell-padding; 14 | background-color: $table-bg-active; 15 | 16 | &.week-number { 17 | width: auto; 18 | } 19 | } 20 | 21 | tbody tr { 22 | height: 100px; 23 | } 24 | 25 | td { 26 | padding: $table-condensed-cell-padding; 27 | border: 1px solid $table-border-color; 28 | font-size: $font-size-small; 29 | vertical-align: top; 30 | 31 | &.week-number { 32 | border: 0 none; 33 | background-color: $table-bg-active; 34 | font-size: 1em; 35 | text-align: right; 36 | } 37 | 38 | p.day-num { 39 | float: right; 40 | font-size: $font-size-large; 41 | text-align: right; 42 | } 43 | 44 | &.odd p.day-num { 45 | color: $gray-600; 46 | } 47 | 48 | &.nwday { 49 | background: $table-bg-accent; 50 | } 51 | 52 | &.today { 53 | background: $highlight-bg; 54 | 55 | p.day-num { 56 | font-weight: $font-weight-bold; 57 | } 58 | } 59 | } 60 | } 61 | 62 | table.cal .starting a, 63 | p.cal.legend .starting, 64 | table.cal .ending a, 65 | p.cal.legend .ending { 66 | @extend %fa-icon; 67 | 68 | &::before { 69 | content: $fa-var-caret-right; 70 | width: 10px; 71 | text-align: right; 72 | } 73 | } 74 | 75 | table.cal .ending a, 76 | p.cal.legend .ending { 77 | &::before { 78 | content: $fa-var-caret-left; 79 | text-align: left; 80 | } 81 | } 82 | 83 | table.cal .starting.ending a, 84 | p.cal.legend .starting.ending { 85 | &::before { 86 | content: $fa-var-square; 87 | transform: scale(.6) rotate(45deg); 88 | text-align: center; 89 | } 90 | } 91 | 92 | p.cal.legend { 93 | span { 94 | display: block; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/mixins/_forms.scss: -------------------------------------------------------------------------------- 1 | // Form control focus state 2 | // 3 | @mixin form-control-focus($color: $input-border-focus) { 4 | &:focus { 5 | border-color: rgba($input-border-focus, $input-border-focus-alpha); 6 | outline: 0; 7 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, .075), 0 0 0 2px rgba($input-border-focus, $input-shadow-focus-alpha); 8 | } 9 | } 10 | 11 | // Placeholder text 12 | // 13 | @mixin placeholder($color: $input-color-placeholder) { 14 | &::placeholder { 15 | opacity: 1; // See https://github.com/twbs/bootstrap/pull/11526 16 | color: $color; 17 | } 18 | } 19 | 20 | 21 | // Form control sizing 22 | // 23 | @mixin input-size($parent, $input-height, $padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) { 24 | #{$parent} { 25 | height: $input-height; 26 | padding: $padding-vertical $padding-horizontal; 27 | border-radius: $border-radius; 28 | font-size: $font-size; 29 | line-height: $line-height; 30 | } 31 | 32 | select#{$parent} { 33 | height: $input-height; 34 | line-height: $input-height; 35 | } 36 | 37 | textarea#{$parent}, 38 | select[multiple]#{$parent} { 39 | height: auto; 40 | } 41 | } 42 | 43 | @mixin check() { 44 | @extend %clearfix; 45 | position: relative; 46 | padding-left: $check-input-gutter; 47 | font-weight: $font-weight-normal; 48 | line-height: $line-height-base; 49 | text-align: left; 50 | 51 | input[type="checkbox"], 52 | input[type="radio"] { 53 | position: absolute; 54 | width: auto; 55 | margin-top: $check-input-margin-vertical; 56 | margin-left: -$check-input-gutter; 57 | } 58 | } 59 | 60 | @mixin check-inline() { 61 | @include check; 62 | display: inline-block; 63 | margin-right: $check-input-margin-horizontal; 64 | } 65 | 66 | @mixin check-list() { 67 | @include check; 68 | display: block; 69 | width: auto; 70 | margin: 0; 71 | padding-top: $check-list-offset-top; 72 | padding-bottom: $check-list-offset-top; 73 | float: none; 74 | 75 | @media screen and (min-width: $screen-sm-min) { 76 | padding-bottom: 0; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | grunt.initConfig({ 3 | src: 'src/', 4 | 5 | sass: { 6 | options: { 7 | implementation: require('sass'), 8 | sourceMap: false, 9 | outputStyle: 'compressed', 10 | functions: { 11 | 'inline-svg($path, $selectors: null)': require('@liquid-js/sass-inline-svg')('./svg', { 12 | optimize: true, 13 | encodingFormat: 'uri' 14 | }) 15 | } 16 | }, 17 | 18 | theme: { 19 | files: { 20 | 'stylesheets/application.css': '<%= src %>sass/application.scss' 21 | } 22 | }, 23 | 24 | plugins: { 25 | files: [ 26 | { 27 | expand: true, 28 | cwd: '<%= src %>sass/plugins/', 29 | src: '**/*.scss', 30 | dest: 'plugins/', 31 | ext: '.css', 32 | extDot: 'last' 33 | } 34 | ] 35 | } 36 | }, 37 | 38 | postcss: { 39 | options: { 40 | processors: [ 41 | require('autoprefixer')() 42 | ] 43 | }, 44 | 45 | all: { 46 | src: [ 47 | 'stylesheets/*.css', 48 | 'plugins/**/*.css' 49 | ] 50 | } 51 | }, 52 | 53 | uglify: { 54 | theme: { 55 | src: [ 56 | '<%= src %>javascripts/modules/*.js', 57 | '<%= src %>javascripts/theme.js' 58 | ], 59 | dest: 'javascripts/theme.js' 60 | } 61 | }, 62 | 63 | watch: { 64 | css: { 65 | files: ['<%= src %>sass/**/*.scss'], 66 | tasks: ['css'] 67 | }, 68 | 69 | js: { 70 | files: ['<%= src %>javascripts/**/*.js'], 71 | tasks: ['js'] 72 | } 73 | } 74 | }) 75 | 76 | grunt.loadNpmTasks('grunt-sass') 77 | grunt.loadNpmTasks('grunt-postcss') 78 | grunt.loadNpmTasks('grunt-contrib-watch') 79 | grunt.loadNpmTasks('grunt-contrib-uglify') 80 | 81 | grunt.registerTask('css', ['sass', 'postcss']) 82 | grunt.registerTask('js', ['uglify']) 83 | 84 | grunt.registerTask('default', ['css', 'js']) 85 | } 86 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_flash.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Flash & error messages 3 | // -------------------------------------------------- 4 | 5 | 6 | #errorExplanation, 7 | .flash, 8 | .nodata, 9 | .warning, 10 | .conflict { 11 | @extend %fa-icon; 12 | margin-bottom: $line-height-computed; 13 | padding: $padding-large-vertical $padding-large-horizontal; 14 | padding-left: $padding-large-horizontal + 8px + 16px; 15 | border: 1px solid; 16 | border-radius: $border-radius-large; 17 | background-repeat: no-repeat; 18 | background-position: $padding-large-horizontal 50%; 19 | 20 | &::before { 21 | margin-left: -(8px + 16px); 22 | float: left; 23 | line-height: $line-height-computed; 24 | } 25 | 26 | > :last-child { 27 | margin-bottom: 0; 28 | } 29 | } 30 | 31 | @mixin flash($color, $background, $border, $link, $icon) { 32 | border-color: $border; 33 | background-color: $background; 34 | color: $color; 35 | 36 | @if $icon == "true" { 37 | $icon: $fa-var-check; 38 | } @else if $icon == "warning" { 39 | $icon: $fa-var-warning; 40 | } @else if $icon == "exclamation" { 41 | $icon: $fa-var-exclamation-circle; 42 | } 43 | 44 | &::before { 45 | content: $icon; 46 | } 47 | 48 | a { 49 | color: $link; 50 | font-weight: $font-weight-bold; 51 | } 52 | } 53 | 54 | .warning, 55 | .conflict, 56 | .nodata { 57 | @include flash($flash-warning-text, $flash-warning-bg, $flash-warning-border, $flash-warning-link, "warning"); 58 | } 59 | 60 | .flash.notice { 61 | @include flash($flash-success-text, $flash-success-bg, $flash-success-border, $flash-success-link, "true"); 62 | } 63 | 64 | #errorExplanation, 65 | .flash.error { 66 | @include flash($flash-error-text, $flash-error-bg, $flash-error-border, $flash-error-link, "exclamation"); 67 | } 68 | 69 | .nodata { 70 | padding-left: $padding-large-horizontal; 71 | text-align: center; 72 | 73 | &.nodata-left { 74 | &::before { 75 | float: left; 76 | } 77 | } 78 | 79 | &::before { 80 | margin-left: 0; 81 | float: none; 82 | } 83 | } 84 | 85 | #errorExplanation { 86 | h2, 87 | p { 88 | display: none; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'pathname' 4 | require 'yaml' 5 | 6 | require 'rspec/core/rake_task' 7 | 8 | task default: [:spec] 9 | 10 | RSpec::Core::RakeTask.new(:spec) do |t| 11 | t.pattern = ENV.fetch('SPEC', 'spec/**/*_spec.rb') 12 | t.ruby_opts = '-Ispec' 13 | t.rspec_opts = '--color --backtrace' 14 | t.rspec_opts << " --seed #{ENV['SEED']}" if ENV['SEED'] 15 | end 16 | 17 | namespace :i18n do 18 | desc 'Fix locale files after tx pull' 19 | task :fix do 20 | Pathname.glob('config/locales/*.yml').each do |file| 21 | data = YAML.safe_load(file.read) 22 | 23 | # Transifex exports data inside the YAML using underscored 24 | # identifiers (e.g. pt_BR), but Redmine needs dashed identifiers 25 | # (pt-bR). We need convert each top-level key to use dashes. 26 | # 27 | # rubocop: We cannot modify a hash when iterating using 28 | # `#each_key`. Therefore, we must us `keys.each` here. 29 | data.keys.each do |key| # rubocop:disable Style/HashEachMethods 30 | if key.include?('_') 31 | data[key.gsub('_', '-')] = data.delete(key) 32 | end 33 | end 34 | 35 | fix_pluralizations = lambda do |locale_data| 36 | # Redmine does not contain pluralization rules, but many 37 | # languages only need an `other` key according to Unicode. Tools 38 | # like transifex expect proper pluralization rules and do not 39 | # export a `one` key when only an `other` key is needed, such as 40 | # for Japanese. 41 | # 42 | # This method searches the locale data for any nested dicitonary 43 | # that looks like a pluralized section (contains only `one`, 44 | # `few`, `other` `many`, `zero` keys). If found, an `one` key 45 | # will be added with the `other` value. 46 | locale_data.each_value do |value| 47 | next unless value.is_a?(Hash) 48 | 49 | if (value.keys - %w[one few other many zero]).empty? 50 | value['one'] ||= value['other'] if value.key?('other') 51 | else 52 | fix_pluralizations.call(value) 53 | end 54 | end 55 | end 56 | 57 | fix_pluralizations.call(data) 58 | 59 | file.write(YAML.dump(data, line_width: -1)) 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/controllers/rdb_taskboard_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RdbTaskboardController < RdbDashboardController 4 | menu_item :dashboard 5 | 6 | def board_type 7 | RdbTaskboard 8 | end 9 | 10 | def move 11 | return flash_error(:rdb_flash_invalid_request) unless (column = @board.columns[params[:column].to_s]) 12 | 13 | # Get all status the user is allowed to assign and that are in the target column 14 | @statuses = @issue.new_statuses_allowed_to(User.current) & column.statuses 15 | 16 | if @statuses.empty? 17 | return flash_error :rdb_flash_illegal_workflow_action, 18 | issue: @issue.subject, source: @issue.status.name, target: column.title 19 | end 20 | 21 | # Show dialog if more than one status are available 22 | return render 'rdb_dashboard/taskboard/column_dialog' if @statuses.count > 1 23 | 24 | params[:status] = @statuses.first.id 25 | update 26 | end 27 | 28 | def update 29 | @issue.init_journal(User.current, params[:notes] || nil) 30 | 31 | @issue.done_ratio = params[:done_ratio].to_i if params[:done_ratio] 32 | @issue.assigned_to_id = nil if params[:unassigne_me] && @issue.assigned_to_id == User.current.id 33 | @issue.assigned_to_id = User.current.id if params[:assigne_me] 34 | 35 | if params[:status] 36 | status = IssueStatus.find params[:status].to_i 37 | if @issue.new_statuses_allowed_to(User.current).include?(status) 38 | @issue.status = status 39 | @issue.assigned_to_id = User.current.id if @board.options[:change_assignee] 40 | else 41 | return flash_error :rdb_flash_illegal_workflow_action, 42 | issue: @issue.subject, source: @issue.status.name, target: @status.name 43 | end 44 | end 45 | 46 | Issue.transaction do 47 | call_hook( 48 | :controller_issues_edit_before_save, 49 | { 50 | params: {}, 51 | issue: @issue, 52 | journal: @issue.current_journal 53 | }, 54 | ) 55 | 56 | if @issue.save 57 | call_hook( 58 | :controller_issues_edit_after_save, 59 | { 60 | params: {}, 61 | issue: @issue, 62 | journal: @issue.current_journal 63 | }, 64 | ) 65 | else 66 | raise ActiveRecord::Rollback 67 | end 68 | end 69 | 70 | render 'index' 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/controllers/rdb_dashboard_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RdbDashboardController < ApplicationController 4 | menu_item :dashboard 5 | before_action :find_project, :authorize 6 | before_action :setup_board, except: :index 7 | before_action :find_issue, only: %i[move update] 8 | before_action :authorize_edit, only: %i[move update] 9 | after_action :save_board_options 10 | 11 | def index 12 | return redirect_to rdb_taskboard_url if params[:controller] == 'rdb_dashboard' 13 | 14 | setup_board 15 | end 16 | 17 | def filter 18 | render action: 'index' 19 | end 20 | 21 | def update 22 | render_404 23 | end 24 | 25 | def move 26 | render_404 27 | end 28 | 29 | private 30 | 31 | def board_type 32 | nil 33 | end 34 | 35 | def board 36 | board_type.new(@project, options_for(board_type.name), params) 37 | end 38 | 39 | def setup_board 40 | return render_404 unless (@board = board) 41 | 42 | @board.setup(params) 43 | @board.update(params) 44 | @board.build 45 | @board 46 | end 47 | 48 | def save_board_options 49 | save_options_for(@board.options, board_type.name) if @board 50 | end 51 | 52 | def authorize_edit 53 | return true if @issue&.attributes_editable? 54 | 55 | raise Unauthorized 56 | end 57 | 58 | def find_project 59 | @project = Project.find params[:id] 60 | end 61 | 62 | def find_issue 63 | flash_error :rdb_flash_missing_lock_version and return false unless params[:lock_version] 64 | 65 | @issue = Issue.find params[:issue] 66 | 67 | if @issue.lock_version != params[:lock_version].to_i 68 | flash_error :rdb_flash_stale_object, update: true, issue: @issue.subject 69 | return false 70 | end 71 | 72 | @issue.lock_version = params[:lock_version].to_i 73 | @issue 74 | end 75 | 76 | def flash_error(sym, **options) 77 | flash.now[:rdb_error] = I18n.t(sym, **options).html_safe 78 | Rails.logger.info "Render Rdb flash error: #{sym}" 79 | options[:update] ? render('index.js') : render('error.js') 80 | end 81 | 82 | def options_for(board) 83 | User.current.pref["rdb_#{@project.id}_#{board}"] || 84 | session["dashboard_#{@project.id}_#{User.current.id}_#{board}"] || {} 85 | end 86 | 87 | def save_options_for(options, board) 88 | User.current.pref["rdb_#{@project.id}_#{board}"] = options 89 | User.current.pref.save 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/javascripts/_sidebar-toggler.scss: -------------------------------------------------------------------------------- 1 | @if $enable-sidebar-toggler { 2 | #main { 3 | // Fix full screen view for dashboard plugin 4 | // https://github.com/jgraichen/redmine_dashboard 5 | @at-root .controller-rdb_taskboard & { 6 | position: static; 7 | } 8 | } 9 | 10 | #sidebar { 11 | @if $fixed-layout { 12 | will-change: margin, opacity; 13 | transition: margin .5s, opacity .5s; 14 | opacity: 1; 15 | } @else { 16 | will-change: margin; 17 | transition: margin .5s; 18 | } 19 | 20 | &.sidebar-hiding { 21 | @if $fixed-layout { 22 | opacity: 0; 23 | } 24 | @if $sidebar-position == "left" { 25 | margin-left: -$sidebar-width; 26 | } @else { 27 | margin-right: -$sidebar-width; 28 | } 29 | } 30 | 31 | &.sidebar-hidden { 32 | display: none; 33 | } 34 | } 35 | 36 | .sidebar-toggler { 37 | display: block; 38 | position: absolute; 39 | z-index: 2; 40 | bottom: -1px; 41 | width: 14px; 42 | height: 16px; 43 | transform: translateY(100%); 44 | border: 2px solid $gray-700; 45 | border-radius: $border-radius-base; 46 | background-color: $gray-200; 47 | background-position: center; 48 | line-height: 1; 49 | user-select: none; 50 | 51 | @media print { 52 | display: none; 53 | } 54 | 55 | &:hover, 56 | &:focus, 57 | &:active { 58 | background-color: $gray-300; 59 | } 60 | 61 | @if $sidebar-position == "left" { 62 | left: 0; 63 | background-image: inline-svg("chevron-left.svg", (path: (fill: $gray-700))); 64 | 65 | @if not $fixed-layout { 66 | border-left: 0; 67 | border-top-left-radius: 0; 68 | border-bottom-left-radius: 0; 69 | } 70 | } @else { 71 | right: 0; 72 | background-image: inline-svg("chevron-right.svg", (path: (fill: $gray-700))); 73 | 74 | @if not $fixed-layout { 75 | border-right: 0; 76 | border-top-right-radius: 0; 77 | border-bottom-right-radius: 0; 78 | } 79 | } 80 | 81 | &.sidebar-hidden { 82 | @if $sidebar-position == "left" { 83 | background-image: inline-svg("chevron-right.svg", (path: (fill: $gray-700))); 84 | } @else { 85 | background-image: inline-svg("chevron-left.svg", (path: (fill: $gray-700))); 86 | } 87 | } 88 | } 89 | } @else { 90 | .sidebar-toggler { 91 | display: none; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/ko.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ko: 3 | project_module_dashboard: 현황판 4 | permission_view_dashboards: 현황판 보기 5 | permission_configure_dashboards: 현황판 설정 6 | menu_label_dashboard: 현황판 7 | rdb_taskboard: 작업판 8 | rdb_planningboard: 계획판 9 | rdb_filter_version_all: 모든 버전 10 | rdb_filter_version_unassigned: 버전 없음 11 | rdb_filter_tracker_all: 모든 유형 12 | rdb_filter_tracker_multiple: 여러 유형 13 | rdb_filter_category_all: 모든 범주 14 | rdb_filter_category_multiple: 여러 범주 15 | rdb_filter_assignee_all: 모든 담당자 16 | rdb_filter_assignee_me: 내 일감 17 | rdb_filter_assignee_none: 담당자 없음 18 | rdb_filter_assignee_others: 다른 사람 19 | rdb_options: 옵션 20 | rdb_options_change_assignee: 담당자 변경 21 | rdb_options_change_assignee_info: 일감을 옮기면서 담당자를 자신으로 변경 22 | rdb_options_hide_done: 닫힌 일감 숨기기 23 | rdb_options_hide_done_info: 닫힌 일감을 숨기고 종료됨 영역을 작게 표시 24 | rdb_options_reset: 필터 재설정 25 | rdb_options_reset_info: 모든 필터를 재설정하여 기본상대로 돌가감 26 | rdb_options_configure: 설정 27 | rdb_options_include_subprojects: 하위 프로젝트 포함 28 | rdb_options_view: 보기 29 | rdb_options_issue_view: 이슈 보기 30 | rdb_options_issue_view_card: 카드 31 | rdb_options_issue_view_compact: 작게 보기 32 | rdb_options_group: 이슈 묶기 33 | rdb_group_none: 묶음 없음 34 | rdb_group_category: 범주 35 | rdb_group_assignee: 담당자 36 | rdb_group_tracker: 유형 37 | rdb_group_priority: 우선순위 38 | rdb_group_version: 버전 39 | rdb_group_parent: 상위 일감 40 | rdb_group_project: 프로젝트 41 | rdb_options_board_view: 현황판 보기 42 | rdb_options_board_view_compact: 클래식 43 | rdb_options_board_view_outline: 개괄 44 | rdb_options_columns: 현황판 열 45 | rdb_options_fullscreen: 전체화면 46 | rdb_legend_priorities: 우선순위 47 | rdb_legend_warnings: 경고 48 | rdb_issue_overdue: 기한 지남 49 | rdb_not_available: N/A 50 | rdb_column_done: 완료 51 | rdb_x_issues: 52 | other: "%{count} 일감" 53 | one: "%{count} 일감" 54 | rdb_dialog_update_issue_title: 일감 갱신 55 | rdb_dialog_update_issue_status: 일감의 새 상태 선택 56 | rdb_other_issues: 다른 일감들 (%{count}) 57 | rdb_unassigned: 지정되지 않음 58 | rdb_others: 기타 59 | rdb_all_issues: 모든 일감 60 | rdb_no_parent: 상위 일감 없음 61 | rdb_issue_menu_progress_title: 진척률 조정 62 | rdb_issue_menu_progress: "%{count}%" 63 | rdb_issue_menu_redmine_issue: 일감 64 | rdb_issue_menu_show: 보기 65 | rdb_issue_menu_edit: 편집 66 | rdb_issue_menu_assign_me: 내가 맡기 67 | rdb_issue_menu_unassign_me: 일감 놓기 68 | rdb_flash_illegal_workflow_action: "

이 업무흐름이 허용되지 않습니다:

%{source}에서 %{target}%{issue} 이동

" 69 | rdb_flash_invalid_request: "

잘못된 요청.

" 70 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/plugins/redmine_backlogs/jquery/jquery.multiselect.scss: -------------------------------------------------------------------------------- 1 | @import "../common"; 2 | 3 | .ui-multiselect { 4 | padding: 2px 0 2px 4px; 5 | text-align: left; 6 | 7 | span.ui-icon { 8 | float: right; 9 | } 10 | } 11 | 12 | .ui-multiselect-single .ui-multiselect-checkboxes { 13 | input { 14 | position: absolute !important; // stylelint-disable-line declaration-no-important 15 | top: auto !important; // stylelint-disable-line declaration-no-important 16 | left: -9999px; 17 | } 18 | 19 | label { 20 | padding: 5px !important; // stylelint-disable-line declaration-no-important 21 | } 22 | } 23 | 24 | .ui-multiselect-header { 25 | margin-bottom: 3px; 26 | padding: 3px; 27 | 28 | ul { 29 | font-size: $font-size-list; 30 | 31 | li { 32 | padding: 0 10px 0 0; 33 | float: left; 34 | } 35 | } 36 | 37 | a { 38 | text-decoration: none; 39 | 40 | &:hover { 41 | text-decoration: underline; 42 | } 43 | } 44 | 45 | span.ui-icon { 46 | float: left; 47 | } 48 | 49 | li.ui-multiselect-close { 50 | padding-right: 0; 51 | float: right; 52 | text-align: right; 53 | } 54 | } 55 | 56 | .ui-multiselect-menu { 57 | @include nice-shadow(2); 58 | display: none; 59 | position: absolute; 60 | z-index: 10000; 61 | padding: 3px; 62 | text-align: left; 63 | } 64 | 65 | .ui-multiselect-checkboxes { 66 | position: relative; 67 | padding-right: 2px; 68 | overflow-y: scroll; 69 | 70 | input[type="checkbox"] { 71 | top: 0; 72 | margin: 3px 0 0 -20px; 73 | float: left; 74 | } 75 | 76 | label { 77 | display: block; 78 | padding: 3px 1px; 79 | padding-left: 20px + 6px; 80 | border: 1px solid transparent; 81 | cursor: default; 82 | user-select: none; 83 | 84 | input { 85 | position: relative; 86 | top: 1px; 87 | } 88 | } 89 | 90 | li { 91 | clear: both; 92 | font-size: $font-size-list; 93 | 94 | &.ui-multiselect-optgroup-label { 95 | margin-bottom: 2px; 96 | border-bottom: 1px solid $panel-border; 97 | font-weight: $font-weight-bold; 98 | text-align: center; 99 | 100 | a { 101 | display: block; 102 | margin: 1px 0; 103 | padding: 3px; 104 | text-decoration: none; 105 | } 106 | } 107 | } 108 | } 109 | 110 | // Remove label borders in IE6 because IE6 does not support transparency 111 | * html .ui-multiselect-checkboxes label { 112 | border: 0 none; 113 | } 114 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/zh.yml: -------------------------------------------------------------------------------- 1 | --- 2 | zh: 3 | project_module_dashboard: 看板 4 | permission_view_dashboards: 浏览看板 5 | permission_configure_dashboards: 配置看板 6 | menu_label_dashboard: 看板 7 | rdb_taskboard: 任务看板 8 | rdb_planningboard: 计划看板 9 | rdb_filter_version_all: 所有版本 10 | rdb_filter_version_unassigned: 未指派 11 | rdb_filter_tracker_all: 所有跟踪 12 | rdb_filter_tracker_multiple: 多个跟踪 13 | rdb_filter_category_all: 所有类别 14 | rdb_filter_category_multiple: 多个类别 15 | rdb_filter_assignee_all: 所有指派 16 | rdb_filter_assignee_me: 我的指派 17 | rdb_filter_assignee_none: 未指派 18 | rdb_filter_assignee_others: 其他指派 19 | rdb_options: 选项 20 | rdb_options_change_assignee: 更换指派 21 | rdb_options_change_assignee_info: 更换指派给移动本问题的人 22 | rdb_options_hide_done: 隐藏已关闭的问题 23 | rdb_options_hide_done_info: 隐藏已关闭的问题并缩小栏位 24 | rdb_options_reset: 重置过滤条件 25 | rdb_options_reset_info: 重置过滤条件为预设 26 | rdb_options_configure: 配置 27 | rdb_options_include_subprojects: 包含子项目 28 | rdb_options_view: 视图 29 | rdb_options_issue_view: 问题视图 30 | rdb_options_issue_view_card: 卡片 31 | rdb_options_issue_view_compact: 精简 32 | rdb_options_group: 问题分组 33 | rdb_group_none: 沒有分组 34 | rdb_group_category: 类别 35 | rdb_group_assignee: 指派人 36 | rdb_group_tracker: 跟踪 37 | rdb_group_priority: 优先级 38 | rdb_group_version: 版本 39 | rdb_group_parent: 父项 40 | rdb_group_project: 项目 41 | rdb_options_board_view: 看板视图 42 | rdb_options_board_view_compact: 精简 43 | rdb_options_board_view_outline: 大纲 44 | rdb_options_columns: 看板栏位 45 | rdb_options_fullscreen: 全屏幕 46 | rdb_legend_priorities: 优先级 47 | rdb_legend_warnings: 警告 48 | rdb_issue_overdue: 过期 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: N/A 51 | rdb_column_done: 完成 52 | rdb_x_issues: 53 | other: "%{count} 问题" 54 | one: "%{count} 问题" 55 | rdb_dialog_update_issue_title: 更新问题 56 | rdb_dialog_update_issue_status: 选择新问题的状态 57 | rdb_other_issues: 其他问题 (%{count}) 58 | rdb_unassigned: 未指派 59 | rdb_others: 其他 60 | rdb_all_issues: 所有问题 61 | rdb_no_parent: 没有父项目 62 | rdb_issue_menu_progress_title: 更新进度 63 | rdb_issue_menu_progress: "%{count}%" 64 | rdb_issue_menu_redmine_issue: Redmine 问题 65 | rdb_issue_menu_show: 显示 66 | rdb_issue_menu_edit: 编辑 67 | rdb_issue_menu_assign_me: 指派给我 68 | rdb_issue_menu_unassign_me: 未指派给我 69 | rdb_flash_illegal_workflow_action: "

你未经许可进行以下操作步骤:

%{issue}%{source} 移动到 %{target}.

" 70 | rdb_flash_missing_lock_version: "

丢失的冻结版本: 无法更新问题,请重试。" 71 | rdb_flash_stale_object: "

试图更改已冻结的问题: %{issue}请重试。" 72 | rdb_flash_invalid_request: "

无效的请求

" 73 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/zh-TW.yml: -------------------------------------------------------------------------------- 1 | --- 2 | zh-TW: 3 | project_module_dashboard: 儀表板 4 | permission_view_dashboards: 檢視儀表板 5 | permission_configure_dashboards: 設定儀表板 6 | menu_label_dashboard: 儀表板 7 | rdb_taskboard: 任務板 8 | rdb_planningboard: 計畫板 9 | rdb_filter_version_all: 所有版本 10 | rdb_filter_version_unassigned: 未指派 11 | rdb_filter_tracker_all: 所有標籤 12 | rdb_filter_tracker_multiple: 多個標籤 13 | rdb_filter_category_all: 所有分類 14 | rdb_filter_category_multiple: 多個分類 15 | rdb_filter_assignee_all: 所有指派 16 | rdb_filter_assignee_me: 我的指派 17 | rdb_filter_assignee_none: 未指派 18 | rdb_filter_assignee_others: 其他指派 19 | rdb_options: 選項 20 | rdb_options_change_assignee: 更換指派 21 | rdb_options_change_assignee_info: 更換指派給移動這個問題的人 22 | rdb_options_hide_done: 隱藏已關閉的問題 23 | rdb_options_hide_done_info: 隱藏已關閉的問題且縮小完成欄 24 | rdb_options_reset: 重置篩選條件 25 | rdb_options_reset_info: 重置篩選條件成預設 26 | rdb_options_configure: 設定 27 | rdb_options_include_subprojects: 包含子項目 28 | rdb_options_view: 視圖 29 | rdb_options_issue_view: 問題視圖 30 | rdb_options_issue_view_card: 卡片 31 | rdb_options_issue_view_compact: 簡潔 32 | rdb_options_group: 問題分組 33 | rdb_group_none: 沒有分組 34 | rdb_group_category: 分類 35 | rdb_group_assignee: 指派人 36 | rdb_group_tracker: 標籤 37 | rdb_group_priority: 優先 38 | rdb_group_version: 版本 39 | rdb_group_parent: 父項目 40 | rdb_group_project: 項目 41 | rdb_options_board_view: 黑板視圖 42 | rdb_options_board_view_compact: 經典 43 | rdb_options_board_view_outline: 大綱 44 | rdb_options_columns: 黑板欄位 45 | rdb_options_fullscreen: 全螢幕 46 | rdb_legend_priorities: 優先權 47 | rdb_legend_warnings: 警告 48 | rdb_issue_overdue: 過期 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: N/A 51 | rdb_column_done: 完成 52 | rdb_x_issues: 53 | other: "%{count} 問題" 54 | one: "%{count} 問題" 55 | rdb_dialog_update_issue_title: 更新問題 56 | rdb_dialog_update_issue_status: 選擇新問題的狀態 57 | rdb_other_issues: 其他問題 (%{count}) 58 | rdb_unassigned: 未指派 59 | rdb_others: 其他 60 | rdb_all_issues: 所有問題 61 | rdb_no_parent: 沒有父項目 62 | rdb_issue_menu_progress_title: 更新進度 63 | rdb_issue_menu_progress: "%{count}%" 64 | rdb_issue_menu_redmine_issue: Redmine 問題 65 | rdb_issue_menu_show: 顯示 66 | rdb_issue_menu_edit: 編輯 67 | rdb_issue_menu_assign_me: 指派給我 68 | rdb_issue_menu_unassign_me: 解除我的指派 69 | rdb_flash_illegal_workflow_action: "

你不被允許進行這樣的工作流程:

%{issue}%{source} 移動到 %{target}.

" 70 | rdb_flash_missing_lock_version: "

遺失的鎖定版本: 無法更新問題,請重試。" 71 | rdb_flash_stale_object: "

更改已穩定的問題: %{issue}請重試。" 72 | rdb_flash_invalid_request: "

無效的請求

" 73 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_login.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Login form 3 | // -------------------------------------------------- 4 | 5 | #login-form { 6 | box-sizing: border-box; 7 | margin: $line-height-computed * 2 auto $line-height-computed; 8 | 9 | label, 10 | input:not([type="checkbox"]) { 11 | width: 100%; 12 | } 13 | 14 | label { 15 | display: block; 16 | margin-bottom: $padding-base-vertical; 17 | font-weight: $font-weight-bold; 18 | line-height: inherit; 19 | 20 | &[for="autologin"] { 21 | @include check; 22 | margin-bottom: $line-height-computed; 23 | } 24 | 25 | > a { 26 | float: right; 27 | font-weight: $font-weight-normal; 28 | } 29 | } 30 | 31 | input[type="text"], 32 | input[type="password"] { 33 | margin-bottom: $panel-body-padding-vertical; 34 | } 35 | 36 | #login-submit { 37 | padding-top: $padding-base-vertical; 38 | padding-bottom: $padding-base-vertical; 39 | } 40 | 41 | table { 42 | margin: auto; 43 | table-layout: fixed; 44 | } 45 | 46 | td { 47 | padding: 0; 48 | 49 | &:first-child { 50 | width: $login-form-label-width; 51 | padding-right: $table-cell-padding; 52 | white-space: nowrap; 53 | } 54 | 55 | > label { 56 | margin-bottom: $panel-body-padding-vertical; 57 | } 58 | 59 | > input[type="submit"] { 60 | width: auto; 61 | margin-right: 0; 62 | } 63 | } 64 | 65 | @media screen and (min-width: $login-form-box-breakpoint) { 66 | width: $login-form-width; 67 | padding: $padding-side; 68 | border: 1px solid $panel-border; 69 | border-radius: $border-radius-base; 70 | background-color: $panel-bg; 71 | box-shadow: $panel-shadow; 72 | color: $panel-color; 73 | 74 | table { 75 | width: 100%; 76 | } 77 | } 78 | 79 | @each $adjustment, $languages in $login-form-adjustments-map { 80 | @each $language in $languages { 81 | html[lang="#{$language}"] & td:first-child { 82 | width: $login-form-label-width + $adjustment * 1em; 83 | } 84 | } 85 | } 86 | } 87 | 88 | #openid_url { 89 | padding-right: $input-padding-horizontal + 24px; 90 | background-image: url("../../../images/openid-bg.gif"); 91 | background-repeat: no-repeat; 92 | background-position: right $input-padding-horizontal center; 93 | } 94 | 95 | 96 | // 97 | // Two-factor authentication 98 | // -------------------------------------------------- 99 | 100 | .controller-twofa { 101 | .splitcontentleft { 102 | width: auto; 103 | padding-right: 0; 104 | } 105 | } 106 | 107 | ul.twofa_backup_codes { 108 | margin-left: 0; 109 | padding: 0; 110 | list-style-type: none; 111 | } 112 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/ja.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ja: 3 | project_module_dashboard: ダッシュボード 4 | permission_view_dashboards: ダッシュボードを表示 5 | permission_configure_dashboards: ダッシュボードの設定 6 | menu_label_dashboard: ダッシュボード 7 | rdb_taskboard: タスクボード 8 | rdb_planningboard: 計画ボード 9 | rdb_filter_version_all: すべてのバージョン 10 | rdb_filter_version_unassigned: 未割当 11 | rdb_filter_tracker_all: すべてのトラッカー 12 | rdb_filter_tracker_multiple: 複数のトラッカー 13 | rdb_filter_category_all: すべてのカテゴリ 14 | rdb_filter_category_multiple: 複数のカテゴリ 15 | rdb_filter_assignee_all: すべての担当 16 | rdb_filter_assignee_me: 自分 17 | rdb_filter_assignee_none: 未割当 18 | rdb_filter_assignee_others: 自分以外 19 | rdb_options: オプション 20 | rdb_options_change_assignee: 担当者を変更する 21 | rdb_options_change_assignee_info: ステータスを移動する際に担当者が自分に変更されます 22 | rdb_options_hide_done: 完了は表示しない 23 | rdb_options_hide_done_info: ステータスが完了しているチケットは表示しません 24 | rdb_options_reset: フィルタをリセット 25 | rdb_options_reset_info: デフォルトのフィルタにリセットします 26 | rdb_options_configure: 設定 27 | rdb_options_include_subprojects: 子プロジェクトを含めます 28 | rdb_options_view: 表示 29 | rdb_options_issue_view: ボードの表示形式 30 | rdb_options_issue_view_card: カード形式 31 | rdb_options_issue_view_compact: 簡易 32 | rdb_options_group: グルーピング 33 | rdb_group_none: グルーピングなし 34 | rdb_group_category: カテゴリ 35 | rdb_group_assignee: 担当 36 | rdb_group_tracker: トラッカー 37 | rdb_group_priority: 優先度 38 | rdb_group_version: バージョン 39 | rdb_group_parent: 親チケット 40 | rdb_group_project: プロジェクト 41 | rdb_options_board_view: ボードビュー 42 | rdb_options_board_view_compact: クラシック 43 | rdb_options_board_view_outline: アウトライン 44 | rdb_options_columns: ボードに表示するチケットのステータス 45 | rdb_options_fullscreen: 全画面表示 46 | rdb_legend_priorities: 優先度 47 | rdb_legend_warnings: 警告 48 | rdb_issue_overdue: 期日超過 49 | rdb_not_available: 利用不可 50 | rdb_column_done: 完了 51 | rdb_x_issues: 52 | other: "%{count} 件のチケット" 53 | one: "%{count} 件のチケット" 54 | rdb_dialog_update_issue_title: チケットの更新 55 | rdb_dialog_update_issue_status: チケットのステータスを選んでください 56 | rdb_other_issues: 他のチケット (%{count}) 57 | rdb_unassigned: 未割当 58 | rdb_others: その他 59 | rdb_all_issues: すべてのチケット 60 | rdb_no_parent: 親のないチケット 61 | rdb_issue_menu_progress_title: 進捗率の変更 62 | rdb_issue_menu_progress: "%{count}%" 63 | rdb_issue_menu_redmine_issue: チケット 64 | rdb_issue_menu_show: チケットを表示 65 | rdb_issue_menu_edit: チケットの編集 66 | rdb_issue_menu_assign_me: 担当を自分にする 67 | rdb_issue_menu_unassign_me: 担当を未割当にする 68 | rdb_flash_illegal_workflow_action: "

このワークフローアクションを実行することはできません。

%{issue} %{source} から%{target}.

" 69 | rdb_flash_missing_lock_version: "

ロックされたバージョンがありません:もう一度やり直してください" 70 | rdb_flash_stale_object: "

チケットはすでに更新されています: %{issue}. 変更を確認して再度更新してください" 71 | rdb_flash_invalid_request: "

リクエストは無効です

" 72 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_admin.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Admin 3 | // -------------------------------------------------- 4 | 5 | #admin-menu { 6 | ul:nth-child(n) { 7 | li { 8 | list-style-type: none; 9 | 10 | > a:not(.icon-only) { 11 | padding-left: $sidebar-padding-horizontal + 5px + $icon-width; 12 | background-repeat: no-repeat; 13 | background-position: $sidebar-padding-horizontal center; 14 | } 15 | } 16 | } 17 | 18 | #admin-index > & { 19 | ul { 20 | margin: 0; 21 | padding: 0; 22 | } 23 | 24 | li { 25 | padding: ($sidebar-padding-vertical + 1px) ($sidebar-padding-horizontal + 3px); 26 | } 27 | 28 | a { 29 | display: inline-block; 30 | padding-left: 5px + $icon-width; 31 | background-position: 0 center; 32 | } 33 | } 34 | } 35 | 36 | 37 | //== Groups 38 | // 39 | 40 | table.members, 41 | table.memberships { 42 | td.roles { 43 | width: 45%; 44 | } 45 | } 46 | 47 | 48 | //== Permissions 49 | // 50 | 51 | table.permissions { 52 | td.role { 53 | color: $gray-700; 54 | font-weight: $font-weight-normal; 55 | text-align: center; 56 | vertical-align: bottom; 57 | } 58 | } 59 | 60 | 61 | //== Workflows 62 | // 63 | 64 | .controller-workflows { 65 | table.list, 66 | fieldset.collapsible { 67 | margin-bottom: $line-height-computed; 68 | } 69 | } 70 | 71 | table.transitions { 72 | td.enabled { 73 | background: $state-success; 74 | } 75 | } 76 | 77 | #workflow_copy_form select { 78 | width: 200px; 79 | } 80 | 81 | #workflow_form table select { 82 | width: 90%; 83 | min-width: 60px; 84 | } 85 | 86 | table.fields_permissions { 87 | td.readonly { 88 | background: $gray-600; 89 | } 90 | 91 | td.required { 92 | background: $state-danger; 93 | } 94 | } 95 | 96 | 97 | //== Custom fields -> Issues -> Key values 98 | // 99 | 100 | #custom_field_enumerations { 101 | padding-left: 0; 102 | list-style: none; 103 | 104 | li { 105 | min-height: $input-height-base; 106 | padding: 1px 0; 107 | 108 | .sort-handle, 109 | label { 110 | line-height: $input-height-base; 111 | } 112 | 113 | label input { 114 | vertical-align: baseline; 115 | } 116 | } 117 | } 118 | 119 | 120 | //== Settings labels 121 | // 122 | 123 | fieldset.settings label { 124 | display: block; 125 | } 126 | 127 | 128 | //== Settings -> Notifications 129 | // 130 | 131 | fieldset#notified_events { 132 | .parent { 133 | padding-left: 20px; 134 | } 135 | } 136 | 137 | 138 | //== Settings -> Repositories 139 | // 140 | 141 | .settings.enabled_scm { 142 | table { 143 | width: 100%; 144 | } 145 | 146 | td.scm_name { 147 | font-weight: $font-weight-bold; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/javascripts/dashboard.ui.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | 3 | $.fn.rdbMenu = function() { 4 | $(this).rdbFindUp('.rdb-menu'); 5 | } 6 | 7 | $.fn.rdbMenuShow = function() { 8 | $(this).addClass('rdb-menu-active'); 9 | } 10 | 11 | $.fn.rdbMenuHide = function() { 12 | $(this).removeClass('rdb-menu-active'); 13 | } 14 | 15 | /* ===================================================== 16 | ** Dashboard Drop-Down Menus 17 | */ 18 | var lastMenu; 19 | 20 | Rdb.rdbMenuClose = function() { 21 | if(lastMenu != null) { 22 | lastMenu.rdbMenuHide(); 23 | lastMenu = null; 24 | } 25 | } 26 | 27 | $(document).click(function(e) { 28 | var link = $(e.target).rdbFindUp('a.rdb-menu-link'); 29 | if(link.rdbAny() && link.parents('.rdb-menu-container').rdbEmpty() ) { 30 | e.preventDefault(); 31 | var menu = link.parents('.rdb-menu').first(); 32 | if(menu.rdbAny()) { 33 | if(menu.is(lastMenu)) { 34 | lastMenu.rdbMenuHide(); 35 | lastMenu = null; 36 | } else { 37 | if(lastMenu) lastMenu.rdbMenuHide(); 38 | lastMenu = menu; 39 | lastMenu.rdbMenuShow(); 40 | } 41 | } 42 | } 43 | 44 | if(lastMenu != null && $(e.target).rdbFindUp('.rdb-menu').length == 0) { 45 | lastMenu.rdbMenuHide(); 46 | lastMenu = null; 47 | } 48 | }); 49 | 50 | /* ===================================================== 51 | ** Dashboard Dialog 52 | */ 53 | 54 | $.fn.rdbDialog = function(title, html) { 55 | var dialog = $('
').html(html).dialog({ 56 | title: title, 57 | modal: true, 58 | draggable: false, 59 | resizable: false, 60 | dialogClass: 'alert', 61 | close: function() { Rdb.rdbDADShowIssue(); } 62 | }); 63 | }; 64 | 65 | Rdb.rdbCloseDialog = function() { 66 | $('.rdb-dialog').remove(); 67 | }; 68 | 69 | /* ===================================================== 70 | ** Dashboard Fullscreen 71 | */ 72 | 73 | Rdb.rdbIsFullscreen = function() { 74 | return Rdb.rdbStorageHas('fullscreen', 'fullscreen'); 75 | }; 76 | 77 | Rdb.rdbLoadFullscreen = function() { 78 | if(Rdb.rdbIsFullscreen()) { 79 | Rdb.rdbShowFullscreen(); 80 | } else { 81 | Rdb.rdbHideFullscreen(); 82 | } 83 | }; 84 | 85 | Rdb.rdbToggleFullscreen = function() { 86 | Rdb.rdbMenuClose(); 87 | if(Rdb.rdbIsFullscreen()) { 88 | Rdb.rdbHideFullscreen(); 89 | } else { 90 | Rdb.rdbShowFullscreen(); 91 | } 92 | }; 93 | 94 | Rdb.rdbShowFullscreen = function() { 95 | Rdb.rdbStorageAdd('fullscreen', 'fullscreen'); 96 | Rdb.rdbBase().addClass('rdb-fullscreen'); 97 | }; 98 | 99 | Rdb.rdbHideFullscreen = function() { 100 | Rdb.rdbStorageRemove('fullscreen', 'fullscreen'); 101 | Rdb.rdbBase().removeClass('rdb-fullscreen'); 102 | }; 103 | 104 | Rdb.rdbInit(Rdb.rdbLoadFullscreen); 105 | 106 | })(jQuery); 107 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/javascripts/modules/HistoryTabs.js: -------------------------------------------------------------------------------- 1 | var PurpleMine = PurpleMine || {} // eslint-disable-line no-use-before-define 2 | 3 | PurpleMine.HistoryTabs = (function () { 4 | 'use strict' 5 | 6 | var instance 7 | var translations = { 8 | en: { 9 | all: 'All', 10 | notes: 'Notes', 11 | details: 'Changes' 12 | }, 13 | ro: { 14 | all: 'Toate', 15 | notes: 'Note', 16 | details: 'Schimbări' 17 | }, 18 | fr: { 19 | all: 'Tout', 20 | notes: 'Remarques', 21 | details: 'Changements' 22 | }, 23 | pl: { 24 | all: 'Wszystko', 25 | notes: 'Notatki', 26 | details: 'Zmiany' 27 | }, 28 | de: { 29 | all: 'Alles', 30 | notes: 'Kommentare', 31 | details: 'Änderungen' 32 | }, 33 | ja: { 34 | all: 'すべて', 35 | notes: '注記', 36 | details: '変更' 37 | } 38 | } 39 | 40 | function HistoryTabs () { 41 | if (instance) { 42 | return instance 43 | } 44 | 45 | instance = this 46 | 47 | this.$tabsContainer = null 48 | this.$tabs = null 49 | this.$history = $('#history') 50 | this.lang = document.documentElement.lang 51 | 52 | if (typeof translations[this.lang] === 'undefined') { 53 | this.lang = 'en' 54 | } 55 | 56 | this._ = translations[this.lang] 57 | 58 | if (this.$history.length > 0 && $('#history > h3').length > 0) { 59 | buildTabs() 60 | markFirstOfTypes() 61 | } 62 | } 63 | 64 | function buildTabs () { 65 | var html = '' 66 | var liStart = '
    • ' 71 | html += liStart + 'selected ' + liMid + 'all">' + instance._.all + liEnd 72 | html += liStart + liMid + 'notes">' + instance._.notes + liEnd 73 | html += liStart + liMid + 'details">' + instance._.details + liEnd 74 | html += '
  • ' 75 | 76 | instance.$tabsContainer = $(html) 77 | $('#history > h3').after(instance.$tabsContainer) 78 | 79 | instance.$tabs = instance.$tabsContainer.find('.history-tab') 80 | instance.$tabs.on('click', tabClick) 81 | } 82 | 83 | function markFirstOfTypes () { 84 | instance.$history.find('.has-notes:first').addClass('first-of-notes') 85 | instance.$history.find('.has-details:first').addClass('first-of-details') 86 | } 87 | 88 | var tabClick = function () { 89 | var $this = $(this) 90 | var tab = $this.attr('data-tab') 91 | 92 | instance.$tabs.removeClass('selected') 93 | $this.addClass('selected') 94 | 95 | instance.$history 96 | .removeClass('hide-details') 97 | .removeClass('hide-notes') 98 | 99 | if (tab === 'notes') { 100 | instance.$history.addClass('hide-details') 101 | } else if (tab === 'details') { 102 | instance.$history.addClass('hide-notes') 103 | } 104 | } 105 | 106 | return HistoryTabs 107 | }()) 108 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_simple-list.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Activity and search results list 3 | // -------------------------------------------------- 4 | 5 | #activity dl, 6 | #search-results { 7 | margin-left: $padding-side; 8 | } 9 | 10 | #activity, 11 | #search-results { 12 | dd { 13 | margin-bottom: $line-height-computed; 14 | padding-top: .1em; 15 | } 16 | 17 | dt { 18 | padding-left: $padding-side; 19 | background-repeat: no-repeat; 20 | background-position: 0 center; 21 | } 22 | 23 | span.project::after { 24 | content: " -"; 25 | } 26 | 27 | span.description { 28 | display: block; 29 | color: $gray-700; 30 | font-style: italic; 31 | } 32 | } 33 | 34 | #activity { 35 | $activity-avatar: 24px; 36 | $activity-avatar-space: 5px; 37 | $activity-indent: 20px; 38 | 39 | @if $use-gravatars { 40 | $activity-indent: $activity-indent + $activity-avatar + $activity-avatar-space; 41 | } 42 | 43 | h3, 44 | h4 { 45 | margin: 0 0 $line-height-computed; 46 | padding-bottom: .2em; 47 | border-bottom: 1px dotted $gray-600; 48 | font-size: $font-size-h4; 49 | font-weight: $font-weight-normal; 50 | } 51 | 52 | dt { 53 | &.grouped { 54 | margin-left: $activity-indent; 55 | } 56 | 57 | &.me .time { 58 | border-bottom: 1px solid $gray-400; 59 | } 60 | 61 | .time { 62 | color: $gray-700; 63 | } 64 | 65 | @if $use-gravatars { 66 | .gravatar { 67 | top: 0; 68 | margin-top: -2px; 69 | margin-right: $activity-avatar-space; 70 | float: left; 71 | } 72 | } 73 | } 74 | 75 | dd { 76 | overflow: hidden; 77 | font-size: $font-size-small; 78 | 79 | &.grouped { 80 | margin-left: $activity-indent; 81 | } 82 | } 83 | } 84 | 85 | #search-results-counts { 86 | float: right; 87 | 88 | ul { 89 | @extend %clearfix; 90 | } 91 | 92 | li { 93 | margin-left: 1em; 94 | float: left; 95 | list-style-type: none; 96 | } 97 | } 98 | 99 | 100 | // Search form 101 | 102 | #search-form { 103 | margin-bottom: $line-height-computed; 104 | 105 | input, 106 | select { 107 | margin-right: 5px; 108 | margin-bottom: $line-height-computed * .5; 109 | } 110 | 111 | label { 112 | @include check-inline; 113 | line-height: $input-height-base; 114 | 115 | input[type="checkbox"], 116 | input[type="radio"] { 117 | margin-top: $check-input-margin-btn-v; 118 | } 119 | } 120 | 121 | p:last-child { 122 | margin-bottom: 0; 123 | } 124 | } 125 | 126 | 127 | // Search results highlight 128 | 129 | .highlight { 130 | background-color: saturate(shade($yellow, 100), 25%); 131 | color: saturate(shade($yellow, 800), 25%); 132 | 133 | &.token-1 { 134 | background-color: saturate(shade($red, 100), 25%); 135 | color: saturate(shade($red, 800), 25%); 136 | } 137 | 138 | &.token-2 { 139 | background-color: saturate(shade($green, 100), 25%); 140 | color: saturate(shade($green, 800), 25%); 141 | } 142 | 143 | &.token-3 { 144 | background-color: saturate(shade($blue, 100), 25%); 145 | color: saturate(shade($blue, 800), 25%); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | --- 2 | en: 3 | project_module_dashboard: Dashboard 4 | permission_view_dashboards: View Dashboards 5 | permission_configure_dashboards: Configure Dashboards 6 | menu_label_dashboard: Dashboard 7 | rdb_taskboard: Task Board 8 | rdb_planningboard: Planning Board 9 | rdb_filter_version_all: All Versions 10 | rdb_filter_version_unassigned: Unassigned 11 | rdb_filter_tracker_all: All Trackers 12 | rdb_filter_tracker_multiple: Multiple Trackers 13 | rdb_filter_category_all: All Categories 14 | rdb_filter_category_multiple: Multiple Categories 15 | rdb_filter_assignee_all: All Assignees 16 | rdb_filter_assignee_me: My Issues 17 | rdb_filter_assignee_none: Unassigned 18 | rdb_filter_assignee_others: Others 19 | rdb_options: Options 20 | rdb_options_change_assignee: Change assignee 21 | rdb_options_change_assignee_info: Change assignee to current user when issue is moved. 22 | rdb_options_hide_done: Hide closed issues 23 | rdb_options_hide_done_info: Hide closed issues and makes done column smaller. 24 | rdb_options_reset: Reset filter 25 | rdb_options_reset_info: Reset all filters back to default 26 | rdb_options_configure: Configure 27 | rdb_options_include_subprojects: Include subprojects 28 | rdb_options_view: View 29 | rdb_options_issue_view: Issue View 30 | rdb_options_issue_view_card: Card 31 | rdb_options_issue_view_compact: Compact 32 | rdb_options_group: Issue Grouping 33 | rdb_group_none: No Grouping 34 | rdb_group_category: Category 35 | rdb_group_assignee: Assignee 36 | rdb_group_tracker: Tracker 37 | rdb_group_priority: Priority 38 | rdb_group_version: Version 39 | rdb_group_parent: Parent Task 40 | rdb_group_project: Project 41 | rdb_options_board_view: Board View 42 | rdb_options_board_view_compact: Classic 43 | rdb_options_board_view_outline: Outline 44 | rdb_options_columns: Board Columns 45 | rdb_options_fullscreen: Full Screen 46 | rdb_legend_priorities: Priorities 47 | rdb_legend_warnings: Warnings 48 | rdb_issue_overdue: Overdue 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: N/A 51 | rdb_column_done: Done 52 | rdb_x_issues: 53 | one: 1 Issue 54 | other: "%{count} Issues" 55 | rdb_dialog_update_issue_title: Update Issue 56 | rdb_dialog_update_issue_status: Choose new issue status 57 | rdb_other_issues: Other Issues (%{count}) 58 | rdb_unassigned: Unassigned 59 | rdb_others: Others 60 | rdb_all_issues: All Issues 61 | rdb_no_parent: No parent tasks 62 | rdb_issue_menu_progress_title: Update progress 63 | rdb_issue_menu_progress: "%{count}%" 64 | rdb_issue_menu_redmine_issue: Redmine Issue 65 | rdb_issue_menu_show: Show 66 | rdb_issue_menu_edit: Edit 67 | rdb_issue_menu_assign_me: Assign me 68 | rdb_issue_menu_unassign_me: Unassign me 69 | rdb_flash_illegal_workflow_action: "

    You are not allowed to perform this workflow action:

    Move %{issue} from %{source} to %{target}.

    " 70 | rdb_flash_missing_lock_version: "

    Missing lock version: Cannot update issue without lock version. Try again." 71 | rdb_flash_stale_object: "

    Attempted to update a stale issue: %{issue}. Check changes and try again." 72 | rdb_flash_invalid_request: "

    Invalid request.

    " 73 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/README.md: -------------------------------------------------------------------------------- 1 | # Redmine Dashboard 2 2 | 3 | [![Last release](https://img.shields.io/github/v/release/jgraichen/redmine_dashboard?label=latest%20release&logo=github&style=flat-square)](https://github.com/jgraichen/redmine_dashboard/releases/latest) 4 | [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/jgraichen/redmine_dashboard/test.yml?branch=main&logo=github&style=flat-square)](https://github.com/jgraichen/redmine_dashboard/actions) 5 | [![Rate at redmine.org](http://img.shields.io/badge/rate%20at-redmine.org-blue.svg?style=flat-square)](http://www.redmine.org/plugins/redmine-dashboard) 6 | [![Follow at Twitter](http://img.shields.io/badge/follow%20at-twitter-blue.svg?style=flat-square)](https://twitter.com/RmDashboard) 7 | 8 | This [Redmine](http://redmine.org) plugin adds an issue dashboard that supports drag and drop for issues and various filters. 9 | 10 | **Redmine Dashboard 2** is compatible and tested with Redmine 5.0, 4.2, and Ruby 3.1, 3.0, and 2.7. 11 | 12 | ![Redmine Dashboard v2.x Screenshot](docs/rdb_2-1.png) 13 | 14 | ## Features List 15 | 16 | * Drag-n-drop of issues 17 | * Configurable columns 18 | * Grouping & Filtering 19 | * Group folding 20 | * Hierarchical parent issue view 21 | * Include subproject issues 22 | * Quick edit of assignee and progress 23 | 24 | Rate plugin at [redmine.org](http://www.redmine.org/plugins/redmine-dashboard). 25 | 26 | ## Questions? Stories? 27 | 28 | Please ask your questions, or tell us your stories or experience on [GitHub Discussions](https://github.com/jgraichen/redmine_dashboard/discussions). 29 | 30 | ## Install 31 | 32 | 1. Download the [latest release](https://github.com/jgraichen/redmine_dashboard/releases). 33 | 2. Extract archive to `/plugins`. Make **sure** the plugin directory is called `/plugins/redmine_dashboard/` ([#11](https://github.com/jgraichen/redmine_dashboard/issues/11)). 34 | 3. Install required dependencies by running `bundle install --without development test` in your Redmine directory. **Note**: Bitnami and other appliance are not officially supported and may need additional option e.g. `--path vendor/bundle` ([#58](https://github.com/jgraichen/redmine_dashboard/issues/58)). 35 | 4. A database migration is not needed. Restart Redmine. 36 | 37 | ### Configure Redmine 38 | 39 | 1. Add the dashboard module to your project (`Settings > Modules`). 40 | 2. Configure dashboard permissions to your user roles (`Administration > Roles and permissions`). Users won't see a Dashboard tab without having the `View Dashboard` permission. 41 | 42 | ### Upgrade 43 | 44 | 1. Remove old plugin directory. 45 | 2. Follow installation steps for new release. 46 | 47 | ## Contribute 48 | 49 | I appreciate any help and like Pull Requests. The `main` branch is the current stable branch for v2. The next version, Redmine Dashboard 3, a complete rewrite had been under development on the `develop` branch. Due to limited available time the project is in maintenance only mode but open to new contributors. 50 | 51 | I gladly accept new translations or language additions for any version of Redmine Dashboard. I would prefer new translations via [Transifex](https://www.transifex.com/projects/p/redmine-dashboard/) but you can also send a Pull Request. Feel free to request new languages or to join the team directly on Transifex. 52 | 53 | ## License 54 | 55 | Redmine dashboard is licensed under the Apache License, Version 2.0. 56 | See LICENSE for more information. 57 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/helpers/rdb_dashboard_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module RdbDashboardHelper 4 | def render_rdb_menu(id, title, options = {}, &container) 5 | options[:class] ||= '' 6 | options[:class] += ' rdb-menu-right' if options[:right] 7 | options[:class] += ' rdb-small' if options[:small] 8 | 9 | slim_tag :div, class: "rdb-menu rdb-menu-#{id} #{options[:class]}" do 10 | if options[:anchor] 11 | link = options[:anchor].call.to_s.html_safe 12 | else 13 | link = link_to(title, '#', class: 'rdb-menu-link') 14 | end 15 | 16 | if options[:header] && %i[h1 h2 h3 h4 h5].include?(options[:header].to_sym) 17 | slim_tag(options[:header], link) 18 | else 19 | concat link 20 | end 21 | 22 | slim_tag :div, class: "rdb-container #{options[:right] ? 'rdb-container-right' : ''}" do 23 | slim_tag :div, class: "rdb-container-wrapper #{options[:icons] ? 'rdb-icons' : ''}" do 24 | if options[:inlet] 25 | slim_tag(:div, class: 'rdb-container-inlet', &container) 26 | else 27 | yield 28 | end 29 | end 30 | end 31 | end 32 | end 33 | 34 | def render_rdb_menu_list(items = nil, options = {}) 35 | if items.is_a?(Hash) 36 | options = items 37 | items = nil 38 | end 39 | 40 | slim_tag :div, class: "rdb-list #{options[:async] ? 'rdb-async' : ''} #{options[:class]}" do 41 | slim_tag :h3, options[:title] if options[:title] 42 | slim_tag options[:list_tag] || :ul, class: options[:list_class] do 43 | if items 44 | items.each do |item| 45 | slim_tag :li do 46 | yield item 47 | end 48 | end 49 | else 50 | yield 51 | end 52 | end 53 | end 54 | end 55 | 56 | def render_rdb_menu_list_item(options = {}, &block) 57 | slim_tag(:li, class: options[:async] ? 'rdb-async' : '', &block) 58 | end 59 | 60 | def rdb_checkbox_link_to(*args) 61 | options = args.extract_options! 62 | options[:class] ||= '' 63 | options[:class] += ' rdb-checkbox-link' 64 | options[:class] += ' rdb-checkbox-link-enabled' if options[:enabled] 65 | options[:class] += ' rdb-checkbox-link-disabled' if !options[:enabled] && options[:show_disabled] 66 | options[:class].strip! 67 | 68 | options.delete :enabled 69 | options.delete :show_disabled 70 | 71 | args << options 72 | 73 | link_to(*args) 74 | end 75 | 76 | def rdb_update_path(issue, options = {}) 77 | send(:"rdb_#{@board.id}_update_path", { 78 | issue: issue.id, 79 | lock_version: issue.lock_version 80 | }.merge(options),) 81 | end 82 | 83 | def rdb_move_path(issue, options = {}) 84 | send(:"rdb_#{@board.id}_move_path", { 85 | issue: issue.id, 86 | lock_version: issue.lock_version 87 | }.merge(options),) 88 | end 89 | 90 | def rdb_filter_path(options = {}) 91 | send(:"rdb_#{@board.id}_filter_path", options) 92 | end 93 | 94 | def rdb_board_path(options = {}) 95 | send(:"rdb_#{@board.id}_path", options) 96 | end 97 | 98 | private 99 | 100 | def slim_tag(name, content = nil, **attrs) 101 | concat tag(name, attrs, true, true) 102 | concat(content) if content.present? 103 | yield if block_given? 104 | concat "".html_safe 105 | end 106 | end 107 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/tr.yml: -------------------------------------------------------------------------------- 1 | --- 2 | tr: 3 | project_module_dashboard: Gösterge Paneli 4 | permission_view_dashboards: Gösterge Panelini Görüntüle 5 | permission_configure_dashboards: Gösterge Panelini Yapılandır 6 | menu_label_dashboard: Gösterge Paneli 7 | rdb_taskboard: Görev Panosu 8 | rdb_planningboard: Planlama Panosu 9 | rdb_filter_version_all: Tüm Uyarlamalar 10 | rdb_filter_version_unassigned: Atanmamış 11 | rdb_filter_tracker_all: Tüm Takipçiler 12 | rdb_filter_tracker_multiple: Çoklu Takipçiler 13 | rdb_filter_category_all: Tüm Kategoriler 14 | rdb_filter_category_multiple: Çoklu Kategoriler 15 | rdb_filter_assignee_all: Tüm Atananlar 16 | rdb_filter_assignee_me: Taleplerim 17 | rdb_filter_assignee_none: Atanmamışlar 18 | rdb_filter_assignee_others: Diğerleri 19 | rdb_options: Seçenekler 20 | rdb_options_change_assignee: Atananı Değiştir 21 | rdb_options_change_assignee_info: Talep taşındığında atananı mevcut kullanıcıyla değiştirin. 22 | rdb_options_hide_done: Kapalı talepleri gizle 23 | rdb_options_hide_done_info: Kapalı talepleri gizler ve yapılan sütununu ufaltır. 24 | rdb_options_reset: Süzgeçi sıfırla 25 | rdb_options_reset_info: Tüm süzgeçleri geri varsayılana sıfırla 26 | rdb_options_configure: Yapılandır 27 | rdb_options_include_subprojects: Alt projeleri dahil et 28 | rdb_options_view: Göster 29 | rdb_options_issue_view: Talep Görünümü 30 | rdb_options_issue_view_card: Kart 31 | rdb_options_issue_view_compact: Derli toplu 32 | rdb_options_group: Talep Gruplama 33 | rdb_group_none: Gruplama Yok 34 | rdb_group_category: Kategori 35 | rdb_group_assignee: Atanan 36 | rdb_group_tracker: Takipçi 37 | rdb_group_priority: Öncelik 38 | rdb_group_version: Uyarlama 39 | rdb_group_parent: Üst Görev 40 | rdb_group_project: Proje 41 | rdb_options_board_view: Pano Görünüü 42 | rdb_options_board_view_compact: Klasik 43 | rdb_options_board_view_outline: Anahat 44 | rdb_options_columns: Pano Sütunları 45 | rdb_options_fullscreen: Tam Ekran 46 | rdb_legend_priorities: Öncelikler 47 | rdb_legend_warnings: Uyarılar 48 | rdb_issue_overdue: Vadesi geçmiş 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: N/A 51 | rdb_column_done: Tamam 52 | rdb_x_issues: 53 | one: 1 İş 54 | other: "%{count}Talepler" 55 | rdb_dialog_update_issue_title: Talebi Güncelle 56 | rdb_dialog_update_issue_status: Yeni talep durumunu seçin 57 | rdb_other_issues: Diğer Talepler (%{count}) 58 | rdb_unassigned: Atanmamış 59 | rdb_others: Diğerleri 60 | rdb_all_issues: Tüm Talepler 61 | rdb_no_parent: Üst görev yok 62 | rdb_issue_menu_progress_title: İlerlemeleri güncelle 63 | rdb_issue_menu_progress: "%{count}%" 64 | rdb_issue_menu_redmine_issue: Redmine Talep 65 | rdb_issue_menu_show: Göster 66 | rdb_issue_menu_edit: Düzenle 67 | rdb_issue_menu_assign_me: Bana Ata 68 | rdb_issue_menu_unassign_me: Atamamı kaldır 69 | rdb_flash_illegal_workflow_action: "

    Bu İş akışı eylemini gerçekleştirme izniniz yok:

    Taşı %{issue} durumundan %{source} %{target} durumuna.

    " 70 | rdb_flash_missing_lock_version: "

    Kilit uyarlaması eksik: Kilit uyarlaması olmadan talep güncellenemez. Tekrar deneyin." 71 | rdb_flash_stale_object: "

    Bayat bir talebi güncelleme girişimi: %{issue}. Değişiklikleri denetleyin ve tekrar deneyin." 72 | rdb_flash_invalid_request: "

    Geçersiz istem.

    " 73 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/mn.yml: -------------------------------------------------------------------------------- 1 | --- 2 | mn: 3 | project_module_dashboard: Хянах самбар 4 | permission_view_dashboards: Хянах самбар харах 5 | permission_configure_dashboards: Хянах самбар тохируулах 6 | menu_label_dashboard: Хянах самбар 7 | rdb_taskboard: Ажлын самбар 8 | rdb_planningboard: Төлөвлөгөөний самбар 9 | rdb_filter_version_all: Бүх хувилбар 10 | rdb_filter_version_unassigned: Хуваарилагдаагүй 11 | rdb_filter_tracker_all: Бүх трэкер 12 | rdb_filter_tracker_multiple: Хэд хэдэн трэкер 13 | rdb_filter_category_all: Бүх ангилал 14 | rdb_filter_category_multiple: Хэд хэдэн ангилал 15 | rdb_filter_assignee_all: Бүх хариуцагч 16 | rdb_filter_assignee_me: Миний ажлууд 17 | rdb_filter_assignee_none: Хуваарилагдаагүй 18 | rdb_filter_assignee_others: Бусад 19 | rdb_options: Нэмэлт тохируулга 20 | rdb_options_change_assignee: Хариуцагчийг солих 21 | rdb_options_change_assignee_info: Асуудлыг зөөхөд хариуцагчийг одоогийн хэрэглэгчээр солих 22 | rdb_options_hide_done: Хаагдсан асуудлуудыг нуух 23 | rdb_options_hide_done_info: Хаагдсан асуудлуудыг нууж гүйцэтгэлийн баганыг нарийсгах 24 | rdb_options_reset: Шүүлтийг арилгах 25 | rdb_options_reset_info: Бүх шүүлтийг анхны төлөвт оруулах 26 | rdb_options_configure: Тохируулах 27 | rdb_options_include_subprojects: Бүх дэд төслийг оруулах 28 | rdb_options_view: Харах 29 | rdb_options_issue_view: Асуудлыг харах 30 | rdb_options_issue_view_card: Карт 31 | rdb_options_issue_view_compact: Цомхон 32 | rdb_options_group: Асуудлыг бүлэглэх 33 | rdb_group_none: Бүлэглэхгүй 34 | rdb_group_category: Ангилал 35 | rdb_group_assignee: Хариуцагч 36 | rdb_group_tracker: Трэкер 37 | rdb_group_priority: Зэрэглэл 38 | rdb_group_version: Хувилбар 39 | rdb_group_parent: Эх ажил 40 | rdb_group_project: Төсөл 41 | rdb_options_board_view: Самбар харах 42 | rdb_options_board_view_compact: Сонгодог 43 | rdb_options_board_view_outline: Тойм 44 | rdb_options_columns: Самбарын баганууд 45 | rdb_options_fullscreen: Бүтэн дэлгэцээр 46 | rdb_legend_priorities: Зэрэглэлүүд 47 | rdb_legend_warnings: Анхааруулга 48 | rdb_issue_overdue: Хугацаа хэтэрсэн 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: Хамааралгүй 51 | rdb_column_done: Гүйцэтгэл 52 | rdb_x_issues: 53 | one: 1 асуудал 54 | other: "%{count} асуудал" 55 | rdb_dialog_update_issue_title: Асуудлыг шинэчлэх 56 | rdb_dialog_update_issue_status: Шинэ асуудлын төлөвийг сонго 57 | rdb_other_issues: Бусад асуудлууд (%{count}) 58 | rdb_unassigned: Хуваарилагдаагүй 59 | rdb_others: Бусад 60 | rdb_all_issues: Бүх асуудлууд 61 | rdb_no_parent: Эх ажил алга 62 | rdb_issue_menu_progress_title: Явц шинэчлэх 63 | rdb_issue_menu_progress: "%{count}%" 64 | rdb_issue_menu_redmine_issue: Redmine Issue 65 | rdb_issue_menu_show: Харуулах 66 | rdb_issue_menu_edit: Засварлах 67 | rdb_issue_menu_assign_me: Надад хариуцуул 68 | rdb_issue_menu_unassign_me: Хариуцагчаас намайг хас 69 | rdb_flash_illegal_workflow_action: "

    Танд энэ үйлдлийг хийх эрх алга:

    %{issue}%{source}%{target} уруу зөөх.

    " 70 | rdb_flash_missing_lock_version: "

    Түгжих хувилбар алга: Түгжих хувилбаргүйгээр асуудлыг шинэчилж чадахгүй. Дахин оролд." 71 | rdb_flash_stale_object: "

    Хоосон асуудлыг шинэчлэх гэж оролдсон байна: %{issue}. Өөрчлөлтөө шалгаад дахин оролд." 72 | rdb_flash_invalid_request: "

    Хүсэлт буруу.

    " 73 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/ru.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ru: 3 | project_module_dashboard: Панель задач 4 | permission_view_dashboards: Просмотр Панели 5 | permission_configure_dashboards: Управление панелями 6 | menu_label_dashboard: Панель задач 7 | rdb_taskboard: Панель задач 8 | rdb_planningboard: Доска планирования 9 | rdb_filter_version_all: Все версии 10 | rdb_filter_version_unassigned: Неназначенные 11 | rdb_filter_tracker_all: Все трекеры 12 | rdb_filter_tracker_multiple: Множественные трекеры 13 | rdb_filter_category_all: Все категории 14 | rdb_filter_category_multiple: Множественные категории 15 | rdb_filter_assignee_all: Все ответственные 16 | rdb_filter_assignee_me: Мои задачи 17 | rdb_filter_assignee_none: Не назначены 18 | rdb_filter_assignee_others: Другие 19 | rdb_options: Настройки 20 | rdb_options_change_assignee: Изменить назначение 21 | rdb_options_change_assignee_info: Назначать задачу текущему пользователю при перемещении 22 | rdb_options_hide_done: Скрыть закрытые задачи 23 | rdb_options_hide_done_info: Скрыть закрытые задачи и сделать колонку 'Выполнено' меньше 24 | rdb_options_reset: Очистить фильтр 25 | rdb_options_reset_info: Сбросить все фильтры по-умолчанию 26 | rdb_options_configure: Настроить 27 | rdb_options_include_subprojects: Включить под-проекты 28 | rdb_options_view: Вид 29 | rdb_options_issue_view: Вид задач 30 | rdb_options_issue_view_card: Карточки 31 | rdb_options_issue_view_compact: Компактный 32 | rdb_options_group: Группировка задач 33 | rdb_group_none: Без группировки 34 | rdb_group_category: Категория 35 | rdb_group_assignee: Назначена 36 | rdb_group_tracker: Трекер 37 | rdb_group_priority: Приоритет 38 | rdb_group_version: Версия 39 | rdb_group_parent: Основная задача 40 | rdb_group_project: Проект 41 | rdb_options_board_view: Вид панели 42 | rdb_options_board_view_compact: Классический 43 | rdb_options_board_view_outline: Контур 44 | rdb_options_columns: Колонки панели 45 | rdb_options_fullscreen: Полный экран 46 | rdb_legend_priorities: Приоритеты 47 | rdb_legend_warnings: Предупреждения 48 | rdb_issue_overdue: Изменить дату 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: Нет 51 | rdb_column_done: Выполнено 52 | rdb_x_issues: 53 | one: 1 задача 54 | few: "%{count} задачи" 55 | many: "%{count} задач" 56 | other: "%{count} задач" 57 | rdb_dialog_update_issue_title: Обновить задачу 58 | rdb_dialog_update_issue_status: Выбрать новый статус задачи 59 | rdb_other_issues: Другие задачи (%{count}) 60 | rdb_unassigned: Неназначенные 61 | rdb_others: Другие 62 | rdb_all_issues: Все задачи 63 | rdb_no_parent: Нет основной задачи 64 | rdb_issue_menu_progress_title: Обновить готовность 65 | rdb_issue_menu_progress: "%{count}%" 66 | rdb_issue_menu_redmine_issue: Задача 67 | rdb_issue_menu_show: Просмотр 68 | rdb_issue_menu_edit: Изменить 69 | rdb_issue_menu_assign_me: Назначить мне 70 | rdb_issue_menu_unassign_me: Снять назначение 71 | rdb_flash_illegal_workflow_action: "

    У вас не достаточно прав для выполенния действия:

    Переместить %{issue} из %{source} в %{target}.

    " 72 | rdb_flash_missing_lock_version: "

    Не задана версия: Невозможно обновить задачу без определенной версии. Попробуйте позже." 73 | rdb_flash_stale_object: "

    Задача устарела: %{issue}. Проверьте изменения и попробуйте снова." 74 | rdb_flash_invalid_request: "

    Неверный запрос.

    " 75 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/es.yml: -------------------------------------------------------------------------------- 1 | --- 2 | es: 3 | project_module_dashboard: Tablero 4 | permission_view_dashboards: Ver tableros 5 | permission_configure_dashboards: Configurar tableros 6 | menu_label_dashboard: Tablero 7 | rdb_taskboard: Tareas 8 | rdb_planningboard: Planificación 9 | rdb_filter_version_all: Todas las versiones 10 | rdb_filter_version_unassigned: Sin asignar 11 | rdb_filter_tracker_all: Todos los rastreadores 12 | rdb_filter_tracker_multiple: Varios rastreadores 13 | rdb_filter_category_all: Todas las categorías 14 | rdb_filter_category_multiple: Múltiples categorías 15 | rdb_filter_assignee_all: Todas las asignadas 16 | rdb_filter_assignee_me: Mis tareas 17 | rdb_filter_assignee_none: Sin asignar 18 | rdb_filter_assignee_others: Otros 19 | rdb_options: Opciones 20 | rdb_options_change_assignee: Cambiar asignación 21 | rdb_options_change_assignee_info: Cambiar asignación al usuario actual cuando la tarea se mueva 22 | rdb_options_hide_done: Ocultar tareas cerradas 23 | rdb_options_hide_done_info: Oculta tareas cerradas y disminuye la columna "hecho" 24 | rdb_options_reset: Restablecer filtro 25 | rdb_options_reset_info: Restablecer todos los filtros 26 | rdb_options_configure: Configurar 27 | rdb_options_include_subprojects: Incluir proyectos hijo 28 | rdb_options_view: Ver 29 | rdb_options_issue_view: Vista de tarea 30 | rdb_options_issue_view_card: Tarjeta 31 | rdb_options_issue_view_compact: Compacta 32 | rdb_options_group: Agrupación de tareas 33 | rdb_group_none: Sin agrupar 34 | rdb_group_category: Categoría 35 | rdb_group_assignee: Asignación 36 | rdb_group_tracker: Rastreador 37 | rdb_group_priority: Prioridad 38 | rdb_group_version: Versión 39 | rdb_group_parent: Tarea padre 40 | rdb_group_project: Proyecto 41 | rdb_options_board_view: Vista de tablero 42 | rdb_options_board_view_compact: Clásico 43 | rdb_options_board_view_outline: Esquema 44 | rdb_options_columns: Columnas de tablero 45 | rdb_options_fullscreen: Pantalla completa 46 | rdb_legend_priorities: Prioridades 47 | rdb_legend_warnings: Advertencias 48 | rdb_issue_overdue: Atrasado 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: N/D 51 | rdb_column_done: Hecho 52 | rdb_x_issues: 53 | one: 1 Tarea 54 | many: "%{count} Tareas" 55 | other: "%{count} Tareas" 56 | rdb_dialog_update_issue_title: Actualizar tarea 57 | rdb_dialog_update_issue_status: Escoger nuevo estado de la tarea 58 | rdb_other_issues: Otras tareas (%{count}) 59 | rdb_unassigned: Sin asignar 60 | rdb_others: Otros 61 | rdb_all_issues: Todas las tareas 62 | rdb_no_parent: Sin tareas padre 63 | rdb_issue_menu_progress_title: Progreso de actualización 64 | rdb_issue_menu_progress: "%{count}%" 65 | rdb_issue_menu_redmine_issue: Tarea de Redmine 66 | rdb_issue_menu_show: Ver 67 | rdb_issue_menu_edit: Editar 68 | rdb_issue_menu_assign_me: Asignar a mi 69 | rdb_issue_menu_unassign_me: Desasignar 70 | rdb_flash_illegal_workflow_action: "

    No tienes permiso para realizar la siguiente acción:

    Mover %{issue} de %{source} a %{target}.

    " 71 | rdb_flash_missing_lock_version: "

    Bloqueo de la versión no encontrado: No puedes actualizar la tarea sin bloquear la versión. Inténtalo de nuevo" 72 | rdb_flash_stale_object: "

    Se ha intentado actualizar un tarea antigua: %{issue}. Comprueba los cambios e inténtalo de nuevo." 73 | rdb_flash_invalid_request: "

    Solicitud no válida.

    " 74 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/uk.yml: -------------------------------------------------------------------------------- 1 | --- 2 | uk: 3 | project_module_dashboard: Дошка завдань 4 | permission_view_dashboards: Перегляд 5 | permission_configure_dashboards: Керування 6 | menu_label_dashboard: Дошка завдань 7 | rdb_taskboard: Дошка завдань 8 | rdb_planningboard: Дошка планування 9 | rdb_filter_version_all: Всі версії 10 | rdb_filter_version_unassigned: Без версії 11 | rdb_filter_tracker_all: Всі координатори 12 | rdb_filter_tracker_multiple: Декілька координаторів 13 | rdb_filter_category_all: Всі категорії 14 | rdb_filter_category_multiple: Декілька категорій 15 | rdb_filter_assignee_all: Всі відповідальні 16 | rdb_filter_assignee_me: Мої завдання 17 | rdb_filter_assignee_none: Без відповідального 18 | rdb_filter_assignee_others: Інші 19 | rdb_options: Налаштування 20 | rdb_options_change_assignee: Змінити відповідального 21 | rdb_options_change_assignee_info: При перетягуванні завдання доручити його мені 22 | rdb_options_hide_done: Приховати виконанні завдання 23 | rdb_options_hide_done_info: Приховати виконанні завдання і зменшити колонку "Done" 24 | rdb_options_reset: Скинути фільтр 25 | rdb_options_reset_info: Скинути фільтр за замовчуванням 26 | rdb_options_configure: Налаштування 27 | rdb_options_include_subprojects: Додати підпроекти 28 | rdb_options_view: Вигляд 29 | rdb_options_issue_view: Вигляд 30 | rdb_options_issue_view_card: У формі картки 31 | rdb_options_issue_view_compact: Компактний 32 | rdb_options_group: Групувати за 33 | rdb_group_none: Без групування 34 | rdb_group_category: Категорією 35 | rdb_group_assignee: Відповідальним 36 | rdb_group_tracker: Координатором 37 | rdb_group_priority: Пріоритетом 38 | rdb_group_version: Версією 39 | rdb_group_parent: Батьківським завданням 40 | rdb_group_project: Проєктом 41 | rdb_options_board_view: Вигляд дошки 42 | rdb_options_board_view_compact: Класичний 43 | rdb_options_board_view_outline: Контур 44 | rdb_options_columns: Колонки дошки 45 | rdb_options_fullscreen: На повний екран 46 | rdb_legend_priorities: Пріоритети 47 | rdb_legend_warnings: Попередження 48 | rdb_issue_overdue: Протермінований 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: Недоступно 51 | rdb_column_done: Done 52 | rdb_x_issues: 53 | one: 1 Завдання 54 | few: 1%{count} Завдання 55 | many: 1%{count} Завдання 56 | other: 1%{count} Завдання 57 | rdb_dialog_update_issue_title: Оновити завдання 58 | rdb_dialog_update_issue_status: Виберіть новий статус для завдання 59 | rdb_other_issues: Інші завдання (%{count}) 60 | rdb_unassigned: Не призначений 61 | rdb_others: Інші 62 | rdb_all_issues: Всі завдання 63 | rdb_no_parent: Без батьківського завдання 64 | rdb_issue_menu_progress_title: Оновити прогрес 65 | rdb_issue_menu_progress: "%{count}%" 66 | rdb_issue_menu_redmine_issue: Завдання 67 | rdb_issue_menu_show: Перейти 68 | rdb_issue_menu_edit: Редагувати 69 | rdb_issue_menu_assign_me: Доручити мені 70 | rdb_issue_menu_unassign_me: Зняти з мене 71 | rdb_flash_illegal_workflow_action: "

    Ви не маєте права виконувати цю дію в робочому процесі:

    Перетягнути %{issue} з %{source} у %{target}.

    " 72 | rdb_flash_missing_lock_version: "

    Не вказана версія: Не можливо оновити завдання не вказавши версію. Спробуйте ще раз." 73 | rdb_flash_stale_object: "

    Завдання застарілe: %{issue}. Перевірте зміни і спробуйте ще раз." 74 | rdb_flash_invalid_request: "

    Невірний запит.

    " 75 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/pt-BR.yml: -------------------------------------------------------------------------------- 1 | --- 2 | pt-BR: 3 | project_module_dashboard: Dashboard 4 | permission_view_dashboards: Ver Dashboard 5 | permission_configure_dashboards: Configurar Dashboards 6 | menu_label_dashboard: Dashboard 7 | rdb_taskboard: Tarefas 8 | rdb_planningboard: Planejamento 9 | rdb_filter_version_all: Todas Versões 10 | rdb_filter_version_unassigned: Não atribuído 11 | rdb_filter_tracker_all: Todos Observadores 12 | rdb_filter_tracker_multiple: Múltiplos Observadores 13 | rdb_filter_category_all: Todas Categorias 14 | rdb_filter_category_multiple: Múltiplas Categorias 15 | rdb_filter_assignee_all: Todas Atribuições 16 | rdb_filter_assignee_me: Minhas tarefas 17 | rdb_filter_assignee_none: Não atribuído 18 | rdb_filter_assignee_others: Outros 19 | rdb_options: Opções 20 | rdb_options_change_assignee: Mudar atribuição 21 | rdb_options_change_assignee_info: Mudar atribuição para o usuário atual quando a tarefa for alterada 22 | rdb_options_hide_done: Esconder tarefas fechadas 23 | rdb_options_hide_done_info: Esconder tarefas fechadas e diminuir a coluna "feito" 24 | rdb_options_reset: Resetar filtro 25 | rdb_options_reset_info: Resetar todos filtros para o padrão 26 | rdb_options_configure: Configurar 27 | rdb_options_include_subprojects: Incluir sub-projetos 28 | rdb_options_view: Visualização 29 | rdb_options_issue_view: Visualização de tarefa 30 | rdb_options_issue_view_card: Cartão 31 | rdb_options_issue_view_compact: Compactar 32 | rdb_options_group: Agrupamento de tarefas 33 | rdb_group_none: Sem agrupamento 34 | rdb_group_category: Categoria 35 | rdb_group_assignee: Atribuído para 36 | rdb_group_tracker: Observador 37 | rdb_group_priority: Prioridade 38 | rdb_group_version: Versão 39 | rdb_group_parent: Tarefa pai 40 | rdb_group_project: Projeto 41 | rdb_options_board_view: Modo de visualização 42 | rdb_options_board_view_compact: Classico 43 | rdb_options_board_view_outline: Contorno 44 | rdb_options_columns: Colunas 45 | rdb_options_fullscreen: Tela cheia 46 | rdb_legend_priorities: Prioridades 47 | rdb_legend_warnings: Alertas 48 | rdb_issue_overdue: Atrasado 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: N/A 51 | rdb_column_done: Feito 52 | rdb_x_issues: 53 | one: 1 Tarefa 54 | many: "%{count} Tarefas" 55 | other: "%{count} Tarefas" 56 | rdb_dialog_update_issue_title: Atualizar Tarefa 57 | rdb_dialog_update_issue_status: Escolher status da tarefa 58 | rdb_other_issues: Outras tarefas (%{count}) 59 | rdb_unassigned: Não atribuidas 60 | rdb_others: Outras 61 | rdb_all_issues: Todas Tarefas 62 | rdb_no_parent: Sem tarefas pai 63 | rdb_issue_menu_progress_title: Progresso de atualização 64 | rdb_issue_menu_progress: "%{count}%" 65 | rdb_issue_menu_redmine_issue: Tarefa Redmine 66 | rdb_issue_menu_show: Mostrar 67 | rdb_issue_menu_edit: Editar 68 | rdb_issue_menu_assign_me: Atribuir para mim 69 | rdb_issue_menu_unassign_me: Retirar atribuição 70 | rdb_flash_illegal_workflow_action: "

    Você não tem autorização para altera o fluxo:

    Mover %{issue} de %{source} para %{target}.

    " 71 | rdb_flash_missing_lock_version: "

    Falta versão bloqueada: Não é possível atualizar uma tarefa sem uma versão bloqueada. Tente novamente." 72 | rdb_flash_stale_object: "

    Tentando atualizar uma tarefa antiga: %{issue}. Verifique as mudanças e tente novamente." 73 | rdb_flash_invalid_request: "

    Requisição inválida.

    " 74 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/de.yml: -------------------------------------------------------------------------------- 1 | --- 2 | de: 3 | project_module_dashboard: Dashboard 4 | permission_view_dashboards: Dashboards anschauen 5 | permission_configure_dashboards: Dashboards konfigurieren 6 | menu_label_dashboard: Dashboard 7 | rdb_taskboard: Task Board 8 | rdb_planningboard: Planning Board 9 | rdb_filter_version_all: Alle Versionen 10 | rdb_filter_version_unassigned: Keine Version 11 | rdb_filter_tracker_all: Alle Trackers 12 | rdb_filter_tracker_multiple: Mehrere Trackers 13 | rdb_filter_category_all: Alle Kategorien 14 | rdb_filter_category_multiple: Mehrere Kategorien 15 | rdb_filter_assignee_all: Alle Tickets 16 | rdb_filter_assignee_me: Meine Tickets 17 | rdb_filter_assignee_none: Nicht zugewiesen 18 | rdb_filter_assignee_others: Andere 19 | rdb_options: Optionen 20 | rdb_options_change_assignee: Ändere Verantwortlichen 21 | rdb_options_change_assignee_info: Ändere Verantwortlichen auf aktuellen Benutzer wenn ein Ticket verschoben wird. 22 | rdb_options_hide_done: Verberge fertige Tickets 23 | rdb_options_hide_done_info: Verbirgt fertige Tickets und verkleinert Fertig-Spalte. 24 | rdb_options_reset: Filter zurücksetzen 25 | rdb_options_reset_info: Setzt alle Filter auf Standardeinstellungen zurück. 26 | rdb_options_configure: Konfigurieren 27 | rdb_options_include_subprojects: Unterprojekte einbeziehen 28 | rdb_options_view: Ansicht 29 | rdb_options_issue_view: Ticket-Ansicht 30 | rdb_options_issue_view_card: Karte 31 | rdb_options_issue_view_compact: Kompakt 32 | rdb_options_group: Gruppierung 33 | rdb_group_none: Keine Gruppierung 34 | rdb_group_category: Kategorie 35 | rdb_group_assignee: Verantwortlicher 36 | rdb_group_tracker: Tracker 37 | rdb_group_priority: Priorität 38 | rdb_group_version: Version 39 | rdb_group_parent: Übergeordnete Aufgabe 40 | rdb_group_project: Projekt 41 | rdb_options_board_view: Board Ansicht 42 | rdb_options_board_view_compact: Klassisch (Kompakt) 43 | rdb_options_board_view_outline: Outline 44 | rdb_options_columns: Spalten 45 | rdb_options_fullscreen: Vollbildschirm 46 | rdb_legend_priorities: Prioritäten 47 | rdb_legend_warnings: Warnungen 48 | rdb_issue_overdue: Überfällig 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: N/A 51 | rdb_column_done: Fertig 52 | rdb_x_issues: 53 | one: 1 Ticket 54 | other: "%{count} Tickets" 55 | rdb_dialog_update_issue_title: Ticket aktualisieren 56 | rdb_dialog_update_issue_status: Wähle neuen Ticket-Status 57 | rdb_other_issues: Andere Tickets (%{count}) 58 | rdb_unassigned: Nicht zugewiesen 59 | rdb_others: Andere 60 | rdb_all_issues: Alle Tickets 61 | rdb_no_parent: Keine übergeordneten Aufgaben 62 | rdb_issue_menu_progress_title: Fortschritt ändern 63 | rdb_issue_menu_progress: "%{count}%" 64 | rdb_issue_menu_redmine_issue: Redmine Ticket 65 | rdb_issue_menu_show: Anzeigen 66 | rdb_issue_menu_edit: Bearbeiten 67 | rdb_issue_menu_assign_me: Mich zuweisen 68 | rdb_issue_menu_unassign_me: Zuweisung entfernen 69 | rdb_flash_illegal_workflow_action: "

    Diese Änderung verstößt gegen den festgelegten Arbeitsfluss:

    %{issue} von %{source} nach %{target} ändern.

    " 70 | rdb_flash_missing_lock_version: "

    Lock-Version fehlt: Ticket kann nicht aktualisiert werden. Bitte nochmal probieren." 71 | rdb_flash_stale_object: "

    Ticket wurde verändert: %{issue}. Überprüfe die Änderungen und probiere es erneut." 72 | rdb_flash_invalid_request: "

    Ungültige Anfrage.

    " 73 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/cs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | cs: 3 | project_module_dashboard: Nástěnka 4 | permission_view_dashboards: Zobrazit nástěnky 5 | permission_configure_dashboards: Nastavit nástěnky 6 | menu_label_dashboard: Nástěnka 7 | rdb_taskboard: Nástěnka úkolů 8 | rdb_planningboard: Plánovací nástěnka 9 | rdb_filter_version_all: Všechny verze 10 | rdb_filter_version_unassigned: Nepřiřazené 11 | rdb_filter_tracker_all: Všechny fronty 12 | rdb_filter_tracker_multiple: Více front 13 | rdb_filter_category_all: Všechny kategorie 14 | rdb_filter_category_multiple: Více kategorií 15 | rdb_filter_assignee_all: Přiřazené všem 16 | rdb_filter_assignee_me: Mé úkoly 17 | rdb_filter_assignee_none: Nepřiřazené 18 | rdb_filter_assignee_others: Ostatní 19 | rdb_options: Možnosti 20 | rdb_options_change_assignee: Změnit přiřazeného uživatele 21 | rdb_options_change_assignee_info: Při přesunu úkolu jej přiřadit aktuálně přihlášenému uživateli. 22 | rdb_options_hide_done: Skrýt uzavřené úkoly 23 | rdb_options_hide_done_info: Skrýt uzavřené úkoly a zmenšit sloupec hotových úkolů. 24 | rdb_options_reset: Zrušit filtry 25 | rdb_options_reset_info: Obnoví všechny filtry do výchozího nastavení. 26 | rdb_options_configure: Konfigurovat 27 | rdb_options_include_subprojects: Zahrnout podprojekty 28 | rdb_options_view: Zobrazení 29 | rdb_options_issue_view: Zobrazení úkolů 30 | rdb_options_issue_view_card: Karty 31 | rdb_options_issue_view_compact: Kompaktní 32 | rdb_options_group: Seskupit úkoly podle 33 | rdb_group_none: Neseskupovat 34 | rdb_group_category: Kategorie 35 | rdb_group_assignee: Přiřazeno 36 | rdb_group_tracker: Fronty 37 | rdb_group_priority: Priority 38 | rdb_group_version: Verze 39 | rdb_group_parent: Rodičovského úkolu 40 | rdb_group_project: Projektu 41 | rdb_options_board_view: Zobrazení nástěnky 42 | rdb_options_board_view_compact: Klasické 43 | rdb_options_board_view_outline: Hrubý přehled 44 | rdb_options_columns: Sloupce nástěnky 45 | rdb_options_fullscreen: Celá obrazovka 46 | rdb_legend_priorities: Priority 47 | rdb_legend_warnings: Varování 48 | rdb_issue_overdue: Zpožděné 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: Nedostupné 51 | rdb_column_done: Hotové 52 | rdb_x_issues: 53 | one: 1 úkol 54 | few: "%{count} úkoly" 55 | many: "%{count} úkolů" 56 | other: "%{count} úkolů" 57 | rdb_dialog_update_issue_title: Upravit úkol 58 | rdb_dialog_update_issue_status: Zvolte nový stav úkolu 59 | rdb_other_issues: Ostatní úkoly (%{count}) 60 | rdb_unassigned: Nepřiřazeno 61 | rdb_others: Ostatní 62 | rdb_all_issues: Všechny úkoly 63 | rdb_no_parent: Bez nadřazeného úkolu 64 | rdb_issue_menu_progress_title: Aktualizovat % hotovo 65 | rdb_issue_menu_progress: "%{count}%" 66 | rdb_issue_menu_redmine_issue: Úkol 67 | rdb_issue_menu_show: Zobrazit 68 | rdb_issue_menu_edit: Upravit 69 | rdb_issue_menu_assign_me: Přiřadit mně 70 | rdb_issue_menu_unassign_me: Zrušit přiřazení mně 71 | rdb_flash_illegal_workflow_action: "

    Nemáte oprávnění provést následující akci v průběhu prací:

    Přesunout %{issue} z %{source} na %{target}.

    " 72 | rdb_flash_missing_lock_version: "

    Chybějící uzamčená verze: Nelze aktualizovat úkol bez uzamčené verze. Opakujte akci." 73 | rdb_flash_stale_object: "

    Pokus o odeslání starých změn úkolu %{issue}. Úkol byl nejspíše upraven jiným uživatelem. Zkontrolujte změny a opakujte akci." 74 | rdb_flash_invalid_request: "

    Neplatný požadavek.

    " 75 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/ca.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ca: 3 | project_module_dashboard: Taulers 4 | permission_view_dashboards: Mostra els taulers 5 | permission_configure_dashboards: Configura els taulers 6 | menu_label_dashboard: Tauler 7 | rdb_taskboard: Assumptes 8 | rdb_planningboard: 'Planificació ' 9 | rdb_filter_version_all: Totes les versions 10 | rdb_filter_version_unassigned: Sense assignar 11 | rdb_filter_tracker_all: Tots els rastrejadors 12 | rdb_filter_tracker_multiple: Diversos rastrejadors 13 | rdb_filter_category_all: Totes les categories 14 | rdb_filter_category_multiple: Diverses categories 15 | rdb_filter_assignee_all: Tots els assignats 16 | rdb_filter_assignee_me: Els meus assumptes 17 | rdb_filter_assignee_none: Sense assignar 18 | rdb_filter_assignee_others: Altres 19 | rdb_options: Opcions 20 | rdb_options_change_assignee: 'Canvia l''assignació ' 21 | rdb_options_change_assignee_info: Canvia l'assignació a l'usuari actual quan l'assumpte es mou 22 | rdb_options_hide_done: Amaga els assumptes tancats 23 | rdb_options_hide_done_info: Amaga assumptes tancats i redueix la columna "fet" 24 | rdb_options_reset: Restableix filtre 25 | rdb_options_reset_info: Restableix tots els filtres 26 | rdb_options_configure: Configura 27 | rdb_options_include_subprojects: Inclou subprojects 28 | rdb_options_view: Veure 29 | rdb_options_issue_view: Vista d'assumpte 30 | rdb_options_issue_view_card: Targeta 31 | rdb_options_issue_view_compact: Compacte 32 | rdb_options_group: Agrupació d'assumptes 33 | rdb_group_none: Sense agrupar 34 | rdb_group_category: Categoria 35 | rdb_group_assignee: Assignat 36 | rdb_group_tracker: Rastrejador 37 | rdb_group_priority: Prioritat 38 | rdb_group_version: 'Versió ' 39 | rdb_group_parent: Assumpte pare 40 | rdb_group_project: Projecte 41 | rdb_options_board_view: Vista del tauler 42 | rdb_options_board_view_compact: 'Clàssic ' 43 | rdb_options_board_view_outline: Esquema 44 | rdb_options_columns: Columnes del tauler 45 | rdb_options_fullscreen: Pantalla sencera 46 | rdb_legend_priorities: Prioritats 47 | rdb_legend_warnings: Avisos 48 | rdb_issue_overdue: Endarrerit 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: N/D 51 | rdb_column_done: Fet 52 | rdb_x_issues: 53 | one: 1 Assumpte 54 | other: "%{count} Assumptes" 55 | rdb_dialog_update_issue_title: Actualitza l'assumpte 56 | rdb_dialog_update_issue_status: 'Escull un nou estat per l''assumpte ' 57 | rdb_other_issues: Altres assumptes (%{count}) 58 | rdb_unassigned: Sense assignar 59 | rdb_others: Altres 60 | rdb_all_issues: Tots els assumptes 61 | rdb_no_parent: Sense assumpte pare 62 | rdb_issue_menu_progress_title: 'Posa al dia l''actualització ' 63 | rdb_issue_menu_progress: "%{count}%" 64 | rdb_issue_menu_redmine_issue: Assumpte de Redmine 65 | rdb_issue_menu_show: Veure 66 | rdb_issue_menu_edit: Edita 67 | rdb_issue_menu_assign_me: Assigna-m'ho 68 | rdb_issue_menu_unassign_me: Desassigna-m'ho 69 | rdb_flash_illegal_workflow_action: "

    No tens permís per realitzar l'acció següent:

    Moure%{issue} des de %{source} a %{target}.

    " 70 | rdb_flash_missing_lock_version: "

    No s'ha trobat el bloqueig de la versió :No es pot actualitzar l'assumpte sense el bloqueig de la versió. Torna-ho a provar" 71 | rdb_flash_stale_object: "

    S'ha intentat actualitzar un assumpte antic: %{issue}. Comprova el canvis i torna-ho a intentar." 72 | rdb_flash_invalid_request: "

    Sol·licitud no vàlida.

    " 73 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/nl.yml: -------------------------------------------------------------------------------- 1 | --- 2 | nl: 3 | project_module_dashboard: Dashboard 4 | permission_view_dashboards: Dashboards bekijken 5 | permission_configure_dashboards: Dashboards instellen 6 | menu_label_dashboard: Dashboard 7 | rdb_taskboard: Takenlijst 8 | rdb_planningboard: Planningschema 9 | rdb_filter_version_all: Alle versies 10 | rdb_filter_version_unassigned: Niet toegekend 11 | rdb_filter_tracker_all: Alle trackers 12 | rdb_filter_tracker_multiple: Meerdere trackers 13 | rdb_filter_category_all: Alle Categorieën 14 | rdb_filter_category_multiple: Meerdere Categorieën 15 | rdb_filter_assignee_all: Alle toegewezen personen 16 | rdb_filter_assignee_me: Mijn Issues 17 | rdb_filter_assignee_none: Niet toegewezen 18 | rdb_filter_assignee_others: Andere 19 | rdb_options: Opties 20 | rdb_options_change_assignee: Verander de aangewezen persoon 21 | rdb_options_change_assignee_info: Verander de aangewezen persoon wanneer het issue verplaatst wordt. 22 | rdb_options_hide_done: Verberg afgesloten issues 23 | rdb_options_hide_done_info: Verberg afgesloten issues en maak de klaar kolom smaller 24 | rdb_options_reset: Herstel filter 25 | rdb_options_reset_info: Herstel alle filters naar hun standaardwaarde 26 | rdb_options_configure: Instellen 27 | rdb_options_include_subprojects: Neem ondergeschikte projecten mee 28 | rdb_options_view: Bekijk 29 | rdb_options_issue_view: Issue beeld 30 | rdb_options_issue_view_card: Kaart 31 | rdb_options_issue_view_compact: Bondig 32 | rdb_options_group: Issue groepering 33 | rdb_group_none: Gene groepering 34 | rdb_group_category: Categorie 35 | rdb_group_assignee: Toegewezen persoon 36 | rdb_group_tracker: Tracker 37 | rdb_group_priority: Prioriteit 38 | rdb_group_version: Versie 39 | rdb_group_parent: Bovenliggende taak 40 | rdb_group_project: Project 41 | rdb_options_board_view: Overzichtsbeeld 42 | rdb_options_board_view_compact: Klassiek 43 | rdb_options_board_view_outline: Overzicht 44 | rdb_options_columns: Kolommen in het overzicht 45 | rdb_options_fullscreen: Schermvullend 46 | rdb_legend_priorities: Prioriteiten 47 | rdb_legend_warnings: Waarschuwingen 48 | rdb_issue_overdue: Te laat 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: Niet toepasbaar 51 | rdb_column_done: Klaar 52 | rdb_x_issues: 53 | one: 1 Issue 54 | other: "%{count} Issues" 55 | rdb_dialog_update_issue_title: Issue bijwerken 56 | rdb_dialog_update_issue_status: Kies een nieuwe Issue status 57 | rdb_other_issues: Andere Issues (%{count}) 58 | rdb_unassigned: Niet toegewezen 59 | rdb_others: Andere 60 | rdb_all_issues: Alle Issues 61 | rdb_no_parent: Geen bovenliggende taak 62 | rdb_issue_menu_progress_title: De voortgang bewerken 63 | rdb_issue_menu_progress: "%{count}%" 64 | rdb_issue_menu_redmine_issue: Redmine Issue 65 | rdb_issue_menu_show: Toon 66 | rdb_issue_menu_edit: Bewerken 67 | rdb_issue_menu_assign_me: Aan mezelf toewijzen 68 | rdb_issue_menu_unassign_me: Niet meer aan mezelf toewijzen 69 | rdb_flash_illegal_workflow_action: "

    U hebt geen toegang om deze werkproces actie uit te voeren :

    Verplaats %{issue} van %{source} naar %{target}.

    " 70 | rdb_flash_missing_lock_version: "

    Ontbrekende lock versie: Kan het issue niet bijwerken zonder lock versie. Probeer het opnieuw." 71 | rdb_flash_stale_object: "

    Geprobeerd om een vastgelopen issue bij te werken : %{issue}. Controleer de wijzigingen en probeer opnieuw." 72 | rdb_flash_invalid_request: "

    Ongeldige vraag.

    " 73 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/README.md: -------------------------------------------------------------------------------- 1 | # PurpleMine 2 2 | 3 | A free Redmine 3.0+ theme written in SCSS. 4 | 5 | ![The MIT License](https://img.shields.io/badge/license-MIT-584492.svg) [![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) ![Run linters](https://github.com/mrliptontea/PurpleMine2/workflows/Run%20linters/badge.svg) [![Issues](https://img.shields.io/github/issues/mrliptontea/PurpleMine2.svg)](https://github.com/mrliptontea/PurpleMine2/issues) 6 | 7 | --- 8 | 9 | ![Screenshot](https://github.com/mrliptontea/PurpleMine2/raw/master/screenshots/issues.png) 10 | 11 | It's written in [SCSS]. It uses [normalize.css] and benefits from some parts of [Bootstrap][bootstrap-sass] like mixins, structure, and stuff. 12 | 13 | ## Main features 14 | 15 | * Bigger, easier to read fonts, 16 | * Github-like wiki content look, 17 | * Sidebar moved to the left for better ergonomy, 18 | * Coloring trackers links (on lists, issue pages and even in the wiki content), 19 | * Jira-inspired priority icons, 20 | * Toggling sidebar visibility, 21 | * Easy to customize via variables. 22 | 23 | ## How install it 24 | 25 | To install PurpleMine, just download [.zip](https://github.com/mrliptontea/PurpleMine2/archive/master.zip) and unpack it to your Redmine's `public/themes` folder. 26 | 27 | Then go to Redmine > Administration > Settings > Display and select PurpleMine2 from the list and save the changes. 28 | 29 | ## Plugins 30 | 31 | This theme also features a new look for [Redmine Backlogs][redmine_backlogs] plugin. To install it, simply copy stylesheets from `PurpleMine2/plugins/redmine_backlogs` and overwrite files in `{redmine}/plugins/redmine_backlogs/assets/stylesheets` and restart Redmine. 32 | 33 | Also, [Redmine Time Tracker][redmine_time_tracker] and [Redmine People][redmine_crm_people] plugins should look nice with PurpleMine. 34 | 35 | ## How to customize it 36 | 37 | If you want to customize PurpleMine to your needs, first, make sure that you have installed [node.js](http://nodejs.org/) and `npm` is available in your terminal. 38 | 39 | Then, from the directory that contains PurpleMine run: 40 | 41 | npm install 42 | 43 | Now all the dependencies should be ready to use. Run one more command: 44 | 45 | npm run watch 46 | 47 | And now the grunt is watching for changes in files placed in `src/` folder. Just change what you need, and it'll run Sass preprocessor automatically. 48 | 49 | Regrettably, optional file include is not possible in Sass, so I would recommend creating a new file, e.g. `src/sass/_custom-variables.scss` and importing it a the beginning of the `application.scss` file. That way all the variables with the `!default` flag could be overridden. 50 | 51 | The path `src/sass/_custom-variables.scss` is added to `.gitignore` so it should make upgrading PurpleMine with keeping your changes rather painless, given that the only thing you changed in PurpleMine's source was adding this one line with `@import "custom-variables";`. 52 | 53 | If you need to customize styles for [Redmine Backlogs][redmine_backlogs] remember to include your `_custom-variables.scss` in `src/sass/plugins/redmine_backlogs/_common.scss`. 54 | 55 | ## Changelog 56 | 57 | [Changelog](./CHANGELOG.md). 58 | 59 | [SCSS]: http://sass-lang.com/ 60 | [normalize.css]: https://github.com/necolas/normalize.css 61 | [bootstrap-sass]: https://github.com/twbs/bootstrap-sass 62 | [redmine_backlogs]: https://github.com/backlogs/redmine_backlogs 63 | [redmine_time_tracker]: https://github.com/hicknhack-software/redmine_time_tracker 64 | [redmine_crm_people]: http://www.redminecrm.com/projects/people/ 65 | [stuff_to_do]: https://github.com/raafael911/stuff_to_do_plugin 66 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/it.yml: -------------------------------------------------------------------------------- 1 | --- 2 | it: 3 | project_module_dashboard: Dashboard 4 | permission_view_dashboards: Visualizza Dashboards 5 | permission_configure_dashboards: Configura Dashboards 6 | menu_label_dashboard: Dashboard 7 | rdb_taskboard: Quadro attività 8 | rdb_planningboard: Quadro pianificazione 9 | rdb_filter_version_all: Tutte le versioni 10 | rdb_filter_version_unassigned: Non assegnato 11 | rdb_filter_tracker_all: Tutti i Trackers 12 | rdb_filter_tracker_multiple: Trackers Multipli 13 | rdb_filter_category_all: Tutte le Categorie 14 | rdb_filter_category_multiple: Categorie Multiple 15 | rdb_filter_assignee_all: Tutti gli Assegnatari 16 | rdb_filter_assignee_me: Le mie Segnalazioni 17 | rdb_filter_assignee_none: Non assegnato 18 | rdb_filter_assignee_others: Altri 19 | rdb_options: Opzioni 20 | rdb_options_change_assignee: Cambio assegnatario 21 | rdb_options_change_assignee_info: Cambia assegnatario in utente attuale allo spostamento della segnalazione. 22 | rdb_options_hide_done: Nascondi le segnalazioni chiuse 23 | rdb_options_hide_done_info: Nascondi le segnalazioni chiuse e riduci le colonne del completato. 24 | rdb_options_reset: Reset filtro 25 | rdb_options_reset_info: Reset di tutti i filtri ai valori di default 26 | rdb_options_configure: Configura 27 | rdb_options_include_subprojects: Includi i sottoprogetti 28 | rdb_options_view: Vista 29 | rdb_options_issue_view: Vista delle segnalazioni 30 | rdb_options_issue_view_card: Card 31 | rdb_options_issue_view_compact: Compatta 32 | rdb_options_group: Raggruppamento segnalazioni 33 | rdb_group_none: Nessun raggruppamento 34 | rdb_group_category: Categoria 35 | rdb_group_assignee: Assegnatario 36 | rdb_group_tracker: Tracker 37 | rdb_group_priority: Priorita' 38 | rdb_group_version: Versione 39 | rdb_group_parent: Task padre 40 | rdb_group_project: Progetto 41 | rdb_options_board_view: Board View 42 | rdb_options_board_view_compact: Classic 43 | rdb_options_board_view_outline: Outline 44 | rdb_options_columns: Board Columns 45 | rdb_options_fullscreen: Full Screen 46 | rdb_legend_priorities: Priorita' 47 | rdb_legend_warnings: Avvisi 48 | rdb_issue_overdue: Superato 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: N/A 51 | rdb_column_done: Fatto 52 | rdb_x_issues: 53 | one: 1 segnalazione 54 | many: "%{count} segnalazioni" 55 | other: "%{count} segnalazioni" 56 | rdb_dialog_update_issue_title: Aggiorna la segnalazione 57 | rdb_dialog_update_issue_status: Scegli lo stato della nuova segnalazione 58 | rdb_other_issues: Altre segnalazioni (%{count}) 59 | rdb_unassigned: Non assegnata 60 | rdb_others: Altri 61 | rdb_all_issues: Tutte le segnalazioni 62 | rdb_no_parent: Nessun task padre 63 | rdb_issue_menu_progress_title: Aggiorna avanzamento 64 | rdb_issue_menu_progress: "%{count}%" 65 | rdb_issue_menu_redmine_issue: Segnalazione Redmine 66 | rdb_issue_menu_show: Mostra 67 | rdb_issue_menu_edit: Edita 68 | rdb_issue_menu_assign_me: Assegnalo a me 69 | rdb_issue_menu_unassign_me: Rimuovi l'assegnazione 70 | rdb_flash_illegal_workflow_action: "

    Non sei autorizzato a compiere quest'azione sul workflow:

    Sposta %{issue} da %{source} a %{target}.

    " 71 | rdb_flash_missing_lock_version: "

    Versione lock mancante: Impossibile aggiornare la segnalazione senza il lock della versione. Riprova." 72 | rdb_flash_stale_object: "

    Tentativo di aggiornare una segnalazione scaduta: %{issue}. Controlla le modifiche e riprova." 73 | rdb_flash_invalid_request: "

    Richiesta non valida.

    " 74 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/fr.yml: -------------------------------------------------------------------------------- 1 | --- 2 | fr: 3 | project_module_dashboard: Tableau de bord 4 | permission_view_dashboards: Voir les tableaux de bord 5 | permission_configure_dashboards: Configurer les tableaux de bord 6 | menu_label_dashboard: Tableau de bord 7 | rdb_taskboard: Tableau des tâches 8 | rdb_planningboard: Tableau du planning 9 | rdb_filter_version_all: Toutes les versions 10 | rdb_filter_version_unassigned: Non assigné 11 | rdb_filter_tracker_all: Tous les trackers 12 | rdb_filter_tracker_multiple: Trackers multiples 13 | rdb_filter_category_all: Toutes les catégories 14 | rdb_filter_category_multiple: Catégories multiples 15 | rdb_filter_assignee_all: Tous les membres assignés 16 | rdb_filter_assignee_me: Mes demandes 17 | rdb_filter_assignee_none: Non assigné 18 | rdb_filter_assignee_others: Autres 19 | rdb_options: Options 20 | rdb_options_change_assignee: Changer l'assignation 21 | rdb_options_change_assignee_info: Assigner à l'utilisateur courant lorsque la demande est déplacée. 22 | rdb_options_hide_done: Masquer les demandes fermées 23 | rdb_options_hide_done_info: Masquer les demandes fermées et réduire la colonne Terminé 24 | rdb_options_reset: Réinitialiser le filtre 25 | rdb_options_reset_info: Réinitialiser tous les filtres 26 | rdb_options_configure: Configurer 27 | rdb_options_include_subprojects: Inclure les sous-projets 28 | rdb_options_view: Affichage 29 | rdb_options_issue_view: Affichage des demandes 30 | rdb_options_issue_view_card: Carte 31 | rdb_options_issue_view_compact: Compact 32 | rdb_options_group: Regrouper par demande 33 | rdb_group_none: Pas de regroupement 34 | rdb_group_category: Catégorie 35 | rdb_group_assignee: 'Assigné à ' 36 | rdb_group_tracker: Tracker 37 | rdb_group_priority: Priorité 38 | rdb_group_version: Version 39 | rdb_group_parent: Tâche parente 40 | rdb_group_project: Projet 41 | rdb_options_board_view: Affichage du tableau 42 | rdb_options_board_view_compact: Classique 43 | rdb_options_board_view_outline: Contour 44 | rdb_options_columns: Colonnes du tableau 45 | rdb_options_fullscreen: Plein écran 46 | rdb_legend_priorities: Priorités 47 | rdb_legend_warnings: Avertissements 48 | rdb_issue_overdue: En retard 49 | rdb_property_time: %{actual} / %{estimated} 50 | rdb_not_available: N/A 51 | rdb_column_done: Terminé 52 | rdb_x_issues: 53 | one: 1 demande 54 | many: "%{count} demandes" 55 | other: "%{count} demandes" 56 | rdb_dialog_update_issue_title: Mettre à jour la demande 57 | rdb_dialog_update_issue_status: Choisir le statut des nouvelles demandes 58 | rdb_other_issues: Autres demandes (%{count}) 59 | rdb_unassigned: Non assignée 60 | rdb_others: Autres 61 | rdb_all_issues: Toutes les demandes 62 | rdb_no_parent: Pas de tâche parente 63 | rdb_issue_menu_progress_title: Mettre à jour la progression 64 | rdb_issue_menu_progress: "%{count}%" 65 | rdb_issue_menu_redmine_issue: Demande Redmine 66 | rdb_issue_menu_show: Voir 67 | rdb_issue_menu_edit: Editer 68 | rdb_issue_menu_assign_me: Assigner à moi 69 | rdb_issue_menu_unassign_me: Ne plus assigner à moi 70 | rdb_flash_illegal_workflow_action: "

    Vous n'êtes pas autorisé à effectuer cette action du workflow :

    Déplacer %{issue} de %{source} à %{target}.

    " 71 | rdb_flash_missing_lock_version: "

    Version de verrou manquante : impossible de mettre à jour la demande sans version de verrou. Veuillez réessayer." 72 | rdb_flash_stale_object: "

    Tentative de mise à jour d'une demande dépassée : %{issue}. Vérifiez les changements puis réessayez." 73 | rdb_flash_invalid_request: "

    Requête non valide.

    " 74 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/javascripts/modules/MenuCollapse.js: -------------------------------------------------------------------------------- 1 | var PurpleMine = PurpleMine || {} // eslint-disable-line no-use-before-define 2 | 3 | PurpleMine.MenuCollapse = (function () { 4 | 'use strict' 5 | 6 | var instance 7 | var translations = { 8 | en: { 9 | topMenuToggler: 'Expand/collapse top menu' 10 | }, 11 | ro: { 12 | topMenuToggler: 'Deschide/închide meniul de sus' 13 | }, 14 | fr: { 15 | topMenuToggler: 'Développer/réduire le menu principal' 16 | }, 17 | pl: { 18 | topMenuToggler: 'Zwiń/rozwiń górne menu' 19 | }, 20 | de: { 21 | topMenuToggler: 'Ein-/Ausklappen Hauptmenu' 22 | }, 23 | ja: { 24 | topMenuToggler: 'トップメニューの展開/折りたたみ' 25 | } 26 | } 27 | 28 | function MenuCollapse () { 29 | if (instance) { 30 | return instance 31 | } 32 | 33 | instance = this 34 | 35 | this.lang = document.documentElement.lang 36 | 37 | if (typeof translations[this.lang] === 'undefined') { 38 | this.lang = 'en' 39 | } 40 | 41 | this._ = translations[this.lang] 42 | 43 | this.menus = { 44 | top: { 45 | $el: $('#top-menu') 46 | } 47 | } 48 | 49 | for (var menu in this.menus) { 50 | // eslint-disable-next-line no-prototype-builtins 51 | if (this.menus.hasOwnProperty(menu) && this.menus[menu].$el.length > 0) { 52 | handleMenu(menu) 53 | } 54 | } 55 | } 56 | 57 | function handleMenu (menu) { 58 | if (instance.menus[menu].$el.css('maxHeight') === 'none') { 59 | return false 60 | } 61 | 62 | instance.menus[menu].collapsed = true 63 | 64 | if (window.localStorage) { 65 | instance.menus[menu].collapsed = 66 | localStorage.getItem(getMenuStorageKey(menu)) === null 67 | } 68 | 69 | buildToggleButton(menu) 70 | 71 | if (instance.isCollapsed(menu) === false) { 72 | instance.expandMenu(menu) 73 | } 74 | } 75 | 76 | function getMenuStorageKey (menu) { 77 | return 'PurpleMine:' + menu + 'MenuExpanded' 78 | } 79 | 80 | function buildToggleButton (menu) { 81 | var togglerClass = menu + '-menu-toggler' 82 | var togglerLabel = instance._[menu + 'MenuToggler'] 83 | var togglerHtml = '
    ' 88 | instance.menus[menu].$toggler = $(togglerHtml) 89 | 90 | instance.menus[menu].$el.prepend(instance.menus[menu].$toggler) 91 | instance.menus[menu].$toggler.on('click', { menu: menu }, instance.toggleMenu) 92 | } 93 | 94 | MenuCollapse.prototype.toggleMenu = function (event) { 95 | var menu = event.data.menu || '' 96 | 97 | if (instance.isCollapsed(menu)) { 98 | instance.expandMenu(menu) 99 | } else { 100 | instance.collapseMenu(menu) 101 | } 102 | } 103 | 104 | MenuCollapse.prototype.isCollapsed = function (menu) { 105 | return this.menus[menu].collapsed 106 | } 107 | 108 | MenuCollapse.prototype.expandMenu = function (menu) { 109 | this.menus[menu].$el.addClass('expanded') 110 | this.menus[menu].$toggler.addClass('expanded') 111 | this.menus[menu].collapsed = false 112 | 113 | if (window.localStorage) { 114 | localStorage.setItem(getMenuStorageKey(menu), 'x') 115 | } 116 | } 117 | 118 | MenuCollapse.prototype.collapseMenu = function (menu) { 119 | this.menus[menu].$el.removeClass('expanded') 120 | this.menus[menu].$toggler.removeClass('expanded') 121 | this.menus[menu].collapsed = true 122 | 123 | if (window.localStorage) { 124 | localStorage.removeItem(getMenuStorageKey(menu)) 125 | } 126 | } 127 | 128 | return MenuCollapse 129 | }()) 130 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/config/locales/pl.yml: -------------------------------------------------------------------------------- 1 | --- 2 | pl: 3 | project_module_dashboard: Tablica 4 | permission_view_dashboards: Przeglądanie tablic 5 | permission_configure_dashboards: Konfigurowanie tablic 6 | menu_label_dashboard: Tablica 7 | rdb_taskboard: Tablica zadań 8 | rdb_planningboard: Tablica planowania 9 | rdb_filter_version_all: Wszystkie wersje 10 | rdb_filter_version_unassigned: Nieprzypisane 11 | rdb_filter_tracker_all: Wszystkie typy zagadnień 12 | rdb_filter_tracker_multiple: Wiele typów zagadnień 13 | rdb_filter_category_all: Wszystkie kategorie 14 | rdb_filter_category_multiple: Wiele kategorii 15 | rdb_filter_assignee_all: Wszyscy użytkownicy przypisani do zagadnień 16 | rdb_filter_assignee_me: Moje zagadnienia 17 | rdb_filter_assignee_none: Nieprzypisane 18 | rdb_filter_assignee_others: Inni 19 | rdb_options: Opcje 20 | rdb_options_change_assignee: Zmień przypisaną osobę 21 | rdb_options_change_assignee_info: Zmienia przypisaną do zagadnienia osobę na aktualnego użytkownika gdy zagadnienie jest przesuwane 22 | rdb_options_hide_done: Ukryj zamknięte zagadnienia 23 | rdb_options_hide_done_info: Ukrywa zamknięte zagadnienia i zmniejsza kolumnę wykonane 24 | rdb_options_reset: Resetuj filtr 25 | rdb_options_reset_info: Resetuje wszystkie filtry do ustawień domyślnych 26 | rdb_options_configure: Konfiguruj 27 | rdb_options_include_subprojects: Uwzględnij podprojekty 28 | rdb_options_view: Widok 29 | rdb_options_issue_view: Widok zagadnień 30 | rdb_options_issue_view_card: Karty 31 | rdb_options_issue_view_compact: Kompaktowy 32 | rdb_options_group: Grupowanie zagadnień 33 | rdb_group_none: Bez grupowania 34 | rdb_group_category: Kategoria 35 | rdb_group_assignee: Osoba przypisana do zagadnienia 36 | rdb_group_tracker: Typ zagadnienia 37 | rdb_group_priority: Priorytet 38 | rdb_group_version: Wersja 39 | rdb_group_parent: Zagadnienie nadrzędne 40 | rdb_group_project: Projekt 41 | rdb_options_board_view: Widok tablicy 42 | rdb_options_board_view_compact: Klasyczny 43 | rdb_options_board_view_outline: Zarys 44 | rdb_options_columns: Kolumny tablicy 45 | rdb_options_fullscreen: Pełny ekran 46 | rdb_legend_priorities: Priorytety 47 | rdb_legend_warnings: Ostrzeżenia 48 | rdb_issue_overdue: Opóźnienie 49 | rdb_property_time: '''%{actual} / %{estimated}''' 50 | rdb_not_available: N/A 51 | rdb_column_done: Zrobione 52 | rdb_x_issues: 53 | one: 1 zagadnienie 54 | few: "%{count} zagadnień" 55 | many: "%{count} zagadnień" 56 | other: "%{count} zagadnień" 57 | rdb_dialog_update_issue_title: Aktualizacja zagadnienia 58 | rdb_dialog_update_issue_status: Wybierz nowy status zagadnienia 59 | rdb_other_issues: Inne zagadnienia (%{count}) 60 | rdb_unassigned: Nieprzypisane 61 | rdb_others: Inni 62 | rdb_all_issues: Wszystkie zagadnienia 63 | rdb_no_parent: Brak zagadnień nadrzędnych 64 | rdb_issue_menu_progress_title: Postęp aktualizacji 65 | rdb_issue_menu_progress: "%{count}%" 66 | rdb_issue_menu_redmine_issue: Zagadnienie Redmine 67 | rdb_issue_menu_show: Pokaż 68 | rdb_issue_menu_edit: Edycja 69 | rdb_issue_menu_assign_me: Przypisz do mnie 70 | rdb_issue_menu_unassign_me: Cofnij przypisanie do mnie 71 | rdb_flash_illegal_workflow_action: "

    Nie masz uprawnień do wykonania tej akcji przepływu pracy:

    Przesuń %{issue} z %{source} do %{target}.

    " 72 | rdb_flash_missing_lock_version: "

    Brak wersji docelowej: Nie można zaktualizować zagadnienia bez wersji docelowej. Spróbuj ponownie." 73 | rdb_flash_stale_object: "

    Próba aktualizacji przestarzałego zagadnienia: %{issue}. Sprawdź zmiany i spróbuj ponownie." 74 | rdb_flash_invalid_request: "

    Niepoprawne żądanie.

    " 75 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_dropdown.scss: -------------------------------------------------------------------------------- 1 | .drdn { 2 | position: relative; 3 | 4 | &.expanded { 5 | > .drdn-content { 6 | display: block; 7 | } 8 | } 9 | 10 | &-trigger { 11 | display: inline-block; 12 | position: relative; 13 | box-sizing: border-box; 14 | cursor: pointer; 15 | user-select: none; 16 | } 17 | 18 | &-content { 19 | @include nice-shadow(2); 20 | display: none; 21 | position: absolute; 22 | z-index: 1002; 23 | top: $input-height-base + $btn-padding-vertical; 24 | right: 0; 25 | min-width: 150px; 26 | overflow: hidden; 27 | border-radius: $border-radius-base; 28 | background: $body-bg; 29 | } 30 | 31 | &-items { 32 | max-height: 400px; 33 | overflow: auto; 34 | color: $gray-600; 35 | 36 | &:empty { 37 | border: 0; 38 | } 39 | 40 | &.selection { 41 | > a, 42 | > span { 43 | @extend %fa-icon; 44 | 45 | &::before { 46 | content: " "; 47 | display: inline-block; 48 | width: 1em; 49 | font-weight: $font-weight-bold; 50 | } 51 | } 52 | 53 | > .selected::before { 54 | content: $fa-var-check; 55 | } 56 | } 57 | 58 | > * { 59 | display: block; 60 | margin: 1px; 61 | padding: ($btn-padding-vertical - 1px) ($btn-padding-horizontal-small - 1px); 62 | border-radius: $border-radius-base - 1px; 63 | 64 | &.icon { 65 | padding-left: $icon-width + $btn-padding-horizontal-small; 66 | 67 | &::before { 68 | width: $icon-width; 69 | margin-top: 3px; 70 | float: left; 71 | text-align: center; 72 | } 73 | } 74 | } 75 | } 76 | } 77 | 78 | .contextual { 79 | .drdn-items { 80 | padding: 3px; 81 | 82 | a, 83 | span { 84 | padding-top: $pagination-padding-vertical; 85 | padding-bottom: $pagination-padding-vertical; 86 | border: 1px solid transparent; 87 | border-radius: $border-radius-small; 88 | color: $pagination-color; 89 | 90 | &:hover, 91 | &:focus { 92 | border-color: $pagination-hover-border; 93 | background-color: $pagination-hover-bg; 94 | color: $pagination-hover-color; 95 | text-decoration: none; 96 | 97 | &.icon-del { 98 | color: map-get(map-get($icon-color-map, danger), normal); 99 | } 100 | } 101 | } 102 | } 103 | 104 | &:not(.journal-actions) > .drdn { 105 | &.expanded { 106 | > .drdn-trigger { 107 | border-color: $pagination-active-border; 108 | background-color: $pagination-active-bg; 109 | color: $pagination-active-color; 110 | } 111 | } 112 | 113 | .drdn-trigger { 114 | padding: $btn-padding-vertical $btn-padding-horizontal-small; 115 | border: 1px solid $pagination-border; 116 | border-radius: $border-radius-base; 117 | background-color: $pagination-bg; 118 | box-shadow: none; 119 | color: $pagination-color; 120 | text-align: center; 121 | 122 | > .icon-only { 123 | margin: 0 -4px; 124 | } 125 | 126 | &:hover, 127 | &:focus { 128 | border-color: $pagination-hover-border; 129 | background-color: $pagination-hover-bg; 130 | color: $pagination-hover-color; 131 | } 132 | } 133 | } 134 | } 135 | 136 | .journal-actions { 137 | .drdn-trigger { 138 | color: map-get(map-get($icon-color-map, default), normal); 139 | } 140 | 141 | .drdn-trigger:hover, 142 | .drdn.expanded .drdn-trigger { 143 | color: map-get(map-get($icon-color-map, default), hover); 144 | } 145 | 146 | .drdn-content { 147 | top: $input-height-base; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/sass/components/_base.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Base styles 3 | // -------------------------------------------------- 4 | 5 | html { 6 | overflow-y: scroll; 7 | tab-size: 4; 8 | } 9 | 10 | body { 11 | margin: 0; 12 | padding: 0; 13 | background-color: $body-bg; 14 | color: $text-color; 15 | font-family: $font-family-base; 16 | font-size: $font-size-base; 17 | font-weight: $font-weight-normal; 18 | line-height: $line-height-base; 19 | } 20 | 21 | a { 22 | color: $link-color; 23 | text-decoration: none; 24 | 25 | &:hover, 26 | &:focus { 27 | color: $link-hover-color; 28 | text-decoration: $link-hover-decoration; 29 | } 30 | 31 | &.issue.closed { 32 | color: $link-color-issue-closed; 33 | text-decoration: $link-closed-decoration; 34 | } 35 | 36 | &.project.closed { 37 | color: $link-color-project-closed; 38 | } 39 | 40 | &.user.locked { 41 | color: $link-color-user-locked; 42 | } 43 | } 44 | 45 | // Remove the tapping delay on clickable elements 46 | a, 47 | area, 48 | button, 49 | input, 50 | label, 51 | select, 52 | summary, 53 | textarea, 54 | [tabindex] { 55 | touch-action: manipulation; 56 | } 57 | 58 | h1 { 59 | margin: 0; 60 | font-size: 2em; 61 | font-weight: $font-weight-semi-bold; 62 | line-height: $line-height-large * .825; 63 | } 64 | 65 | h2 { 66 | margin-top: 0; 67 | margin-bottom: $line-height-computed; 68 | font-size: 1.43em; 69 | font-weight: $font-weight-semi-bold; 70 | line-height: $line-height-large; 71 | 72 | img { 73 | vertical-align: middle; 74 | } 75 | } 76 | 77 | h3 { 78 | margin-top: 0; 79 | margin-bottom: $line-height-computed; 80 | font-size: 1.14em; 81 | font-weight: $font-weight-semi-bold; 82 | line-height: $line-height-large; 83 | } 84 | 85 | h4 { 86 | margin-top: 0; 87 | font-size: 1em; 88 | font-weight: $font-weight-semi-bold; 89 | line-height: $line-height-base; 90 | } 91 | 92 | p { 93 | margin: 0 0 ($line-height-computed * .5); 94 | } 95 | 96 | small { 97 | font-size: $font-size-small; 98 | } 99 | 100 | table { 101 | th { 102 | font-weight: $font-weight-bold; 103 | } 104 | 105 | th, 106 | td { 107 | padding: $table-condensed-cell-padding $table-cell-padding; 108 | } 109 | 110 | p { 111 | margin: 0; 112 | } 113 | 114 | form { 115 | p { 116 | margin-bottom: ($line-height-computed * .5); 117 | 118 | &:last-child { 119 | margin-bottom: 0; 120 | } 121 | } 122 | } 123 | } 124 | 125 | ul, 126 | ol { 127 | margin-top: 0; 128 | margin-bottom: ($line-height-computed * .5); 129 | padding-left: 1.5em; 130 | 131 | ul, 132 | ol { 133 | margin-bottom: 0; 134 | } 135 | } 136 | 137 | dl { 138 | margin-top: 0; 139 | margin-bottom: $line-height-computed; 140 | } 141 | 142 | dt { 143 | margin-top: $line-height-computed; 144 | font-weight: $font-weight-bold; 145 | } 146 | 147 | dd { 148 | margin-bottom: $line-height-computed; 149 | margin-left: $line-height-computed; 150 | } 151 | 152 | code, 153 | kbd, 154 | pre, 155 | samp { 156 | font-family: $font-family-monospace; 157 | font-size: 1em; 158 | } 159 | 160 | hr { 161 | margin-top: $line-height-computed; 162 | margin-bottom: $line-height-computed; 163 | border: 0; 164 | border-top: 1px solid $hr-border; 165 | 166 | li & { 167 | margin-top: $line-height-computed * .5; 168 | margin-bottom: $line-height-computed * .5; 169 | } 170 | } 171 | 172 | blockquote { 173 | margin: 0 0 $line-height-computed; 174 | padding: floor($line-height-computed * .25) $padding-large-horizontal; 175 | border-left: 4px solid $blockquote-border-color; 176 | 177 | > :first-child { 178 | margin-top: 0; 179 | } 180 | 181 | > :last-child { 182 | margin-bottom: 0; 183 | } 184 | } 185 | 186 | .clear { 187 | @extend %clearfix; 188 | } 189 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/javascripts/dashboard.taskboard.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | 3 | $.fn.rdbColumn = function() { 4 | return $(this).rdbFindUp('[data-rdb-column-id]'); 5 | }; 6 | 7 | $.fn.rdbColumnId = function() { 8 | return $(this).rdbColumn().data('rdb-column-id'); 9 | }; 10 | 11 | $.fn.rdbGroup = function() { 12 | return $(this).rdbFindUp('[data-rdb-group-id]'); 13 | }; 14 | 15 | $.fn.rdbGroupId = function() { 16 | return $(this).rdbGroup().data('rdb-group-id'); 17 | }; 18 | 19 | /* ==================================================== 20 | ** Drag and drop 21 | */ 22 | 23 | var currentIssue; 24 | 25 | Rdb.rdbDADShowIssue = function() { 26 | if(currentIssue) currentIssue.css({ visibility: 'visible', opacity: 1 }); 27 | }; 28 | 29 | Rdb.rdbInitDAD = function () { 30 | var el = Rdb.rdbBase(); 31 | var baseURL = Rdb.rdbBaseURL(); 32 | 33 | el.find(".rdb-issue-drag").each(function() { 34 | var issue = $(this); 35 | 36 | issue.draggable({ 37 | scroll: false, 38 | revert: true, 39 | // containment: '#rdb-board', 40 | distance: 20, 41 | cancel: 'a,.rdb-menu', 42 | start: function() { 43 | Rdb.rdbMenuClose(); 44 | issue.addClass('rdb-issue-dragged'); 45 | }, 46 | stop: function() { 47 | issue.removeClass('rdb-issue-dragged'); 48 | } 49 | }); 50 | }); 51 | 52 | el.find(".rdb-column").each(function() { 53 | var column = $(this); 54 | var coluid = column.rdbColumnId(); 55 | var cgroup = column.data('rdb-drop-group'); 56 | if(coluid) { 57 | column.droppable({ 58 | accept: function(draggable) { 59 | var issue = draggable.rdbIssue(); 60 | var dropon = issue.data('rdb-drop-on') || ''; 61 | return issue.data('rdb-drop-group') == cgroup && dropon.indexOf(coluid) >= 0; 62 | }, //'[data-rdb-drop-on*="' + accept + '"]', 63 | activeClass: "rdb-column-drop-active", 64 | hoverClass: "rdb-column-drop-hover", 65 | tolerance: "pointer", 66 | drop: function(event, ui) { 67 | var issue = $(ui.draggable).rdbIssue(); 68 | var lock = issue.rdbIssueLockVersion(); 69 | var issueId = issue.rdbIssueId(); 70 | var groupId = issue.rdbGroupId(); 71 | 72 | if(issueId && issue.rdbColumnId() != coluid) { 73 | currentIssue = issue; 74 | currentIssue.css({ visibility: 'hidden', opacity: 0 }); 75 | $.getScript( 76 | baseURL + '/move?issue=' + issueId + '&lock_version=' + lock + '&column=' + coluid + '&group=' + groupId) 77 | .fail(function(jqxhr, settings, exception) { 78 | Rdb.rdbDADShowIssue(); 79 | Rdb.rdbError('Error: ' + exception); 80 | }); 81 | } 82 | } 83 | }); 84 | } 85 | }); 86 | }; 87 | 88 | Rdb.rdbDestroyDAD = function () { 89 | Rdb.rdbBase().find(".rdb-issue-drag").draggable('destroy'); 90 | }; 91 | 92 | Rdb.rdbInit(function() { 93 | Rdb.rdbInitDAD(); 94 | }); 95 | 96 | /* ==================================================== 97 | ** Collapse groups 98 | */ 99 | 100 | $(document).click(function (e) { 101 | var link = $(e.target).rdbFindUp('a').first(); 102 | var group = link.rdbGroup(); 103 | if(link.rdbAny() && group.rdbAny() && link.parents().is('.rdb-group-header')) { 104 | e.preventDefault(); 105 | if(group.hasClass('rdb-collapsed')) { 106 | Rdb.rdbStorageRemove('collapsed-groups', group.rdbGroupId()); 107 | group.removeClass('rdb-collapsed'); 108 | } else { 109 | Rdb.rdbStorageAdd('collapsed-groups', group.rdbGroupId()); 110 | group.addClass('rdb-collapsed'); 111 | } 112 | } 113 | }); 114 | 115 | Rdb.rdbInit(function() { 116 | $('.rdb-group').each(function() { 117 | var group = $(this); 118 | if(Rdb.rdbStorageHas('collapsed-groups', group.rdbGroupId())) { 119 | group.addClass('rdb-collapsed'); 120 | } 121 | }); 122 | }); 123 | 124 | })(jQuery);; 125 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/javascripts/modules/SidebarToggler.js: -------------------------------------------------------------------------------- 1 | var PurpleMine = PurpleMine || {} // eslint-disable-line no-use-before-define 2 | 3 | PurpleMine.SidebarToggler = (function () { 4 | 'use strict' 5 | 6 | var instance 7 | var translations = { 8 | en: { 9 | toggler: 'Toggle sidebar' 10 | }, 11 | ro: { 12 | toggler: 'Deschide/închide bara laterală' 13 | }, 14 | fr: { 15 | toggler: 'Basculer la barre latérale' 16 | }, 17 | pl: { 18 | toggler: 'Pokaż/ukryj panel boczny' 19 | }, 20 | ja: { 21 | toggler: 'サイドバーの切り替え' 22 | } 23 | } 24 | 25 | function SidebarToggler () { 26 | if (instance) { 27 | return instance 28 | } 29 | 30 | instance = this 31 | 32 | this.sidebarVisible = true 33 | this.sidebarHiding = null 34 | this.$toggler = null 35 | this.$header = $('#header') 36 | this.$main = $('#main') 37 | this.$sidebar = $('#sidebar') 38 | this.lang = document.documentElement.lang 39 | 40 | if (typeof translations[this.lang] === 'undefined') { 41 | this.lang = 'en' 42 | } 43 | 44 | this._ = translations[this.lang] 45 | 46 | handleSidebar() 47 | } 48 | 49 | function handleSidebar () { 50 | if (window.localStorage) { 51 | instance.sidebarVisible = 52 | localStorage.getItem('PurpleMine:sidebarHidden') === null 53 | } 54 | 55 | if ( 56 | instance.$sidebar.length > 0 && 57 | instance.$main.hasClass('nosidebar') === false 58 | ) { 59 | buildButton() 60 | bindKeyHandler() 61 | 62 | if (instance.sidebarVisible === false) { 63 | instance.hideSidebar(true) 64 | } 65 | } 66 | } 67 | 68 | function bindKeyHandler () { 69 | var body = document.getElementsByTagName('body')[0] 70 | 71 | window.onkeydown = function (event) { 72 | if ( 73 | body === event.target && 74 | event.keyCode === 83 && // "s" 75 | event.ctrlKey === false && 76 | event.altKey === false && 77 | event.shiftKey === false 78 | ) { 79 | instance.toggleSidebar() 80 | } 81 | } 82 | } 83 | 84 | function buildButton () { 85 | var togglerClass = 'sidebar-toggler' 86 | var togglerHtml = '' 91 | instance.$toggler = $(togglerHtml) 92 | 93 | instance.$header.append(instance.$toggler) 94 | instance.$toggler.on('click', instance.toggleSidebar) 95 | } 96 | 97 | SidebarToggler.prototype.toggleSidebar = function () { 98 | if (instance.sidebarVisible) { 99 | instance.hideSidebar() 100 | } else { 101 | instance.showSidebar() 102 | } 103 | } 104 | 105 | SidebarToggler.prototype.hideSidebar = function (immediate) { 106 | if (immediate === true) { 107 | this.$sidebar.addClass('sidebar-hiding sidebar-hidden') 108 | } else { 109 | this.$sidebar.addClass('sidebar-hiding') 110 | this.sidebarHiding = setTimeout(function sidebarTimeout () { 111 | instance.$sidebar.addClass('sidebar-hidden') 112 | }, 500) 113 | } 114 | 115 | this.$toggler.addClass('sidebar-hidden') 116 | this.sidebarVisible = false 117 | 118 | if (window.localStorage) { 119 | localStorage.setItem('PurpleMine:sidebarHidden', 'x') 120 | } 121 | } 122 | 123 | SidebarToggler.prototype.showSidebar = function () { 124 | clearTimeout(this.sidebarHiding) 125 | 126 | instance.$sidebar.removeClass('sidebar-hidden') 127 | setTimeout(function sidebarTimeout () { 128 | instance.$sidebar.removeClass('sidebar-hiding') 129 | }, 50) 130 | 131 | this.$toggler.removeClass('sidebar-hidden') 132 | this.sidebarVisible = true 133 | 134 | if (window.localStorage) { 135 | localStorage.removeItem('PurpleMine:sidebarHidden') 136 | } 137 | } 138 | 139 | return SidebarToggler 140 | }()) 141 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/javascripts/dashboard.js: -------------------------------------------------------------------------------- 1 | (function(global, $) { 2 | 3 | global.Rdb = {}; 4 | var rdbInits = []; 5 | 6 | /* extend */ 7 | String.prototype.startsWith = function (string) { 8 | return(this.indexOf(string) === 0); 9 | }; 10 | 11 | $.fn.rdbAny = function(selector) { 12 | return $(this).length > 0; 13 | }; 14 | 15 | $.fn.rdbEmpty = function(selector) { 16 | return $(this).length == 0; 17 | }; 18 | 19 | $.fn.rdbFindUp = function(selector) { 20 | var el = $(this); 21 | if(el.is(selector)) 22 | return $(this); 23 | return el.parents(selector); 24 | }; 25 | 26 | Rdb.rdbInit = function(fn) { 27 | $.fn.rdbInit.call(Rdb.rdbBase(), fn); 28 | } 29 | 30 | $.fn.rdbInit = function(fn) { 31 | if(fn) { 32 | rdbInits.push(fn); 33 | } else { 34 | for(var i in rdbInits) { 35 | rdbInits[i].call(this); 36 | } 37 | } 38 | }; 39 | 40 | $.fn.rdbIssue = function() { 41 | return $(this).rdbFindUp('[data-rdb-issue-id]'); 42 | }; 43 | 44 | $.fn.rdbIssueId = function() { 45 | return $(this).rdbIssue().data('rdb-issue-id'); 46 | }; 47 | 48 | $.fn.rdbIssueLockVersion = function() { 49 | return $(this).rdbIssue().data('rdb-lock-version'); 50 | }; 51 | 52 | Rdb.rdbError = function(message) { 53 | var box = $('#rdb-errors'); 54 | var msg = $('
    ').html(message).hide(); 55 | 56 | msg.append('') 57 | 58 | msg.find('a.close').click(function(e) { 59 | e.preventDefault(); 60 | msg.fadeOut(function() { 61 | msg.remove(); 62 | }); 63 | }); 64 | 65 | msg.appendTo(box).fadeIn(function() { 66 | setTimeout(function() { 67 | msg.fadeOut(function() { 68 | msg.remove(); 69 | }); 70 | }, 12000); 71 | }); 72 | }; 73 | 74 | $.fn.rdbVisible = function() { 75 | var el = $(this); 76 | var docTop = $(window).scrollTop(); 77 | var docBottom = docTop + $(window).height(); 78 | 79 | var top = $(el).offset().top; 80 | var bottom = top + $(el).height(); 81 | 82 | return ((bottom <= docBottom) && (top >= docTop)); 83 | }; 84 | 85 | Rdb.rdbStorageAdd = function(id, value) { 86 | var storage = $.totalStorage('rdb-' + id); 87 | if(!storage) storage = new Array; 88 | storage.push(value); 89 | $.totalStorage('rdb-' + id, storage); 90 | return true; 91 | }; 92 | 93 | Rdb.rdbStorageRemove = function(id, value) { 94 | var storage = $.totalStorage('rdb-' + id); 95 | if(!storage) return false; 96 | var i = -1; 97 | while((i = storage.indexOf(value)) >= 0) { 98 | storage.splice(i, 1) 99 | } 100 | $.totalStorage('rdb-' + id, storage); 101 | return true; 102 | }; 103 | 104 | Rdb.rdbStorageHas = function(id, value) { 105 | var storage = $.totalStorage('rdb-' + id); 106 | if(!storage) return false; 107 | for(var i in storage) { 108 | if(storage[i] == value) { 109 | return true; 110 | } 111 | } 112 | return false; 113 | }; 114 | 115 | Rdb.rdbBase = function() { 116 | return $('#rdb'); 117 | }; 118 | 119 | Rdb.rdbBaseURL = function() { 120 | return Rdb.rdbBase().data('rdb-base'); 121 | }; 122 | 123 | /* 124 | * Ajax Filter / Options 125 | */ 126 | $(document).click(function(e) { 127 | var link = $(e.target).rdbFindUp('a').first(); 128 | if(link.rdbFindUp('.rdb-async').rdbAny() && link.attr('href') != '#' && !link.is('.rdb-sync') && !link.attr('href').startsWith('javascript:')) { 129 | Rdb.rdbMenuClose(); 130 | Rdb.rdbCloseDialog(); 131 | e.preventDefault(); 132 | $.getScript( 133 | link.attr('href') 134 | ).fail(function(jqxhr, settings, exception) { 135 | Rdb.rdbError('Ajax Error: ' + exception); 136 | }); 137 | } 138 | }); 139 | 140 | /* Issue subject text ellipsis */ 141 | $(document).ready(function () { 142 | var resizeActions = function() { 143 | $('.rdb-property-subject').ellipsis(); 144 | 145 | var box = $('#rdb-errors'); 146 | var board = $('#rdb-board'); 147 | if($('#rdb-footer').rdbVisible()) { 148 | box.css({ 'position': 'absolute', 'bottom': '30px' }); 149 | } else { 150 | box.css({ 'position': 'fixed', 'bottom': '30px' }); 151 | } 152 | }; 153 | 154 | Rdb.rdbInit(resizeActions); 155 | $(window).resize(resizeActions); 156 | }); 157 | 158 | /* load board on startup */ 159 | $(document).ready(function () { 160 | $.getScript('?'); 161 | }); 162 | 163 | })(window, jQuery); 164 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/app/views/rdb_dashboard/taskboard/_header.html.slim: -------------------------------------------------------------------------------- 1 | .rdb-board 2 | = link_to '', rdb_board_path, class: 'rdb-async', id: 'rdb-refresh' 3 | 4 | - render_rdb_menu :board, @board.name, header: :h2 do 5 | - render_rdb_menu_list [:taskboard] do |val| 6 | = link_to t("rdb_#{val}"), rdb_path(board: val) 7 | 8 | - if @board.versions.any? 9 | .rdb-filter.rdb-async 10 | - render_rdb_menu :versions, @board.filters[:version].title do 11 | - render_rdb_menu_list [:all, :unassigned] do |val| 12 | = link_to t("rdb_filter_version_#{val}"), rdb_filter_path(version: val) 13 | - render_rdb_menu_list @board.filters[:version].versions do |val| 14 | = link_to val.name, rdb_filter_path(version: val.id) 15 | 16 | .rdb-filter.rdb-async 17 | - render_rdb_menu :tracker, @board.filters[:tracker].title, icons: true do 18 | - render_rdb_menu_list [:all] do |val| 19 | = link_to t("rdb_filter_tracker_#{val}"), rdb_filter_path(tracker: val) 20 | - render_rdb_menu_list @board.trackers do |val| 21 | span.rdb-multicheck 22 | = rdb_checkbox_link_to '', rdb_filter_path(tracker: val.id), enabled: @board.filters[:tracker].enabled?(val.id), show_disabled: true 23 | = link_to val.name, rdb_filter_path(tracker: val.id, only: true) 24 | 25 | - if @board.issue_categories.any? 26 | .rdb-filter.rdb-async 27 | - render_rdb_menu :categories, @board.filters[:category].title, icons: true do 28 | - render_rdb_menu_list [:all] do |val| 29 | = link_to t("rdb_filter_category_#{val}"), rdb_filter_path(category: val) 30 | - render_rdb_menu_list @board.issue_categories do |val| 31 | span.rdb-multicheck 32 | = rdb_checkbox_link_to '', rdb_filter_path(category: val.id), enabled: @board.filters[:category].enabled?(val.id), show_disabled: true 33 | = link_to val.name, rdb_filter_path(category: val.id, only: true) 34 | 35 | .rdb-filter.rdb-async 36 | - render_rdb_menu :assignee, @board.filters[:assignee].title do 37 | - render_rdb_menu_list [:all, :me, :none] do |val| 38 | = link_to t("rdb_filter_assignee_#{val}"), rdb_filter_path(assignee: val) 39 | - render_rdb_menu_list @board.assignees do |val| 40 | - if User === val 41 | = link_to val.name, rdb_filter_path(assignee: val.id) 42 | - render_rdb_menu_list @board.assignees do |val| 43 | - if Group === val 44 | = link_to val.name, rdb_filter_path(assignee: val.id) 45 | 46 | .rdb-option.rdb-async 47 | - render_rdb_menu :options, t(:rdb_options), right: true, icons: true do 48 | - render_rdb_menu_list do 49 | - render_rdb_menu_list_item do 50 | = rdb_checkbox_link_to t(:rdb_options_change_assignee), rdb_board_path(change_assignee: !@board.options[:change_assignee]), 51 | enabled: @board.options[:change_assignee], title: t(:rdb_options_change_assignee_info) 52 | = rdb_checkbox_link_to t(:rdb_options_hide_done), rdb_board_path(hide_done: !@board.options[:hide_done]), 53 | enabled: @board.options[:hide_done], title: t(:rdb_options_hide_done_info) 54 | = rdb_checkbox_link_to t(:rdb_options_include_subprojects), rdb_board_path(include_subprojects: (@board.project_ids.size > 1) ? 'false' : 'true'), 55 | enabled: (@board.project_ids.size > 1) 56 | - render_rdb_menu_list @board.column_list, title: t(:rdb_options_columns) do |column| 57 | = rdb_checkbox_link_to column.title, rdb_board_path(hide_column: column.id), enabled: @board.columns[column.id].visible? 58 | - render_rdb_menu_list do 59 | - render_rdb_menu_list_item do 60 | = link_to t(:rdb_options_fullscreen), 'javascript:Rdb.rdbToggleFullscreen();', id: "rdb-option-fullscreen" 61 | - render_rdb_menu_list_item do 62 | = link_to t(:rdb_options_reset), rdb_filter_path(reset: 1), id: "rdb-reset", title: t(:rdb_options_reset_info) 63 | 64 | .rdb-option.rdb-async 65 | - render_rdb_menu :view, t(:rdb_options_view), right: true do 66 | - render_rdb_menu_list RdbDashboard::VIEW_MODES, title: t(:rdb_options_issue_view) do |view| 67 | = rdb_checkbox_link_to t(:"rdb_options_issue_view_#{view}"), rdb_board_path(view: view), enabled: @board.options[:view] == view 68 | - render_rdb_menu_list [:none, :tracker, :category, :priority, :assignee, :version, :parent, :project], title: t(:rdb_options_group) do |group| 69 | = rdb_checkbox_link_to t(:"rdb_group_#{group}"), rdb_board_path(group: group), enabled: @board.options[:group] == group 70 | -------------------------------------------------------------------------------- /themes/PurpleMine2-master/src/javascripts/modules/RevisionGraph.js: -------------------------------------------------------------------------------- 1 | var PurpleMine = PurpleMine || {} // eslint-disable-line no-use-before-define 2 | /* global Raphael: false, revisionGraph: true */ 3 | 4 | PurpleMine.RevisionGraph = function (holder, commitsHash, graphSpace) { 5 | 'use strict' 6 | 7 | var XSTEP = 20 8 | var CIRCLE_INROW_OFFSET = 17 9 | var commitsByScmid = commitsHash 10 | var commits = $.map(commitsByScmid, function (val) { return val }) 11 | var maxRdmid = commits.length - 1 12 | var commitTableRows = $('table.changesets tr.changeset') 13 | 14 | // create graph 15 | if (revisionGraph !== null) { 16 | revisionGraph.clear() 17 | } else { 18 | revisionGraph = new Raphael(holder) 19 | } 20 | 21 | var top = revisionGraph.set() 22 | 23 | // init dimensions 24 | var graphXOffset = commitTableRows.first().find('td').first().position().left - $(holder).position().left 25 | var graphYOffset = $(holder).position().top 26 | var graphRightSide = graphXOffset + (graphSpace + 1) * XSTEP 27 | var graphBottom = commitTableRows.last().position().top + commitTableRows.last().height() - graphYOffset 28 | 29 | revisionGraph.setSize(graphRightSide, graphBottom) 30 | 31 | // init colors 32 | var colors = [ 33 | '#e74c3c', 34 | '#584492', 35 | '#019851', 36 | '#ed820c', 37 | '#4183c4' 38 | ] 39 | 40 | // get more colors if needed 41 | if (graphSpace >= colors.length) { 42 | Raphael.getColor.reset() 43 | 44 | for (var k = 0; k <= graphSpace; k++) { 45 | colors.push(Raphael.getColor(0.9)) 46 | } 47 | } 48 | 49 | var parentCommit 50 | var x, y, parentX, parentY 51 | var path, title 52 | var revisionDotOverlay 53 | 54 | $.each(commits, function (index, commit) { 55 | // eslint-disable-next-line no-prototype-builtins 56 | if (!commit.hasOwnProperty('space')) { 57 | commit.space = 0 58 | } 59 | 60 | y = commitTableRows.eq(maxRdmid - commit.rdmid).position().top - graphYOffset + CIRCLE_INROW_OFFSET 61 | x = graphXOffset + XSTEP / 2 + XSTEP * commit.space 62 | 63 | revisionGraph 64 | .circle(x, y, 3.5) 65 | .attr({ 66 | fill: colors[commit.space], 67 | stroke: 'none' 68 | }) 69 | .toFront() 70 | 71 | // paths to parents 72 | $.each(commit.parent_scmids, function (index, parentScmid) { 73 | parentCommit = commitsByScmid[parentScmid] 74 | 75 | if (parentCommit) { 76 | // eslint-disable-next-line no-prototype-builtins 77 | if (!parentCommit.hasOwnProperty('space')) { 78 | parentCommit.space = 0 79 | } 80 | 81 | parentY = commitTableRows.eq(maxRdmid - parentCommit.rdmid).position().top - graphYOffset + CIRCLE_INROW_OFFSET 82 | parentX = graphXOffset + XSTEP / 2 + XSTEP * parentCommit.space 83 | 84 | if (parentCommit.space === commit.space) { 85 | // vertical path 86 | path = revisionGraph.path([ 87 | 'M', x, y, 88 | 'V', parentY]) 89 | } else { 90 | // path to a commit in a different branch (Bezier curve) 91 | path = revisionGraph.path([ 92 | 'M', x, y, 93 | 'C', x, y, x, y + (parentY - y) / 2, x + (parentX - x) / 2, y + (parentY - y) / 2, 94 | 'C', x + (parentX - x) / 2, y + (parentY - y) / 2, parentX, parentY - (parentY - y) / 2, parentX, parentY 95 | ]) 96 | } 97 | } else { 98 | // vertical path ending at the bottom of the revisionGraph 99 | path = revisionGraph.path([ 100 | 'M', x, y, 101 | 'V', graphBottom 102 | ]) 103 | } 104 | 105 | path 106 | .attr({ 107 | stroke: colors[commit.space], 108 | 'stroke-width': 1.5 109 | }) 110 | .toBack() 111 | }) 112 | 113 | revisionDotOverlay = revisionGraph.circle(x, y, 10) 114 | revisionDotOverlay 115 | .attr({ 116 | fill: '#000', 117 | opacity: 0, 118 | cursor: 'pointer', 119 | href: commit.href 120 | }) 121 | 122 | if (commit.refs !== null && commit.refs.length > 0) { 123 | title = document.createElementNS(revisionGraph.canvas.namespaceURI, 'title') 124 | title.appendChild(document.createTextNode(commit.refs)) 125 | revisionDotOverlay.node.appendChild(title) 126 | } 127 | 128 | top.push(revisionDotOverlay) 129 | }) 130 | 131 | top.toFront() 132 | } 133 | 134 | $(function () { 135 | 'use strict' 136 | 137 | if (window.drawRevisionGraph) { 138 | // override Redmine's function 139 | window.drawRevisionGraph = PurpleMine.RevisionGraph 140 | // make graph redraw itself 141 | $(window).resize() 142 | } 143 | }) 144 | -------------------------------------------------------------------------------- /plugins/redmine_dashboard/assets/javascripts/jquery.total-storage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TotalStorage 3 | * 4 | * Copyright (c) 2012 Jared Novack & Upstatement (upstatement.com) 5 | * Dual licensed under the MIT and GPL licenses: 6 | * http://www.opensource.org/licenses/mit-license.php 7 | * http://www.gnu.org/licenses/gpl.html 8 | * 9 | * Total Storage is the conceptual the love child of jStorage by Andris Reinman, 10 | * and Cookie by Klaus Hartl -- though this is not connected to either project. 11 | */ 12 | 13 | /** 14 | * Create a local storage parameter 15 | * 16 | == What makes it TOTAL Storage? == 17 | 18 | * The browser doesn't support local storage it will fall-back to cookies! (Using the 19 | wonderful $.cookie plugin). 20 | * Send it strings, numbers even complex object arrays! TotalStorage does not care. 21 | Your efforts to defeat it will prove futile. 22 | * Simple as shit. jStorage and some other very well-written plugins provide a bevy of 23 | options for expiration, security and so forth. Frequently this is more power than you 24 | need and vulnerable to confusion if you're just want it to work (JWITW) 25 | 26 | * @desc Set the value of a key to a string 27 | * @example $.totalStorage('the_key', 'the_value'); 28 | * @desc Set the value of a key to a number 29 | * @example $.totalStorage('the_key', 800.2); 30 | * @desc Set the value of a key to a complex Array 31 | * @example var myArray = new Array(); 32 | * myArray.push({name:'Jared', company:'Upstatement', zip:63124}); 33 | myArray.push({name:'McGruff', company:'Police', zip:60652}; 34 | $.totalStorage('people', myArray); 35 | //to return: 36 | $.totalStorage('people'); 37 | * 38 | * @name $.totalStorage 39 | * @cat Plugins/Cookie 40 | * @author Jared Novack/jared@upstatement.com 41 | * @version 1.1 42 | * @url http://upstatement.com/blog/2012/01/jquery-local-storage-done-right-and-easy/ 43 | */ 44 | 45 | ;(function($){ 46 | 47 | /* Variables I'll need throghout */ 48 | 49 | var ls = window.localStorage; 50 | var supported; 51 | if (typeof ls == 'undefined' || typeof window.JSON == 'undefined'){ 52 | supported = false; 53 | } else { 54 | supported = true; 55 | } 56 | // supported = false; 57 | // console.log('supported = ' + supported); 58 | /* Make the methods public */ 59 | 60 | $.totalStorage = function(key, value, options){ 61 | return $.totalStorage.impl.init(key, value); 62 | } 63 | 64 | $.totalStorage.setItem = function(key, value){ 65 | return $.totalStorage.impl.setItem(key, value); 66 | } 67 | 68 | $.totalStorage.getItem = function(key){ 69 | return $.totalStorage.impl.getItem(key); 70 | } 71 | 72 | $.totalStorage.getAll = function(){ 73 | return $.totalStorage.impl.getAll(); 74 | } 75 | 76 | /* Object to hold all methods: public and private */ 77 | 78 | $.totalStorage.impl = { 79 | 80 | init: function(key, value){ 81 | if (typeof value != 'undefined') { 82 | return this.setItem(key, value); 83 | } else { 84 | return this.getItem(key); 85 | } 86 | }, 87 | 88 | setItem: function(key, value){ 89 | if (!supported){ 90 | try { 91 | $.cookie(key, value); 92 | return value; 93 | } catch(e){ 94 | console.log('Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality'); 95 | } 96 | } 97 | var saver = JSON.stringify(value); 98 | ls.setItem(key, saver); 99 | return this.parseResult(saver); 100 | }, 101 | 102 | getItem: function(key){ 103 | if (!supported){ 104 | try { 105 | return this.parseResult($.cookie(key)); 106 | } catch(e){ 107 | return null; 108 | } 109 | } 110 | return this.parseResult(ls.getItem(key)); 111 | }, 112 | 113 | getAll: function(){ 114 | var items = new Array(); 115 | if (!supported){ 116 | try { 117 | var pairs = document.cookie.split(";"); 118 | for (var i = 0; i