diff --git a/Gemfile b/Gemfile index 5a0ee6553f..0e970ea39a 100644 --- a/Gemfile +++ b/Gemfile @@ -161,7 +161,7 @@ gem 'sprockets', '~> 3.7.0' # also, better than thin since we can control worker concurrency. gem 'unicorn' -gem 'nokogiri', '~> 1.8.4' +gem 'nokogiri', '~> 1.8.5' # carrierwave 0.11.3 should allow to use fog-aws without the rest of the # fog dependency chain. We only need aws here, so we can avoid it diff --git a/Gemfile.lock b/Gemfile.lock index e981f1c1d9..6bd367da5e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -86,14 +86,14 @@ GIT PATH remote: vendored-plugins/openproject-auth_plugins specs: - openproject-auth_plugins (8.0.2) + openproject-auth_plugins (8.1.0) omniauth (~> 1.0) rails (~> 5.0) PATH remote: vendored-plugins/openproject-avatars specs: - openproject-avatars (8.0.2) + openproject-avatars (8.1.0) fastimage (~> 2.1.0) gravatar_image_tag (~> 1.2.0) rails (~> 5.0) @@ -101,52 +101,52 @@ PATH PATH remote: vendored-plugins/openproject-backlogs specs: - openproject-backlogs (8.0.2) + openproject-backlogs (8.1.0) acts_as_silent_list (~> 3.0.0) - openproject-pdf_export (= 8.0.2) + openproject-pdf_export (= 8.1.0) PATH remote: vendored-plugins/openproject-costs specs: - openproject-costs (8.0.2) + openproject-costs (8.1.0) PATH remote: vendored-plugins/openproject-documents specs: - openproject-documents (8.0.2) + openproject-documents (8.1.0) PATH remote: vendored-plugins/openproject-github_integration specs: - openproject-github_integration (8.0.2) - openproject-webhooks (~> 8.0.2) + openproject-github_integration (8.1.0) + openproject-webhooks (~> 8.1.0) rails (~> 5.0) PATH remote: vendored-plugins/openproject-global_roles specs: - openproject-global_roles (8.0.2) + openproject-global_roles (8.1.0) PATH remote: vendored-plugins/openproject-ldap_groups specs: - openproject-ldap_groups (8.0.2) + openproject-ldap_groups (8.1.0) PATH remote: vendored-plugins/openproject-meeting specs: - openproject-meeting (8.0.2) + openproject-meeting (8.1.0) icalendar (~> 2.3.0) PATH remote: vendored-plugins/openproject-my_project_page specs: - openproject-my_project_page (8.0.2) + openproject-my_project_page (8.1.0) PATH remote: vendored-plugins/openproject-openid_connect specs: - openproject-openid_connect (8.0.2) + openproject-openid_connect (8.1.0) lobby_boy (~> 0.1.3) omniauth-openid_connect-providers (~> 0.1) openproject-auth_plugins (~> 8.0) @@ -155,22 +155,22 @@ PATH PATH remote: vendored-plugins/openproject-pdf_export specs: - openproject-pdf_export (8.0.2) + openproject-pdf_export (8.1.0) pdf-inspector (~> 1.3.0) prawn (~> 2.2) PATH remote: vendored-plugins/openproject-reporting specs: - openproject-reporting (8.0.2) + openproject-reporting (8.1.0) jquery-tablesorter (~> 1.25.5) - openproject-costs (= 8.0.2) + openproject-costs (= 8.1.0) reporting_engine (>= 1.1.0) PATH remote: vendored-plugins/openproject-two_factor_authentication specs: - openproject-two_factor_authentication (8.0.2) + openproject-two_factor_authentication (8.1.0) aws-sdk-sns (~> 1.1.0) messagebird-rest (~> 1.3.2) rails (~> 5) @@ -179,19 +179,19 @@ PATH PATH remote: vendored-plugins/openproject-webhooks specs: - openproject-webhooks (8.0.2) + openproject-webhooks (8.1.0) rails (~> 5.0) PATH remote: vendored-plugins/openproject-xls_export specs: - openproject-xls_export (8.0.2) + openproject-xls_export (8.1.0) spreadsheet (~> 0.8.9) PATH remote: vendored-plugins/reporting_engine specs: - reporting_engine (8.0.2) + reporting_engine (8.1.0) json rails (~> 5.1.0) @@ -524,7 +524,7 @@ GEM netrc (0.11.0) newrelic_rpm (4.5.0.337) nio4r (2.3.0) - nokogiri (1.8.4) + nokogiri (1.8.5) mini_portile2 (~> 2.3.0) nokogumbo (1.5.0) nokogiri @@ -880,7 +880,7 @@ DEPENDENCIES mysql2 (~> 0.5.0) net-ldap (~> 0.16.0) newrelic_rpm - nokogiri (~> 1.8.4) + nokogiri (~> 1.8.5) oj (~> 3.5.0) okcomputer (~> 1.16.0) omniauth! diff --git a/app/assets/javascripts/application.js.erb b/app/assets/javascripts/application.js.erb index 0aba70d0cd..6f204eccac 100644 --- a/app/assets/javascripts/application.js.erb +++ b/app/assets/javascripts/application.js.erb @@ -49,6 +49,9 @@ //= require danger_zone_validation //= require flash_messages +//= require_tree ./onboarding + + function checkAll(selector, checked) { jQuery('#' + selector + ' input:checkbox').not(':disabled').each(function() { this.checked = checked; @@ -241,20 +244,6 @@ jQuery(document).ready(function($) { addClickEventToAllErrorMessages(); }); - // file table thumbnails - jQuery("table a.has-thumb").hover(function() { - jQuery(this).removeAttr("title").toggleClass("active"); - - // grab the image dimensions to position it properly - var thumbImg = $(this).find("img"); - var thumbImgLeft = -(thumbImg.outerWidth() ); - var thumbImgTop = -(thumbImg.height() / 2 ); - thumbImg.css({top: thumbImgTop, left: thumbImgLeft}).show(); - - }, function() { - jQuery(this).toggleClass("active").find("img").hide(); - }); - // show/hide the files table jQuery(".attachments h4").click(function() { jQuery(this).toggleClass("closed").next().slideToggle(animationRate); diff --git a/app/assets/javascripts/members_form.js b/app/assets/javascripts/members_form.js index 8e99077afb..5f7d844223 100644 --- a/app/assets/javascripts/members_form.js +++ b/app/assets/javascripts/members_form.js @@ -67,13 +67,6 @@ function hideAddMemberForm() { } jQuery(document).ready(function($) { - $("#tab-content-members").submit('#members_add_form', function () { - var error = $('.errorExplanation, .flash'); - if (error) { - error.remove(); - } - }); - // Show/Hide content when page is loaded if (window.OpenProject.guardedLocalStorage("showFilter") === "true") { showFilter(filter = findFilter()); diff --git a/app/assets/javascripts/onboarding/backlogs_tour.js b/app/assets/javascripts/onboarding/backlogs_tour.js new file mode 100644 index 0000000000..6690a6abe4 --- /dev/null +++ b/app/assets/javascripts/onboarding/backlogs_tour.js @@ -0,0 +1,45 @@ +(function ($) { + $(function() { + window.scrumBacklogsTourSteps = [ + { + 'next #content-wrapper': I18n.t('js.onboarding.steps.backlogs_overview'), + 'showSkip': false, + 'containerClass': '-dark -hidden-arrow' + }, + { + 'event_type': 'next', + 'selector': '#sprint_backlogs_container .backlog .menu-trigger', + 'description': I18n.t('js.onboarding.steps.backlogs_task_board_arrow'), + 'showSkip': false, + onNext: function () { + $('#sprint_backlogs_container .backlog .menu-trigger')[0].click(); + } + }, + { + 'event_type': 'next', + 'selector': '#sprint_backlogs_container .backlog .menu .items', + 'description': I18n.t('js.onboarding.steps.backlogs_task_board_select'), + 'showSkip': false, + 'containerClass': '-dark', + onNext: function () { + $('#sprint_backlogs_container .backlog .show_task_board')[0].click(); + } + } + ]; + + window.scrumTaskBoardTourSteps = [ + { + 'next #content-wrapper': I18n.t('js.onboarding.steps.backlogs_task_board'), + 'showSkip': false, + 'containerClass': '-dark -hidden-arrow' + }, + { + 'next #main-menu-work-packages-wrapper': I18n.t('js.onboarding.steps.wp_toggler'), + 'showSkip': false, + onNext: function () { + $('#main-menu-work-packages')[0].click(); + } + }, + ]; + }); +}(jQuery)) diff --git a/app/assets/javascripts/onboarding/homescreen_tour.js b/app/assets/javascripts/onboarding/homescreen_tour.js new file mode 100644 index 0000000000..00686a4935 --- /dev/null +++ b/app/assets/javascripts/onboarding/homescreen_tour.js @@ -0,0 +1,34 @@ +(function ($) { + $(function() { + window.homescreenOnboardingTourSteps = [ + { + 'next #top-menu': I18n.t('js.onboarding.steps.welcome'), + 'skipButton': {className: 'enjoyhint_btn-transparent'}, + 'containerClass': '-hidden-arrow' + }, + { + 'description': I18n.t('js.onboarding.steps.project_selection'), + 'selector': '.widget-box.welcome', + 'event': 'custom', + 'showSkip': false, + 'containerClass': '-dark -hidden-arrow', + 'containerClass': '-dark -hidden-arrow', + 'clickable': true, + onBeforeStart: function () { + // Handle the correct project selection and redirection + // This will be removed once the project selection is implemented + jQuery(".widget-box.welcome a:contains(" + scrumDemoProjectName + ")").click(function () { + tutorialInstance.trigger('next'); + window.location = this.href + '/backlogs/?start_scrum_onboarding_tour=true'; + }); + jQuery(".widget-box.welcome a:contains(" + demoProjectName + ")").click(function () { + tutorialInstance.trigger('next'); + window.location = this.href + '/work_packages/?start_onboarding_tour=true'; + }); + // Disable clicks on other links + $('.widget-box.welcome a').addClass('-disabled').bind('click', preventClickHandler); + } + } + ]; + }); +}(jQuery)) diff --git a/app/assets/javascripts/onboarding/onboarding_tour.js b/app/assets/javascripts/onboarding/onboarding_tour.js new file mode 100644 index 0000000000..eb37d90d24 --- /dev/null +++ b/app/assets/javascripts/onboarding/onboarding_tour.js @@ -0,0 +1,125 @@ +(function ($) { + $(function() { + // ------------------------------- Global ------------------------------- + window.tutorialInstance; + window.preventClickHandler = function (e) { + e.preventDefault(); + e.stopPropagation(); + }; + window.waitForElement = function(element, container, execFunction) { + // Wait for the element to be ready + var observer = new MutationObserver(function (mutations, observerInstance) { + if ($(element).length) { + observerInstance.disconnect(); // stop observing + execFunction(); + return; + } + }); + observer.observe($(container)[0], { + childList: true, + subtree: true + }); + }; + window.demoProjectName = 'Demo project'; + window.scrumDemoProjectName = 'Scrum project'; + + var storageKey = 'openProject-onboardingTour'; + var currentTourPart = sessionStorage.getItem(storageKey); + var url = new URL(window.location.href); + + // ------------------------------- Initial start ------------------------------- + // Do not show the tutorial on mobile or when the demo data has been deleted + if(!(bowser.mobile || bowser.ios || bowser.android) && $('meta[name=demo_projects_available]').attr('content') == "true") { + + // Start after the intro modal (language selection) + // This has to be changed once the project selection is implemented + if (url.searchParams.get("first_time_user") && demoProjectsLinks().length == 2) { + currentTourPart = ''; + sessionStorage.setItem(storageKey, 'readyToStart'); + + // Start automatically when the language selection is closed + $('.op-modal--modal-close-button').click(function () { + homescreenTour(); + }); + } + + // ------------------------------- Tutorial Homescreen page ------------------------------- + if (currentTourPart === "readyToStart") { + homescreenTour(); + } + + // ------------------------------- Tutorial WP page ------------------------------- + if (currentTourPart === "startWpTour" || url.searchParams.get("start_onboarding_tour")) { + workPackageTour(); + } + + // ------------------------------- Tutorial Backlogs page ------------------------------- + if (url.searchParams.get("start_scrum_onboarding_tour")) { + if ($('.backlogs-menu-item').length > 0) { + backlogsTour(); + } + } + + // ------------------------------- Tutorial Task Board page ------------------------------- + if (currentTourPart === "startTaskBoardTour") { + taskboardTour(); + } + } + + function demoProjectsLinks() { + demoProjects = []; + demoProjectsLink = jQuery(".widget-box.welcome a:contains(" + demoProjectName + ")"); + scrumDemoProjectsLink = jQuery(".widget-box.welcome a:contains(" + scrumDemoProjectName + ")"); + if (demoProjectsLink.length) demoProjects.push(demoProjectsLink); + if (scrumDemoProjectsLink.length) demoProjects.push(scrumDemoProjectsLink); + + return demoProjects; + } + + function initializeTour(storageValue, disabledElements, projectSelection) { + tutorialInstance = new EnjoyHint({ + onStart: function () { + $('#content-wrapper, #menu-sidebar').addClass('-hidden-overflow'); + }, + onEnd: function () { + sessionStorage.setItem(storageKey, storageValue); + $('#content-wrapper, #menu-sidebar').removeClass('-hidden-overflow'); + }, + onSkip: function () { + sessionStorage.setItem(storageKey, 'skipped'); + if (disabledElements) jQuery(disabledElements).removeClass('-disabled').unbind('click', preventClickHandler); + if (projectSelection) $.each(demoProjectsLinks(), function(i, e) { $(e).off('click')}); + $('#content-wrapper, #menu-sidebar').removeClass('-hidden-overflow'); + } + }); + } + + function startTour(steps) { + tutorialInstance.set(steps); + tutorialInstance.run(); + } + + function homescreenTour() { + initializeTour('startProjectTour', '.widget-box--blocks--buttons a', true); + startTour(homescreenOnboardingTourSteps); + } + + function backlogsTour() { + initializeTour('startTaskBoardTour'); + startTour(scrumBacklogsTourSteps); + } + + function taskboardTour() { + initializeTour('startWpTour'); + startTour(scrumTaskBoardTourSteps); + } + + function workPackageTour() { + initializeTour('wpFinished'); + + waitForElement('.work-package--results-tbody', '.work-packages-split-view--tabletimeline-side', function() { + startTour(wpOnboardingTourSteps); + }); + } + }); +}(jQuery)); diff --git a/app/assets/javascripts/onboarding/work_package_tour.js b/app/assets/javascripts/onboarding/work_package_tour.js new file mode 100644 index 0000000000..05395c51bb --- /dev/null +++ b/app/assets/javascripts/onboarding/work_package_tour.js @@ -0,0 +1,64 @@ +(function ($) { + $(function() { + window.wpOnboardingTourSteps = [ + { + 'next .wp-table--row': I18n.t('js.onboarding.steps.wp_list'), + 'showSkip': false, + onNext: function () { + $(".wp-table--cell-span.id a ")[0].click(); + } + }, + { + 'next .work-packages-full-view--split-left': I18n.t('js.onboarding.steps.wp_full_view'), + 'showSkip': false, + 'containerClass': '-dark -hidden-arrow' + }, + { + 'next .work-packages-list-view-button': I18n.t('js.onboarding.steps.wp_back_button'), + 'showSkip': false, + onNext: function () { + $('.work-packages-list-view-button')[0].click(); + } + }, + { + 'next .add-work-package': I18n.t('js.onboarding.steps.wp_create_button'), + 'showSkip': false, + 'shape': 'circle' + }, + { + 'next .timeline-toolbar--button': I18n.t('js.onboarding.steps.wp_timeline_button'), + 'showSkip': false, + 'shape': 'circle', + onNext: function () { + $('.timeline-toolbar--button')[0].click(); + } + }, + { + 'next .work-packages-tabletimeline--timeline-side': I18n.t('js.onboarding.steps.wp_timeline'), + 'showSkip': false, + 'containerClass': '-dark -hidden-arrow' + }, + { + 'next .main-menu--arrow-left-to-project': I18n.t('js.onboarding.steps.sidebar_arrow'), + 'showSkip': false, + onNext: function () { + $('.main-menu--arrow-left-to-project')[0].click(); + } + }, + { + 'next .members-menu-item': I18n.t('js.onboarding.steps.members'), + 'showSkip': false + }, + { + 'next .wiki-menu--main-item': I18n.t('js.onboarding.steps.wiki'), + 'showSkip': false + }, + { + 'next .menu-item--help': I18n.t('js.onboarding.steps.help_menu'), + 'shape': 'circle', + 'nextButton': {text: I18n.t('js.onboarding.steps.got_it')}, + 'showSkip': false + } + ]; + }); +}(jQuery)) diff --git a/app/assets/javascripts/settings.js.erb b/app/assets/javascripts/settings.js.erb index 82a21f54a2..aa81c73aab 100644 --- a/app/assets/javascripts/settings.js.erb +++ b/app/assets/javascripts/settings.js.erb @@ -100,5 +100,26 @@ See docs/COPYRIGHT.rdoc for more details. .removeAttr('required') // Rails 4.0 still seems to use attribute .prop('required', wasChecked); }) + + /** Toggle highlighted attributes visibility depending on if the highlighting mode 'inline' was selected*/ + $('.settings--highlighting-mode select').change(function() { + var highlightingMode = $(this).val(); + $(".settings--highlighted-attributes").toggle(highlightingMode === "inline") + }) + + /** Initialize hightlighted attributes checkboxes. If none is selected, it means we want them all. So let's + * show them all as selected. + * On submitting the form, we remove all checkboxes before sending to communicate, we actually want all and not + * only the selected.*/ + if ($(".settings--highlighted-attributes input[type='checkbox']:checked").length == 0) { + $(".settings--highlighted-attributes input[type='checkbox']").prop("checked", true); + } + $('#tab-content-work_packages form').submit(function() { + var availableAttributes = $(".settings--highlighted-attributes input[type='checkbox']"); + var selectedAttributes = $(".settings--highlighted-attributes input[type='checkbox']:checked"); + if (selectedAttributes.length == availableAttributes.length) { + availableAttributes.prop("checked", false); + } + }) }); }(jQuery)); diff --git a/app/assets/javascripts/specific/main_menu.js.erb b/app/assets/javascripts/specific/main_menu.js.erb index 3d5c97f552..458c9787ec 100644 --- a/app/assets/javascripts/specific/main_menu.js.erb +++ b/app/assets/javascripts/specific/main_menu.js.erb @@ -115,4 +115,8 @@ jQuery(document).ready(function($) { $(child).before(header); }) + if($('.menu_root').hasClass('closed')) { + // TODO: Instead of hiding the sidebar move sidebar's contents to submenus and cache it. + $('#sidebar').toggleClass('-hidden', true); + } }); diff --git a/app/assets/javascripts/vendor/enjoyhint.js b/app/assets/javascripts/vendor/enjoyhint.js new file mode 100755 index 0000000000..4de8647ddc --- /dev/null +++ b/app/assets/javascripts/vendor/enjoyhint.js @@ -0,0 +1,1589 @@ +var EnjoyHint; + +(function ($) { + EnjoyHint = function (_options) { + var $event_element; + var that = this; + + var defaults = { + + onStart: function () { + + }, + + onEnd: function () { + + }, + + onSkip: function () { + + }, + + onNext: function () { + + } + }; + + var options = $.extend(defaults, _options); + var data = []; + var current_step = 0; + + $body = $('body'); + + + /********************* PRIVATE METHODS ***************************************/ + + var init = function () { + + if ($('.enjoyhint')) { + + $('.enjoyhint').remove(); + } + + $body.css({'overflow':'hidden'}); + $body.addClass('enjoyhint-tutorial'); + + $(document).on("touchmove",lockTouch); + + $body.enjoyhint({ + + onNextClick: function () { + + if (data[current_step].onNext && typeof data[current_step].onNext === 'function') { + data[current_step].onNext(); + } + + nextStep(); + }, + + onSkipClick: function () { + + options.onSkip(); + skipAll(); + } + }); + }; + + var lockTouch = function(e) { + + e.preventDefault(); + }; + + var destroyEnjoy = function () { + + $('.enjoyhint').remove(); + $body.css({'overflow':'auto'}); + $body.removeClass('enjoyhint-tutorial'); + $(document).off("touchmove", lockTouch); + }; + + that.clear = function(){ + + var $nextBtn = $('.enjoyhint_next_btn'); + var $skipBtn = $('.enjoyhint_skip_btn'); + + $nextBtn.removeClass(that.nextUserClass); + $nextBtn.text("Next"); + $skipBtn.removeClass(that.skipUserClass); + $skipBtn.text("Skip"); + }; + + var stepAction = function () { + + if (!(data && data[current_step])) { + + $body.enjoyhint('hide'); + options.onEnd(); + destroyEnjoy(); + return; + } + + options.onNext(); + + var $enjoyhint = $('.enjoyhint'); + var step_data = data[current_step]; + + // Remove all classes + $enjoyhint.removeClass(); + $enjoyhint.addClass("enjoyhint enjoyhint-step-" + (current_step + 1)); + if (step_data.clickable) $enjoyhint.addClass('-clickable'); + if (step_data.containerClass) $enjoyhint.addClass(step_data.containerClass); + + + if (step_data.onBeforeStart && typeof step_data.onBeforeStart === 'function') { + + step_data.onBeforeStart(); + } + + var timeout = step_data.timeout || 0; + + setTimeout(function () { + + if (!step_data.selector) { + + for (var prop in step_data) { + + if (step_data.hasOwnProperty(prop) && prop.split(" ")[1]) { + + step_data.selector = prop.split(" ")[1]; + step_data.event = prop.split(" ")[0]; + + if (prop.split(" ")[0] == 'next' || prop.split(" ")[0] == 'auto' || prop.split(" ")[0] == 'custom') { + + step_data.event_type = prop.split(" ")[0]; + } + + step_data.description = step_data[prop]; + } + } + } + + setTimeout(function () { + + that.clear(); + }, 250); + + $(document.body).scrollTop(step_data.selector, step_data.scrollAnimationSpeed || 250, {offset: -100}); + + setTimeout(function () { + + var $element = $(step_data.selector); + var event = makeEventName(step_data.event); + + $body.enjoyhint('show'); + $body.enjoyhint('hide_next'); + $event_element = $element; + + if (step_data.event_selector) { + + $event_element = $(step_data.event_selector); + } + + if (!step_data.event_type && step_data.event == "key") { + + $element.keydown(function (event) { + + if (event.which == step_data.keyCode) { + + current_step++; + stepAction(); + } + }); + } + + if (step_data.showNext == true) { + + $body.enjoyhint('show_next'); + } + + if (step_data.showSkip == false) { + + $body.enjoyhint('hide_skip'); + } else { + + $body.enjoyhint('show_skip'); + } + + if (step_data.showSkip == true) { + + } + + if (step_data.nextButton) { + + var $nextBtn = $('.enjoyhint_next_btn'); + + $nextBtn.addClass(step_data.nextButton.className || ""); + $nextBtn.text(step_data.nextButton.text || "Next"); + that.nextUserClass = step_data.nextButton.className; + } + + if (step_data.skipButton) { + + var $skipBtn = $('.enjoyhint_skip_btn'); + + $skipBtn.addClass(step_data.skipButton.className || ""); + $skipBtn.text(step_data.skipButton.text || "Skip"); + that.skipUserClass = step_data.skipButton.className; + } + + if (step_data.event_type) { + + switch (step_data.event_type) { + + case 'auto': + + $element[step_data.event](); + + switch (step_data.event) { + + case 'click': + break; + } + + current_step++; + stepAction(); + + return; + break; + + case 'custom': + + on(step_data.event, function () { + + current_step++; + off(step_data.event); + stepAction(); + }); + + break; + + case 'next': + + $body.enjoyhint('show_next'); + break; + } + + } else { + + $event_element.on(event, function (e) { + + if (step_data.keyCode && e.keyCode != step_data.keyCode) { + + return; + } + + current_step++; + $(this).off(event); + + stepAction(); // clicked + }); + } + + var max_habarites = Math.max($element.outerWidth(), $element.outerHeight()); + var radius = step_data.radius || Math.round(max_habarites / 2) + 5; + var offset = $element.offset(); + var w = $element.outerWidth(); + var h = $element.outerHeight(); + var shape_margin = (step_data.margin !== undefined) ? step_data.margin : 10; + + var coords = { + x: offset.left + Math.round(w / 2), + y: offset.top + Math.round(h / 2) - $(document).scrollTop() + }; + + var shape_data = { + enjoyHintElementSelector: step_data.selector, + center_x: coords.x, + center_y: coords.y, + text: step_data.description, + top: step_data.top, + bottom: step_data.bottom, + left: step_data.left, + right: step_data.right, + margin: step_data.margin, + scroll: step_data.scroll + }; + + if (step_data.shape && step_data.shape == 'circle') { + + shape_data.shape = 'circle'; + shape_data.radius = radius; + } else { + + shape_data.radius = 0; + shape_data.width = w + shape_margin; + shape_data.height = h + shape_margin; + } + + $body.enjoyhint('render_label_with_shape', shape_data, that.stop); + }, step_data.scrollAnimationSpeed + 20 || 270); + }, timeout); + }; + + var nextStep = function() { + + current_step++; + stepAction(); + }; + + var skipAll = function() { + + var step_data = data[current_step]; + var $element = $(step_data.selector); + + off(step_data.event); + $element.off(makeEventName(step_data.event)); + + destroyEnjoy(); + }; + + var makeEventName = function (name, is_custom) { + + return name + (is_custom ? 'custom' : '') + '.enjoy_hint'; + }; + + var on = function (event_name, callback) { + + $body.on(makeEventName(event_name, true), callback); + }; + + var off = function (event_name) { + + $body.off(makeEventName(event_name, true)); + }; + + + /********************* PUBLIC METHODS ***************************************/ + + window.addEventListener('resize', function() { + + if ($event_element != null) { + + $body.enjoyhint('redo_events_near_rect', $event_element[0].getBoundingClientRect()); + } + }); + + that.stop = function() { + + skipAll(); + }; + + that.reRunScript = function(cs) { + + current_step = cs; + stepAction(); + }; + + that.runScript = function () { + + current_step = 0; + options.onStart(); + stepAction(); + }; + + that.resumeScript = function () { + + stepAction(); + }; + + that.setCurrentStep = function(cs) { + + current_step = cs; + }; + + that.getCurrentStep = function () { + + return current_step; + }; + + that.trigger = function (event_name) { + + switch (event_name) { + + case 'next': + + nextStep(); + break; + + case 'skip': + + skipAll(); + break; + } + }; + + that.setScript = function (_data) { + + if (_data) { + + data = _data; + } + }; + + //support deprecated API methods + that.set = function (_data) { + + that.setScript(_data); + }; + + that.setSteps = function (_data) { + + that.setScript(_data); + }; + + that.run = function () { + + that.runScript(); + }; + + that.resume = function () { + + that.resumeScript(); + }; + + init(); + };;CanvasRenderingContext2D.prototype.roundRect = function (x, y, w, h, r) { + + if (w < 2 * r) r = w / 2; + if (h < 2 * r) r = h / 2; + this.beginPath(); + this.moveTo(x + r, y); + this.arcTo(x + w, y, x + w, y + h, r); + this.arcTo(x + w, y + h, x, y + h, r); + this.arcTo(x, y + h, x, y, r); + this.arcTo(x, y, x + w, y, r); + this.closePath(); + return this; + }; + + (function ($) { + + var that; + + var originalLabelLeft, originalLabelTop; + var originalArrowLeft, originalArrowTop; + var originalCenterX, originalCenterY; + var originalSkipbuttonLeft, originalSkipbuttonTop; + var prevWindowWidth, prevWindowHeight; + var originalWidth = window.innerWidth, originalHeight = window.innerHeight; + + var methods = { + + init: function (options) { + + return this.each(function () { + + var defaults = { + + onNextClick: function () { + + }, + onSkipClick: function () { + + }, + + animation_time: 800 + }; + + this.enjoyhint_obj = {}; + that = this.enjoyhint_obj; + + that.resetComponentStuff = function() { + + originalLabelLeft = null; + originalLabelTop = null; + originalArrowLeft = null; + originalArrowTop = null; + originalCenterX = null; + originalCenterY = null; + originalSkipbuttonLeft = null; + originalSkipbuttonTop = null; + prevWindowWidth = null; + prevWindowHeight = null; + originalWidth = window.innerWidth; + originalHeight = window.innerHeight; + }; + + + var $that = $(this); + that.options = jQuery.extend(defaults, options); + + //general classes + that.gcl = { + + chooser: 'enjoyhint' + }; + + // classes + that.cl = { + + enjoy_hint: 'enjoyhint', + hide: 'enjoyhint_hide', + disable_events_element: 'enjoyhint_disable_events', + btn: 'enjoyhint_btn', + skip_btn: 'enjoyhint_skip_btn', + close_btn: 'enjoyhint_close_btn', + next_btn: 'enjoyhint_next_btn', + main_canvas: 'enjoyhint_canvas', + main_svg: 'enjoyhint_svg', + svg_wrapper: 'enjoyhint_svg_wrapper', + svg_transparent: 'enjoyhint_svg_transparent', + kinetic_container: 'kinetic_container' + }; + + function makeSVG(tag, attrs) { + + var el = document.createElementNS('http://www.w3.org/2000/svg', tag); + + for (var k in attrs) { + + el.setAttribute(k, attrs[k]); + } + + return el; + } + + + // ======================================================================= + // ========================---- enjoyhint ----============================== + // ======================================================================= + + that.canvas_size = { + + w: $(window).width()*1.4, + h: $(window).height()*1.4 + }; + + var canvas_id = "enj_canvas"; + + that.enjoyhint = $('
', {'class': that.cl.enjoy_hint + ' ' + that.cl.svg_transparent}).appendTo($that); + that.enjoyhint_svg_wrapper = $('
', {'class': that.cl.svg_wrapper + ' ' + that.cl.svg_transparent}).appendTo(that.enjoyhint); + that.$stage_container = $('
').appendTo(that.enjoyhint); + that.$canvas = $('').appendTo(that.enjoyhint); + that.$svg = $('').appendTo(that.enjoyhint_svg_wrapper); + + var defs = $(makeSVG('defs')); + var marker = $(makeSVG('marker', {id: "arrowMarker", viewBox: "0 0 36 21", refX: "21", refY: "10", markerUnits: "strokeWidth", orient: "auto", markerWidth: "16", markerHeight: "12"})); + var polilyne = $(makeSVG('path', {style: "fill:none; stroke:rgb(255,255,255); stroke-width:2", d: "M0,0 c30,11 30,9 0,20"})); + + defs.append(marker.append(polilyne)).appendTo(that.$svg); + + that.kinetic_stage = new Kinetic.Stage({ + container: that.cl.kinetic_container, + width: that.canvas_size.w, + height: that.canvas_size.h, + scaleX: 1 + }); + + that.layer = new Kinetic.Layer(); + that.rect = new Kinetic.Rect({ + fill: 'rgba(0,0,0,0.6)', + width: that.canvas_size.w, + height: that.canvas_size.h + }); + + var $top_dis_events = $('
', {'class': that.cl.disable_events_element}).appendTo(that.enjoyhint); + var $bottom_dis_events = $top_dis_events.clone().appendTo(that.enjoyhint); + var $left_dis_events = $top_dis_events.clone().appendTo(that.enjoyhint); + var $right_dis_events = $top_dis_events.clone().appendTo(that.enjoyhint); + + var stopPropagation = function(e) { + + e.stopImmediatePropagation(); + }; + + $("button").focusout(stopPropagation); + $top_dis_events.click(stopPropagation); + $bottom_dis_events.click(stopPropagation); + $left_dis_events.click(stopPropagation); + $right_dis_events.click(stopPropagation); + + + that.$skip_btn = $('
', {'class': that.cl.skip_btn}).appendTo(that.enjoyhint).html('Skip').click(function (e) { + + that.hide(); + that.options.onSkipClick(); + }); + that.$next_btn = $('
', {'class': that.cl.next_btn}).appendTo(that.enjoyhint).html('Next').click(function (e) { + + that.options.onNextClick(); + }); + + that.$close_btn = $('
', {'class': that.cl.close_btn}).appendTo(that.enjoyhint).html('').click(function (e) { + + that.hide(); + that.options.onSkipClick(); + }); + + that.$canvas.mousedown(function (e) { + + $('canvas').css({left: '4000px'}); + + var BottomElement = document.elementFromPoint(e.clientX, e.clientY); + $('canvas').css({left: '0px'}); + + $(BottomElement).click(); + + return false; + }); + + + var circle_r = 0; + var shape_init_shift = 130; + + that.shape = new Kinetic.Shape({ + radius: circle_r, + center_x: -shape_init_shift, + center_y: -shape_init_shift, + width: 0, + height: 0, + sceneFunc: function (context) { + + var ctx = this.getContext("2d")._context; + var pos = this.pos; + var def_comp = ctx.globalCompositeOperation; + ctx.globalCompositeOperation = 'destination-out'; + ctx.beginPath(); + + var x = this.attrs.center_x - Math.round(this.attrs.width / 2); + var y = this.attrs.center_y - Math.round(this.attrs.height / 2); + ctx.roundRect(x, y, this.attrs.width, this.attrs.height, this.attrs.radius); + ctx.fillStyle = "red"; + ctx.fill(); + + ctx.globalCompositeOperation = def_comp; + } + }); + + that.shape.radius = circle_r; + that.layer.add(that.rect); + that.layer.add(that.shape); + that.kinetic_stage.add(that.layer); + + $(window).on('resize', function() { + + if (!($(that.stepData.enjoyHintElementSelector).is(":visible"))) { + + that.stopFunction(); + $(window).off('resize'); + return; + } + + prevWindowWidth = window.innerWidth; + prevWindowHeight = window.innerHeight; + + var boundingClientRect = $(that.stepData.enjoyHintElementSelector)[0].getBoundingClientRect(); + + that.shape.attrs.center_x = Math.round(boundingClientRect.left + boundingClientRect.width / 2); + that.shape.attrs.center_y = Math.round(boundingClientRect.top + boundingClientRect.height / 2); + that.shape.attrs.width = boundingClientRect.width + 11; + that.shape.attrs.height = boundingClientRect.height + 11; + + var newWidth = window.innerWidth; + var newHeight = window.innerHeight; + var scaleX = newWidth / originalWidth; + var scaleY = newHeight / originalHeight; + + that.kinetic_stage.setAttr('width', originalWidth * scaleX); + that.kinetic_stage.setAttr('height', originalHeight * scaleY); + + if (that.stepData != null) { + + prevWindowWidth = window.innerWidth; + prevWindowHeight = window.innerHeight; + + + /* Init */ + + if (!originalCenterX) { + + originalCenterX = that.shape.attrs.center_x; + originalCenterY = that.shape.attrs.center_y; + } + + if (!originalArrowLeft) { + + originalArrowLeft = []; + var attr = $('#enjoyhint_arrpw_line').attr('d'); + originalArrowLeft.push(attr.substr(1).split(',')[0]); + originalArrowLeft.push(attr.substr(attr.indexOf('Q') + 1).split(',')[0]); + originalArrowLeft.push(attr.split(' ')[2].split(',')[0]); + originalArrowTop = []; + originalArrowTop.push(attr.split(',')[1].split(' ')[0]); + originalArrowTop.push(attr.split(',')[2].split(' ')[0]); + originalArrowTop.push(attr.split(',')[3]); + } + + var labelElement = $('.enjoy_hint_label'); + + if (!originalLabelLeft) { + + originalLabelLeft = labelElement[0].getBoundingClientRect().left; + originalLabelTop = labelElement[0].getBoundingClientRect().top; + } + + var skipButton = $('.enjoyhint_skip_btn'); + + if (!originalSkipbuttonLeft) { + + originalSkipbuttonLeft = skipButton[0].getBoundingClientRect().left; + originalSkipbuttonTop = skipButton[0].getBoundingClientRect().top; + } + + + /* Resizing label */ + + labelElement.css('left', window.innerWidth / 2 - labelElement.outerWidth() / 2); + + + /* Resizing arrow */ + + var labelRect = labelElement[0].getBoundingClientRect(); + + if (window.innerWidth < 640) { + + $('#enjoyhint_arrpw_line').hide(); + labelElement.css('top', window.innerHeight / 2 - labelElement.outerHeight() / 2); + } else { + + $('#enjoyhint_arrpw_line').show(); + + labelElement.css('top', originalLabelTop); + + var x1, x2, y1, y2; + + var labelLeftOfShape = labelRect.left + labelRect.width / 2 < that.shape.attrs.center_x; + var labelAboveShape = labelRect.top + labelRect.height / 2 < that.shape.attrs.center_y; + + if (window.innerWidth < 900) { + + x1 = Math.round(labelRect.left + (labelRect.width / 2 + 15) * (labelRect.left + labelRect.width / 2 < that.shape.attrs.center_x ? 1 : -1)); + y1 = Math.round(labelRect.top + labelRect.height * (labelRect.top + labelRect.height / 2 < that.shape.attrs.center_y ? 1 : -1)); + x2 = Math.round(that.shape.attrs.center_x + (that.shape.attrs.radius + 15) * (labelLeftOfShape ? -1 : 1)); + y2 = Math.round(that.shape.attrs.center_y); + } else { + + x1 = Math.round((labelRect.left + (labelRect.width / 2)) + ((labelRect.width / 2 + 15) * (labelLeftOfShape ? 1 : -1))); + y1 = Math.round(labelRect.top + labelRect.height / 2); + x2 = Math.round(that.shape.attrs.center_x); + y2 = Math.round(that.shape.attrs.center_y + (((that.shape.attrs.height / 2) + 15) * (labelAboveShape ? -1 : 1))); + } + + var midX = x1 + (x2 - x1) / 2; + var midY = y1 + (y2 - y1) / 2; + + var bezX = x1 < x2 ? x2 : x1; + var bezY = y1 < y2 ? y1 : y2; + + if (Math.abs(labelRect.left + labelRect.width / 2 - that.shape.attrs.center_x) < 200) { + + x1 = x2 = labelRect.left + labelRect.width / 2; + y1 = labelRect.top; + bezX = x1; + bezY = y1; + console.log("ok"); + } + + if (window.innerWidth < 900) { + + bezX = x1 < x2 ? x1 : x2; + bezY = y1 < y2 ? y2 : y1; + } + + var newCoordsLine = "M%d1,%d2 Q%d3,%d4 %d5,%d6" + .replace("%d1", x1).replace("%d2", y1) + .replace("%d3", bezX).replace("%d4", bezY) + .replace("%d5", x2).replace("%d6", y2); + $('#enjoyhint_arrpw_line')[0].setAttribute('d', newCoordsLine); + } + + + /* Resizing skip button */ + + var newSkipbuttonLeft = +originalSkipbuttonLeft + (that.shape.attrs.center_x - originalCenterX) / 2; + skipButton.css('left', newSkipbuttonLeft < 15 ? 15 : newSkipbuttonLeft); + skipButton.css('top', labelRect.top + labelRect.height + 20); + } + + that.rect = new Kinetic.Rect({ + fill: 'rgba(0,0,0,0.6)', + width: window.innerWidth, + height: window.innerHeight + }); + + that.layer.removeChildren(); + that.layer.add(that.rect); + that.layer.add(that.shape); + that.layer.draw(); + that.kinetic_stage.draw(); + }); + + var enjoyhint_elements = [ + that.enjoyhint, + $top_dis_events, + $bottom_dis_events, + $left_dis_events, + $right_dis_events + ]; + + that.show = function () { + + that.enjoyhint.removeClass(that.cl.hide); + }; + + that.hide = function () { + + that.enjoyhint.addClass(that.cl.hide); + + var tween = new Kinetic.Tween({ + node: that.shape, + duration: 0.002, + center_x: -shape_init_shift, + center_y: -shape_init_shift + }); + + tween.play(); + }; + + that.hide(); + + that.hideNextBtn = function () { + + that.$next_btn.addClass(that.cl.hide); + that.nextBtn = "hide"; + }; + + that.showNextBtn = function () { + + that.$next_btn.removeClass(that.cl.hide); + that.nextBtn = "show"; + }; + + that.hideSkipBtn = function () { + + that.$skip_btn.addClass(that.cl.hide); + }; + + that.showSkipBtn = function () { + + that.$skip_btn.removeClass(that.cl.hide); + }; + + that.renderCircle = function (data) { + + var r = data.r || 0; + var x = data.x || 0; + var y = data.y || 0; + + var tween = new Kinetic.Tween({ + node: that.shape, + duration: 0.2, + center_x: x, + center_y: y, + width: r * 2, + height: r * 2, + radius: r + }); + + tween.play(); + + var left = x - r; + var right = x + r; + var top = y - r; + var bottom = y + r; + var margin = 20; + + return { + x: x, + y: y, + left: left, + right: right, + top: top, + bottom: bottom, + conn: { + left: { + x: left - margin, + y: y + }, + right: { + x: right + margin, + y: y + }, + top: { + x: x, + y: top - margin + }, + bottom: { + x: x, + y: bottom + margin + } + } + }; + + }; + + that.renderRect = function (data, timeout) { + + var r = data.r || 0; + var x = data.x || 0; + var y = data.y || 0; + var w = data.w || 0; + var h = data.h || 0; + var margin = 20; + + var tween = new Kinetic.Tween({ + node: that.shape, + duration: timeout, + center_x: x, + center_y: y, + width: w, + height: h, + radius: r + }); + + tween.play(); + + var half_w = Math.round(w / 2); + var half_h = Math.round(h / 2); + var left = x - half_w; + var right = x + half_w; + var top = y - half_h; + var bottom = y + half_h; + + return { + x: x, + y: y, + left: left, + right: right, + top: top, + bottom: bottom, + conn: { + left: { + x: left - margin, + y: y + }, + right: { + x: right + margin, + y: y + }, + top: { + x: x, + y: top - margin + }, + bottom: { + x: x, + y: bottom + margin + } + } + }; + }; + + that.renderLabel = function (data) { + + var x = data.x || 0; + that.originalElementX = x; + var y = data.y || 0; + var text = data.text || 0; + + var label = that.getLabelElement({ + x: x, + y: y, + text: data.text + }); + + var label_w = label.width(); + var label_h = label.height(); + var label_left = label.offset().left; + var label_right = label.offset().left + label_w; + var label_top = label.offset().top - $(document).scrollTop(); + var label_bottom = label.offset().top + label_h; + + var margin = 10; + + var conn_left = { + x: label_left - margin, + y: label_top + Math.round(label_h / 2) + }; + + var conn_right = { + x: label_right + margin, + y: label_top + Math.round(label_h / 2) + }; + + var conn_top = { + x: label_left + Math.round(label_w / 2), + y: label_top - margin + }; + + var conn_bottom = { + x: label_left + Math.round(label_w / 2), + y: label_bottom + margin + }; + + label.detach(); + + setTimeout(function () { + + $('#enjoyhint_label').remove(); + label.appendTo(that.enjoyhint); + }, that.options.animation_time / 2); + + return { + label: label, + left: label_left, + right: label_right, + top: label_top, + bottom: label_bottom, + conn: { + left: conn_left, + right: conn_right, + top: conn_top, + bottom: conn_bottom + } + + }; + }; + + that.renderArrow = function (data) { + + if (window.innerWidth >= 640) { + + var x_from = data.x_from || 0; + var y_from = data.y_from || 0; + var x_to = data.x_to || 0; + var y_to = data.y_to || 0; + var by_top_side = data.by_top_side; + var control_point_x = 0; + var control_point_y = 0; + if (by_top_side) { + + if (y_from >= y_to) { + + control_point_y = y_to; + control_point_x = x_from; + } else { + + control_point_y = y_from; + control_point_x = x_to; + } + } else { + + if (y_from >= y_to) { + + control_point_y = y_from; + control_point_x = x_to; + } else { + + control_point_y = y_to; + control_point_x = x_from; + } + } + } + + + var text = data.text || ''; + that.enjoyhint.addClass(that.cl.svg_transparent); + + setTimeout(function () { + + $('#enjoyhint_arrpw_line').remove(); + + var d = 'M' + x_from + ',' + y_from + ' Q' + control_point_x + ',' + control_point_y + ' ' + x_to + ',' + y_to; + that.$svg.append(makeSVG('path', {style: "fill:none; stroke:rgb(255,255,255); stroke-width:3", 'marker-end': "url(" + location.href + "#arrowMarker)", d: d, id: 'enjoyhint_arrpw_line'})); + that.enjoyhint.removeClass(that.cl.svg_transparent); + + }, that.options.animation_time / 2); + }; + + that.getLabelElement = function (data) { + + return $('
', {"class": 'enjoy_hint_label', id: 'enjoyhint_label'}) + .css({ + 'top': data.y + 'px', + 'left': data.x + 'px' + }) + .html(data.text).appendTo(that.enjoyhint); + }; + + + that.disableEventsNearRect = function (rect) { + + $top_dis_events.css({ + top: '0', + left: '0' + }).height(rect.top); + + $bottom_dis_events.css({ + top: rect.bottom + 'px', + left: '0' + }); + + $left_dis_events.css({ + top: '0', + left: 0 + 'px' + }).width(rect.left); + + $right_dis_events.css({ + top: '0', + left: rect.right + 'px' + }); + }; + + (function($) { + + $.event.special.destroyed = { + + remove: function(o) { + + if (o.handler) { + + o.handler() + } + } + } + })(jQuery); + + that.renderLabelWithShape = function (data) { + + that.stepData = data; + + function findParentDialog(element) { + + if (element.tagName === "MD-DIALOG") { + + return element; + } else if (typeof element.tagName == "undefined") { + + return null; + } else { + + return findParentDialog($(element).parent()[0]); + } + } + + var dialog = findParentDialog($(that.stepData.enjoyHintElementSelector)[0]); + + if (dialog != null) { + + $(dialog).on('dialogClosing', function() { + + that.stopFunction(); + return; + }); + } + + that.resetComponentStuff(); + + var shape_type = data.shape || 'rect'; + var shape_data = {}; + + var half_w = 0; + var half_h = 0; + + var shape_offsets = { + top: data.top || 0, + bottom: data.bottom || 0, + left: data.left || 0, + right: data.right || 0 + }; + + switch (shape_type) { + + case 'circle': + + half_w = half_h = data.radius; + + var sides_pos = { + top: data.center_y - half_h + shape_offsets.top, + bottom: data.center_y + half_h - shape_offsets.bottom, + left: data.center_x - half_w + shape_offsets.left, + right: data.center_x + half_w - shape_offsets.right + }; + + var width = sides_pos.right - sides_pos.left; + var height = sides_pos.bottom - sides_pos.top; + data.radius = Math.round(Math.min(width, height) / 2); + + //new half habarites + half_w = half_h = Math.round(data.radius / 2); + + var new_half_w = Math.round(width / 2); + var new_half_h = Math.round(height / 2); + + //new center_x and center_y + data.center_x = sides_pos.left + new_half_w; + data.center_y = sides_pos.top + new_half_h; + + shape_data = that.renderCircle({ + x: data.center_x, + y: data.center_y, + r: data.radius + }); + + break; + + case 'rect': + + half_w = Math.round(data.width / 2); + half_h = Math.round(data.height / 2); + + var sides_pos = { + top: data.center_y - half_h + shape_offsets.top, + bottom: data.center_y + half_h - shape_offsets.bottom, + left: data.center_x - half_w + shape_offsets.left, + right: data.center_x + half_w - shape_offsets.right + }; + + data.width = sides_pos.right - sides_pos.left; + data.height = sides_pos.bottom - sides_pos.top; + + half_w = Math.round(data.width / 2); + half_h = Math.round(data.height / 2); + + //new center_x and center_y + data.center_x = sides_pos.left + half_w; + data.center_y = sides_pos.top + half_h; + + shape_data = that.renderRect({ + x: data.center_x, + y: data.center_y, + w: data.width, + h: data.height, + r: data.radius + }, 0.2); + + break; + } + + var body_size = { + w: that.enjoyhint.width(), + h: that.enjoyhint.height() + }; + + var label = that.getLabelElement({ + x: 0, + y: 0, + text: data.text + }); + + var label_width = label.outerWidth(); + var label_height = label.outerHeight(); + label.remove(); + var top_offset = data.center_y - half_h; + var bottom_offset = body_size.h - (data.center_y + half_h); + var left_offset = data.center_x - half_w; + var right_offset = body_size.w - (data.center_x + half_w); + + var label_hor_side = (body_size.w - data.center_x) < data.center_x ? 'left' : 'right'; + var label_ver_side = (body_size.h - data.center_y) < data.center_y ? 'top' : 'bottom'; + var label_shift = 150; + var label_margin = 40; + var label_shift_with_label_width = label_shift + label_width + label_margin; + var label_shift_with_label_height = label_shift + label_height + label_margin; + var label_hor_offset = half_w + label_shift; + var label_ver_offset = half_h + label_shift; + + //original: var label_x = (label_hor_side == 'left') ? data.center_x - label_hor_offset - label_width : data.center_x + label_hor_offset; + var label_y = (label_ver_side == 'top') ? data.center_y - label_ver_offset - label_height : data.center_y + label_ver_offset; + var label_x = window.innerWidth / 2 - label_width / 2; + + if (top_offset < label_shift_with_label_height && bottom_offset < label_shift_with_label_height) { + + label_y = data.center_y + label_margin; + } + + if (window.innerWidth <= 640) { + + } + + var label_data = that.renderLabel({ + x: label_x, + y: label_y, + text: data.text + }); + + var next_btn_x = window.innerWidth / 2 - that.$next_btn.width() / 2; + that.$next_btn.css({ + left: next_btn_x, + top: label_y + label_height + 20 + }); + + var left_skip = next_btn_x + that.$next_btn.width() + 10; + + if (that.nextBtn == "hide"){ + + left_skip = label_x; + } + + that.$skip_btn.css({ + left: left_skip, + top: label_y + label_height + 20 + }); + + that.$close_btn.css({ + right : 10, + top: 10 + }); + + that.disableEventsNearRect({ + top: shape_data.top, + bottom: shape_data.bottom, + left: shape_data.left, + right: shape_data.right + }); + + var x_to = 0; + var y_to = 0; + var arrow_side = false; + var conn_label_side = 'left'; + var conn_circle_side = 'left'; + + var is_center = (label_data.left <= shape_data.x && label_data.right >= shape_data.x); + var is_left = (label_data.right < shape_data.x); + var is_right = (label_data.left > shape_data.x); + + var is_abs_left = (label_data.right < shape_data.left); + var is_abs_right = (label_data.left > shape_data.right); + + var is_top = (label_data.bottom < shape_data.top); + var is_bottom = (label_data.top > shape_data.bottom); + var is_mid = (label_data.bottom >= shape_data.y && label_data.top <= shape_data.y); + var is_mid_top = (label_data.bottom <= shape_data.y && !is_top); + var is_mid_bottom = (label_data.top >= shape_data.y && !is_bottom); + + + function setArrowData(l_s, c_s, a_s) { + + conn_label_side = l_s; + conn_circle_side = c_s; + arrow_side = a_s; + } + + function sideStatements(top_s, mid_top_s, mid_s, mid_bottom_s, bottom_s) { + + var statement = []; + + if (is_top) { + + statement = top_s; + } else if (is_mid_top) { + + statement = mid_top_s; + } else if (is_mid) { + + statement = mid_s; + } else if (is_mid_bottom) { + + statement = mid_bottom_s; + } else {//bottom + + statement = bottom_s; + } + + if (!statement) { + + return; + } else { + + setArrowData(statement[0], statement[1], statement[2]); + } + } + + if (is_center) { + + if (is_top) { + + setArrowData('bottom', 'top', 'top'); + } else if (is_bottom) { + + setArrowData('top', 'bottom', 'bottom'); + } else { + + return; + } + + } else if (is_left) { + + sideStatements( + ['right', 'top', 'top'],//top + ['bottom', 'left', 'bottom'],//mid_top + ['right', 'left', 'top'],//mid + ['top', 'left', 'top'],//mid_bot + ['right', 'bottom', 'bottom']//bot + ); + + } else {//right + + sideStatements( + ['left', 'top', 'top'],//top + ['bottom', 'right', 'bottom'],//mid_top + ['left', 'right', 'top'],//mid + ['top', 'right', 'top'],//mid_bot + ['left', 'bottom', 'bottom']//bot + ); + + } + + var label_conn_coordinates = label_data.conn[conn_label_side]; + var circle_conn_coordinates = shape_data.conn[conn_circle_side]; + var by_top_side = (arrow_side == 'top'); + + that.renderArrow({ + x_from: label_conn_coordinates.x, + y_from: label_conn_coordinates.y, + x_to: window.innerWidth < 640 ? shape_data.left + (shape_data.left > 0) : circle_conn_coordinates.x, + y_to: window.innerWidth < 640 ? shape_data.conn.left.y : circle_conn_coordinates.y, + by_top_side: by_top_side + }); + + }; + + that.clear = function () { + + that.ctx.clearRect(0, 0, 3000, 2000); + }; + + return this; + }); + }, + + set: function (val) { + + this.each(function () { + + this.enjoyhint_obj.setValue(val); + }); + + return this; + }, + + show: function () { + + this.each(function () { + + this.enjoyhint_obj.show(); + }); + + return this; + }, + + hide: function () { + + this.each(function () { + + this.enjoyhint_obj.hide(); + }); + + return this; + }, + + hide_next: function () { + + this.each(function () { + + this.enjoyhint_obj.hideNextBtn(); + }); + + return this; + }, + + show_next: function () { + + this.each(function () { + + this.enjoyhint_obj.showNextBtn(); + }); + + return this; + }, + + hide_skip: function () { + + this.each(function () { + + this.enjoyhint_obj.hideSkipBtn(); + }); + + return this; + }, + + show_skip: function () { + + this.each(function () { + + this.enjoyhint_obj.showSkipBtn(); + }); + + return this; + }, + + render_circle: function (x, y, r) { + + this.each(function () { + + this.enjoyhint_obj.renderCircle(x, y, r); + }); + + return this; + }, + + render_label: function (x, y, r) { + + this.each(function () { + + this.enjoyhint_obj.renderLabel(x, y, r); + }); + + return this; + }, + + render_label_with_shape: function (data, stopFunction) { + + this.each(function () { + + that.stopFunction = stopFunction; + this.enjoyhint_obj.renderLabelWithShape(data); + }); + + return this; + }, + + redo_events_near_rect: function(rect) { + + that.disableEventsNearRect({ + top: rect.top, + bottom: rect.bottom, + left: rect.left, + right: rect.right + }); + }, + + clear: function () { + + this.each(function () { + + this.enjoyhint_obj.clear(); + }); + + return this; + }, + + close: function (val) { + + this.each(function () { + + this.enjoyhint_obj.closePopdown(); + }); + + return this; + } + }; + + $.fn.enjoyhint = function (method) { + + if (methods[method]) { + + return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); + } else if (typeof method === 'object' || !method) { + + return methods.init.apply(this, arguments); + } else { + + $.error('Method ' + method + ' does not exist on $.numinput'); + } + + return this; + }; + })(window.jQuery);;/*! KineticJS v5.2.0 2015-01-22 http://lavrton.github.io/KineticJS/ by Eric Rowell @ericdrowell, Anton Lavrenov @lavrton - MIT License https://github.com/lavrton/KineticJS/wiki/License*/ + var Kinetic={};!function(a){var b=Math.PI/180;Kinetic={version:"5.2.0",stages:[],idCounter:0,ids:{},names:{},shapes:{},listenClickTap:!1,inDblClickWindow:!1,enableTrace:!1,traceArrMax:100,dblClickWindow:400,pixelRatio:void 0,dragDistance:0,angleDeg:!0,showWarnings:!0,Filters:{},Node:function(a){this._init(a)},Shape:function(a){this.__init(a)},Container:function(a){this.__init(a)},Stage:function(a){this.___init(a)},BaseLayer:function(a){this.___init(a)},Layer:function(a){this.____init(a)},FastLayer:function(a){this.____init(a)},Group:function(a){this.___init(a)},isDragging:function(){var a=Kinetic.DD;return a?a.isDragging:!1},isDragReady:function(){var a=Kinetic.DD;return a?!!a.node:!1},_addId:function(a,b){void 0!==b&&(this.ids[b]=a)},_removeId:function(a){void 0!==a&&delete this.ids[a]},_addName:function(a,b){if(void 0!==b)for(var c=b.split(/\s/g),d=0;d"),Kinetic.window=Kinetic.document.createWindow(),Kinetic.window.Image=d.Image,Kinetic._nodeCanvas=d}return Kinetic.root=a,void(module.exports=c)}"function"==typeof define&&define.amd&&define(b),Kinetic.document=document,Kinetic.window=window,Kinetic.root=a}(this,function(){return Kinetic}),function(){Kinetic.Collection=function(){var a=[].slice.call(arguments),b=a.length,c=0;for(this.length=b;b>c;c++)this[c]=a[c];return this},Kinetic.Collection.prototype=[],Kinetic.Collection.prototype.each=function(a){for(var b=0;ba;a++)b.push(this[a]);return b},Kinetic.Collection.toCollection=function(a){var b,c=new Kinetic.Collection,d=a.length;for(b=0;d>b;b++)c.push(a[b]);return c},Kinetic.Collection._mapMethod=function(a){Kinetic.Collection.prototype[a]=function(){var b,c=this.length,d=[].slice.call(arguments);for(b=0;c>b;b++)this[b][a].apply(this[b],d);return this}},Kinetic.Collection.mapMethods=function(a){var b=a.prototype;for(var c in b)Kinetic.Collection._mapMethod(c)},Kinetic.Transform=function(a){this.m=a&&a.slice()||[1,0,0,1,0,0]},Kinetic.Transform.prototype={copy:function(){return new Kinetic.Transform(this.m)},point:function(a){var b=this.m;return{x:b[0]*a.x+b[2]*a.y+b[4],y:b[1]*a.x+b[3]*a.y+b[5]}},translate:function(a,b){return this.m[4]+=this.m[0]*a+this.m[2]*b,this.m[5]+=this.m[1]*a+this.m[3]*b,this},scale:function(a,b){return this.m[0]*=a,this.m[1]*=a,this.m[2]*=b,this.m[3]*=b,this},rotate:function(a){var b=Math.cos(a),c=Math.sin(a),d=this.m[0]*b+this.m[2]*c,e=this.m[1]*b+this.m[3]*c,f=this.m[0]*-c+this.m[2]*b,g=this.m[1]*-c+this.m[3]*b;return this.m[0]=d,this.m[1]=e,this.m[2]=f,this.m[3]=g,this},getTranslation:function(){return{x:this.m[4],y:this.m[5]}},skew:function(a,b){var c=this.m[0]+this.m[2]*b,d=this.m[1]+this.m[3]*b,e=this.m[2]+this.m[0]*a,f=this.m[3]+this.m[1]*a;return this.m[0]=c,this.m[1]=d,this.m[2]=e,this.m[3]=f,this},multiply:function(a){var b=this.m[0]*a.m[0]+this.m[2]*a.m[1],c=this.m[1]*a.m[0]+this.m[3]*a.m[1],d=this.m[0]*a.m[2]+this.m[2]*a.m[3],e=this.m[1]*a.m[2]+this.m[3]*a.m[3],f=this.m[0]*a.m[4]+this.m[2]*a.m[5]+this.m[4],g=this.m[1]*a.m[4]+this.m[3]*a.m[5]+this.m[5];return this.m[0]=b,this.m[1]=c,this.m[2]=d,this.m[3]=e,this.m[4]=f,this.m[5]=g,this},invert:function(){var a=1/(this.m[0]*this.m[3]-this.m[1]*this.m[2]),b=this.m[3]*a,c=-this.m[1]*a,d=-this.m[2]*a,e=this.m[0]*a,f=a*(this.m[2]*this.m[5]-this.m[3]*this.m[4]),g=a*(this.m[1]*this.m[4]-this.m[0]*this.m[5]);return this.m[0]=b,this.m[1]=c,this.m[2]=d,this.m[3]=e,this.m[4]=f,this.m[5]=g,this},getMatrix:function(){return this.m},setAbsolutePosition:function(a,b){var c=this.m[0],d=this.m[1],e=this.m[2],f=this.m[3],g=this.m[4],h=this.m[5],i=(c*(b-h)-d*(a-g))/(c*f-d*e),j=(a-g-e*i)/c;return this.translate(j,i)}};var a="2d",b="[object Array]",c="[object Number]",d="[object String]",e=Math.PI/180,f=180/Math.PI,g="#",h="",i="0",j="Kinetic warning: ",k="Kinetic error: ",l="rgb(",m={aqua:[0,255,255],lime:[0,255,0],silver:[192,192,192],black:[0,0,0],maroon:[128,0,0],teal:[0,128,128],blue:[0,0,255],navy:[0,0,128],white:[255,255,255],fuchsia:[255,0,255],olive:[128,128,0],yellow:[255,255,0],orange:[255,165,0],gray:[128,128,128],purple:[128,0,128],green:[0,128,0],red:[255,0,0],pink:[255,192,203],cyan:[0,255,255],transparent:[255,255,255,0]},n=/rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/;Kinetic.Util={_isElement:function(a){return!(!a||1!=a.nodeType)},_isFunction:function(a){return!!(a&&a.constructor&&a.call&&a.apply)},_isObject:function(a){return!!a&&a.constructor==Object},_isArray:function(a){return Object.prototype.toString.call(a)==b},_isNumber:function(a){return Object.prototype.toString.call(a)==c},_isString:function(a){return Object.prototype.toString.call(a)==d},_throttle:function(a,b,c){var d,e,f,g=null,h=0,i=c||{},j=function(){h=i.leading===!1?0:(new Date).getTime(),g=null,f=a.apply(d,e),d=e=null};return function(){var c=(new Date).getTime();h||i.leading!==!1||(h=c);var k=b-(c-h);return d=this,e=arguments,0>=k?(clearTimeout(g),g=null,h=c,f=a.apply(d,e),d=e=null):g||i.trailing===!1||(g=setTimeout(j,k)),f}},_hasMethods:function(a){var b,c=[];for(b in a)this._isFunction(a[b])&&c.push(b);return c.length>0},createCanvasElement:function(){var a=Kinetic.document.createElement("canvas");try{a.style=a.style||{}}catch(b){}return a},isBrowser:function(){return"object"!=typeof exports},_isInDocument:function(a){for(;a=a.parentNode;)if(a==Kinetic.document)return!0;return!1},_simplifyArray:function(a){var b,c,d=[],e=a.length,f=Kinetic.Util;for(b=0;e>b;b++)c=a[b],f._isNumber(c)?c=Math.round(1e3*c)/1e3:f._isString(c)||(c=c.toString()),d.push(c);return d},_getImage:function(b,c){var d,e;if(b)if(this._isElement(b))c(b);else if(this._isString(b))d=new Kinetic.window.Image,d.onload=function(){c(d)},d.src=b;else if(b.data){e=Kinetic.Util.createCanvasElement(),e.width=b.width,e.height=b.height;var f=e.getContext(a);f.putImageData(b,0,0),this._getImage(e.toDataURL(),c)}else c(null);else c(null)},_getRGBAString:function(a){var b=a.red||0,c=a.green||0,d=a.blue||0,e=a.alpha||1;return["rgba(",b,",",c,",",d,",",e,")"].join(h)},_rgbToHex:function(a,b,c){return((1<<24)+(a<<16)+(b<<8)+c).toString(16).slice(1)},_hexToRgb:function(a){a=a.replace(g,h);var b=parseInt(a,16);return{r:b>>16&255,g:b>>8&255,b:255&b}},getRandomColor:function(){for(var a=(16777215*Math.random()<<0).toString(16);a.length<6;)a=i+a;return g+a},get:function(a,b){return void 0===a?b:a},getRGB:function(a){var b;return a in m?(b=m[a],{r:b[0],g:b[1],b:b[2]}):a[0]===g?this._hexToRgb(a.substring(1)):a.substr(0,4)===l?(b=n.exec(a.replace(/ /g,"")),{r:parseInt(b[1],10),g:parseInt(b[2],10),b:parseInt(b[3],10)}):{r:0,g:0,b:0}},_merge:function(a,b){var c=this._clone(b);for(var d in a)c[d]=this._isObject(a[d])?this._merge(a[d],c[d]):a[d];return c},cloneObject:function(a){var b={};for(var c in a)b[c]=this._isObject(a[c])?this.cloneObject(a[c]):this._isArray(a[c])?this.cloneArray(a[c]):a[c];return b},cloneArray:function(a){return a.slice(0)},_degToRad:function(a){return a*e},_radToDeg:function(a){return a*f},_capitalize:function(a){return a.charAt(0).toUpperCase()+a.slice(1)},error:function(a){throw new Error(k+a)},warn:function(a){Kinetic.root.console&&console.warn&&Kinetic.showWarnings&&console.warn(j+a)},extend:function(a,b){function c(){this.constructor=a}c.prototype=b.prototype;var d=a.prototype;a.prototype=new c;for(var e in d)d.hasOwnProperty(e)&&(a.prototype[e]=d[e]);a.__super__=b.prototype},addMethods:function(a,b){var c;for(c in b)a.prototype[c]=b[c]},_getControlPoints:function(a,b,c,d,e,f,g){var h=Math.sqrt(Math.pow(c-a,2)+Math.pow(d-b,2)),i=Math.sqrt(Math.pow(e-c,2)+Math.pow(f-d,2)),j=g*h/(h+i),k=g*i/(h+i),l=c-j*(e-a),m=d-j*(f-b),n=c+k*(e-a),o=d+k*(f-b);return[l,m,n,o]},_expandPoints:function(a,b){var c,d,e=a.length,f=[];for(c=2;e-2>c;c+=2)d=Kinetic.Util._getControlPoints(a[c-2],a[c-1],a[c],a[c+1],a[c+2],a[c+3],b),f.push(d[0]),f.push(d[1]),f.push(a[c]),f.push(a[c+1]),f.push(d[2]),f.push(d[3]);return f},_removeLastLetter:function(a){return a.substring(0,a.length-1)}}}(),function(){var a=Kinetic.Util.createCanvasElement(),b=a.getContext("2d"),c=Kinetic.UA.mobile?function(){var a=window.devicePixelRatio||1,c=b.webkitBackingStorePixelRatio||b.mozBackingStorePixelRatio||b.msBackingStorePixelRatio||b.oBackingStorePixelRatio||b.backingStorePixelRatio||1;return a/c}():1;Kinetic.Canvas=function(a){this.init(a)},Kinetic.Canvas.prototype={init:function(a){var b=a||{},d=b.pixelRatio||Kinetic.pixelRatio||c;this.pixelRatio=d,this._canvas=Kinetic.Util.createCanvasElement(),this._canvas.style.padding=0,this._canvas.style.margin=0,this._canvas.style.border=0,this._canvas.style.background="transparent",this._canvas.style.position="absolute",this._canvas.style.top=0,this._canvas.style.left=0},getContext:function(){return this.context},getPixelRatio:function(){return this.pixelRatio},setPixelRatio:function(a){this.pixelRatio=a,this.setSize(this.getWidth(),this.getHeight())},setWidth:function(a){this.width=this._canvas.width=a*this.pixelRatio,this._canvas.style.width=a+"px"},setHeight:function(a){this.height=this._canvas.height=a*this.pixelRatio,this._canvas.style.height=a+"px"},getWidth:function(){return this.width},getHeight:function(){return this.height},setSize:function(a,b){this.setWidth(a),this.setHeight(b)},toDataURL:function(a,b){try{return this._canvas.toDataURL(a,b)}catch(c){try{return this._canvas.toDataURL()}catch(d){return Kinetic.Util.warn("Unable to get data URL. "+d.message),""}}}},Kinetic.SceneCanvas=function(a){var b=a||{},c=b.width||0,d=b.height||0;Kinetic.Canvas.call(this,b),this.context=new Kinetic.SceneContext(this),this.setSize(c,d)},Kinetic.SceneCanvas.prototype={setWidth:function(a){var b=this.pixelRatio,c=this.getContext()._context;Kinetic.Canvas.prototype.setWidth.call(this,a),c.scale(b,b)},setHeight:function(a){var b=this.pixelRatio,c=this.getContext()._context;Kinetic.Canvas.prototype.setHeight.call(this,a),c.scale(b,b)}},Kinetic.Util.extend(Kinetic.SceneCanvas,Kinetic.Canvas),Kinetic.HitCanvas=function(a){var b=a||{},c=b.width||0,d=b.height||0;Kinetic.Canvas.call(this,b),this.context=new Kinetic.HitContext(this),this.setSize(c,d),this.hitCanvas=!0},Kinetic.Util.extend(Kinetic.HitCanvas,Kinetic.Canvas)}(),function(){var a=",",b="(",c=")",d="([",e="])",f=";",g="()",h="=",i=["arc","arcTo","beginPath","bezierCurveTo","clearRect","clip","closePath","createLinearGradient","createPattern","createRadialGradient","drawImage","fill","fillText","getImageData","createImageData","lineTo","moveTo","putImageData","quadraticCurveTo","rect","restore","rotate","save","scale","setLineDash","setTransform","stroke","strokeText","transform","translate"];Kinetic.Context=function(a){this.init(a)},Kinetic.Context.prototype={init:function(a){this.canvas=a,this._context=a._canvas.getContext("2d"),Kinetic.enableTrace&&(this.traceArr=[],this._enableTrace())},fillShape:function(a){a.getFillEnabled()&&this._fill(a)},strokeShape:function(a){a.getStrokeEnabled()&&this._stroke(a)},fillStrokeShape:function(a){var b=a.getFillEnabled();b&&this._fill(a),a.getStrokeEnabled()&&this._stroke(a)},getTrace:function(i){var j,k,l,m,n=this.traceArr,o=n.length,p="";for(j=0;o>j;j++)k=n[j],l=k.method,l?(m=k.args,p+=l,p+=i?g:Kinetic.Util._isArray(m[0])?d+m.join(a)+e:b+m.join(a)+c):(p+=k.property,i||(p+=h+k.val)),p+=f;return p},clearTrace:function(){this.traceArr=[]},_trace:function(a){var b,c=this.traceArr;c.push(a),b=c.length,b>=Kinetic.traceArrMax&&c.shift()},reset:function(){var a=this.getCanvas().getPixelRatio();this.setTransform(1*a,0,0,1*a,0,0)},getCanvas:function(){return this.canvas},clear:function(a){var b=this.getCanvas();a?this.clearRect(a.x||0,a.y||0,a.width||0,a.height||0):this.clearRect(0,0,b.getWidth(),b.getHeight())},_applyLineCap:function(a){var b=a.getLineCap();b&&this.setAttr("lineCap",b)},_applyOpacity:function(a){var b=a.getAbsoluteOpacity();1!==b&&this.setAttr("globalAlpha",b)},_applyLineJoin:function(a){var b=a.getLineJoin();b&&this.setAttr("lineJoin",b)},setAttr:function(a,b){this._context[a]=b},arc:function(){var a=arguments;this._context.arc(a[0],a[1],a[2],a[3],a[4],a[5])},beginPath:function(){this._context.beginPath()},bezierCurveTo:function(){var a=arguments;this._context.bezierCurveTo(a[0],a[1],a[2],a[3],a[4],a[5])},clearRect:function(){var a=arguments;this._context.clearRect(a[0],a[1],a[2],a[3])},clip:function(){this._context.clip()},closePath:function(){this._context.closePath()},createImageData:function(){var a=arguments;return 2===a.length?this._context.createImageData(a[0],a[1]):1===a.length?this._context.createImageData(a[0]):void 0},createLinearGradient:function(){var a=arguments;return this._context.createLinearGradient(a[0],a[1],a[2],a[3])},createPattern:function(){var a=arguments;return this._context.createPattern(a[0],a[1])},createRadialGradient:function(){var a=arguments;return this._context.createRadialGradient(a[0],a[1],a[2],a[3],a[4],a[5])},drawImage:function(){var a=arguments,b=this._context;3===a.length?b.drawImage(a[0],a[1],a[2]):5===a.length?b.drawImage(a[0],a[1],a[2],a[3],a[4]):9===a.length&&b.drawImage(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8])},fill:function(){this._context.fill()},fillText:function(){var a=arguments;this._context.fillText(a[0],a[1],a[2])},getImageData:function(){var a=arguments;return this._context.getImageData(a[0],a[1],a[2],a[3])},lineTo:function(){var a=arguments;this._context.lineTo(a[0],a[1])},moveTo:function(){var a=arguments;this._context.moveTo(a[0],a[1])},rect:function(){var a=arguments;this._context.rect(a[0],a[1],a[2],a[3])},putImageData:function(){var a=arguments;this._context.putImageData(a[0],a[1],a[2])},quadraticCurveTo:function(){var a=arguments;this._context.quadraticCurveTo(a[0],a[1],a[2],a[3])},restore:function(){this._context.restore()},rotate:function(){var a=arguments;this._context.rotate(a[0])},save:function(){this._context.save()},scale:function(){var a=arguments;this._context.scale(a[0],a[1])},setLineDash:function(){var a=arguments,b=this._context;this._context.setLineDash?b.setLineDash(a[0]):"mozDash"in b?b.mozDash=a[0]:"webkitLineDash"in b&&(b.webkitLineDash=a[0])},setTransform:function(){var a=arguments;this._context.setTransform(a[0],a[1],a[2],a[3],a[4],a[5])},stroke:function(){this._context.stroke()},strokeText:function(){var a=arguments;this._context.strokeText(a[0],a[1],a[2])},transform:function(){var a=arguments;this._context.transform(a[0],a[1],a[2],a[3],a[4],a[5])},translate:function(){var a=arguments;this._context.translate(a[0],a[1])},_enableTrace:function(){var a,b,c=this,d=i.length,e=Kinetic.Util._simplifyArray,f=this.setAttr,g=function(a){var d,f=c[a];c[a]=function(){return b=e(Array.prototype.slice.call(arguments,0)),d=f.apply(c,arguments),c._trace({method:a,args:b}),d}};for(a=0;d>a;a++)g(i[a]);c.setAttr=function(){f.apply(c,arguments),c._trace({property:arguments[0],val:arguments[1]})}}},Kinetic.SceneContext=function(a){Kinetic.Context.call(this,a)},Kinetic.SceneContext.prototype={_fillColor:function(a){var b=a.fill()||Kinetic.Util._getRGBAString({red:a.fillRed(),green:a.fillGreen(),blue:a.fillBlue(),alpha:a.fillAlpha()});this.setAttr("fillStyle",b),a._fillFunc(this)},_fillPattern:function(a){var b=a.getFillPatternImage(),c=a.getFillPatternX(),d=a.getFillPatternY(),e=a.getFillPatternScale(),f=Kinetic.getAngle(a.getFillPatternRotation()),g=a.getFillPatternOffset(),h=a.getFillPatternRepeat();(c||d)&&this.translate(c||0,d||0),f&&this.rotate(f),e&&this.scale(e.x,e.y),g&&this.translate(-1*g.x,-1*g.y),this.setAttr("fillStyle",this.createPattern(b,h||"repeat")),this.fill()},_fillLinearGradient:function(a){var b=a.getFillLinearGradientStartPoint(),c=a.getFillLinearGradientEndPoint(),d=a.getFillLinearGradientColorStops(),e=this.createLinearGradient(b.x,b.y,c.x,c.y);if(d){for(var f=0;fh;h++)i=e[h],a[i]=this.getAttr(d+k(i));return a},c.prototype[m]=function(a){var b,c=this.attrs[d];f&&(a=f.call(this,a));for(b in a)this._setAttr(d+k(b),a[b]);return this._fireChangeEvent(d,c,a),g&&g.call(this),this},this.addOverloadedGetterSetter(c,d)},addOverloadedGetterSetter:function(c,d){var e=Kinetic.Util._capitalize(d),f=b+e,g=a+e;c.prototype[d]=function(){return arguments.length?(this[f](arguments[0]),this):this[g]()}},backCompat:function(a,b){var c;for(c in b)a.prototype[c]=a.prototype[b[c]]},afterSetFilter:function(){this._filterUpToDate=!1}},Kinetic.Validators={RGBComponent:function(a){return a>255?255:0>a?0:Math.round(a)},alphaComponent:function(a){return a>1?1:1e-4>a?1e-4:a}}}(),function(){var a="absoluteOpacity",b="absoluteTransform",c="Change",d="children",e=".",f="",g="get",h="id",i="kinetic",j="listening",k="mouseenter",l="mouseleave",m="name",n="set",o="Shape",p=" ",q="stage",r="transform",s="Stage",t="visible",u=["id"],v=["xChange.kinetic","yChange.kinetic","scaleXChange.kinetic","scaleYChange.kinetic","skewXChange.kinetic","skewYChange.kinetic","rotationChange.kinetic","offsetXChange.kinetic","offsetYChange.kinetic","transformsEnabledChange.kinetic"].join(p);Kinetic.Util.addMethods(Kinetic.Node,{_init:function(c){var d=this;this._id=Kinetic.idCounter++,this.eventListeners={},this.attrs={},this._cache={},this._filterUpToDate=!1,this.setAttrs(c),this.on(v,function(){this._clearCache(r),d._clearSelfAndDescendantCache(b)}),this.on("visibleChange.kinetic",function(){d._clearSelfAndDescendantCache(t)}),this.on("listeningChange.kinetic",function(){d._clearSelfAndDescendantCache(j)}),this.on("opacityChange.kinetic",function(){d._clearSelfAndDescendantCache(a)})},_clearCache:function(a){a?delete this._cache[a]:this._cache={}},_getCache:function(a,b){var c=this._cache[a];return void 0===c&&(this._cache[a]=b.call(this)),this._cache[a]},_clearSelfAndDescendantCache:function(a){this._clearCache(a),this.children&&this.getChildren().each(function(b){b._clearSelfAndDescendantCache(a)})},clearCache:function(){return delete this._cache.canvas,this._filterUpToDate=!1,this},cache:function(a){var b=a||{},c=b.x||0,d=b.y||0,e=b.width||this.width(),f=b.height||this.height(),g=b.drawBorder||!1;if(0===e||0===f)return void Kinetic.Util.warn("Width or height of caching configuration equals 0. Cache is ignored.");var h=new Kinetic.SceneCanvas({pixelRatio:1,width:e,height:f}),i=new Kinetic.SceneCanvas({pixelRatio:1,width:e,height:f}),j=new Kinetic.HitCanvas({width:e,height:f}),k=h.getContext(),l=j.getContext();return j.isCache=!0,this.clearCache(),k.save(),l.save(),g&&(k.save(),k.beginPath(),k.rect(0,0,e,f),k.closePath(),k.setAttr("strokeStyle","red"),k.setAttr("lineWidth",5),k.stroke(),k.restore()),k.translate(-1*c,-1*d),l.translate(-1*c,-1*d),"Shape"===this.nodeType&&(k.translate(-1*this.x(),-1*this.y()),l.translate(-1*this.x(),-1*this.y())),this.drawScene(h,this),this.drawHit(j,this),k.restore(),l.restore(),this._cache.canvas={scene:h,filter:i,hit:j},this},_drawCachedSceneCanvas:function(a){a.save(),this.getLayer()._applyTransform(this,a),a._applyOpacity(this),a.drawImage(this._getCachedSceneCanvas()._canvas,0,0),a.restore()},_getCachedSceneCanvas:function(){var a,b,c,d,e=this.filters(),f=this._cache.canvas,g=f.scene,h=f.filter,i=h.getContext();if(e){if(!this._filterUpToDate){try{for(a=e.length,i.clear(),i.drawImage(g._canvas,0,0),b=i.getImageData(0,0,h.getWidth(),h.getHeight()),c=0;a>c;c++)d=e[c],d.call(this,b),i.putImageData(b,0,0)}catch(j){Kinetic.Util.warn("Unable to apply filter. "+j.message)}this._filterUpToDate=!0}return h}return g},_drawCachedHitCanvas:function(a){var b=this._cache.canvas,c=b.hit;a.save(),this.getLayer()._applyTransform(this,a),a.drawImage(c._canvas,0,0),a.restore()},on:function(a,b){var c,d,g,h,i,j=a.split(p),k=j.length;for(c=0;k>c;c++)d=j[c],g=d.split(e),h=g[0],i=g[1]||f,this.eventListeners[h]||(this.eventListeners[h]=[]),this.eventListeners[h].push({name:i,handler:b});return this},off:function(a){var b,c,d,f,g,h,i=(a||"").split(p),j=i.length;if(!a)for(c in this.eventListeners)this._off(c);for(b=0;j>b;b++)if(d=i[b],f=d.split(e),g=f[0],h=f[1],g)this.eventListeners[g]&&this._off(g,h);else for(c in this.eventListeners)this._off(c,h);return this},dispatchEvent:function(a){var b={target:this,type:a.type,evt:a};this.fire(a.type,b)},addEventListener:function(a,b){this.on(a,function(a){b.call(this,a.evt)})},removeEventListener:function(a){this.off(a)},remove:function(){var c=this.getParent();return c&&c.children&&(c.children.splice(this.index,1),c._setChildrenIndices(),delete this.parent),this._clearSelfAndDescendantCache(q),this._clearSelfAndDescendantCache(b),this._clearSelfAndDescendantCache(t),this._clearSelfAndDescendantCache(j),this._clearSelfAndDescendantCache(a),this},destroy:function(){Kinetic._removeId(this.getId()),Kinetic._removeName(this.getName(),this._id),this.remove()},getAttr:function(a){var b=g+Kinetic.Util._capitalize(a);return Kinetic.Util._isFunction(this[b])?this[b]():this.attrs[a]},getAncestors:function(){for(var a=this.getParent(),b=new Kinetic.Collection;a;)b.push(a),a=a.getParent();return b},getAttrs:function(){return this.attrs||{}},setAttrs:function(a){var b,c;if(a)for(b in a)b===d||a[b]instanceof Kinetic.Node||(c=n+Kinetic.Util._capitalize(b),Kinetic.Util._isFunction(this[c])?this[c](a[b]):this._setAttr(b,a[b]));return this},isListening:function(){return this._getCache(j,this._isListening)},_isListening:function(){var a=this.getListening(),b=this.getParent();return"inherit"===a?b?b.isListening():!0:a},isVisible:function(){return this._getCache(t,this._isVisible)},_isVisible:function(){var a=this.getVisible(),b=this.getParent();return"inherit"===a?b?b.isVisible():!0:a},shouldDrawHit:function(a){var b=this.getLayer();return a&&a.isCache||b&&b.hitGraphEnabled()&&this.isListening()&&this.isVisible()},show:function(){return this.setVisible(!0),this},hide:function(){return this.setVisible(!1),this},getZIndex:function(){return this.index||0},getAbsoluteZIndex:function(){function a(i){for(b=[],c=i.length,d=0;c>d;d++)e=i[d],h++,e.nodeType!==o&&(b=b.concat(e.getChildren().toArray())),e._id===g._id&&(d=c);b.length>0&&b[0].getDepth()<=f&&a(b)}var b,c,d,e,f=this.getDepth(),g=this,h=0;return g.nodeType!==s&&a(g.getStage().getChildren()),h},getDepth:function(){for(var a=0,b=this.parent;b;)a++,b=b.parent;return a},setPosition:function(a){return this.setX(a.x),this.setY(a.y),this},getPosition:function(){return{x:this.getX(),y:this.getY()}},getAbsolutePosition:function(){var a=this.getAbsoluteTransform().getMatrix(),b=new Kinetic.Transform,c=this.offset();return b.m=a.slice(),b.translate(c.x,c.y),b.getTranslation()},setAbsolutePosition:function(a){var b,c=this._clearTransform();return this.attrs.x=c.x,this.attrs.y=c.y,delete c.x,delete c.y,b=this.getAbsoluteTransform(),b.invert(),b.translate(a.x,a.y),a={x:this.attrs.x+b.getTranslation().x,y:this.attrs.y+b.getTranslation().y},this.setPosition({x:a.x,y:a.y}),this._setTransform(c),this},_setTransform:function(a){var c;for(c in a)this.attrs[c]=a[c];this._clearCache(r),this._clearSelfAndDescendantCache(b)},_clearTransform:function(){var a={x:this.getX(),y:this.getY(),rotation:this.getRotation(),scaleX:this.getScaleX(),scaleY:this.getScaleY(),offsetX:this.getOffsetX(),offsetY:this.getOffsetY(),skewX:this.getSkewX(),skewY:this.getSkewY()};return this.attrs.x=0,this.attrs.y=0,this.attrs.rotation=0,this.attrs.scaleX=1,this.attrs.scaleY=1,this.attrs.offsetX=0,this.attrs.offsetY=0,this.attrs.skewX=0,this.attrs.skewY=0,this._clearCache(r),this._clearSelfAndDescendantCache(b),a},move:function(a){var b=a.x,c=a.y,d=this.getX(),e=this.getY();return void 0!==b&&(d+=b),void 0!==c&&(e+=c),this.setPosition({x:d,y:e}),this},_eachAncestorReverse:function(a,b){var c,d,e=[],f=this.getParent();if(b&&b._id===this._id)return a(this),!0;for(e.unshift(this);f&&(!b||f._id!==b._id);)e.unshift(f),f=f.parent;for(c=e.length,d=0;c>d;d++)a(e[d])},rotate:function(a){return this.setRotation(this.getRotation()+a),this},moveToTop:function(){if(!this.parent)return void Kinetic.Util.warn("Node has no parent. moveToTop function is ignored.");var a=this.index;return this.parent.children.splice(a,1),this.parent.children.push(this),this.parent._setChildrenIndices(),!0},moveUp:function(){if(!this.parent)return void Kinetic.Util.warn("Node has no parent. moveUp function is ignored.");var a=this.index,b=this.parent.getChildren().length;return b-1>a?(this.parent.children.splice(a,1),this.parent.children.splice(a+1,0,this),this.parent._setChildrenIndices(),!0):!1},moveDown:function(){if(!this.parent)return void Kinetic.Util.warn("Node has no parent. moveDown function is ignored.");var a=this.index;return a>0?(this.parent.children.splice(a,1),this.parent.children.splice(a-1,0,this),this.parent._setChildrenIndices(),!0):!1},moveToBottom:function(){if(!this.parent)return void Kinetic.Util.warn("Node has no parent. moveToBottom function is ignored.");var a=this.index;return a>0?(this.parent.children.splice(a,1),this.parent.children.unshift(this),this.parent._setChildrenIndices(),!0):!1},setZIndex:function(a){if(!this.parent)return void Kinetic.Util.warn("Node has no parent. zIndex parameter is ignored.");var b=this.index;return this.parent.children.splice(b,1),this.parent.children.splice(a,0,this),this.parent._setChildrenIndices(),this},getAbsoluteOpacity:function(){return this._getCache(a,this._getAbsoluteOpacity)},_getAbsoluteOpacity:function(){var a=this.getOpacity();return this.getParent()&&(a*=this.getParent().getAbsoluteOpacity()),a},moveTo:function(a){return this.getParent()!==a&&(this.remove(),a.add(this)),this},toObject:function(){var a,b,c,d,e=Kinetic.Util,f={},g=this.getAttrs();f.attrs={};for(a in g)b=g[a],e._isFunction(b)||e._isElement(b)||e._isObject(b)&&e._hasMethods(b)||(c=this[a],delete g[a],d=c?c.call(this):null,g[a]=b,d!==b&&(f.attrs[a]=b));return f.className=this.getClassName(),f},toJSON:function(){return JSON.stringify(this.toObject())},getParent:function(){return this.parent},getLayer:function(){var a=this.getParent();return a?a.getLayer():null},getStage:function(){return this._getCache(q,this._getStage)},_getStage:function(){var a=this.getParent();return a?a.getStage():void 0},fire:function(a,b,c){return c?this._fireAndBubble(a,b||{}):this._fire(a,b||{}),this},getAbsoluteTransform:function(a){return a?this._getAbsoluteTransform(a):this._getCache(b,this._getAbsoluteTransform)},_getAbsoluteTransform:function(a){var b,c,d=new Kinetic.Transform;return this._eachAncestorReverse(function(a){b=a.transformsEnabled(),c=a.getTransform(),"all"===b?d.multiply(c):"position"===b&&d.translate(a.x(),a.y())},a),d},getTransform:function(){return this._getCache(r,this._getTransform)},_getTransform:function(){var a=new Kinetic.Transform,b=this.getX(),c=this.getY(),d=Kinetic.getAngle(this.getRotation()),e=this.getScaleX(),f=this.getScaleY(),g=this.getSkewX(),h=this.getSkewY(),i=this.getOffsetX(),j=this.getOffsetY();return(0!==b||0!==c)&&a.translate(b,c),0!==d&&a.rotate(d),(0!==g||0!==h)&&a.skew(g,h),(1!==e||1!==f)&&a.scale(e,f),(0!==i||0!==j)&&a.translate(-1*i,-1*j),a},clone:function(a){var b,c,d,e,f,g=this.getClassName(),h=Kinetic.Util.cloneObject(this.attrs);for(var j in u){var k=u[j];delete h[k]}for(b in a)h[b]=a[b];var l=new Kinetic[g](h);for(b in this.eventListeners)for(c=this.eventListeners[b],d=c.length,e=0;d>e;e++)f=c[e],f.name.indexOf(i)<0&&(l.eventListeners[b]||(l.eventListeners[b]=[]),l.eventListeners[b].push(f));return l},toDataURL:function(a){a=a||{};var b=a.mimeType||null,c=a.quality||null,d=this.getStage(),e=a.x||0,f=a.y||0,g=new Kinetic.SceneCanvas({width:a.width||this.getWidth()||(d?d.getWidth():0),height:a.height||this.getHeight()||(d?d.getHeight():0),pixelRatio:1}),h=g.getContext();return h.save(),(e||f)&&h.translate(-1*e,-1*f),this.drawScene(g),h.restore(),g.toDataURL(b,c)},toImage:function(a){Kinetic.Util._getImage(this.toDataURL(a),function(b){a.callback(b)})},setSize:function(a){return this.setWidth(a.width),this.setHeight(a.height),this},getSize:function(){return{width:this.getWidth(),height:this.getHeight()}},getWidth:function(){return this.attrs.width||0},getHeight:function(){return this.attrs.height||0},getClassName:function(){return this.className||this.nodeType},getType:function(){return this.nodeType},getDragDistance:function(){return void 0!==this.attrs.dragDistance?this.attrs.dragDistance:this.parent?this.parent.getDragDistance():Kinetic.dragDistance + },_get:function(a){return this.className===a||this.nodeType===a?[this]:[]},_off:function(a,b){var c,d,e=this.eventListeners[a];for(c=0;ce;e++)c.add(this._createNode(g[e]));return c},Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Node,"position"),Kinetic.Factory.addGetterSetter(Kinetic.Node,"x",0),Kinetic.Factory.addGetterSetter(Kinetic.Node,"y",0),Kinetic.Factory.addGetterSetter(Kinetic.Node,"opacity",1),Kinetic.Factory.addGetter(Kinetic.Node,"name"),Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Node,"name"),Kinetic.Factory.addGetter(Kinetic.Node,"id"),Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Node,"id"),Kinetic.Factory.addGetterSetter(Kinetic.Node,"rotation",0),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Node,"scale",["x","y"]),Kinetic.Factory.addGetterSetter(Kinetic.Node,"scaleX",1),Kinetic.Factory.addGetterSetter(Kinetic.Node,"scaleY",1),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Node,"skew",["x","y"]),Kinetic.Factory.addGetterSetter(Kinetic.Node,"skewX",0),Kinetic.Factory.addGetterSetter(Kinetic.Node,"skewY",0),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Node,"offset",["x","y"]),Kinetic.Factory.addGetterSetter(Kinetic.Node,"offsetX",0),Kinetic.Factory.addGetterSetter(Kinetic.Node,"offsetY",0),Kinetic.Factory.addSetter(Kinetic.Node,"dragDistance"),Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Node,"dragDistance"),Kinetic.Factory.addSetter(Kinetic.Node,"width",0),Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Node,"width"),Kinetic.Factory.addSetter(Kinetic.Node,"height",0),Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Node,"height"),Kinetic.Factory.addGetterSetter(Kinetic.Node,"listening","inherit"),Kinetic.Factory.addGetterSetter(Kinetic.Node,"filters",void 0,function(a){return this._filterUpToDate=!1,a}),Kinetic.Factory.addGetterSetter(Kinetic.Node,"visible","inherit"),Kinetic.Factory.addGetterSetter(Kinetic.Node,"transformsEnabled","all"),Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Node,"size"),Kinetic.Factory.backCompat(Kinetic.Node,{rotateDeg:"rotate",setRotationDeg:"setRotation",getRotationDeg:"getRotation"}),Kinetic.Collection.mapMethods(Kinetic.Node)}(),function(){Kinetic.Filters.Grayscale=function(a){var b,c,d=a.data,e=d.length;for(b=0;e>b;b+=4)c=.34*d[b]+.5*d[b+1]+.16*d[b+2],d[b]=c,d[b+1]=c,d[b+2]=c}}(),function(){Kinetic.Filters.Brighten=function(a){var b,c=255*this.brightness(),d=a.data,e=d.length;for(b=0;e>b;b+=4)d[b]+=c,d[b+1]+=c,d[b+2]+=c},Kinetic.Factory.addGetterSetter(Kinetic.Node,"brightness",0,null,Kinetic.Factory.afterSetFilter)}(),function(){Kinetic.Filters.Invert=function(a){var b,c=a.data,d=c.length;for(b=0;d>b;b+=4)c[b]=255-c[b],c[b+1]=255-c[b+1],c[b+2]=255-c[b+2]}}(),function(){function a(){this.r=0,this.g=0,this.b=0,this.a=0,this.next=null}function b(b,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D=b.data,E=b.width,F=b.height,G=e+e+1,H=E-1,I=F-1,J=e+1,K=J*(J+1)/2,L=new a,M=null,N=L,O=null,P=null,Q=c[e],R=d[e];for(h=1;G>h;h++)N=N.next=new a,h==J&&(M=N);for(N.next=L,l=k=0,g=0;F>g;g++){for(u=v=w=x=m=n=o=p=0,q=J*(y=D[k]),r=J*(z=D[k+1]),s=J*(A=D[k+2]),t=J*(B=D[k+3]),m+=K*y,n+=K*z,o+=K*A,p+=K*B,N=L,h=0;J>h;h++)N.r=y,N.g=z,N.b=A,N.a=B,N=N.next;for(h=1;J>h;h++)i=k+((h>H?H:h)<<2),m+=(N.r=y=D[i])*(C=J-h),n+=(N.g=z=D[i+1])*C,o+=(N.b=A=D[i+2])*C,p+=(N.a=B=D[i+3])*C,u+=y,v+=z,w+=A,x+=B,N=N.next;for(O=L,P=M,f=0;E>f;f++)D[k+3]=B=p*Q>>R,0!==B?(B=255/B,D[k]=(m*Q>>R)*B,D[k+1]=(n*Q>>R)*B,D[k+2]=(o*Q>>R)*B):D[k]=D[k+1]=D[k+2]=0,m-=q,n-=r,o-=s,p-=t,q-=O.r,r-=O.g,s-=O.b,t-=O.a,i=l+((i=f+e+1)f;f++){for(v=w=x=u=n=o=p=m=0,k=f<<2,q=J*(y=D[k]),r=J*(z=D[k+1]),s=J*(A=D[k+2]),t=J*(B=D[k+3]),m+=K*y,n+=K*z,o+=K*A,p+=K*B,N=L,h=0;J>h;h++)N.r=y,N.g=z,N.b=A,N.a=B,N=N.next;for(j=E,h=1;e>=h;h++)k=j+f<<2,m+=(N.r=y=D[k])*(C=J-h),n+=(N.g=z=D[k+1])*C,o+=(N.b=A=D[k+2])*C,p+=(N.a=B=D[k+3])*C,u+=y,v+=z,w+=A,x+=B,N=N.next,I>h&&(j+=E);for(k=f,O=L,P=M,g=0;F>g;g++)i=k<<2,D[i+3]=B=p*Q>>R,B>0?(B=255/B,D[i]=(m*Q>>R)*B,D[i+1]=(n*Q>>R)*B,D[i+2]=(o*Q>>R)*B):D[i]=D[i+1]=D[i+2]=0,m-=q,n-=r,o-=s,p-=t,q-=O.r,r-=O.g,s-=O.b,t-=O.a,i=f+((i=g+J)0&&b(a,c)},Kinetic.Factory.addGetterSetter(Kinetic.Node,"blurRadius",0,null,Kinetic.Factory.afterSetFilter)}(),function(){function a(a,b,c){var d=4*(c*a.width+b),e=[];return e.push(a.data[d++],a.data[d++],a.data[d++],a.data[d++]),e}function b(a,b){return Math.sqrt(Math.pow(a[0]-b[0],2)+Math.pow(a[1]-b[1],2)+Math.pow(a[2]-b[2],2))}function c(a){for(var b=[0,0,0],c=0;cn?0:255}return l}}function e(a,b){for(var c=0;ch;h++)for(var i=0;b>i;i++){for(var j=h*b+i,k=0,l=0;e>l;l++)for(var m=0;e>m;m++){var n=h+l-f,o=i+m-f;if(n>=0&&c>n&&o>=0&&b>o){var p=n*b+o,q=d[l*e+m];k+=a[p]*q}}g[j]=2040===k?255:0}return g}function g(a,b,c){for(var d=[1,1,1,1,1,1,1,1,1],e=Math.round(Math.sqrt(d.length)),f=Math.floor(e/2),g=[],h=0;c>h;h++)for(var i=0;b>i;i++){for(var j=h*b+i,k=0,l=0;e>l;l++)for(var m=0;e>m;m++){var n=h+l-f,o=i+m-f;if(n>=0&&c>n&&o>=0&&b>o){var p=n*b+o,q=d[l*e+m];k+=a[p]*q}}g[j]=k>=1020?255:0}return g}function h(a,b,c){for(var d=[1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9],e=Math.round(Math.sqrt(d.length)),f=Math.floor(e/2),g=[],h=0;c>h;h++)for(var i=0;b>i;i++){for(var j=h*b+i,k=0,l=0;e>l;l++)for(var m=0;e>m;m++){var n=h+l-f,o=i+m-f;if(n>=0&&c>n&&o>=0&&b>o){var p=n*b+o,q=d[l*e+m];k+=a[p]*q}}g[j]=k}return g}Kinetic.Filters.Mask=function(a){var b=this.threshold(),c=d(a,b);return c&&(c=f(c,a.width,a.height),c=g(c,a.width,a.height),c=h(c,a.width,a.height),e(a,c)),a},Kinetic.Factory.addGetterSetter(Kinetic.Node,"threshold",0,null,Kinetic.Factory.afterSetFilter)}(),function(){Kinetic.Filters.RGB=function(a){var b,c,d=a.data,e=d.length,f=this.red(),g=this.green(),h=this.blue();for(b=0;e>b;b+=4)c=(.34*d[b]+.5*d[b+1]+.16*d[b+2])/255,d[b]=c*f,d[b+1]=c*g,d[b+2]=c*h,d[b+3]=d[b+3]},Kinetic.Factory.addGetterSetter(Kinetic.Node,"red",0,function(a){return this._filterUpToDate=!1,a>255?255:0>a?0:Math.round(a)}),Kinetic.Factory.addGetterSetter(Kinetic.Node,"green",0,function(a){return this._filterUpToDate=!1,a>255?255:0>a?0:Math.round(a)}),Kinetic.Factory.addGetterSetter(Kinetic.Node,"blue",0,Kinetic.Validators.RGBComponent,Kinetic.Factory.afterSetFilter)}(),function(){Kinetic.Filters.HSV=function(a){var b,c,d,e,f,g=a.data,h=g.length,i=Math.pow(2,this.value()),j=Math.pow(2,this.saturation()),k=Math.abs(this.hue()+360)%360,l=i*j*Math.cos(k*Math.PI/180),m=i*j*Math.sin(k*Math.PI/180),n=.299*i+.701*l+.167*m,o=.587*i-.587*l+.33*m,p=.114*i-.114*l-.497*m,q=.299*i-.299*l-.328*m,r=.587*i+.413*l+.035*m,s=.114*i-.114*l+.293*m,t=.299*i-.3*l+1.25*m,u=.587*i-.586*l-1.05*m,v=.114*i+.886*l-.2*m;for(b=0;h>b;b+=4)c=g[b+0],d=g[b+1],e=g[b+2],f=g[b+3],g[b+0]=n*c+o*d+p*e,g[b+1]=q*c+r*d+s*e,g[b+2]=t*c+u*d+v*e,g[b+3]=f},Kinetic.Factory.addGetterSetter(Kinetic.Node,"hue",0,null,Kinetic.Factory.afterSetFilter),Kinetic.Factory.addGetterSetter(Kinetic.Node,"saturation",0,null,Kinetic.Factory.afterSetFilter),Kinetic.Factory.addGetterSetter(Kinetic.Node,"value",0,null,Kinetic.Factory.afterSetFilter)}(),function(){Kinetic.Factory.addGetterSetter(Kinetic.Node,"hue",0,null,Kinetic.Factory.afterSetFilter),Kinetic.Factory.addGetterSetter(Kinetic.Node,"saturation",0,null,Kinetic.Factory.afterSetFilter),Kinetic.Factory.addGetterSetter(Kinetic.Node,"luminance",0,null,Kinetic.Factory.afterSetFilter),Kinetic.Filters.HSL=function(a){var b,c,d,e,f,g=a.data,h=g.length,i=1,j=Math.pow(2,this.saturation()),k=Math.abs(this.hue()+360)%360,l=127*this.luminance(),m=i*j*Math.cos(k*Math.PI/180),n=i*j*Math.sin(k*Math.PI/180),o=.299*i+.701*m+.167*n,p=.587*i-.587*m+.33*n,q=.114*i-.114*m-.497*n,r=.299*i-.299*m-.328*n,s=.587*i+.413*m+.035*n,t=.114*i-.114*m+.293*n,u=.299*i-.3*m+1.25*n,v=.587*i-.586*m-1.05*n,w=.114*i+.886*m-.2*n;for(b=0;h>b;b+=4)c=g[b+0],d=g[b+1],e=g[b+2],f=g[b+3],g[b+0]=o*c+p*d+q*e+l,g[b+1]=r*c+s*d+t*e+l,g[b+2]=u*c+v*d+w*e+l,g[b+3]=f}}(),function(){Kinetic.Filters.Emboss=function(a){var b=10*this.embossStrength(),c=255*this.embossWhiteLevel(),d=this.embossDirection(),e=this.embossBlend(),f=0,g=0,h=a.data,i=a.width,j=a.height,k=4*i,l=j;switch(d){case"top-left":f=-1,g=-1;break;case"top":f=-1,g=0;break;case"top-right":f=-1,g=1;break;case"right":f=0,g=1;break;case"bottom-right":f=1,g=1;break;case"bottom":f=1,g=0;break;case"bottom-left":f=1,g=-1;break;case"left":f=0,g=-1}do{var m=(l-1)*k,n=f;1>l+n&&(n=0),l+n>j&&(n=0);var o=(l-1+n)*i*4,p=i;do{var q=m+4*(p-1),r=g;1>p+r&&(r=0),p+r>i&&(r=0);var s=o+4*(p-1+r),t=h[q]-h[s],u=h[q+1]-h[s+1],v=h[q+2]-h[s+2],w=t,x=w>0?w:-w,y=u>0?u:-u,z=v>0?v:-v;if(y>x&&(w=u),z>x&&(w=v),w*=b,e){var A=h[q]+w,B=h[q+1]+w,C=h[q+2]+w;h[q]=A>255?255:0>A?0:A,h[q+1]=B>255?255:0>B?0:B,h[q+2]=C>255?255:0>C?0:C}else{var D=c-w;0>D?D=0:D>255&&(D=255),h[q]=h[q+1]=h[q+2]=D}}while(--p)}while(--l)},Kinetic.Factory.addGetterSetter(Kinetic.Node,"embossStrength",.5,null,Kinetic.Factory.afterSetFilter),Kinetic.Factory.addGetterSetter(Kinetic.Node,"embossWhiteLevel",.5,null,Kinetic.Factory.afterSetFilter),Kinetic.Factory.addGetterSetter(Kinetic.Node,"embossDirection","top-left",null,Kinetic.Factory.afterSetFilter),Kinetic.Factory.addGetterSetter(Kinetic.Node,"embossBlend",!1,null,Kinetic.Factory.afterSetFilter)}(),function(){function a(a,b,c,d,e){var f,g=c-b,h=e-d;return 0===g?d+h/2:0===h?d:(f=(a-b)/g,f=h*f+d)}Kinetic.Filters.Enhance=function(b){var c,d,e,f,g=b.data,h=g.length,i=g[0],j=i,k=g[1],l=k,m=g[2],n=m,o=this.enhance();if(0!==o){for(f=0;h>f;f+=4)c=g[f+0],i>c?i=c:c>j&&(j=c),d=g[f+1],k>d?k=d:d>l&&(l=d),e=g[f+2],m>e?m=e:e>n&&(n=e);j===i&&(j=255,i=0),l===k&&(l=255,k=0),n===m&&(n=255,m=0);var p,q,r,s,t,u,v,w,x;for(o>0?(q=j+o*(255-j),r=i-o*(i-0),t=l+o*(255-l),u=k-o*(k-0),w=n+o*(255-n),x=m-o*(m-0)):(p=.5*(j+i),q=j+o*(j-p),r=i+o*(i-p),s=.5*(l+k),t=l+o*(l-s),u=k+o*(k-s),v=.5*(n+m),w=n+o*(n-v),x=m+o*(m-v)),f=0;h>f;f+=4)g[f+0]=a(g[f+0],i,j,r,q),g[f+1]=a(g[f+1],k,l,u,t),g[f+2]=a(g[f+2],m,n,x,w)}},Kinetic.Factory.addGetterSetter(Kinetic.Node,"enhance",0,null,Kinetic.Factory.afterSetFilter)}(),function(){Kinetic.Filters.Posterize=function(a){var b,c=Math.round(254*this.levels())+1,d=a.data,e=d.length,f=255/c;for(b=0;e>b;b+=1)d[b]=Math.floor(d[b]/f)*f},Kinetic.Factory.addGetterSetter(Kinetic.Node,"levels",.5,null,Kinetic.Factory.afterSetFilter)}(),function(){Kinetic.Filters.Noise=function(a){var b,c=255*this.noise(),d=a.data,e=d.length,f=c/2;for(b=0;e>b;b+=4)d[b+0]+=f-2*f*Math.random(),d[b+1]+=f-2*f*Math.random(),d[b+2]+=f-2*f*Math.random()},Kinetic.Factory.addGetterSetter(Kinetic.Node,"noise",.2,null,Kinetic.Factory.afterSetFilter)}(),function(){Kinetic.Filters.Pixelate=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p=Math.ceil(this.pixelSize()),q=a.width,r=a.height,s=Math.ceil(q/p),t=Math.ceil(r/p);for(a=a.data,m=0;s>m;m+=1)for(n=0;t>n;n+=1){for(e=0,f=0,g=0,h=0,i=m*p,j=i+p,k=n*p,l=k+p,o=0,b=i;j>b;b+=1)if(!(b>=q))for(c=k;l>c;c+=1)c>=r||(d=4*(q*c+b),e+=a[d+0],f+=a[d+1],g+=a[d+2],h+=a[d+3],o+=1);for(e/=o,f/=o,g/=o,b=i;j>b;b+=1)if(!(b>=q))for(c=k;l>c;c+=1)c>=r||(d=4*(q*c+b),a[d+0]=e,a[d+1]=f,a[d+2]=g,a[d+3]=h)}},Kinetic.Factory.addGetterSetter(Kinetic.Node,"pixelSize",8,null,Kinetic.Factory.afterSetFilter)}(),function(){Kinetic.Filters.Threshold=function(a){var b,c=255*this.threshold(),d=a.data,e=d.length;for(b=0;e>b;b+=1)d[b]=d[b]255?255:h,k[d+1]=i>255?255:i,k[d+2]=j>255?255:j,k[d+3]=k[d+3];while(--c)}while(--m)}}(),function(){Kinetic.Filters.Solarize=function(a){var b=a.data,c=a.width,d=a.height,e=4*c,f=d;do{var g=(f-1)*e,h=c;do{var i=g+4*(h-1),j=b[i],k=b[i+1],l=b[i+2];j>127&&(j=255-j),k>127&&(k=255-k),l>127&&(l=255-l),b[i]=j,b[i+1]=k,b[i+2]=l}while(--h)}while(--f)}}(),function(){var a=function(a,b,c){var d,e,f,g,h=a.data,i=b.data,j=a.width,k=a.height,l=c.polarCenterX||j/2,m=c.polarCenterY||k/2,n=0,o=0,p=0,q=0,r=Math.sqrt(l*l+m*m);e=j-l,f=k-m,g=Math.sqrt(e*e+f*f),r=g>r?g:r;var s,t,u,v,w=k,x=j,y=360/x*Math.PI/180;for(t=0;x>t;t+=1)for(u=Math.sin(t*y),v=Math.cos(t*y),s=0;w>s;s+=1)e=Math.floor(l+r*s/w*v),f=Math.floor(m+r*s/w*u),d=4*(f*j+e),n=h[d+0],o=h[d+1],p=h[d+2],q=h[d+3],d=4*(t+s*j),i[d+0]=n,i[d+1]=o,i[d+2]=p,i[d+3]=q},b=function(a,b,c){var d,e,f,g,h,i,j=a.data,k=b.data,l=a.width,m=a.height,n=c.polarCenterX||l/2,o=c.polarCenterY||m/2,p=0,q=0,r=0,s=0,t=Math.sqrt(n*n+o*o);e=l-n,f=m-o,i=Math.sqrt(e*e+f*f),t=i>t?i:t;var u,v,w,x,y=m,z=l,A=c.polarRotation||0;for(e=0;l>e;e+=1)for(f=0;m>f;f+=1)g=e-n,h=f-o,u=Math.sqrt(g*g+h*h)*y/t,v=(180*Math.atan2(h,g)/Math.PI+360+A)%360,v=v*z/360,w=Math.floor(v),x=Math.floor(u),d=4*(x*l+w),p=j[d+0],q=j[d+1],r=j[d+2],s=j[d+3],d=4*(f*l+e),k[d+0]=p,k[d+1]=q,k[d+2]=r,k[d+3]=s},c=Kinetic.Util.createCanvasElement();Kinetic.Filters.Kaleidoscope=function(d){var e,f,g,h,i,j,k,l,m,n,o=d.width,p=d.height,q=Math.round(this.kaleidoscopePower()),r=Math.round(this.kaleidoscopeAngle()),s=Math.floor(o*(r%360)/360);if(!(1>q)){c.width=o,c.height=p;var t=c.getContext("2d").getImageData(0,0,o,p);a(d,t,{polarCenterX:o/2,polarCenterY:p/2});for(var u=o/Math.pow(2,q);8>=u;)u=2*u,q-=1;u=Math.ceil(u);var v=u,w=0,x=v,y=1;for(s+u>o&&(w=v,x=0,y=-1),f=0;p>f;f+=1)for(e=w;e!==x;e+=y)g=Math.round(e+s)%o,m=4*(o*f+g),i=t.data[m+0],j=t.data[m+1],k=t.data[m+2],l=t.data[m+3],n=4*(o*f+e),t.data[n+0]=i,t.data[n+1]=j,t.data[n+2]=k,t.data[n+3]=l;for(f=0;p>f;f+=1)for(v=Math.floor(u),h=0;q>h;h+=1){for(e=0;v+1>e;e+=1)m=4*(o*f+e),i=t.data[m+0],j=t.data[m+1],k=t.data[m+2],l=t.data[m+3],n=4*(o*f+2*v-e-1),t.data[n+0]=i,t.data[n+1]=j,t.data[n+2]=k,t.data[n+3]=l;v*=2}b(t,d,{polarRotation:0})}},Kinetic.Factory.addGetterSetter(Kinetic.Node,"kaleidoscopePower",2,null,Kinetic.Factory.afterSetFilter),Kinetic.Factory.addGetterSetter(Kinetic.Node,"kaleidoscopeAngle",0,null,Kinetic.Factory.afterSetFilter)}(),function(){function a(a){setTimeout(a,1e3/60)}function b(){return e.apply(Kinetic.root,arguments)}var c=500,d=function(){return Kinetic.root.performance&&Kinetic.root.performance.now?function(){return Kinetic.root.performance.now()}:function(){return(new Date).getTime()}}(),e=function(){return Kinetic.root.requestAnimationFrame||Kinetic.root.webkitRequestAnimationFrame||Kinetic.root.mozRequestAnimationFrame||Kinetic.root.oRequestAnimationFrame||Kinetic.root.msRequestAnimationFrame||a}();Kinetic.Animation=function(a,b){var c=Kinetic.Animation;this.func=a,this.setLayers(b),this.id=c.animIdCounter++,this.frame={time:0,timeDiff:0,lastTime:d()}},Kinetic.Animation.prototype={setLayers:function(a){var b=[];b=a?a.length>0?a:[a]:[],this.layers=b},getLayers:function(){return this.layers},addLayer:function(a){var b,c,d=this.layers;if(d){for(b=d.length,c=0;b>c;c++)if(d[c]._id===a._id)return!1}else this.layers=[];return this.layers.push(a),!0},isRunning:function(){var a,b=Kinetic.Animation,c=b.animations,d=c.length;for(a=0;d>a;a++)if(c[a].id===this.id)return!0;return!1},start:function(){var a=Kinetic.Animation;this.stop(),this.frame.timeDiff=0,this.frame.lastTime=d(),a._addAnimation(this)},stop:function(){Kinetic.Animation._removeAnimation(this)},_updateFrameObject:function(a){this.frame.timeDiff=a-this.frame.lastTime,this.frame.lastTime=a,this.frame.time+=this.frame.timeDiff,this.frame.frameRate=1e3/this.frame.timeDiff}},Kinetic.Animation.animations=[],Kinetic.Animation.animIdCounter=0,Kinetic.Animation.animRunning=!1,Kinetic.Animation._addAnimation=function(a){this.animations.push(a),this._handleAnimation()},Kinetic.Animation._removeAnimation=function(a){var b,c=a.id,d=this.animations,e=d.length;for(b=0;e>b;b++)if(d[b].id===c){this.animations.splice(b,1);break}},Kinetic.Animation._runFrames=function(){var a,b,c,e,f,g,h,i,j,k={},l=this.animations;for(e=0;ef;f++)h=b[f],void 0!==h._id&&(k[h._id]=h);for(i in k)k[i].draw()},Kinetic.Animation._animationLoop=function(){var a=Kinetic.Animation;a.animations.length?(b(a._animationLoop),a._runFrames()):a.animRunning=!1},Kinetic.Animation._handleAnimation=function(){var a=this;this.animRunning||(this.animRunning=!0,a._animationLoop())};var f=Kinetic.Node.prototype.moveTo;Kinetic.Node.prototype.moveTo=function(a){f.call(this,a)},Kinetic.BaseLayer.prototype.batchDraw=function(){var a=this,b=Kinetic.Animation;this.batchAnim||(this.batchAnim=new b(function(){a.lastBatchDrawTime&&d()-a.lastBatchDrawTime>c&&a.batchAnim.stop()},this)),this.lastBatchDrawTime=d(),this.batchAnim.isRunning()||(this.draw(),this.batchAnim.start())},Kinetic.Stage.prototype.batchDraw=function(){this.getChildren().each(function(a){a.batchDraw()})}}(this),function(){var a={node:1,duration:1,easing:1,onFinish:1,yoyo:1},b=1,c=2,d=3,e=0;Kinetic.Tween=function(b){var c,d,g=this,h=b.node,i=h._id,j=b.easing||Kinetic.Easings.Linear,k=!!b.yoyo;c="undefined"==typeof b.duration?1:0===b.duration?.001:b.duration,this.node=h,this._id=e++,this.anim=new Kinetic.Animation(function(){g.tween.onEnterFrame()},h.getLayer()||(h instanceof Kinetic.Stage?h.getLayers():null)),this.tween=new f(d,function(a){g._tweenFunc(a)},j,0,1,1e3*c,k),this._addListeners(),Kinetic.Tween.attrs[i]||(Kinetic.Tween.attrs[i]={}),Kinetic.Tween.attrs[i][this._id]||(Kinetic.Tween.attrs[i][this._id]={}),Kinetic.Tween.tweens[i]||(Kinetic.Tween.tweens[i]={});for(d in b)void 0===a[d]&&this._addAttr(d,b[d]);this.reset(),this.onFinish=b.onFinish,this.onReset=b.onReset},Kinetic.Tween.attrs={},Kinetic.Tween.tweens={},Kinetic.Tween.prototype={_addAttr:function(a,b){var c,d,e,f,g,h=this.node,i=h._id;if(e=Kinetic.Tween.tweens[i][a],e&&delete Kinetic.Tween.attrs[i][e][a],c=h.getAttr(a),Kinetic.Util._isArray(b))for(d=[],g=b.length,f=0;g>f;f++)d.push(b[f]-c[f]);else d=b-c;Kinetic.Tween.attrs[i][this._id][a]={start:c,diff:d},Kinetic.Tween.tweens[i][a]=this._id},_tweenFunc:function(a){var b,c,d,e,f,g,h,i=this.node,j=Kinetic.Tween.attrs[i._id][this._id];for(b in j){if(c=j[b],d=c.start,e=c.diff,Kinetic.Util._isArray(d))for(f=[],h=d.length,g=0;h>g;g++)f.push(d[g]+e[g]*a);else f=d+e*a;i.setAttr(b,f)}},_addListeners:function(){var a=this;this.tween.onPlay=function(){a.anim.start()},this.tween.onReverse=function(){a.anim.start()},this.tween.onPause=function(){a.anim.stop()},this.tween.onFinish=function(){a.onFinish&&a.onFinish()},this.tween.onReset=function(){a.onReset&&a.onReset()}},play:function(){return this.tween.play(),this},reverse:function(){return this.tween.reverse(),this},reset:function(){return this.tween.reset(),this},seek:function(a){return this.tween.seek(1e3*a),this},pause:function(){return this.tween.pause(),this},finish:function(){return this.tween.finish(),this},destroy:function(){var a,b=this.node._id,c=this._id,d=Kinetic.Tween.tweens[b];this.pause();for(a in d)delete Kinetic.Tween.tweens[b][a];delete Kinetic.Tween.attrs[b][c]}};var f=function(a,b,c,d,e,f,g){this.prop=a,this.propFunc=b,this.begin=d,this._pos=d,this.duration=f,this._change=0,this.prevPos=0,this.yoyo=g,this._time=0,this._position=0,this._startTime=0,this._finish=0,this.func=c,this._change=e-this.begin,this.pause()};f.prototype={fire:function(a){var b=this[a];b&&b()},setTime:function(a){a>this.duration?this.yoyo?(this._time=this.duration,this.reverse()):this.finish():0>a?this.yoyo?(this._time=0,this.play()):this.reset():(this._time=a,this.update())},getTime:function(){return this._time},setPosition:function(a){this.prevPos=this._pos,this.propFunc(a),this._pos=a},getPosition:function(a){return void 0===a&&(a=this._time),this.func(a,this.begin,this._change,this.duration)},play:function(){this.state=c,this._startTime=this.getTimer()-this._time,this.onEnterFrame(),this.fire("onPlay")},reverse:function(){this.state=d,this._time=this.duration-this._time,this._startTime=this.getTimer()-this._time,this.onEnterFrame(),this.fire("onReverse")},seek:function(a){this.pause(),this._time=a,this.update(),this.fire("onSeek")},reset:function(){this.pause(),this._time=0,this.update(),this.fire("onReset")},finish:function(){this.pause(),this._time=this.duration,this.update(),this.fire("onFinish")},update:function(){this.setPosition(this.getPosition(this._time))},onEnterFrame:function(){var a=this.getTimer()-this._startTime;this.state===c?this.setTime(a):this.state===d&&this.setTime(this.duration-a)},pause:function(){this.state=b,this.fire("onPause")},getTimer:function(){return(new Date).getTime()}},Kinetic.Easings={BackEaseIn:function(a,b,c,d){var e=1.70158;return c*(a/=d)*a*((e+1)*a-e)+b},BackEaseOut:function(a,b,c,d){var e=1.70158;return c*((a=a/d-1)*a*((e+1)*a+e)+1)+b},BackEaseInOut:function(a,b,c,d){var e=1.70158;return(a/=d/2)<1?c/2*a*a*(((e*=1.525)+1)*a-e)+b:c/2*((a-=2)*a*(((e*=1.525)+1)*a+e)+2)+b},ElasticEaseIn:function(a,b,c,d,e,f){var g=0;return 0===a?b:1==(a/=d)?b+c:(f||(f=.3*d),!e||ea?-.5*e*Math.pow(2,10*(a-=1))*Math.sin(2*(a*d-g)*Math.PI/f)+b:e*Math.pow(2,-10*(a-=1))*Math.sin(2*(a*d-g)*Math.PI/f)*.5+c+b)},BounceEaseOut:function(a,b,c,d){return(a/=d)<1/2.75?7.5625*c*a*a+b:2/2.75>a?c*(7.5625*(a-=1.5/2.75)*a+.75)+b:2.5/2.75>a?c*(7.5625*(a-=2.25/2.75)*a+.9375)+b:c*(7.5625*(a-=2.625/2.75)*a+.984375)+b},BounceEaseIn:function(a,b,c,d){return c-Kinetic.Easings.BounceEaseOut(d-a,0,c,d)+b},BounceEaseInOut:function(a,b,c,d){return d/2>a?.5*Kinetic.Easings.BounceEaseIn(2*a,0,c,d)+b:.5*Kinetic.Easings.BounceEaseOut(2*a-d,0,c,d)+.5*c+b},EaseIn:function(a,b,c,d){return c*(a/=d)*a+b},EaseOut:function(a,b,c,d){return-c*(a/=d)*(a-2)+b},EaseInOut:function(a,b,c,d){return(a/=d/2)<1?c/2*a*a+b:-c/2*(--a*(a-2)-1)+b},StrongEaseIn:function(a,b,c,d){return c*(a/=d)*a*a*a*a+b},StrongEaseOut:function(a,b,c,d){return c*((a=a/d-1)*a*a*a*a+1)+b},StrongEaseInOut:function(a,b,c,d){return(a/=d/2)<1?c/2*a*a*a*a*a+b:c/2*((a-=2)*a*a*a*a+2)+b},Linear:function(a,b,c,d){return c*a/d+b}}}(),function(){Kinetic.DD={anim:new Kinetic.Animation(function(){var a=this.dirty;return this.dirty=!1,a}),isDragging:!1,justDragged:!1,offset:{x:0,y:0},node:null,_drag:function(a){var b=Kinetic.DD,c=b.node;if(c){if(!b.isDragging){var d=c.getStage().getPointerPosition(),e=c.dragDistance(),f=Math.max(Math.abs(d.x-b.startPointerPos.x),Math.abs(d.y-b.startPointerPos.y));if(e>f)return}c._setDragPosition(a),b.isDragging||(b.isDragging=!0,c.fire("dragstart",{type:"dragstart",target:c,evt:a},!0)),c.fire("dragmove",{type:"dragmove",target:c,evt:a},!0)}},_endDragBefore:function(a){var b,c,d=Kinetic.DD,e=d.node;e&&(b=e.nodeType,c=e.getLayer(),d.anim.stop(),d.isDragging&&(d.isDragging=!1,d.justDragged=!0,Kinetic.listenClickTap=!1,a&&(a.dragEndNode=e)),delete d.node,(c||e).draw())},_endDragAfter:function(a){a=a||{};var b=a.dragEndNode;a&&b&&b.fire("dragend",{type:"dragend",target:b,evt:a},!0)}},Kinetic.Node.prototype.startDrag=function(){var a=Kinetic.DD,b=this.getStage(),c=this.getLayer(),d=b.getPointerPosition(),e=this.getAbsolutePosition();d&&(a.node&&a.node.stopDrag(),a.node=this,a.startPointerPos=d,a.offset.x=d.x-e.x,a.offset.y=d.y-e.y,a.anim.setLayers(c||this.getLayers()),a.anim.start(),this._setDragPosition())},Kinetic.Node.prototype._setDragPosition=function(a){var b=Kinetic.DD,c=this.getStage().getPointerPosition(),d=this.getDragBoundFunc();if(c){var e={x:c.x-b.offset.x,y:c.y-b.offset.y};void 0!==d&&(e=d.call(this,e,a)),this.setAbsolutePosition(e),this._lastPos&&this._lastPos.x===e.x&&this._lastPos.y===e.y||(b.anim.dirty=!0),this._lastPos=e}},Kinetic.Node.prototype.stopDrag=function(){var a=Kinetic.DD,b={};a._endDragBefore(b),a._endDragAfter(b)},Kinetic.Node.prototype.setDraggable=function(a){this._setAttr("draggable",a),this._dragChange()};var a=Kinetic.Node.prototype.destroy;Kinetic.Node.prototype.destroy=function(){var b=Kinetic.DD;b.node&&b.node._id===this._id&&this.stopDrag(),a.call(this)},Kinetic.Node.prototype.isDragging=function(){var a=Kinetic.DD;return!(!a.node||a.node._id!==this._id||!a.isDragging)},Kinetic.Node.prototype._listenDrag=function(){var a=this;this._dragCleanup(),"Stage"===this.getClassName()?this.on("contentMousedown.kinetic contentTouchstart.kinetic",function(b){Kinetic.DD.node||a.startDrag(b)}):this.on("mousedown.kinetic touchstart.kinetic",function(b){1!==b.evt.button&&2!==b.evt.button&&(Kinetic.DD.node||a.startDrag(b))})},Kinetic.Node.prototype._dragChange=function(){if(this.attrs.draggable)this._listenDrag();else{this._dragCleanup();var a=this.getStage(),b=Kinetic.DD;a&&b.node&&b.node._id===this._id&&b.node.stopDrag()}},Kinetic.Node.prototype._dragCleanup=function(){"Stage"===this.getClassName()?(this.off("contentMousedown.kinetic"),this.off("contentTouchstart.kinetic")):(this.off("mousedown.kinetic"),this.off("touchstart.kinetic"))},Kinetic.Factory.addGetterSetter(Kinetic.Node,"dragBoundFunc"),Kinetic.Factory.addGetter(Kinetic.Node,"draggable",!1),Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Node,"draggable");var b=Kinetic.document.documentElement;b.addEventListener("mouseup",Kinetic.DD._endDragBefore,!0),b.addEventListener("touchend",Kinetic.DD._endDragBefore,!0),b.addEventListener("mouseup",Kinetic.DD._endDragAfter,!1),b.addEventListener("touchend",Kinetic.DD._endDragAfter,!1)}(),function(){Kinetic.Util.addMethods(Kinetic.Container,{__init:function(a){this.children=new Kinetic.Collection,Kinetic.Node.call(this,a)},getChildren:function(a){if(a){var b=new Kinetic.Collection;return this.children.each(function(c){a(c)&&b.push(c)}),b}return this.children},hasChildren:function(){return this.getChildren().length>0},removeChildren:function(){for(var a,b=Kinetic.Collection.toCollection(this.children),c=0;c1){for(var b=0;bb;b++)if(d=j[b],"#"===d.charAt(0))f=this._getNodeById(d.slice(1)),f&&i.push(f);else if("."===d.charAt(0))e=this._getNodesByName(d.slice(1)),i=i.concat(e);else for(g=this.getChildren(),h=g.length,c=0;h>c;c++)i=i.concat(g[c]._get(d));return Kinetic.Collection.toCollection(i)},_getNodeById:function(a){var b=Kinetic.ids[a];return void 0!==b&&this.isAncestorOf(b)?b:null},_getNodesByName:function(a){var b=Kinetic.names[a]||[];return this._getDescendants(b)},_get:function(a){for(var b=Kinetic.Node.prototype._get.call(this,a),c=this.getChildren(),d=c.length,e=0;d>e;e++)b=b.concat(c[e]._get(a));return b},toObject:function(){var a=Kinetic.Node.prototype.toObject.call(this); + a.children=[];for(var b=this.getChildren(),c=b.length,d=0;c>d;d++){var e=b[d];a.children.push(e.toObject())}return a},_getDescendants:function(a){for(var b=[],c=a.length,d=0;c>d;d++){var e=a[d];this.isAncestorOf(e)&&b.push(e)}return b},isAncestorOf:function(a){for(var b=a.getParent();b;){if(b._id===this._id)return!0;b=b.getParent()}return!1},clone:function(a){var b=Kinetic.Node.prototype.clone.call(this,a);return this.getChildren().each(function(a){b.add(a.clone())}),b},getAllIntersections:function(a){var b=[];return this.find("Shape").each(function(c){c.isVisible()&&c.intersects(a)&&b.push(c)}),b},_setChildrenIndices:function(){this.children.each(function(a,b){a.index=b})},drawScene:function(a,b){var c=this.getLayer(),d=a||c&&c.getCanvas(),e=d&&d.getContext(),f=this._cache.canvas,g=f&&f.scene;return this.isVisible()&&(g?this._drawCachedSceneCanvas(e):this._drawChildren(d,"drawScene",b)),this},drawHit:function(a,b){var c=this.getLayer(),d=a||c&&c.hitCanvas,e=d&&d.getContext(),f=this._cache.canvas,g=f&&f.hit;return this.shouldDrawHit(d)&&(c&&c.clearHitCache(),g?this._drawCachedHitCanvas(e):this._drawChildren(d,"drawHit",b)),this},_drawChildren:function(a,b,c){var d,e,f=this.getLayer(),g=a&&a.getContext(),h=this.getClipWidth(),i=this.getClipHeight(),j=h&&i;j&&f&&(d=this.getClipX(),e=this.getClipY(),g.save(),f._applyTransform(this,g),g.beginPath(),g.rect(d,e,h,i),g.clip(),g.reset()),this.children.each(function(d){d[b](a,c)}),j&&g.restore()},shouldDrawHit:function(a){var b=this.getLayer(),c=Kinetic.DD,d=c&&Kinetic.isDragging()&&-1!==Kinetic.DD.anim.getLayers().indexOf(b);return a&&a.isCache||b&&b.hitGraphEnabled()&&this.isVisible()&&!d}}),Kinetic.Util.extend(Kinetic.Container,Kinetic.Node),Kinetic.Container.prototype.get=Kinetic.Container.prototype.find,Kinetic.Factory.addComponentsGetterSetter(Kinetic.Container,"clip",["x","y","width","height"]),Kinetic.Factory.addGetterSetter(Kinetic.Container,"clipX"),Kinetic.Factory.addGetterSetter(Kinetic.Container,"clipY"),Kinetic.Factory.addGetterSetter(Kinetic.Container,"clipWidth"),Kinetic.Factory.addGetterSetter(Kinetic.Container,"clipHeight"),Kinetic.Collection.mapMethods(Kinetic.Container)}(),function(){function a(a){a.fill()}function b(a){a.stroke()}function c(a){a.fill()}function d(a){a.stroke()}function e(){this._clearCache(f)}var f="hasShadow";Kinetic.Util.addMethods(Kinetic.Shape,{__init:function(f){this.nodeType="Shape",this._fillFunc=a,this._strokeFunc=b,this._fillFuncHit=c,this._strokeFuncHit=d;for(var g,h=Kinetic.shapes;;)if(g=Kinetic.Util.getRandomColor(),g&&!(g in h))break;this.colorKey=g,h[g]=this,Kinetic.Node.call(this,f),this.on("shadowColorChange.kinetic shadowBlurChange.kinetic shadowOffsetChange.kinetic shadowOpacityChange.kinetic shadowEnabledChange.kinetic",e)},hasChildren:function(){return!1},getChildren:function(){return[]},getContext:function(){return this.getLayer().getContext()},getCanvas:function(){return this.getLayer().getCanvas()},hasShadow:function(){return this._getCache(f,this._hasShadow)},_hasShadow:function(){return this.getShadowEnabled()&&0!==this.getShadowOpacity()&&!!(this.getShadowColor()||this.getShadowBlur()||this.getShadowOffsetX()||this.getShadowOffsetY())},hasFill:function(){return!!(this.getFill()||this.getFillPatternImage()||this.getFillLinearGradientColorStops()||this.getFillRadialGradientColorStops())},hasStroke:function(){return!!(this.stroke()||this.strokeRed()||this.strokeGreen()||this.strokeBlue())},intersects:function(a){var b,c=this.getStage(),d=c.bufferHitCanvas;return d.getContext().clear(),this.drawScene(d),b=d.context.getImageData(Math.round(a.x),Math.round(a.y),1,1).data,b[3]>0},destroy:function(){Kinetic.Node.prototype.destroy.call(this),delete Kinetic.shapes[this.colorKey]},_useBufferCanvas:function(){return(this.hasShadow()||1!==this.getAbsoluteOpacity())&&this.hasFill()&&this.hasStroke()&&this.getStage()},drawScene:function(a,b){var c,d,e,f=this.getLayer(),g=a||f.getCanvas(),h=g.getContext(),i=this._cache.canvas,j=this.sceneFunc(),k=this.hasShadow();if(this.isVisible())if(i)this._drawCachedSceneCanvas(h);else if(j){if(h.save(),this._useBufferCanvas()){if(c=this.getStage(),d=c.bufferCanvas,e=d.getContext(),e.clear(),e.save(),e._applyLineJoin(this),f)f._applyTransform(this,e,b);else{var l=this.getAbsoluteTransform(b).getMatrix();h.transform(l[0],l[1],l[2],l[3],l[4],l[5])}j.call(this,e),e.restore(),k&&!g.hitCanvas&&(h.save(),h._applyShadow(this),h.drawImage(d._canvas,0,0),h.restore()),h._applyOpacity(this),h.drawImage(d._canvas,0,0)}else{if(h._applyLineJoin(this),f)f._applyTransform(this,h,b);else{var m=this.getAbsoluteTransform(b).getMatrix();h.transform(m[0],m[1],m[2],m[3],m[4],m[5])}k&&!g.hitCanvas&&(h.save(),h._applyShadow(this),j.call(this,h),h.restore()),h._applyOpacity(this),j.call(this,h)}h.restore()}return this},drawHit:function(a,b){var c=this.getLayer(),d=a||c.hitCanvas,e=d.getContext(),f=this.hitFunc()||this.sceneFunc(),g=this._cache.canvas,h=g&&g.hit;if(this.shouldDrawHit(d))if(c&&c.clearHitCache(),h)this._drawCachedHitCanvas(e);else if(f){if(e.save(),e._applyLineJoin(this),c)c._applyTransform(this,e,b);else{var i=this.getAbsoluteTransform(b).getMatrix();e.transform(i[0],i[1],i[2],i[3],i[4],i[5])}f.call(this,e),e.restore()}return this},drawHitFromCache:function(a){var b,c,d,e,f,g,h,i,j=a||0,k=this._cache.canvas,l=this._getCachedSceneCanvas(),m=l.getContext(),n=k.hit,o=n.getContext(),p=l.getWidth(),q=l.getHeight();o.clear();try{for(b=m.getImageData(0,0,p,q),c=b.data,d=o.getImageData(0,0,p,q),e=d.data,f=c.length,g=Kinetic.Util._hexToRgb(this.colorKey),h=0;f>h;h+=4)i=c[h+3],i>j&&(e[h]=g.r,e[h+1]=g.g,e[h+2]=g.b,e[h+3]=255);o.putImageData(d,0,0)}catch(r){Kinetic.Util.warn("Unable to draw hit graph from cached scene canvas. "+r.message)}return this}}),Kinetic.Util.extend(Kinetic.Shape,Kinetic.Node),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"stroke"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"strokeRed",0,Kinetic.Validators.RGBComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"strokeGreen",0,Kinetic.Validators.RGBComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"strokeBlue",0,Kinetic.Validators.RGBComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"strokeAlpha",1,Kinetic.Validators.alphaComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"strokeWidth",2),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"lineJoin"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"lineCap"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"sceneFunc"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"hitFunc"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"dash"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"shadowColor"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"shadowRed",0,Kinetic.Validators.RGBComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"shadowGreen",0,Kinetic.Validators.RGBComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"shadowBlue",0,Kinetic.Validators.RGBComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"shadowAlpha",1,Kinetic.Validators.alphaComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"shadowBlur"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"shadowOpacity"),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Shape,"shadowOffset",["x","y"]),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"shadowOffsetX",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"shadowOffsetY",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillPatternImage"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fill"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillRed",0,Kinetic.Validators.RGBComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillGreen",0,Kinetic.Validators.RGBComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillBlue",0,Kinetic.Validators.RGBComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillAlpha",1,Kinetic.Validators.alphaComponent),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillPatternX",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillPatternY",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillLinearGradientColorStops"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillRadialGradientStartRadius",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillRadialGradientEndRadius",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillRadialGradientColorStops"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillPatternRepeat","repeat"),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillEnabled",!0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"strokeEnabled",!0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"shadowEnabled",!0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"dashEnabled",!0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"strokeScaleEnabled",!0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillPriority","color"),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Shape,"fillPatternOffset",["x","y"]),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillPatternOffsetX",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillPatternOffsetY",0),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Shape,"fillPatternScale",["x","y"]),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillPatternScaleX",1),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillPatternScaleY",1),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Shape,"fillLinearGradientStartPoint",["x","y"]),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillLinearGradientStartPointX",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillLinearGradientStartPointY",0),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Shape,"fillLinearGradientEndPoint",["x","y"]),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillLinearGradientEndPointX",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillLinearGradientEndPointY",0),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Shape,"fillRadialGradientStartPoint",["x","y"]),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillRadialGradientStartPointX",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillRadialGradientStartPointY",0),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Shape,"fillRadialGradientEndPoint",["x","y"]),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillRadialGradientEndPointX",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillRadialGradientEndPointY",0),Kinetic.Factory.addGetterSetter(Kinetic.Shape,"fillPatternRotation",0),Kinetic.Factory.backCompat(Kinetic.Shape,{dashArray:"dash",getDashArray:"getDash",setDashArray:"getDash",drawFunc:"sceneFunc",getDrawFunc:"getSceneFunc",setDrawFunc:"setSceneFunc",drawHitFunc:"hitFunc",getDrawHitFunc:"getHitFunc",setDrawHitFunc:"setHitFunc"}),Kinetic.Collection.mapMethods(Kinetic.Shape)}(),function(){function a(a,b){a.content.addEventListener(b,function(c){a[L+b](c)},!1)}var b="Stage",c="string",d="px",e="mouseout",f="mouseleave",g="mouseover",h="mouseenter",i="mousemove",j="mousedown",k="mouseup",l="click",m="dblclick",n="touchstart",o="touchend",p="tap",q="dbltap",r="touchmove",s="DOMMouseScroll",t="mousewheel",u="wheel",v="contentMouseout",w="contentMouseover",x="contentMousemove",y="contentMousedown",z="contentMouseup",A="contentClick",B="contentDblclick",C="contentTouchstart",D="contentTouchend",E="contentDbltap",F="contentTouchmove",G="div",H="relative",I="inline-block",J="kineticjs-content",K=" ",L="_",M="container",N="",O=[j,i,k,e,n,r,o,g,s,t,u],P=O.length;Kinetic.Util.addMethods(Kinetic.Stage,{___init:function(a){this.nodeType=b,Kinetic.Container.call(this,a),this._id=Kinetic.idCounter++,this._buildDOM(),this._bindContentEvents(),this._enableNestedTransforms=!1,Kinetic.stages.push(this)},_validateAdd:function(a){"Layer"!==a.getType()&&Kinetic.Util.error("You may only add layers to the stage.")},setContainer:function(a){if(typeof a===c){var b=a;if(a=Kinetic.document.getElementById(a),!a)throw"Can not find container in document with id "+b}return this._setAttr(M,a),this},shouldDrawHit:function(){return!0},draw:function(){return Kinetic.Node.prototype.draw.call(this),this},setHeight:function(a){return Kinetic.Node.prototype.setHeight.call(this,a),this._resizeDOM(),this},setWidth:function(a){return Kinetic.Node.prototype.setWidth.call(this,a),this._resizeDOM(),this},clear:function(){var a,b=this.children,c=b.length;for(a=0;c>a;a++)b[a].clear();return this},clone:function(a){return a||(a={}),a.container=Kinetic.document.createElement(G),Kinetic.Container.prototype.clone.call(this,a)},destroy:function(){var a=this.content;Kinetic.Container.prototype.destroy.call(this),a&&Kinetic.Util._isInDocument(a)&&this.getContainer().removeChild(a);var b=Kinetic.stages.indexOf(this);b>-1&&Kinetic.stages.splice(b,1)},getPointerPosition:function(){return this.pointerPos},getStage:function(){return this},getContent:function(){return this.content},toDataURL:function(a){function b(e){var f=i[e],j=f.toDataURL(),k=new Kinetic.window.Image;k.onload=function(){h.drawImage(k,0,0),e=0;b--)if(c=d[b].getIntersection(a))return c;return null},_resizeDOM:function(){if(this.content){var a,b,c=this.getWidth(),e=this.getHeight(),f=this.getChildren(),g=f.length;for(this.content.style.width=c+d,this.content.style.height=e+d,this.bufferCanvas.setSize(c,e),this.bufferHitCanvas.setSize(c,e),a=0;g>a;a++)b=f[a],b.setSize(c,e),b.draw()}},add:function(a){if(!(arguments.length>1))return Kinetic.Container.prototype.add.call(this,a),a._setCanvasSize(this.width(),this.height()),a.draw(),this.content.appendChild(a.canvas._canvas),this;for(var b=0;bb;b++)a(this,O[b])},_mouseover:function(a){Kinetic.UA.mobile||(this._setPointerPosition(a),this._fire(w,{evt:a}))},_mouseout:function(a){if(!Kinetic.UA.mobile){this._setPointerPosition(a);var b=this.targetShape;b&&!Kinetic.isDragging()&&(b._fireAndBubble(e,{evt:a}),b._fireAndBubble(f,{evt:a}),this.targetShape=null),this.pointerPos=void 0,this._fire(v,{evt:a})}},_mousemove:function(a){if(Kinetic.UA.ieMobile)return this._touchmove(a);if(("undefined"==typeof a.webkitMovementX&&"undefined"==typeof a.webkitMovementY||0!==a.webkitMovementY||0!==a.webkitMovementX)&&!Kinetic.UA.mobile){this._setPointerPosition(a);var b,c=Kinetic.DD;Kinetic.isDragging()||(b=this.getIntersection(this.getPointerPosition()),b&&b.isListening()?Kinetic.isDragging()||this.targetShape&&this.targetShape._id===b._id?b._fireAndBubble(i,{evt:a}):(this.targetShape&&(this.targetShape._fireAndBubble(e,{evt:a},b),this.targetShape._fireAndBubble(f,{evt:a},b)),b._fireAndBubble(g,{evt:a},this.targetShape),b._fireAndBubble(h,{evt:a},this.targetShape),this.targetShape=b):this.targetShape&&!Kinetic.isDragging()&&(this.targetShape._fireAndBubble(e,{evt:a}),this.targetShape._fireAndBubble(f,{evt:a}),this.targetShape=null),this._fire(x,{evt:a})),c&&c._drag(a),a.preventDefault&&a.preventDefault()}},_mousedown:function(a){if(Kinetic.UA.ieMobile)return this._touchstart(a);if(!Kinetic.UA.mobile){this._setPointerPosition(a);var b=this.getIntersection(this.getPointerPosition());Kinetic.listenClickTap=!0,b&&b.isListening()&&(this.clickStartShape=b,b._fireAndBubble(j,{evt:a})),this._fire(y,{evt:a})}a.preventDefault&&a.preventDefault()},_mouseup:function(a){if(Kinetic.UA.ieMobile)return this._touchend(a);if(!Kinetic.UA.mobile){this._setPointerPosition(a);var b=this.getIntersection(this.getPointerPosition()),c=this.clickStartShape,d=!1,e=Kinetic.DD;Kinetic.inDblClickWindow?(d=!0,Kinetic.inDblClickWindow=!1):e&&e.justDragged?e&&(e.justDragged=!1):Kinetic.inDblClickWindow=!0,setTimeout(function(){Kinetic.inDblClickWindow=!1},Kinetic.dblClickWindow),b&&b.isListening()&&(b._fireAndBubble(k,{evt:a}),Kinetic.listenClickTap&&c&&c._id===b._id&&(b._fireAndBubble(l,{evt:a}),d&&b._fireAndBubble(m,{evt:a}))),this._fire(z,{evt:a}),Kinetic.listenClickTap&&(this._fire(A,{evt:a}),d&&this._fire(B,{evt:a})),Kinetic.listenClickTap=!1}a.preventDefault&&a.preventDefault()},_touchstart:function(a){this._setPointerPosition(a);var b=this.getIntersection(this.getPointerPosition());Kinetic.listenClickTap=!0,b&&b.isListening()&&(this.tapStartShape=b,b._fireAndBubble(n,{evt:a}),b.isListening()&&a.preventDefault&&a.preventDefault()),this._fire(C,{evt:a})},_touchend:function(a){this._setPointerPosition(a);var b=this.getIntersection(this.getPointerPosition()),c=!1;Kinetic.inDblClickWindow?(c=!0,Kinetic.inDblClickWindow=!1):Kinetic.inDblClickWindow=!0,setTimeout(function(){Kinetic.inDblClickWindow=!1},Kinetic.dblClickWindow),b&&b.isListening()&&(b._fireAndBubble(o,{evt:a}),Kinetic.listenClickTap&&b._id===this.tapStartShape._id&&(b._fireAndBubble(p,{evt:a}),c&&b._fireAndBubble(q,{evt:a})),b.isListening()&&a.preventDefault&&a.preventDefault()),Kinetic.listenClickTap&&(this._fire(D,{evt:a}),c&&this._fire(E,{evt:a})),Kinetic.listenClickTap=!1},_touchmove:function(a){this._setPointerPosition(a);var b,c=Kinetic.DD;Kinetic.isDragging()||(b=this.getIntersection(this.getPointerPosition()),b&&b.isListening()&&(b._fireAndBubble(r,{evt:a}),b.isListening()&&a.preventDefault&&a.preventDefault()),this._fire(F,{evt:a})),c&&(c._drag(a),Kinetic.isDragging()&&a.preventDefault())},_DOMMouseScroll:function(a){this._mousewheel(a)},_mousewheel:function(a){this._setPointerPosition(a);var b=this.getIntersection(this.getPointerPosition());b&&b.isListening()&&b._fireAndBubble(t,{evt:a})},_wheel:function(a){this._mousewheel(a)},_setPointerPosition:function(a){var b,c=this._getContentPosition(),d=a.offsetX,e=a.clientX,f=null,g=null;a=a?a:window.event,void 0!==a.touches?a.touches.length>0&&(b=a.touches[0],f=b.clientX-c.left,g=b.clientY-c.top):void 0!==d?(f=d,g=a.offsetY):"mozilla"===Kinetic.UA.browser?(f=a.layerX,g=a.layerY):void 0!==e&&c&&(f=e-c.left,g=a.clientY-c.top),null!==f&&null!==g&&(this.pointerPos={x:f,y:g})},_getContentPosition:function(){var a=this.content.getBoundingClientRect?this.content.getBoundingClientRect():{top:0,left:0};return{top:a.top,left:a.left}},_buildDOM:function(){var a=this.getContainer();if(!a){if(Kinetic.Util.isBrowser())throw"Stage has no container. A container is required.";a=Kinetic.document.createElement(G)}a.innerHTML=N,this.content=Kinetic.document.createElement(G),this.content.style.position=H,this.content.style.display=I,this.content.className=J,this.content.setAttribute("role","presentation"),a.appendChild(this.content),this.bufferCanvas=new Kinetic.SceneCanvas({pixelRatio:1}),this.bufferHitCanvas=new Kinetic.HitCanvas,this._resizeDOM()},_onContent:function(a,b){var c,d,e=a.split(K),f=e.length;for(c=0;f>c;c++)d=e[c],this.content.addEventListener(d,b,!1)},cache:function(){Kinetic.Util.warn("Cache function is not allowed for stage. You may use cache only for layers, groups and shapes.")},clearCache:function(){}}),Kinetic.Util.extend(Kinetic.Stage,Kinetic.Container),Kinetic.Factory.addGetter(Kinetic.Stage,"container"),Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Stage,"container")}(),function(){Kinetic.Util.addMethods(Kinetic.BaseLayer,{___init:function(a){this.nodeType="Layer",Kinetic.Container.call(this,a)},createPNGStream:function(){return this.canvas._canvas.createPNGStream()},getCanvas:function(){return this.canvas},getHitCanvas:function(){return this.hitCanvas},getContext:function(){return this.getCanvas().getContext()},clear:function(a){return this.getContext().clear(a),this.getHitCanvas().getContext().clear(a),this},clearHitCache:function(){this._hitImageData=void 0},setZIndex:function(a){Kinetic.Node.prototype.setZIndex.call(this,a);var b=this.getStage();return b&&(b.content.removeChild(this.getCanvas()._canvas),ac;c++){if(f=d[c],b=this._getIntersection({x:a.x+f.x*h,y:a.y+f.y*h}),g=b.shape)return g;b.antialiased&&(i=!0)}if(!i)return;h+=1}},_getImageData:function(a,b){var c=this.hitCanvas.width||1,d=this.hitCanvas.height||1,e=Math.round(b)*c+Math.round(a);return this._hitImageData||(this._hitImageData=this.hitCanvas.context.getImageData(0,0,c,d)),[this._hitImageData.data[4*e+0],this._hitImageData.data[4*e+1],this._hitImageData.data[4*e+2],this._hitImageData.data[4*e+3]]},_getIntersection:function(b){var c,d,e=this.hitCanvas.context.getImageData(b.x,b.y,1,1).data,f=e[3];return 255===f?(c=Kinetic.Util._rgbToHex(e[0],e[1],e[2]),d=Kinetic.shapes[a+c],{shape:d}):f>0?{antialiased:!0}:{}},drawScene:function(a,d){var e=this.getLayer(),f=a||e&&e.getCanvas();return this._fire(b,{node:this}),this.getClearBeforeDraw()&&f.getContext().clear(),Kinetic.Container.prototype.drawScene.call(this,f,d),this._fire(c,{node:this}),this},_applyTransform:function(a,b,c){var d=a.getAbsoluteTransform(c).getMatrix();b.transform(d[0],d[1],d[2],d[3],d[4],d[5])},drawHit:function(a,b){var c=this.getLayer(),d=a||c&&c.hitCanvas;return c&&c.getClearBeforeDraw()&&c.getHitCanvas().getContext().clear(),Kinetic.Container.prototype.drawHit.call(this,d,b),this.imageData=null,this},clear:function(a){return this.getContext().clear(a),this.getHitCanvas().getContext().clear(a),this.imageData=null,this},setVisible:function(a){return Kinetic.Node.prototype.setVisible.call(this,a),a?(this.getCanvas()._canvas.style.display="block",this.hitCanvas._canvas.style.display="block"):(this.getCanvas()._canvas.style.display="none",this.hitCanvas._canvas.style.display="none"),this},enableHitGraph:function(){return this.setHitGraphEnabled(!0),this},disableHitGraph:function(){return this.setHitGraphEnabled(!1),this},setSize:function(a,b){Kinetic.BaseLayer.prototype.setSize.call(this,a,b),this.hitCanvas.setSize(a,b)}}),Kinetic.Util.extend(Kinetic.Layer,Kinetic.BaseLayer),Kinetic.Factory.addGetterSetter(Kinetic.Layer,"hitGraphEnabled",!0),Kinetic.Collection.mapMethods(Kinetic.Layer)}(),function(){Kinetic.Util.addMethods(Kinetic.FastLayer,{____init:function(a){this.nodeType="Layer",this.canvas=new Kinetic.SceneCanvas,Kinetic.BaseLayer.call(this,a)},_validateAdd:function(a){var b=a.getType();"Shape"!==b&&Kinetic.Util.error("You may only add shapes to a fast layer.")},_setCanvasSize:function(a,b){this.canvas.setSize(a,b)},hitGraphEnabled:function(){return!1},getIntersection:function(){return null},drawScene:function(a){var b=this.getLayer(),c=a||b&&b.getCanvas();return this.getClearBeforeDraw()&&c.getContext().clear(),Kinetic.Container.prototype.drawScene.call(this,c),this},_applyTransform:function(a,b,c){if(!c||c._id!==this._id){var d=a.getTransform().getMatrix();b.transform(d[0],d[1],d[2],d[3],d[4],d[5])}},draw:function(){return this.drawScene(),this},clear:function(a){return this.getContext().clear(a),this},setVisible:function(a){return Kinetic.Node.prototype.setVisible.call(this,a),this.getCanvas()._canvas.style.display=a?"block":"none",this}}),Kinetic.Util.extend(Kinetic.FastLayer,Kinetic.BaseLayer),Kinetic.Collection.mapMethods(Kinetic.FastLayer)}(),function(){Kinetic.Util.addMethods(Kinetic.Group,{___init:function(a){this.nodeType="Group",Kinetic.Container.call(this,a)},_validateAdd:function(a){var b=a.getType();"Group"!==b&&"Shape"!==b&&Kinetic.Util.error("You may only add groups and shapes to groups.")}}),Kinetic.Util.extend(Kinetic.Group,Kinetic.Container),Kinetic.Collection.mapMethods(Kinetic.Group)}(),function(){Kinetic.Rect=function(a){this.___init(a)},Kinetic.Rect.prototype={___init:function(a){Kinetic.Shape.call(this,a),this.className="Rect",this.sceneFunc(this._sceneFunc)},_sceneFunc:function(a){var b=this.getCornerRadius(),c=this.getWidth(),d=this.getHeight();a.beginPath(),b?(a.moveTo(b,0),a.lineTo(c-b,0),a.arc(c-b,b,b,3*Math.PI/2,0,!1),a.lineTo(c,d-b),a.arc(c-b,d-b,b,0,Math.PI/2,!1),a.lineTo(b,d),a.arc(b,d-b,b,Math.PI/2,Math.PI,!1),a.lineTo(0,b),a.arc(b,b,b,Math.PI,3*Math.PI/2,!1)):a.rect(0,0,c,d),a.closePath(),a.fillStrokeShape(this)}},Kinetic.Util.extend(Kinetic.Rect,Kinetic.Shape),Kinetic.Factory.addGetterSetter(Kinetic.Rect,"cornerRadius",0),Kinetic.Collection.mapMethods(Kinetic.Rect)}(),function(){var a=2*Math.PI-1e-4,b="Circle";Kinetic.Circle=function(a){this.___init(a)},Kinetic.Circle.prototype={___init:function(a){Kinetic.Shape.call(this,a),this.className=b,this.sceneFunc(this._sceneFunc)},_sceneFunc:function(b){b.beginPath(),b.arc(0,0,this.getRadius(),0,a,!1),b.closePath(),b.fillStrokeShape(this)},getWidth:function(){return 2*this.getRadius()},getHeight:function(){return 2*this.getRadius()},setWidth:function(a){Kinetic.Node.prototype.setWidth.call(this,a),this.radius()!==a/2&&this.setRadius(a/2)},setHeight:function(a){Kinetic.Node.prototype.setHeight.call(this,a),this.radius()!==a/2&&this.setRadius(a/2)},setRadius:function(a){this._setAttr("radius",a),this.setWidth(2*a),this.setHeight(2*a)}},Kinetic.Util.extend(Kinetic.Circle,Kinetic.Shape),Kinetic.Factory.addGetter(Kinetic.Circle,"radius",0),Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Circle,"radius"),Kinetic.Collection.mapMethods(Kinetic.Circle)}(),function(){var a=2*Math.PI-1e-4,b="Ellipse";Kinetic.Ellipse=function(a){this.___init(a)},Kinetic.Ellipse.prototype={___init:function(a){Kinetic.Shape.call(this,a),this.className=b,this.sceneFunc(this._sceneFunc)},_sceneFunc:function(b){var c=this.getRadiusX(),d=this.getRadiusY();b.beginPath(),b.save(),c!==d&&b.scale(1,d/c),b.arc(0,0,c,0,a,!1),b.restore(),b.closePath(),b.fillStrokeShape(this)},getWidth:function(){return 2*this.getRadiusX()},getHeight:function(){return 2*this.getRadiusY()},setWidth:function(a){Kinetic.Node.prototype.setWidth.call(this,a),this.setRadius({x:a/2})},setHeight:function(a){Kinetic.Node.prototype.setHeight.call(this,a),this.setRadius({y:a/2})}},Kinetic.Util.extend(Kinetic.Ellipse,Kinetic.Shape),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Ellipse,"radius",["x","y"]),Kinetic.Factory.addGetterSetter(Kinetic.Ellipse,"radiusX",0),Kinetic.Factory.addGetterSetter(Kinetic.Ellipse,"radiusY",0),Kinetic.Collection.mapMethods(Kinetic.Ellipse)}(),function(){var a=2*Math.PI-1e-4;Kinetic.Ring=function(a){this.___init(a)},Kinetic.Ring.prototype={___init:function(a){Kinetic.Shape.call(this,a),this.className="Ring",this.sceneFunc(this._sceneFunc)},_sceneFunc:function(b){b.beginPath(),b.arc(0,0,this.getInnerRadius(),0,a,!1),b.moveTo(this.getOuterRadius(),0),b.arc(0,0,this.getOuterRadius(),a,0,!0),b.closePath(),b.fillStrokeShape(this)},getWidth:function(){return 2*this.getOuterRadius()},getHeight:function(){return 2*this.getOuterRadius()},setWidth:function(a){Kinetic.Node.prototype.setWidth.call(this,a),this.outerRadius()!==a/2&&this.setOuterRadius(a/2)},setHeight:function(a){Kinetic.Node.prototype.setHeight.call(this,a),this.outerRadius()!==a/2&&this.setOuterRadius(a/2)},setOuterRadius:function(a){this._setAttr("outerRadius",a),this.setWidth(2*a),this.setHeight(2*a)}},Kinetic.Util.extend(Kinetic.Ring,Kinetic.Shape),Kinetic.Factory.addGetterSetter(Kinetic.Ring,"innerRadius",0),Kinetic.Factory.addGetter(Kinetic.Ring,"outerRadius",0),Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Ring,"outerRadius"),Kinetic.Collection.mapMethods(Kinetic.Ring)}(),function(){Kinetic.Wedge=function(a){this.___init(a)},Kinetic.Wedge.prototype={___init:function(a){Kinetic.Shape.call(this,a),this.className="Wedge",this.sceneFunc(this._sceneFunc)},_sceneFunc:function(a){a.beginPath(),a.arc(0,0,this.getRadius(),0,Kinetic.getAngle(this.getAngle()),this.getClockwise()),a.lineTo(0,0),a.closePath(),a.fillStrokeShape(this)}},Kinetic.Util.extend(Kinetic.Wedge,Kinetic.Shape),Kinetic.Factory.addGetterSetter(Kinetic.Wedge,"radius",0),Kinetic.Factory.addGetterSetter(Kinetic.Wedge,"angle",0),Kinetic.Factory.addGetterSetter(Kinetic.Wedge,"clockwise",!1),Kinetic.Factory.backCompat(Kinetic.Wedge,{angleDeg:"angle",getAngleDeg:"getAngle",setAngleDeg:"setAngle"}),Kinetic.Collection.mapMethods(Kinetic.Wedge)}(),function(){Kinetic.Arc=function(a){this.___init(a)},Kinetic.Arc.prototype={___init:function(a){Kinetic.Shape.call(this,a),this.className="Arc",this.sceneFunc(this._sceneFunc)},_sceneFunc:function(a){var b=Kinetic.getAngle(this.angle()),c=this.clockwise();a.beginPath(),a.arc(0,0,this.getOuterRadius(),0,b,c),a.arc(0,0,this.getInnerRadius(),b,0,!c),a.closePath(),a.fillStrokeShape(this)}},Kinetic.Util.extend(Kinetic.Arc,Kinetic.Shape),Kinetic.Factory.addGetterSetter(Kinetic.Arc,"innerRadius",0),Kinetic.Factory.addGetterSetter(Kinetic.Arc,"outerRadius",0),Kinetic.Factory.addGetterSetter(Kinetic.Arc,"angle",0),Kinetic.Factory.addGetterSetter(Kinetic.Arc,"clockwise",!1),Kinetic.Collection.mapMethods(Kinetic.Arc)}(),function(){var a="Image";Kinetic.Image=function(a){this.___init(a)},Kinetic.Image.prototype={___init:function(b){Kinetic.Shape.call(this,b),this.className=a,this.sceneFunc(this._sceneFunc),this.hitFunc(this._hitFunc)},_useBufferCanvas:function(){return(this.hasShadow()||1!==this.getAbsoluteOpacity())&&this.hasStroke()&&this.getStage()},_sceneFunc:function(a){var b,c,d,e=this.getWidth(),f=this.getHeight(),g=this.getImage();g&&(b=this.getCropWidth(),c=this.getCropHeight(),d=b&&c?[g,this.getCropX(),this.getCropY(),b,c,0,0,e,f]:[g,0,0,e,f]),(this.hasFill()||this.hasStroke()||this.hasShadow())&&(a.beginPath(),a.rect(0,0,e,f),a.closePath(),a.fillStrokeShape(this)),g&&a.drawImage.apply(a,d) + },_hitFunc:function(a){var b=this.getWidth(),c=this.getHeight();a.beginPath(),a.rect(0,0,b,c),a.closePath(),a.fillStrokeShape(this)},getWidth:function(){var a=this.getImage();return this.attrs.width||(a?a.width:0)},getHeight:function(){var a=this.getImage();return this.attrs.height||(a?a.height:0)}},Kinetic.Util.extend(Kinetic.Image,Kinetic.Shape),Kinetic.Factory.addGetterSetter(Kinetic.Image,"image"),Kinetic.Factory.addComponentsGetterSetter(Kinetic.Image,"crop",["x","y","width","height"]),Kinetic.Factory.addGetterSetter(Kinetic.Image,"cropX",0),Kinetic.Factory.addGetterSetter(Kinetic.Image,"cropY",0),Kinetic.Factory.addGetterSetter(Kinetic.Image,"cropWidth",0),Kinetic.Factory.addGetterSetter(Kinetic.Image,"cropHeight",0),Kinetic.Collection.mapMethods(Kinetic.Image)}(),function(){function a(a){a.fillText(this.partialText,0,0)}function b(a){a.strokeText(this.partialText,0,0)}var c="auto",d="center",e="Change.kinetic",f="2d",g="-",h="",i="left",j="text",k="Text",l="middle",m="normal",n="px ",o=" ",p="right",q="word",r="char",s="none",t=["fontFamily","fontSize","fontStyle","fontVariant","padding","align","lineHeight","text","width","height","wrap"],u=t.length,v=Kinetic.Util.createCanvasElement().getContext(f);Kinetic.Text=function(a){this.___init(a)},Kinetic.Text.prototype={___init:function(d){d=d||{},d.fill=d.fill||"black",void 0===d.width&&(d.width=c),void 0===d.height&&(d.height=c),Kinetic.Shape.call(this,d),this._fillFunc=a,this._strokeFunc=b,this.className=k;for(var f=0;u>f;f++)this.on(t[f]+e,this._setTextData);this._setTextData(),this.sceneFunc(this._sceneFunc),this.hitFunc(this._hitFunc)},_sceneFunc:function(a){var b,c=this.getPadding(),e=this.getTextHeight(),f=this.getLineHeight()*e,g=this.textArr,h=g.length,j=this.getWidth();for(a.setAttr("font",this._getContextFont()),a.setAttr("textBaseline",l),a.setAttr("textAlign",i),a.save(),a.translate(c,0),a.translate(0,c+e/2),b=0;h>b;b++){var k=g[b],m=k.text,n=k.width;a.save(),this.getAlign()===p?a.translate(j-n-2*c,0):this.getAlign()===d&&a.translate((j-n-2*c)/2,0),this.partialText=m,a.fillStrokeShape(this),a.restore(),a.translate(0,f)}a.restore()},_hitFunc:function(a){var b=this.getWidth(),c=this.getHeight();a.beginPath(),a.rect(0,0,b,c),a.closePath(),a.fillStrokeShape(this)},setText:function(a){var b=Kinetic.Util._isString(a)?a:a.toString();return this._setAttr(j,b),this},getWidth:function(){return this.attrs.width===c?this.getTextWidth()+2*this.getPadding():this.attrs.width},getHeight:function(){return this.attrs.height===c?this.getTextHeight()*this.textArr.length*this.getLineHeight()+2*this.getPadding():this.attrs.height},getTextWidth:function(){return this.textWidth},getTextHeight:function(){return this.textHeight},_getTextSize:function(a){var b,c=v,d=this.getFontSize();return c.save(),c.font=this._getContextFont(),b=c.measureText(a),c.restore(),{width:b.width,height:parseInt(d,10)}},_getContextFont:function(){return this.getFontStyle()+o+this.getFontVariant()+o+this.getFontSize()+n+this.getFontFamily()},_addTextLine:function(a,b){return this.textArr.push({text:a,width:b})},_getTextWidth:function(a){return v.measureText(a).width},_setTextData:function(){var a=this.getText().split("\n"),b=+this.getFontSize(),d=0,e=this.getLineHeight()*b,f=this.attrs.width,h=this.attrs.height,i=f!==c,j=h!==c,k=this.getPadding(),l=f-2*k,m=h-2*k,n=0,p=this.getWrap(),q=p!==s,t=p!==r&&q;this.textArr=[],v.save(),v.font=this._getContextFont();for(var u=0,w=a.length;w>u;++u){var x=a[u],y=this._getTextWidth(x);if(i&&y>l)for(;x.length>0;){for(var z=0,A=x.length,B="",C=0;A>z;){var D=z+A>>>1,E=x.slice(0,D+1),F=this._getTextWidth(E);l>=F?(z=D+1,B=E,C=F):A=D}if(!B)break;if(t){var G=Math.max(B.lastIndexOf(o),B.lastIndexOf(g))+1;G>0&&(z=G,B=B.slice(0,z),C=this._getTextWidth(B))}if(this._addTextLine(B,C),d=Math.max(d,C),n+=e,!q||j&&n+e>m)break;if(x=x.slice(z),x.length>0&&(y=this._getTextWidth(x),l>=y)){this._addTextLine(x,y),n+=e,d=Math.max(d,y);break}}else this._addTextLine(x,y),n+=e,d=Math.max(d,y);if(j&&n+e>m)break}v.restore(),this.textHeight=b,this.textWidth=d}},Kinetic.Util.extend(Kinetic.Text,Kinetic.Shape),Kinetic.Factory.addGetterSetter(Kinetic.Text,"fontFamily","Arial"),Kinetic.Factory.addGetterSetter(Kinetic.Text,"fontSize",12),Kinetic.Factory.addGetterSetter(Kinetic.Text,"fontStyle",m),Kinetic.Factory.addGetterSetter(Kinetic.Text,"fontVariant",m),Kinetic.Factory.addGetterSetter(Kinetic.Text,"padding",0),Kinetic.Factory.addGetterSetter(Kinetic.Text,"align",i),Kinetic.Factory.addGetterSetter(Kinetic.Text,"lineHeight",1),Kinetic.Factory.addGetterSetter(Kinetic.Text,"wrap",q),Kinetic.Factory.addGetter(Kinetic.Text,"text",h),Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Text,"text"),Kinetic.Collection.mapMethods(Kinetic.Text)}(),function(){Kinetic.Line=function(a){this.___init(a)},Kinetic.Line.prototype={___init:function(a){Kinetic.Shape.call(this,a),this.className="Line",this.on("pointsChange.kinetic tensionChange.kinetic closedChange.kinetic",function(){this._clearCache("tensionPoints")}),this.sceneFunc(this._sceneFunc)},_sceneFunc:function(a){var b,c,d,e=this.getPoints(),f=e.length,g=this.getTension(),h=this.getClosed();if(f){if(a.beginPath(),a.moveTo(e[0],e[1]),0!==g&&f>4){for(b=this.getTensionPoints(),c=b.length,d=h?0:4,h||a.quadraticCurveTo(b[0],b[1],b[2],b[3]);c-2>d;)a.bezierCurveTo(b[d++],b[d++],b[d++],b[d++],b[d++],b[d++]);h||a.quadraticCurveTo(b[c-2],b[c-1],e[f-2],e[f-1])}else for(d=2;f>d;d+=2)a.lineTo(e[d],e[d+1]);h?(a.closePath(),a.fillStrokeShape(this)):a.strokeShape(this)}},getTensionPoints:function(){return this._getCache("tensionPoints",this._getTensionPoints)},_getTensionPoints:function(){return this.getClosed()?this._getTensionPointsClosed():Kinetic.Util._expandPoints(this.getPoints(),this.getTension())},_getTensionPointsClosed:function(){var a=this.getPoints(),b=a.length,c=this.getTension(),d=Kinetic.Util,e=d._getControlPoints(a[b-2],a[b-1],a[0],a[1],a[2],a[3],c),f=d._getControlPoints(a[b-4],a[b-3],a[b-2],a[b-1],a[0],a[1],c),g=Kinetic.Util._expandPoints(a,c),h=[e[2],e[3]].concat(g).concat([f[0],f[1],a[b-2],a[b-1],f[2],f[3],e[0],e[1],a[0],a[1]]);return h}},Kinetic.Util.extend(Kinetic.Line,Kinetic.Shape),Kinetic.Factory.addGetterSetter(Kinetic.Line,"closed",!1),Kinetic.Factory.addGetterSetter(Kinetic.Line,"tension",0),Kinetic.Factory.addGetterSetter(Kinetic.Line,"points",[]),Kinetic.Collection.mapMethods(Kinetic.Line)}(),function(){Kinetic.Sprite=function(a){this.___init(a)},Kinetic.Sprite.prototype={___init:function(a){Kinetic.Shape.call(this,a),this.className="Sprite",this._updated=!0;var b=this;this.anim=new Kinetic.Animation(function(){var a=b._updated;return b._updated=!1,a}),this.on("animationChange.kinetic",function(){this.frameIndex(0)}),this.on("frameIndexChange.kinetic",function(){this._updated=!0}),this.on("frameRateChange.kinetic",function(){this.anim.isRunning()&&(clearInterval(this.interval),this._setInterval())}),this.sceneFunc(this._sceneFunc),this.hitFunc(this._hitFunc)},_sceneFunc:function(a){var b=this.getAnimation(),c=this.frameIndex(),d=4*c,e=this.getAnimations()[b],f=this.frameOffsets(),g=e[d+0],h=e[d+1],i=e[d+2],j=e[d+3],k=this.getImage();if(k)if(f){var l=f[b],m=2*c;a.drawImage(k,g,h,i,j,l[m+0],l[m+1],i,j)}else a.drawImage(k,g,h,i,j,0,0,i,j)},_hitFunc:function(a){var b=this.getAnimation(),c=this.frameIndex(),d=4*c,e=this.getAnimations()[b],f=this.frameOffsets(),g=e[d+2],h=e[d+3];if(a.beginPath(),f){var i=f[b],j=2*c;a.rect(i[j+0],i[j+1],g,h)}else a.rect(0,0,g,h);a.closePath(),a.fillShape(this)},_useBufferCanvas:function(){return(this.hasShadow()||1!==this.getAbsoluteOpacity())&&this.hasStroke()},_setInterval:function(){var a=this;this.interval=setInterval(function(){a._updateIndex()},1e3/this.getFrameRate())},start:function(){var a=this.getLayer();this.anim.setLayers(a),this._setInterval(),this.anim.start()},stop:function(){this.anim.stop(),clearInterval(this.interval)},isRunning:function(){return this.anim.isRunning()},_updateIndex:function(){var a=this.frameIndex(),b=this.getAnimation(),c=this.getAnimations(),d=c[b],e=d.length/4;this.frameIndex(e-1>a?a+1:0)}},Kinetic.Util.extend(Kinetic.Sprite,Kinetic.Shape),Kinetic.Factory.addGetterSetter(Kinetic.Sprite,"animation"),Kinetic.Factory.addGetterSetter(Kinetic.Sprite,"animations"),Kinetic.Factory.addGetterSetter(Kinetic.Sprite,"frameOffsets"),Kinetic.Factory.addGetterSetter(Kinetic.Sprite,"image"),Kinetic.Factory.addGetterSetter(Kinetic.Sprite,"frameIndex",0),Kinetic.Factory.addGetterSetter(Kinetic.Sprite,"frameRate",17),Kinetic.Factory.backCompat(Kinetic.Sprite,{index:"frameIndex",getIndex:"getFrameIndex",setIndex:"setFrameIndex"}),Kinetic.Collection.mapMethods(Kinetic.Sprite)}(),function(){Kinetic.Path=function(a){this.___init(a)},Kinetic.Path.prototype={___init:function(a){this.dataArray=[];var b=this;Kinetic.Shape.call(this,a),this.className="Path",this.dataArray=Kinetic.Path.parsePathData(this.getData()),this.on("dataChange.kinetic",function(){b.dataArray=Kinetic.Path.parsePathData(this.getData())}),this.sceneFunc(this._sceneFunc)},_sceneFunc:function(a){var b=this.dataArray,c=!1;a.beginPath();for(var d=0;dj?i:j,p=i>j?1:i/j,q=i>j?j/i:1;a.translate(g,h),a.rotate(m),a.scale(p,q),a.arc(0,0,o,k,k+l,1-n),a.scale(1/p,1/q),a.rotate(-m),a.translate(-g,-h);break;case"z":a.closePath(),c=!0}}c?a.fillStrokeShape(this):a.strokeShape(this)}},Kinetic.Util.extend(Kinetic.Path,Kinetic.Shape),Kinetic.Path.getLineLength=function(a,b,c,d){return Math.sqrt((c-a)*(c-a)+(d-b)*(d-b))},Kinetic.Path.getPointOnLine=function(a,b,c,d,e,f,g){void 0===f&&(f=b),void 0===g&&(g=c);var h=(e-c)/(d-b+1e-8),i=Math.sqrt(a*a/(1+h*h));b>d&&(i*=-1);var j,k=h*i;if(d===b)j={x:f,y:g+k};else if((g-c)/(f-b+1e-8)===h)j={x:f+i,y:g+k};else{var l,m,n=this.getLineLength(b,c,d,e);if(1e-8>n)return void 0;var o=(f-b)*(d-b)+(g-c)*(e-c);o/=n*n,l=b+o*(d-b),m=c+o*(e-c);var p=this.getLineLength(f,g,l,m),q=Math.sqrt(a*a-p*p);i=Math.sqrt(q*q/(1+h*h)),b>d&&(i*=-1),k=h*i,j={x:l+i,y:m+k}}return j},Kinetic.Path.getPointOnCubicBezier=function(a,b,c,d,e,f,g,h,i){function j(a){return a*a*a}function k(a){return 3*a*a*(1-a)}function l(a){return 3*a*(1-a)*(1-a)}function m(a){return(1-a)*(1-a)*(1-a)}var n=h*j(a)+f*k(a)+d*l(a)+b*m(a),o=i*j(a)+g*k(a)+e*l(a)+c*m(a);return{x:n,y:o}},Kinetic.Path.getPointOnQuadraticBezier=function(a,b,c,d,e,f,g){function h(a){return a*a}function i(a){return 2*a*(1-a)}function j(a){return(1-a)*(1-a)}var k=f*h(a)+d*i(a)+b*j(a),l=g*h(a)+e*i(a)+c*j(a);return{x:k,y:l}},Kinetic.Path.getPointOnEllipticalArc=function(a,b,c,d,e,f){var g=Math.cos(f),h=Math.sin(f),i={x:c*Math.cos(e),y:d*Math.sin(e)};return{x:a+(i.x*g-i.y*h),y:b+(i.x*h+i.y*g)}},Kinetic.Path.parsePathData=function(a){if(!a)return[];var b=a,c=["m","M","l","L","v","V","h","H","z","Z","c","C","q","Q","t","T","s","S","a","A"];b=b.replace(new RegExp(" ","g"),",");for(var d=0;d0&&""===k[0]&&k.shift();for(var l=0;l0&&!isNaN(k[0]);){var m,n,o,p,q,r,s,t,u,v,w=null,x=[],y=g,z=h;switch(j){case"l":g+=k.shift(),h+=k.shift(),w="L",x.push(g,h);break;case"L":g=k.shift(),h=k.shift(),x.push(g,h);break;case"m":var A=k.shift(),B=k.shift();if(g+=A,h+=B,w="M",f.length>2&&"z"===f[f.length-1].command)for(var C=f.length-2;C>=0;C--)if("M"===f[C].command){g=f[C].points[0]+A,h=f[C].points[1]+B;break}x.push(g,h),j="l";break;case"M":g=k.shift(),h=k.shift(),w="M",x.push(g,h),j="L";break;case"h":g+=k.shift(),w="L",x.push(g,h);break;case"H":g=k.shift(),w="L",x.push(g,h);break;case"v":h+=k.shift(),w="L",x.push(g,h);break;case"V":h=k.shift(),w="L",x.push(g,h);break;case"C":x.push(k.shift(),k.shift(),k.shift(),k.shift()),g=k.shift(),h=k.shift(),x.push(g,h);break;case"c":x.push(g+k.shift(),h+k.shift(),g+k.shift(),h+k.shift()),g+=k.shift(),h+=k.shift(),w="C",x.push(g,h);break;case"S":n=g,o=h,m=f[f.length-1],"C"===m.command&&(n=g+(g-m.points[2]),o=h+(h-m.points[3])),x.push(n,o,k.shift(),k.shift()),g=k.shift(),h=k.shift(),w="C",x.push(g,h);break;case"s":n=g,o=h,m=f[f.length-1],"C"===m.command&&(n=g+(g-m.points[2]),o=h+(h-m.points[3])),x.push(n,o,g+k.shift(),h+k.shift()),g+=k.shift(),h+=k.shift(),w="C",x.push(g,h);break;case"Q":x.push(k.shift(),k.shift()),g=k.shift(),h=k.shift(),x.push(g,h);break;case"q":x.push(g+k.shift(),h+k.shift()),g+=k.shift(),h+=k.shift(),w="Q",x.push(g,h);break;case"T":n=g,o=h,m=f[f.length-1],"Q"===m.command&&(n=g+(g-m.points[0]),o=h+(h-m.points[1])),g=k.shift(),h=k.shift(),w="Q",x.push(n,o,g,h);break;case"t":n=g,o=h,m=f[f.length-1],"Q"===m.command&&(n=g+(g-m.points[0]),o=h+(h-m.points[1])),g+=k.shift(),h+=k.shift(),w="Q",x.push(n,o,g,h);break;case"A":p=k.shift(),q=k.shift(),r=k.shift(),s=k.shift(),t=k.shift(),u=g,v=h,g=k.shift(),h=k.shift(),w="A",x=this.convertEndpointToCenterParameterization(u,v,g,h,s,t,p,q,r);break;case"a":p=k.shift(),q=k.shift(),r=k.shift(),s=k.shift(),t=k.shift(),u=g,v=h,g+=k.shift(),h+=k.shift(),w="A",x=this.convertEndpointToCenterParameterization(u,v,g,h,s,t,p,q,r)}f.push({command:w||j,points:x,start:{x:y,y:z},pathLength:this.calcLength(y,z,w||j,x)})}("z"===j||"Z"===j)&&f.push({command:"z",points:[],start:void 0,pathLength:0})}return f},Kinetic.Path.calcLength=function(a,b,c,d){var e,f,g,h,i=Kinetic.Path;switch(c){case"L":return i.getLineLength(a,b,d[0],d[1]);case"C":for(e=0,f=i.getPointOnCubicBezier(0,a,b,d[0],d[1],d[2],d[3],d[4],d[5]),h=.01;1>=h;h+=.01)g=i.getPointOnCubicBezier(h,a,b,d[0],d[1],d[2],d[3],d[4],d[5]),e+=i.getLineLength(f.x,f.y,g.x,g.y),f=g;return e;case"Q":for(e=0,f=i.getPointOnQuadraticBezier(0,a,b,d[0],d[1],d[2],d[3]),h=.01;1>=h;h+=.01)g=i.getPointOnQuadraticBezier(h,a,b,d[0],d[1],d[2],d[3]),e+=i.getLineLength(f.x,f.y,g.x,g.y),f=g;return e;case"A":e=0;var j=d[4],k=d[5],l=d[4]+k,m=Math.PI/180;if(Math.abs(j-l)k)for(h=j-m;h>l;h-=m)g=i.getPointOnEllipticalArc(d[0],d[1],d[2],d[3],h,0),e+=i.getLineLength(f.x,f.y,g.x,g.y),f=g;else for(h=j+m;l>h;h+=m)g=i.getPointOnEllipticalArc(d[0],d[1],d[2],d[3],h,0),e+=i.getLineLength(f.x,f.y,g.x,g.y),f=g;return g=i.getPointOnEllipticalArc(d[0],d[1],d[2],d[3],l,0),e+=i.getLineLength(f.x,f.y,g.x,g.y)}return 0},Kinetic.Path.convertEndpointToCenterParameterization=function(a,b,c,d,e,f,g,h,i){var j=i*(Math.PI/180),k=Math.cos(j)*(a-c)/2+Math.sin(j)*(b-d)/2,l=-1*Math.sin(j)*(a-c)/2+Math.cos(j)*(b-d)/2,m=k*k/(g*g)+l*l/(h*h);m>1&&(g*=Math.sqrt(m),h*=Math.sqrt(m));var n=Math.sqrt((g*g*h*h-g*g*l*l-h*h*k*k)/(g*g*l*l+h*h*k*k));e===f&&(n*=-1),isNaN(n)&&(n=0);var o=n*g*l/h,p=n*-h*k/g,q=(a+c)/2+Math.cos(j)*o-Math.sin(j)*p,r=(b+d)/2+Math.sin(j)*o+Math.cos(j)*p,s=function(a){return Math.sqrt(a[0]*a[0]+a[1]*a[1])},t=function(a,b){return(a[0]*b[0]+a[1]*b[1])/(s(a)*s(b))},u=function(a,b){return(a[0]*b[1]=1&&(y=0),0===f&&y>0&&(y-=2*Math.PI),1===f&&0>y&&(y+=2*Math.PI),[q,r,g,h,v,y,j,f]},Kinetic.Factory.addGetterSetter(Kinetic.Path,"data"),Kinetic.Collection.mapMethods(Kinetic.Path)}(),function(){function a(a){a.fillText(this.partialText,0,0)}function b(a){a.strokeText(this.partialText,0,0)}var c="",d="normal";Kinetic.TextPath=function(a){this.___init(a)},Kinetic.TextPath.prototype={___init:function(c){var d=this;this.dummyCanvas=Kinetic.Util.createCanvasElement(),this.dataArray=[],Kinetic.Shape.call(this,c),this._fillFunc=a,this._strokeFunc=b,this._fillFuncHit=a,this._strokeFuncHit=b,this.className="TextPath",this.dataArray=Kinetic.Path.parsePathData(this.attrs.data),this.on("dataChange.kinetic",function(){d.dataArray=Kinetic.Path.parsePathData(this.attrs.data)}),this.on("textChange.kinetic textStroke.kinetic textStrokeWidth.kinetic",d._setTextData),d._setTextData(),this.sceneFunc(this._sceneFunc)},_sceneFunc:function(a){a.setAttr("font",this._getContextFont()),a.setAttr("textBaseline","middle"),a.setAttr("textAlign","left"),a.save();for(var b=this.glyphInfo,c=0;c0)return g=d,b[d];"M"==b[d].command&&(c={x:b[d].points[0],y:b[d].points[1]})}return{}},j=function(b){var f=a._getTextSize(b).width,g=0,j=0;for(d=void 0;Math.abs(f-g)/f>.01&&25>j;){j++;for(var k=g;void 0===e;)e=i(),e&&k+e.pathLengthf?d=Kinetic.Path.getPointOnLine(f,c.x,c.y,e.points[0],e.points[1],c.x,c.y):e=void 0;break;case"A":var m=e.points[4],n=e.points[5],o=e.points[4]+n;0===h?h=m+1e-8:f>g?h+=Math.PI/180*n/Math.abs(n):h-=Math.PI/360*n/Math.abs(n),(0>n&&o>h||n>=0&&h>o)&&(h=o,l=!0),d=Kinetic.Path.getPointOnEllipticalArc(e.points[0],e.points[1],e.points[2],e.points[3],h,e.points[6]);break;case"C":0===h?h=f>e.pathLength?1e-8:f/e.pathLength:f>g?h+=(f-g)/e.pathLength:h-=(g-f)/e.pathLength,h>1&&(h=1,l=!0),d=Kinetic.Path.getPointOnCubicBezier(h,e.start.x,e.start.y,e.points[0],e.points[1],e.points[2],e.points[3],e.points[4],e.points[5]);break;case"Q":0===h?h=f/e.pathLength:f>g?h+=(f-g)/e.pathLength:h-=(g-f)/e.pathLength,h>1&&(h=1,l=!0),d=Kinetic.Path.getPointOnQuadraticBezier(h,e.start.x,e.start.y,e.points[0],e.points[1],e.points[2],e.points[3])}void 0!==d&&(g=Kinetic.Path.getLineLength(c.x,c.y,d.x,d.y)),l&&(l=!1,e=void 0)}},k=0;kb;b++)c=f*Math.sin(2*b*Math.PI/e),d=-1*f*Math.cos(2*b*Math.PI/e),a.lineTo(c,d);a.closePath(),a.fillStrokeShape(this)}},Kinetic.Util.extend(Kinetic.RegularPolygon,Kinetic.Shape),Kinetic.Factory.addGetterSetter(Kinetic.RegularPolygon,"radius",0),Kinetic.Factory.addGetterSetter(Kinetic.RegularPolygon,"sides",0),Kinetic.Collection.mapMethods(Kinetic.RegularPolygon)}(),function(){Kinetic.Star=function(a){this.___init(a)},Kinetic.Star.prototype={___init:function(a){Kinetic.Shape.call(this,a),this.className="Star",this.sceneFunc(this._sceneFunc)},_sceneFunc:function(a){var b=this.innerRadius(),c=this.outerRadius(),d=this.numPoints();a.beginPath(),a.moveTo(0,0-c);for(var e=1;2*d>e;e++){var f=e%2===0?c:b,g=f*Math.sin(e*Math.PI/d),h=-1*f*Math.cos(e*Math.PI/d);a.lineTo(g,h)}a.closePath(),a.fillStrokeShape(this)}},Kinetic.Util.extend(Kinetic.Star,Kinetic.Shape),Kinetic.Factory.addGetterSetter(Kinetic.Star,"numPoints",5),Kinetic.Factory.addGetterSetter(Kinetic.Star,"innerRadius",0),Kinetic.Factory.addGetterSetter(Kinetic.Star,"outerRadius",0),Kinetic.Collection.mapMethods(Kinetic.Star)}(),function(){var a=["fontFamily","fontSize","fontStyle","padding","lineHeight","text"],b="Change.kinetic",c="none",d="up",e="right",f="down",g="left",h="Label",i=a.length;Kinetic.Label=function(a){this.____init(a)},Kinetic.Label.prototype={____init:function(a){var b=this;Kinetic.Group.call(this,a),this.className=h,this.on("add.kinetic",function(a){b._addListeners(a.child),b._sync()})},getText:function(){return this.find("Text")[0]},getTag:function(){return this.find("Tag")[0]},_addListeners:function(c){var d,e=this,f=function(){e._sync()};for(d=0;i>d;d++)c.on(a[d]+b,f)},getWidth:function(){return this.getText().getWidth()},getHeight:function(){return this.getText().getHeight()},_sync:function(){var a,b,c,h,i,j,k,l=this.getText(),m=this.getTag();if(l&&m){switch(a=l.getWidth(),b=l.getHeight(),c=m.getPointerDirection(),h=m.getPointerWidth(),k=m.getPointerHeight(),i=0,j=0,c){case d:i=a/2,j=-1*k;break;case e:i=a+h,j=b/2;break;case f:i=a/2,j=b+k;break;case g:i=-1*h,j=b/2}m.setAttrs({x:-1*i,y:-1*j,width:a,height:b}),l.setAttrs({x:-1*i,y:-1*j})}}},Kinetic.Util.extend(Kinetic.Label,Kinetic.Group),Kinetic.Collection.mapMethods(Kinetic.Label),Kinetic.Tag=function(a){this.___init(a)},Kinetic.Tag.prototype={___init:function(a){Kinetic.Shape.call(this,a),this.className="Tag",this.sceneFunc(this._sceneFunc)},_sceneFunc:function(a){var b=this.getWidth(),c=this.getHeight(),h=this.getPointerDirection(),i=this.getPointerWidth(),j=this.getPointerHeight(),k=this.getCornerRadius();a.beginPath(),a.moveTo(0,0),h===d&&(a.lineTo((b-i)/2,0),a.lineTo(b/2,-1*j),a.lineTo((b+i)/2,0)),k?(a.lineTo(b-k,0),a.arc(b-k,k,k,3*Math.PI/2,0,!1)):a.lineTo(b,0),h===e&&(a.lineTo(b,(c-j)/2),a.lineTo(b+i,c/2),a.lineTo(b,(c+j)/2)),k?(a.lineTo(b,c-k),a.arc(b-k,c-k,k,0,Math.PI/2,!1)):a.lineTo(b,c),h===f&&(a.lineTo((b+i)/2,c),a.lineTo(b/2,c+j),a.lineTo((b-i)/2,c)),k?(a.lineTo(k,c),a.arc(k,c-k,k,Math.PI/2,Math.PI,!1)):a.lineTo(0,c),h===g&&(a.lineTo(0,(c+j)/2),a.lineTo(-1*i,c/2),a.lineTo(0,(c-j)/2)),k&&(a.lineTo(0,k),a.arc(k,k,k,Math.PI,3*Math.PI/2,!1)),a.closePath(),a.fillStrokeShape(this)}},Kinetic.Util.extend(Kinetic.Tag,Kinetic.Shape),Kinetic.Factory.addGetterSetter(Kinetic.Tag,"pointerDirection",c),Kinetic.Factory.addGetterSetter(Kinetic.Tag,"pointerWidth",0),Kinetic.Factory.addGetterSetter(Kinetic.Tag,"pointerHeight",0),Kinetic.Factory.addGetterSetter(Kinetic.Tag,"cornerRadius",0),Kinetic.Collection.mapMethods(Kinetic.Tag)}(),function(){Kinetic.Arrow=function(a){this.____init(a)},Kinetic.Arrow.prototype={____init:function(a){Kinetic.Line.call(this,a),this.className="Arrow"},_sceneFunc:function(a){var b=2*Math.PI,c=this.points(),d=c.length,e=c[d-2]-c[d-4],f=c[d-1]-c[d-3],g=(Math.atan2(f,e)+b)%b,h=this.pointerLength(),i=this.pointerWidth();a.save(),a.beginPath(),a.translate(c[d-2],c[d-1]),a.rotate(g),a.moveTo(0,0),a.lineTo(-h,i/2),a.lineTo(-h,-i/2),a.closePath(),a.restore(),this.pointerAtBeginning()&&(a.save(),a.translate(c[0],c[1]),e=c[2]-c[0],f=c[3]-c[1],a.rotate((Math.atan2(-f,-e)+b)%b),a.moveTo(0,0),a.lineTo(-10,6),a.lineTo(-10,-6),a.closePath(),a.restore()),a.fillStrokeShape(this),Kinetic.Line.prototype._sceneFunc.apply(this,arguments)}},Kinetic.Util.extend(Kinetic.Arrow,Kinetic.Line),Kinetic.Factory.addGetterSetter(Kinetic.Arrow,"pointerLength",10),Kinetic.Factory.addGetterSetter(Kinetic.Arrow,"pointerWidth",10),Kinetic.Factory.addGetterSetter(Kinetic.Arrow,"pointerAtBeginning",!1),Kinetic.Collection.mapMethods(Kinetic.Arrow)}();;/** + * Copyright (c) 2007-2015 Ariel Flesler - afleslergmailcom | http://flesler.blogspot.com + * Licensed under MIT + * @author Ariel Flesler + * @version 2.1.2 + */ + ;(function(f){"use strict";"function"===typeof define&&define.amd?define(["jquery"],f):"undefined"!==typeof module&&module.exports?module.exports=f(require("jquery")):f(jQuery)})(function($){"use strict";function n(a){return!a.nodeName||-1!==$.inArray(a.nodeName.toLowerCase(),["iframe","#document","html","body"])}function h(a){return $.isFunction(a)||$.isPlainObject(a)?a:{top:a,left:a}}var p=$.scrollTo=function(a,d,b){return $(window).scrollTo(a,d,b)};p.defaults={axis:"xy",duration:0,limit:!0};$.fn.scrollTo=function(a,d,b){"object"=== typeof d&&(b=d,d=0);"function"===typeof b&&(b={onAfter:b});"max"===a&&(a=9E9);b=$.extend({},p.defaults,b);d=d||b.duration;var u=b.queue&&1=f[g]?0:Math.min(f[g],n));!a&&1 .form-label line-height: 2rem diff --git a/app/assets/stylesheets/content/_index.sass b/app/assets/stylesheets/content/_index.sass index 8ff2272b3e..d29184c9d3 100644 --- a/app/assets/stylesheets/content/_index.sass +++ b/app/assets/stylesheets/content/_index.sass @@ -1,6 +1,7 @@ @import content/accounts @import content/accounts_mobile @import content/badges +@import content/blockquotes @import content/context_menu @import content/editable_toolbar @import content/forms @@ -18,6 +19,7 @@ @import content/action_menu_main @import content/legacy_actions @import content/enterprise +@import content/members @import content/my_account @import content/my_page @import content/project_overview diff --git a/app/assets/stylesheets/content/_journal.sass b/app/assets/stylesheets/content/_journal.sass index 42bbdf4f79..0938d587b8 100644 --- a/app/assets/stylesheets/content/_journal.sass +++ b/app/assets/stylesheets/content/_journal.sass @@ -74,17 +74,15 @@ padding: 0 overflow: visible margin-left: 50px - .contextual - float: right - a - float: left - display: block - margin-left: 5px - height: 16px - width: 16px - background: - repeat: no-repeat - position: center center + .contextual a + float: left + display: block + margin-left: 5px + height: 16px + width: 16px + background: + repeat: no-repeat + position: center center .journal-attributes color: #333333 diff --git a/app/assets/stylesheets/content/_members.sass b/app/assets/stylesheets/content/_members.sass new file mode 100644 index 0000000000..709c943cdf --- /dev/null +++ b/app/assets/stylesheets/content/_members.sass @@ -0,0 +1,77 @@ +//-- copyright +// OpenProject is a project management system. +// Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License version 3. +// +// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +// Copyright (C) 2006-2017 Jean-Philippe Lang +// Copyright (C) 2010-2013 the ChiliProject Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// See docs/COPYRIGHT.rdoc for more details. +//++ + + +#members_add_form + display: none + margin-bottom: 1rem + .-flex + display: flex + align-items: flex-end + + // Neccassary to avoid the appearance of a scroll bar + .select2-search-field + margin: 0 + + .form--field, + #member-add-submit-button--container + margin-bottom: 1px + flex-basis: 50% + + &:not(.-with-button) + .form--field + overflow: hidden + + // Override default margin to allow correct vertical alignment + #add-member--submit-button + margin-bottom: 0 + margin-left: 1rem + // Neccessary so that button and select box have the same height + line-height: 0.6rem + +@include breakpoint(680px down) + #members_add_form .-flex + align-items: flex-start + + &.-with-button + flex-direction: column + // Workaround for safari and IE + // They are not able to get the correct height with flex-direction: column + height: 120px + + #add-member--submit-button + margin-left: 0 + .form--field + margin-bottom: 1rem + +@media screen and (max-width: 87rem) and (min-width: 681px) + #members_add_form .-flex.-with-button + .form--field + max-width: 60% + select + max-width: 60% diff --git a/app/assets/stylesheets/content/_modal.sass b/app/assets/stylesheets/content/_modal.sass index ea23e5a293..eb37660ef8 100644 --- a/app/assets/stylesheets/content/_modal.sass +++ b/app/assets/stylesheets/content/_modal.sass @@ -56,7 +56,7 @@ $ng-modal-image-width: $ng-modal-image-height transition: opacity 0.25s ease background: $ng-modal-background margin: auto - width: 40% + width: 50% max-height: 95% position: relative padding: $ng-modal-padding / 2 diff --git a/app/assets/stylesheets/content/_my_page.sass b/app/assets/stylesheets/content/_my_page.sass index 07863220bc..7133d80547 100644 --- a/app/assets/stylesheets/content/_my_page.sass +++ b/app/assets/stylesheets/content/_my_page.sass @@ -26,17 +26,6 @@ // See docs/COPYRIGHT.rdoc for more details. //++ -#content - .mypage-box - @include content-box - i - float: left - padding: 7px 10px 0 0 - - .generic-table--container - margin-top: 45px - table, td, th - border: none .my-page--container #right, @@ -88,16 +77,3 @@ div.box-actions #visible-grid & min-height: 32px - - div.mypage-box - margin-top: 8px - padding-bottom: 8px - -div.mypage-box p.summary - font-style: normal - -div.mypage-box div.overview p.author - margin-bottom: 7px - -div.mypage-box .hascontextmenu - cursor: auto diff --git a/app/assets/stylesheets/content/_project_overview.sass b/app/assets/stylesheets/content/_project_overview.sass index 1fa37bb0bc..c3905d7c55 100644 --- a/app/assets/stylesheets/content/_project_overview.sass +++ b/app/assets/stylesheets/content/_project_overview.sass @@ -32,18 +32,6 @@ /* Legacy styles for my project page plugin version (without widget-box styles) */ #invisible-grid - #list-left - .mypage-box - margin-right: 10px - - #list-right - .mypage-box - margin-left: 10px - - .mypage-box - .box-actions - margin-top: -60px - #top padding: 0 4px diff --git a/app/assets/stylesheets/content/_projects_list.sass b/app/assets/stylesheets/content/_projects_list.sass index c7b876020d..89a19503e8 100644 --- a/app/assets/stylesheets/content/_projects_list.sass +++ b/app/assets/stylesheets/content/_projects_list.sass @@ -174,3 +174,12 @@ body.controller-projects.action-index .generic-table--container min-height: 1 overflow: visible + + +// project list in types configuration +#type_project_ids + ul + margin: 0 + padding-left: 1em + li + list-style-type: none diff --git a/app/assets/stylesheets/content/_search.sass b/app/assets/stylesheets/content/_search.sass index 7e001e2588..e6091c819f 100644 --- a/app/assets/stylesheets/content/_search.sass +++ b/app/assets/stylesheets/content/_search.sass @@ -6,3 +6,30 @@ span.search-highlight background-color: #afa &.token-3 background-color: #aaf + + +#search-results + margin-left: 2em + + dd + padding-left: 30px + font-size: 0.9em + + span.description + display: block + color: #808080 + font-style: italic + +div#search-results-counts + float: right + ul + margin-top: 0.5em + li + list-style-type: none + float: left + margin-left: 1em + +.search-pagination + text-align: center + a + padding: 0 5px diff --git a/app/assets/stylesheets/content/_table.sass b/app/assets/stylesheets/content/_table.sass index be7e6b0370..3f154adc5a 100644 --- a/app/assets/stylesheets/content/_table.sass +++ b/app/assets/stylesheets/content/_table.sass @@ -173,7 +173,7 @@ table.generic-table // become even wider. &.-max width: 100% - max-width: 600px + max-width: 500px &.info a diff --git a/app/assets/stylesheets/content/_watchers.sass b/app/assets/stylesheets/content/_watchers.sass index 3446f87d63..dc414098fd 100644 --- a/app/assets/stylesheets/content/_watchers.sass +++ b/app/assets/stylesheets/content/_watchers.sass @@ -41,6 +41,11 @@ float: left line-height: $user-avatar-mini-width +div#watchers + margin-top: 25px + > form > p + margin-top: 5px + .work-package--watchers.-read-only .remove-watcher-btn display: none diff --git a/app/assets/stylesheets/content/_widget_box.sass b/app/assets/stylesheets/content/_widget_box.sass index 27df28974a..d6cef0c115 100644 --- a/app/assets/stylesheets/content/_widget_box.sass +++ b/app/assets/stylesheets/content/_widget_box.sass @@ -28,14 +28,13 @@ $widget-box--enumeration-width: 20px -.widget-boxes--screen-header - margin-left: 10px - .widget-boxes &.-flex display: flex flex-flow: row wrap + // cancel the margin of the outer elements to align with the rest of the page + margin: 0 -10px .widget-box flex: 1 @@ -48,6 +47,9 @@ $widget-box--enumeration-width: 20px .widget-box--feature-list flex-grow: 2 + &.-vertical + flex-flow: column wrap + .icon-context:before padding-right: 5px @@ -67,6 +69,16 @@ $widget-box--enumeration-width: 20px word-wrap: break-word overflow: hidden + &.-thin + min-height: 100px + &.-wider + flex-grow: 3 + &.-minimal + flex-grow: 0 + &.-no-border + padding: 0 + border: 0 + .widget-box--header font-weight: bold font-size: 1.25rem diff --git a/app/assets/stylesheets/content/_wiki.sass b/app/assets/stylesheets/content/_wiki.sass index ff2b72c8f7..8aa3cd917f 100644 --- a/app/assets/stylesheets/content/_wiki.sass +++ b/app/assets/stylesheets/content/_wiki.sass @@ -91,6 +91,9 @@ div.wiki li list-style-type: none + ul li + word-wrap: break-word + // ------------------- GENERAL ------------------- .external.icon-context:before @@ -150,15 +153,6 @@ h1:hover, h2:hover, h3:hover #wiki_page_parent_id overflow: auto -blockquote - font-style: italic - &.icon:before - color: #e0e0e0 - position: relative - bottom: 10px - right: 15px - padding: 0 0 0 0 - .toolbar-container ~ .wiki-content margin-top: 0 @@ -172,9 +166,6 @@ blockquote body.controller-wiki - #content - overflow: initial - .ck-content min-height: 25vh diff --git a/app/assets/stylesheets/content/menus/_project_autocompletion.sass b/app/assets/stylesheets/content/menus/_project_autocompletion.sass index 106210d9c5..1e6d8d21ee 100644 --- a/app/assets/stylesheets/content/menus/_project_autocompletion.sass +++ b/app/assets/stylesheets/content/menus/_project_autocompletion.sass @@ -28,19 +28,6 @@ right: 25px font-size: 14px - .select2-results - margin: 6px 0 - padding: 0 - - .select2-highlighted - @include varprop(background, drop-down-selected-bg-color, !important) - border-radius: 0 !important - font-weight: normal !important - @include varprop(color, drop-down-selected-font-color) - &:hover - @include varprop(background, drop-down-hover-bg-color, !important) - @include varprop(color, drop-down-hover-font-color, !important) - // Search input wrapper .project-menu-autocomplete--input-container padding: 12px 0 diff --git a/app/assets/stylesheets/content/work_packages/_table_configuration_modal.sass b/app/assets/stylesheets/content/work_packages/_table_configuration_modal.sass index f945588ee5..1f1c8e9787 100644 --- a/app/assets/stylesheets/content/work_packages/_table_configuration_modal.sass +++ b/app/assets/stylesheets/content/work_packages/_table_configuration_modal.sass @@ -20,3 +20,6 @@ .ee-attribute-highlighting-upsale margin-bottom: 1.5rem + + multi-toggled-select + display: inline-block diff --git a/app/assets/stylesheets/content/work_packages/_table_content.sass b/app/assets/stylesheets/content/work_packages/_table_content.sass index a2d13096a8..b93fed4c3a 100644 --- a/app/assets/stylesheets/content/work_packages/_table_content.sass +++ b/app/assets/stylesheets/content/work_packages/_table_content.sass @@ -92,6 +92,8 @@ html:not(.-browser-mobile) .icon:before @include varprop(color, content-link-color) padding: 0 0 0 0.25rem + &.-disabled .icon:before + color: $gray-dark &:hover text-decoration: none @@ -101,10 +103,6 @@ html:not(.-browser-mobile) .wp-table-context-menu-link padding-left: 5px -table.generic-table tbody tr.issue .checkbox - overflow: visible - padding-left: 5px - .wp-table--cell .ui-datepicker margin-left: -38% diff --git a/app/assets/stylesheets/content/work_packages/single_view/_single_view.sass b/app/assets/stylesheets/content/work_packages/single_view/_single_view.sass index 050b4a23ce..98091b4da3 100644 --- a/app/assets/stylesheets/content/work_packages/single_view/_single_view.sass +++ b/app/assets/stylesheets/content/work_packages/single_view/_single_view.sass @@ -136,7 +136,7 @@ i text-align: center cursor: pointer - .wp-relations-count + .wp-tabs-count margin-left: 5px border-radius: 0.5rem min-width: 1rem @@ -167,7 +167,7 @@ i @include varprop(border-bottom-color, content-link-color) a @include varprop(color, content-link-color) - .wp-relations-count + .wp-tabs-count @include varprop(color, content-link-color) &:hover @include varprop(color, content-link-color) diff --git a/app/assets/stylesheets/content/work_packages/tabs/_activities.sass b/app/assets/stylesheets/content/work_packages/tabs/_activities.sass index 23782b4b91..4acf93db74 100644 --- a/app/assets/stylesheets/content/work_packages/tabs/_activities.sass +++ b/app/assets/stylesheets/content/work_packages/tabs/_activities.sass @@ -31,13 +31,7 @@ margin: 12px 0 0 0 padding: 0 25px 0 0 - li - span - word-wrap: break-word - // important for IE - display: block - max-width: 100% - p + li, p word-wrap: break-word &.wiki @@ -77,6 +71,10 @@ padding: 0 !important margin: 0 !important +h4.comment + margin-bottom: 8px + margin-top: 18px + .work-package-details-activities-list list-style-type: none margin: 0 diff --git a/app/assets/stylesheets/layout/_base.sass b/app/assets/stylesheets/layout/_base.sass index e3dee2a05e..31c4a56363 100644 --- a/app/assets/stylesheets/layout/_base.sass +++ b/app/assets/stylesheets/layout/_base.sass @@ -56,15 +56,6 @@ body overflow: visible #content-wrapper - &.hidden-navigation - margin-left: $main-menu-folded-width - width: calc(100% - #{$main-menu-folded-width}) - - &.nosidebar - padding: 0 - width: 100% - margin-left: 0 - &.nomenus top: 0 padding: 0 @@ -81,7 +72,8 @@ body margin: 0 0 0 0 padding: 10px 20px width: auto - height: auto + height: calc(100vh - #{$header-height}) + overflow: auto background-color: #fff width: 100% // As this is a flex item we need to set min-width to 0 so that its children's @@ -113,7 +105,6 @@ body #content padding: 0 margin: 0 0 0 0 - overflow: hidden width: 100% z-index: 10 background-color: $body-background diff --git a/app/assets/stylesheets/layout/_base_mobile.sass b/app/assets/stylesheets/layout/_base_mobile.sass index 7ee0bf4768..23020f4f75 100644 --- a/app/assets/stylesheets/layout/_base_mobile.sass +++ b/app/assets/stylesheets/layout/_base_mobile.sass @@ -62,7 +62,6 @@ padding: 5px 15px 0 15px !important #breadcrumb, - #sidebar, .hidden-for-mobile display: none !important diff --git a/app/assets/stylesheets/layout/_drop_down.sass b/app/assets/stylesheets/layout/_drop_down.sass index e2fa010f7c..e48779099a 100644 --- a/app/assets/stylesheets/layout/_drop_down.sass +++ b/app/assets/stylesheets/layout/_drop_down.sass @@ -89,6 +89,10 @@ LI > A.inactive color: #999999 + LI > A.selected + @include varprop(background, drop-down-selected-bg-color) + @include varprop(color, drop-down-selected-font-color) + .dropdown @include dot_border_width_style @@ -98,9 +102,6 @@ // https://github.com/plapier/jquery-dropdown // (dual MIT/GPL-Licensed) -#column-context-menu .menu - margin: 0 - .dropdown // Will be overridden by the js code but having this here will prevent the // dropdown to displayed in the upper right corner until the js sets the diff --git a/app/assets/stylesheets/layout/_main_menu.sass b/app/assets/stylesheets/layout/_main_menu.sass index 3e6807d519..0974918f15 100644 --- a/app/assets/stylesheets/layout/_main_menu.sass +++ b/app/assets/stylesheets/layout/_main_menu.sass @@ -39,30 +39,33 @@ $menu-item-line-height: 30px border-right-style: solid @include varprop(border-right-width, main-menu-border-width) @include varprop(border-right-color, main-menu-border-color) - - // min-height is full height minus header and footer. - min-height: calc(100vh - 55px) - @include varprop(background-color, main-menu-bg-color) + // min-height is full height minus header and footer. + min-height: calc(100vh - #{$header-height}) #menu-sidebar - height: 100% - overflow: auto - - %absolute-layout-mode & + +allow-vertical-scrolling + -ms-overflow-style: -ms-autohiding-scrollbar + height: calc(100vh - #{$header-height}) position: relative + @include styled-scroll-bar // Fixed heights to allow inner scrolling .menu_root.closed, .menu_root > li.open, - .main-menu--children > li.partial, wp-query-select, .wp-query-menu--container, - .wp-query-menu--search-container + .wp-query-menu--search-container, + .main-menu--children > li.partial:only-child height: 100% + .main-menu--children > li.partial + height: initial + .main-menu--children - height: calc(100% - (#{$main-menu-item-height} + 20px)) + height: calc(100% - (#{$main-menu-item-height} + 10px)) // 10px spacing + overflow: auto + @include styled-scroll-bar ul margin: 0 @@ -314,9 +317,6 @@ a.main-menu--parent-node &.-hidden display: none - %absolute-layout-mode & - display: none - .menu-wiki-pages-tree height: 100% overflow: auto @@ -347,8 +347,6 @@ a.main-menu--parent-node vertical-align: middle z-index: 1 cursor: col-resize - %absolute-layout-mode & - z-index: 100 &:hover @include varprop(border-left-color, main-menu-resizer-color) .main-menu--navigation-toggler @@ -395,8 +393,6 @@ a.main-menu--parent-node i:before padding-left: 0 @include icon-mixin-arrow-left2 - %absolute-layout-mode & - z-index: 100 #main-menu ul ul.main-menu--children ul.pages-hierarchy .tree-menu--hierarchy-indicator diff --git a/app/assets/stylesheets/layout/_main_menu_mobile.sass b/app/assets/stylesheets/layout/_main_menu_mobile.sass index 61c01e29fc..4bf3426472 100644 --- a/app/assets/stylesheets/layout/_main_menu_mobile.sass +++ b/app/assets/stylesheets/layout/_main_menu_mobile.sass @@ -29,17 +29,13 @@ @include breakpoint(680px down) .main-menu - position: absolute !important - min-height: 100% + position: fixed z-index: 11 border-bottom: 1px solid $main-menu-border-color width: 100vw !important border: none box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.15) - %absolute-layout-mode & - height: auto - .hidden-navigation .main-menu display: none diff --git a/app/assets/stylesheets/layout/_top_menu.sass b/app/assets/stylesheets/layout/_top_menu.sass index a1051a384f..4450d03ea7 100644 --- a/app/assets/stylesheets/layout/_top_menu.sass +++ b/app/assets/stylesheets/layout/_top_menu.sass @@ -102,31 +102,9 @@ $hamburger-width: 50px width: 400px left: 0px - li.drop-down - &:hover - @include varprop(background-color, header-item-bg-hover-color) - > a - @include varprop(color, header-item-font-hover-color) - i.icon-help:before - @include varprop(border-color, header-item-font-hover-color) - - &.open - @include varprop(background-color, header-item-bg-hover-color) - > a - @include varprop(color, header-item-font-hover-color) - i.icon-help:before - @include varprop(border-color, header-item-font-hover-color) - - .button--dropdown-indicator - &:before - @include icon-mixin-pulldown-up - - li - > a - color: $header-drop-down-item-font-color - &:hover, &:focus - @include varprop(background, drop-down-hover-bg-color) - @include varprop(color, drop-down-hover-font-color) + li.drop-down.open + .button--dropdown-indicator:before + @include icon-mixin-pulldown-up li.last-child > ul, .drop-down--help, diff --git a/app/assets/stylesheets/layout/work_packages/_full_view.sass b/app/assets/stylesheets/layout/work_packages/_full_view.sass index 646c0fc901..fb66363532 100644 --- a/app/assets/stylesheets/layout/work_packages/_full_view.sass +++ b/app/assets/stylesheets/layout/work_packages/_full_view.sass @@ -26,10 +26,7 @@ // See docs/COPYRIGHT.rdoc for more details. //++ -body.controller-work_packages.action-show body.controller-work_packages.full-create - overflow-x: auto - // Fix selenium scrolling the #content which shouldn't be possible // This appears to be caused by somehow setting the scrollTop to move to an element. #content-wrapper, @@ -130,10 +127,7 @@ body.controller-work_packages.full-create position: relative .work-packages--panel-inner - position: absolute - display: inline-block - padding: 15px 15px 0px 0px - width: calc(100% - 18px) + padding: 15px 15px 0px 15px .work-package-details-activities-activity-contents ul.work-package-details-activities-messages padding-left: 0 @@ -150,7 +144,6 @@ body.controller-work_packages.full-create top: 50% bottom: 50% width: 18px - display: inline-block .work-packages--resizer left: -2px width: 18px @@ -176,6 +169,9 @@ body.controller-work_packages.full-create .work-packages--show-view // Important for Safari height: initial + .work-packages-full-view--split-right + overflow: visible + flex-basis: initial !important @media only screen and (max-width: 679px) #toolbar diff --git a/app/assets/stylesheets/layout/work_packages/_mobile.sass b/app/assets/stylesheets/layout/work_packages/_mobile.sass index 7e60056f9b..7848dda4b1 100644 --- a/app/assets/stylesheets/layout/work_packages/_mobile.sass +++ b/app/assets/stylesheets/layout/work_packages/_mobile.sass @@ -30,8 +30,7 @@ // ------------- FULL SCREEN ------------------- &.action-show - overflow: auto !important - overflow-y: scroll !important + #main, #content-wrapper, @@ -44,21 +43,13 @@ #content-wrapper, #content height: 100% !important - overflow: visible + overflow: auto #main padding-bottom: 0 + height: calc(100vh - #{$header-height}) #content-wrapper - &.hidden-navigation - margin-left: 0 - width: 100% - - &.nosidebar - padding: 0 - width: 100% - margin-left: 0 - &.nomenus top: 0 padding: 0 @@ -105,7 +96,7 @@ .work-packages-list-view--container padding-left: 5px - + .toolbar-container min-height: 36px padding-right: 0 diff --git a/app/assets/stylesheets/layout/work_packages/_print.sass b/app/assets/stylesheets/layout/work_packages/_print.sass index d91310d80b..f7c3bbff5b 100644 --- a/app/assets/stylesheets/layout/work_packages/_print.sass +++ b/app/assets/stylesheets/layout/work_packages/_print.sass @@ -106,13 +106,15 @@ .work-packages-full-view--split-container display: block - // ------------------Only WP full scren view ------------------ + // ------------------Only WP full screen view ------------------ body.controller-work_packages.action-show // Since there is no toolbar and WP-back button the header can span 100% .wp-show--header-container flex-basis: 100% .work-packages-full-view--split-right - overflow: auto + overflow: visible + flex-basis: initial !important + // decrease padding under subject .work-packages--show-view > .toolbar-container @@ -121,7 +123,7 @@ // Overwrite "click to add description" placeholder with a simple dash. .wp-edit-field.description.-placeholder - span + .read-value--html display: none &:after content: '-' diff --git a/app/assets/stylesheets/layout/work_packages/_query_menu.sass b/app/assets/stylesheets/layout/work_packages/_query_menu.sass index 2908bdab71..44436e16ff 100644 --- a/app/assets/stylesheets/layout/work_packages/_query_menu.sass +++ b/app/assets/stylesheets/layout/work_packages/_query_menu.sass @@ -20,9 +20,7 @@ $wp-query-menu-search-container-height: 35px .wp-query-menu--results-container padding-top: 5px - - %absolute-layout-mode & - height: calc(100% - #{$wp-query-menu-search-container-height}) + height: calc(100% - #{$wp-query-menu-search-container-height}) // Firefox needs more left padding for whatever reason html.-browser-firefox & diff --git a/app/assets/stylesheets/openproject/_generic.sass b/app/assets/stylesheets/openproject/_generic.sass index d3670317f4..d2dcb58ae2 100644 --- a/app/assets/stylesheets/openproject/_generic.sass +++ b/app/assets/stylesheets/openproject/_generic.sass @@ -44,3 +44,28 @@ border-left: 1px solid $table-row-border-color .-table-border-right border-right: 1px solid $table-row-border-color + +.autoscroll + overflow-x: auto + padding: 1px + margin-bottom: 1.2em + +.-hidden-overflow + overflow: hidden !important + +.indent + padding-left: 10px + +.total-hours + font-weight: bold + +.ellipsis, +.form--field.ellipsis .form--label + @include text-shortener + +.other-formats + font-size: 0.9em + color: $gray-dark + + span + span:before + content: "| " diff --git a/app/assets/stylesheets/openproject/_homescreen.sass b/app/assets/stylesheets/openproject/_homescreen.sass index 6d22db063a..576743da80 100644 --- a/app/assets/stylesheets/openproject/_homescreen.sass +++ b/app/assets/stylesheets/openproject/_homescreen.sass @@ -37,12 +37,13 @@ .homescreen--links - @include widget-box--style + margin: 10px 0 display: flex padding: 20px 20% align-items: center justify-content: center background: $homescreen-footer-bg-color + border: 1px solid $content-default-border-color .icon-context:before padding-right: 0 @@ -73,9 +74,3 @@ flex: auto margin: 20px 0 width: 50% - - .controller-homescreen - .widget-boxes--screen-header - margin-left: 0px - .widget-boxes .widget-box - margin: 10px 0px diff --git a/app/assets/stylesheets/openproject/_index.sass b/app/assets/stylesheets/openproject/_index.sass index a10e93138d..35eac8ae58 100644 --- a/app/assets/stylesheets/openproject/_index.sass +++ b/app/assets/stylesheets/openproject/_index.sass @@ -3,9 +3,6 @@ @import openproject/functions @import openproject/homescreen -// Legacy styles, remove if possible -@import openproject/legacy - @import openproject/generic @import openproject/mixins diff --git a/app/assets/stylesheets/openproject/_legacy.sass b/app/assets/stylesheets/openproject/_legacy.sass deleted file mode 100644 index 78c6fbe497..0000000000 --- a/app/assets/stylesheets/openproject/_legacy.sass +++ /dev/null @@ -1,611 +0,0 @@ -//-- copyright -// OpenProject is a project management system. -// Copyright (C) 2012-2018 the OpenProject Foundation (OPF) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License version 3. -// -// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -// Copyright (C) 2006-2017 Jean-Philippe Lang -// Copyright (C) 2010-2013 the ChiliProject Team -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// See docs/COPYRIGHT.rdoc for more details. -//++ - - -// IMPORTANT! - -// This is a "junk-drawer" containing CSS rule sets that could not be easily -// placed elsewhere. Pleade DO NOT add to this file. Instead MOVE, refactor or -// REMOVE with ruthlessness. - -$version-summary-width: 380px - -#watchers - ul - margin: 0 - padding: 0 - - a.delete - opacity: 0.4 - &:hover - opacity: 1 - -.contextual - float: right - white-space: nowrap - line-height: 1.4em - margin-top: 8px - padding-left: 10px - input, select - font-size: 0.9em - -.message .contextual - margin-top: 0 - -.message.reply h4 - min-height: 42px - line-height: 2 - -form - display: inline - -hr - width: 100% - height: 1px - background: #ccc - border: 0 - -blockquote - font-style: italic - border-left: 3px solid #e0e0e0 - padding-left: 0.6em - margin-left: 2.4em - blockquote - margin-left: 0 - -li p - margin-top: 0 - -p - &.breadcrumb - font-size: 0.9em - margin: 4px 0 4px 0 - &.footnote - font-size: 0.9em - margin-top: 0 - margin-bottom: 0 - -div.issue div.subject - div div - padding-left: 16px - p - margin: 0 - margin-bottom: 0.1em - font-size: 90% - color: #999 - > div > p - margin-top: 0.5em - -.buttons - margin-top: 1em - -div - &#work_package-changesets - float: right - width: 45% - margin: 1em 0 1em 1em - background: #fff - padding-left: 1em - h3 - margin-top: 0 - div.changeset - padding: 4px - border-bottom: 1px solid #ddd - p - margin-top: 0 - margin-bottom: 1em - -div#activity span.project:after, #search-results span.project:after - content: " -" - -#search-results - margin-left: 2em - - dd - margin-bottom: 1em - padding-left: 30px - margin-left: 0 - font-size: 0.9em - - span.description - display: block - color: #808080 - font-style: italic - -div#search-results-counts - float: right - ul - margin-top: 0.5em - li - list-style-type: none - float: left - margin-left: 1em - -.search-pagination - text-align: center - a - padding: 0 5px - -#project-search-container .select2-container - display: block - -div - &#roadmap - .related-issues - border: 0 - margin-bottom: 1em - td.checkbox - display: none - - @media only screen and (min-width: 680px) - .generic-table--no-results-container - max-width: calc(100% - #{$version-summary-width}) - - &#version-summary - float: right - width: $version-summary-width - margin-left: 16px - margin-bottom: 16px - background-color: #fff - .total-hours - text-align: right - -.top-page - width: 100% - border-bottom: 1px solid #bbbbbb - margin: 0 0 10px - h2 - padding-right: 0 !important - border: none - margin: 0 - text-align: left - display: block - @include text-shortener - - &.message-title - padding-top: 12px - padding-bottom: 19px - white-space: normal - overflow: visible - float: left - - ul - margin: 0 - text-align: right - white-space: nowrap - - -#type_project_ids - ul - margin: 0 - padding-left: 1em - li - list-style-type: none - -ul.properties - padding: 0 - font-size: 0.9em - color: #333 - li - list-style-type: none - span - font-style: italic - -.total-hours - font-size: 110% - font-weight: bold - span.hours-int - font-size: 120% - -.autoscroll - overflow-x: auto - padding: 1px - margin-bottom: 1.2em - -#workflow_copy_form select - width: 200px - -textarea#custom_field_possible_values - width: 99% - - -div.attachments - margin-top: 12px - margin-bottom: 12px - p - margin: 4px 0 2px 0 - img - vertical-align: middle - span.author - font-size: 0.9em - color: #888 - -p.other-formats - font-size: 0.9em - color: #666 - -.other-formats span + span:before - content: "| " - -/* Project members tab */ - -div#tab-content-members - .user.status_registered, label.status_registered - opacity: 0.8 - .member - .icon-group:before - padding-left: 0 - -input#user_search - width: 100% - -.quick_info - padding-bottom: 0.5em - &.attributes .label - font-weight: bold - -.journal-link - float: right - -h2 img - vertical-align: middle - -h1.title - margin: 12px 24px 9px - -form#issue-list - position: relative - -div.issue hr - margin-top: 10px - margin-bottom: 10px - clear: both - -#content div.issue h3, div.issue h3 - border: 0 - margin-top: -6px - margin-bottom: 0 - -#content blockquote - padding-left: 22px - -#project-links - right: 30px - color: #ccc - font-weight: bold - -.nosidebar - blockquote - margin: 1em 0 - p - margin-bottom: 1em - -li - &.root - margin-bottom: 24px - -.profile-wrap - float: right - position: relative - width: 42px - height: 42px - top: 7px - right: 14px - -td.issue div.issue-wrap-outer - position: relative - -.menu li - position: relative - &:first-child - border-top: 0 - &:last-child - border-bottom: 0 - -.inline - display: inline - -form#issue-list - display: block - -.js-tooltip - width: 100% - -.js-tooltip-inner - width: 100% - max-height: none - -.js-tooltip .issue-tooltip-description - max-height: 200px - overflow: hidden - -/* roadmap breathing */ - -#roadmap h3 - margin: 21px 0 12px - -div.issue div#relations - margin-top: 25px - -/* all kinds of wonderful tweaks*/ - -.question pre - color: #111 - -div.issue hr - width: auto - -.question .wiki - margin: 0 - -// The min-height takes care that menus within the toolbar can be seen. -// On the full screen view the min-height crashes the complete view -// when anchors in the url were used on small sreens, because there the body is not scrollable. -body:not(.action-show) #content - min-height: 300px - -#content - h3 - margin: 12px 0 6px - h2 + h3 - margin-top: 12px - -.nosidebar - ol.ui-sortable li - list-style: none outside none - -tr.time-entry - white-space: normal - -/* scm */ - -#content table .changeset td.id a:hover - text-decoration: underline - - -/* member settings [pc] */ - -select#member_role_id - width: 75px - -/* fix for thumbnail jankiness */ - -a.has-thumb - &.active - left: auto - margin-left: -10px - margin-right: 0 - *left: -10px - /* IE6 & 7 hacks */ - *margin-left: 0 - img - z-index: 1001 - -#more-menu.drop-down ul li a.projects - border-top: 1px solid #555 - -.reorder-icons img - padding-right: 3px - padding-left: 3px - - -/* Cut of text with '...' - working on all major browsers and IE6+ - * not working for Firefox < 7 */ - -.ellipsis, -.form--field.ellipsis .form--label - @include text-shortener - -label - margin-bottom: 0rem - &.label-with-input - display: block - white-space: nowrap - zoom: 1 - margin-left: 0 - float: none - -#query_form_content - padding-top: 10px - -#watchers .contextual - margin-top: 0 - -div - &.issues.box > p, &.mypage-box p - margin-top: 15px - - &.overview - padding: 6px - margin-bottom: 10px - line-height: 1.5em - -td.table-buttons - vertical-align: middle - -select#available_columns - margin-right: 0 - -.pages-hierarchy - padding-left: 10px - list-style-type: disc - list-style-position: inside - -#menu-sidebar.hidden - display: none - -div#watchers - margin-top: 25px - > form > p - margin-top: 5px - -a > img.imgtag-icon - float: left - margin-right: 3px - -th.checkbox img - margin-left: 3px - margin-top: 3px - -p.buttons - margin-left: 10px - -strong.related-issues-heading - display: block - margin-top: 10px - -div.indent - padding-left: 10px - -/* Menu item configuration */ - -.menu-item-form - p - padding-left: 0 - label - display: inline-block - margin-bottom: 10px - margin-left: 0 - width: auto - font-weight: bold - select#parent_wiki_menu_item - margin-left: 7px - margin-top: -1px - line-height: normal - #item-name - float: left - padding-left: 3px - margin-right: 4px - line-height: 21px - label#with-select - margin-left: 0 - select#parent_wiki_menu_item_wiki_page - margin-bottom: 10px - p - &.item-name - padding-top: 10px - &.main_item - padding-bottom: 0 - &.wiki_menu_item_optional_links - margin-left: 10px - padding-top: 0 - -/*Cost-Plugin specific styles */ - -input::-webkit-input-placeholder, :-moz-placeholder - color: #000000 - -#ui-dialog-closer - cursor: pointer - position: absolute - right: 0px - top: 5px - z-index: 5000 - - &.icon:before - color: $body-font-color - -#modalDiv - padding: 2em 0 0 1.5em - - &.-full - padding: 0 - -h4.comment - margin-bottom: 8px - margin-top: 18px - img - margin-right: 3px - -/* - * Legacy headings to create headings which are similiar to the toolbar - * but cannot use the toolbar yet (e.g Legacy forms) - */ -.legacy-heading - // this will harmonize the headings in the old legacy form - // to be the same as if using a toolbar component - // TODO: once WP full screen create hits, remove this - padding-top: 12px - border: 0 - @include breakpoint(medium down) - font-size: $h2-font-size - -#members_add_form - display: none - margin-bottom: 1rem - .-flex - display: flex - align-items: flex-end - - // Neccassary to avoid the appearance of a scroll bar - .select2-search-field - margin: 0 - - .form--field, - #member-add-submit-button--container - margin-bottom: 1px - flex-basis: 50% - - &:not(.-with-button) - .form--field - overflow: hidden - - // Override default margin to allow correct vertical alignment - #add-member--submit-button - margin-bottom: 0 - margin-left: 1rem - // Neccessary so that button and select box have the same height - line-height: 0.6rem - -@include breakpoint(680px down) - #members_add_form .-flex - align-items: flex-start - - &.-with-button - flex-direction: column - // Workaround for safari and IE - // They are not able to get the correct height with flex-direction: column - height: 120px - - #add-member--submit-button - margin-left: 0 - .form--field - margin-bottom: 1rem - -@media screen and (max-width: 87rem) and (min-width: 681px) - #members_add_form .-flex.-with-button - .form--field - max-width: 60% - select - max-width: 60% - -// Avoid content cut off in IE -#new-member-message + div.grid-block - min-height: 6rem - div.grid-block - overflow: visible diff --git a/app/assets/stylesheets/vendor/_enjoyhint.sass b/app/assets/stylesheets/vendor/_enjoyhint.sass new file mode 100755 index 0000000000..21ef98e539 --- /dev/null +++ b/app/assets/stylesheets/vendor/_enjoyhint.sass @@ -0,0 +1,231 @@ +@mixin onboarding-button-styles + color: white + border: 2px solid + @include varprop(border-color, alternative-color) + @include varprop(background, alternative-color) + -webkit-box-sizing: content-box + box-sizing: content-box + -webkit-transition: background-color 0.3s cubic-bezier(0, 0, 0, 0), color 0.3s cubic-bezier(0, 0, 0, 0), width 0.3s cubic-bezier(0, 0, 0, 0), border-width 0.3s cubic-bezier(0, 0, 0, 0), border-color 0.3s cubic-bezier(0, 0, 0, 0) + -moz-transition: background-color 0.3s cubic-bezier(0, 0, 0, 0), color 0.3s cubic-bezier(0, 0, 0, 0), width 0.3s cubic-bezier(0, 0, 0, 0), border-width 0.3s cubic-bezier(0, 0, 0, 0), border-color 0.3s cubic-bezier(0, 0, 0, 0) + -o-transition: background-color 0.3s cubic-bezier(0, 0, 0, 0), color 0.3s cubic-bezier(0, 0, 0, 0), width 0.3s cubic-bezier(0, 0, 0, 0), border-width 0.3s cubic-bezier(0, 0, 0, 0), border-color 0.3s cubic-bezier(0, 0, 0, 0) + transition: background-color 0.3s cubic-bezier(0, 0, 0, 0), color 0.3s cubic-bezier(0, 0, 0, 0), width 0.3s cubic-bezier(0, 0, 0, 0), border-width 0.3s cubic-bezier(0, 0, 0, 0), border-color 0.3s cubic-bezier(0, 0, 0, 0) + &:hover + @include varprop(border-color, button--alt-highlight-background-hover-color) + @include varprop(background, button--alt-highlight-background-hover-color) + &:active + @include varprop(border-color, button--alt-highlight-background-hover-color) + @include varprop(background, button--alt-highlight-background-hover-color) + -webkit-transition: none + -moz-transition: none + -o-transition: none + transition: none + +.enjoyhint + position: fixed + width: 100% + height: 100% + top: 0 + left: 0 + z-index: 1010 + pointer-events: all + overflow: hidden + +.enjoyhint_hide + display: none + +.enjoyhint_disable_events + position: absolute + width: 2000px + height: 1500px + z-index: 1011 + pointer-events: all + +.enjoyhint_next_btn, .enjoyhint_skip_btn + -webkit-box-sizing: content-box + width: 100px + height: 40px + font: normal normal normal 17px/40px "Advent Pro", Helvetica, sans-serif + cursor: pointer + margin: 0 auto + letter-spacing: 1px + text-align: center + +.enjoyhint_close_btn, .enjoyhint_next_btn, .enjoyhint_skip_btn + z-index: 1012 + pointer-events: all + -o-text-overflow: clip + text-overflow: clip + -moz-box-sizing: content-box + font-weight: bold + @include onboarding-button-styles + +.enjoyhint_next_btn + position: absolute + -webkit-border-radius: 40px + border-radius: 40px + + +.enjoyhint_skip_btn + position: fixed + -webkit-border-radius: 40px + border-radius: 40px + +.enjoyhint_close_btn + display: inline-block + position: absolute + width: .3em + height: .3em + border: none + -webkit-border-radius: 1em + border-radius: 1em + font: 400 8em/normal Arial, Helvetica, sans-serif + &::after + -webkit-box-sizing: content-box + -moz-box-sizing: content-box + box-sizing: content-box + width: 73% + height: 2px + top: 46% + left: 15% + -webkit-transform: rotateZ(-45deg) + transform: rotateZ(-45deg) + position: absolute + content: "" + border: none + font: 400 100%/normal Arial, Helvetica, sans-serif + color: rgba(0, 0, 0, 1) + background: #fff + text-shadow: none + -o-text-overflow: clip + text-overflow: clip + display: inline-block + &::before + -webkit-box-sizing: content-box + width: 73% + height: 2px + position: absolute + content: "" + border: none + font: 400 100%/normal Arial, Helvetica, sans-serif + color: rgba(0, 0, 0, 1) + background: #fff + text-shadow: none + -o-text-overflow: clip + text-overflow: clip + display: inline-block + -moz-box-sizing: content-box + box-sizing: content-box + top: 48% + left: 14% + -webkit-transform: rotateZ(45deg) + transform: rotateZ(45deg) + +.enjoyhint_btn + width: 150px + height: 40px + cursor: pointer + margin: 0 auto + -webkit-border-radius: 40px + border-radius: 40px + font: normal normal normal 17px/40px "Advent Pro", Helvetica, sans-serif + text-align: center + -o-text-overflow: clip + text-overflow: clip + letter-spacing: 1px + @include onboarding-button-styles + +.enjoyhint_btn-transparent + background: transparent + @include varprop(color, alternative-color) + &:hover + color: white + &:active + color: white + +#kinetic_container, .enjoyhint_canvas + width: 100% + height: 100% + position: absolute + +.enjoyhint_svg_wrapper + width: 100% + height: 100% + position: absolute + svg + width: 100% + height: 100% + position: absolute + +.enjoyhint_btn + &:hover + color: rgba(255, 255, 255, 1) + @include varprop(background, button--alt-highlight-background-hover-color) + &:active + border: 2px solid rgba(33, 224, 163, 1) + background: rgba(33, 224, 163, 1) + -webkit-transition: none + -moz-transition: none + -o-transition: none + transition: none + +.enjoyhint div.canvas-container + position: absolute + +.enjoyhint_canvas + z-index: 100 + pointer-events: none + +#kinetic_container + pointer-events: none + top: 0 + left: 0 + +.enjoyhint_svg_wrapper + top: 0 + left: 0 + z-index: 100 + -webkit-transition: opacity 0.4s cubic-bezier(0.42, 0, 0.58, 1) + -moz-transition: opacity 0.4s cubic-bezier(0.42, 0, 0.58, 1) + transition: opacity 0.4s cubic-bezier(0.42, 0, 0.58, 1) + svg + top: 0 + left: 0 + +.-dark .enjoyhint_svg_wrapper path + stroke: rgb(0, 0, 0) !important + +.-hidden-arrow .enjoyhint_svg_wrapper path + display: none !important + +.enjoyhint_svg_transparent + .enjoy_hint_label, .enjoyhint_svg_wrapper + opacity: 0 + +.enjoy_hint_label + position: absolute + color: #fff + z-index: 107 + font-size: 22px + font-family: casino_handregular, Arial + -webkit-transition: opacity 0.4s cubic-bezier(0.42, 0, 0.58, 1) + -moz-transition: opacity 0.4s cubic-bezier(0.42, 0, 0.58, 1) + transition: opacity 0.4s cubic-bezier(0.42, 0, 0.58, 1) + display: inline-block + min-width: 200px + text-align: center + max-width: 80% + line-height: 28px + +.-dark .enjoy_hint_label + background-color: rgba(0, 0, 0, 0.75) + padding: 10px 25px + -webkit-border-radius: 40px + -moz-border-radius: 40px + border-radius: 40px + +div.kineticjs-content + position: absolute !important + +.enjoyhint-tutorial .-clickable + pointer-events: none + diff --git a/app/assets/stylesheets/vendor/_index.sass b/app/assets/stylesheets/vendor/_index.sass index 7fa6a84968..133d318f83 100644 --- a/app/assets/stylesheets/vendor/_index.sass +++ b/app/assets/stylesheets/vendor/_index.sass @@ -4,3 +4,4 @@ @import vendor/dragula @import vendor/select2 @import vendor/jquery_ui +@import vendor/enjoyhint diff --git a/app/contracts/queries/base_contract.rb b/app/contracts/queries/base_contract.rb index 99c9685568..54c23400b2 100644 --- a/app/contracts/queries/base_contract.rb +++ b/app/contracts/queries/base_contract.rb @@ -41,6 +41,7 @@ class BaseContract < ::ModelContract attribute :timeline_zoom_level attribute :timeline_labels attribute :highlighting_mode + attribute :highlighted_attributes attribute :show_hierarchies attribute :column_names # => columns diff --git a/app/contracts/work_packages/update_contract.rb b/app/contracts/work_packages/update_contract.rb index a03101466f..357e58ec1d 100644 --- a/app/contracts/work_packages/update_contract.rb +++ b/app/contracts/work_packages/update_contract.rb @@ -37,7 +37,6 @@ class UpdateContract < BaseContract end end - validate :user_allowed_to_access validate :user_allowed_to_edit diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 98766efac7..4d24d5ee80 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -192,11 +192,13 @@ def custom_fields def archive flash[:error] = l(:error_can_not_archive_project) unless @project.archive redirect_to(url_for(controller: '/projects', action: 'index', status: params[:status])) + update_demo_project_settings @project, false end def unarchive @project.unarchive if !@project.active? redirect_to(url_for(controller: '/projects', action: 'index', status: params[:status])) + update_demo_project_settings @project, true end # Delete @project @@ -213,6 +215,8 @@ def destroy end hide_project_in_layout + + update_demo_project_settings @project_to_destroy, false end def destroy_info @@ -337,4 +341,11 @@ def validate_parent_id end true end + + def update_demo_project_settings(project, value) + # e.g. when one of the demo projects gets deleted or a archived + if project.identifier == 'your-scrum-project' || project.identifier == 'demo-project' + Setting.demo_projects_available = value + end + end end diff --git a/app/controllers/timelog_controller.rb b/app/controllers/timelog_controller.rb index 0f43f731e8..fecfdde557 100644 --- a/app/controllers/timelog_controller.rb +++ b/app/controllers/timelog_controller.rb @@ -84,6 +84,7 @@ def index .includes(:project, :work_package) .references(:projects) .where(cond.conditions) + .distinct(false) .sum(:hours).to_f set_entries(cond) diff --git a/app/controllers/versions_controller.rb b/app/controllers/versions_controller.rb index 84fe45a5b9..866c274320 100644 --- a/app/controllers/versions_controller.rb +++ b/app/controllers/versions_controller.rb @@ -35,8 +35,6 @@ class VersionsController < ApplicationController before_action :find_project, only: [:index, :new, :create, :close_completed] before_action :authorize - include VersionsHelper - def index @types = @project.types.order('position') retrieve_selected_type_ids(@types, @types.select(&:is_in_roadmap?)) @@ -131,13 +129,6 @@ def destroy end end - def status_by - respond_to do |format| - format.html do render action: 'show' end - format.js do render_status_by @version, params[:status_by] end - end - end - private def find_project diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index c4d95889b5..590ebb486e 100644 --- a/app/controllers/wiki_controller.rb +++ b/app/controllers/wiki_controller.rb @@ -128,11 +128,6 @@ def create # display a page (in editing mode if it doesn't exist) def show - # TODO FIXME OMG! this is the ugliest hack I ever performed - # We need to hide the clearfix in the wiki to avoid additional spacing in the wiki - # THIS HACK NEEDS TO BE REPLACED BY AN ENGINEERS SOLUTION! - @no_clearfix = true - @page = @wiki.find_or_new_page(wiki_page_title) if @page.new_record? if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? diff --git a/app/helpers/versions_helper.rb b/app/helpers/versions_helper.rb deleted file mode 100644 index 91de4946e2..0000000000 --- a/app/helpers/versions_helper.rb +++ /dev/null @@ -1,66 +0,0 @@ -#-- encoding: UTF-8 -#-- copyright -# OpenProject is a project management system. -# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2017 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See docs/COPYRIGHT.rdoc for more details. -#++ - -module VersionsHelper - include WorkPackagesFilterHelper - - STATUS_BY_CRITERIAS = %w(category type status priority author assigned_to) - - def render_status_by(version, criteria) - criteria = 'category' unless STATUS_BY_CRITERIAS.include?(criteria) - - h = Hash.new { |k, v| k[v] = [0, 0] } - begin - # Total issue count - WorkPackage.group(criteria) - .where(["#{WorkPackage.table_name}.fixed_version_id = ?", version.id]) - .count.each do |c, s| - h[c][0] = s - end - # Open issues count - WorkPackage.group(criteria) - .includes(:status) - .where(["#{WorkPackage.table_name}.fixed_version_id = ? AND #{Status.table_name}.is_closed = ?", version.id, false]) - .references(:statuses) - .count.each { |c, s| - h[c][1] = s - } - rescue ActiveRecord::RecordNotFound - # When grouping by an association, Rails throws this exception if there's no result (bug) - end - counts = h.keys.compact.sort.map { |k| { group: k, total: h[k][0], open: h[k][1], closed: (h[k][0] - h[k][1]) } } - max = counts.map { |c| c[:total] }.max - - render partial: 'work_package_counts', locals: { version: version, criteria: criteria, counts: counts, max: max } - end - - def status_by_options_for_select(value) - options_for_select(STATUS_BY_CRITERIAS.map { |criteria| [WorkPackage.human_attribute_name(criteria.to_sym), criteria] }, value) - end -end diff --git a/app/helpers/work_packages_helper.rb b/app/helpers/work_packages_helper.rb index 59a95e2373..707cd0934b 100644 --- a/app/helpers/work_packages_helper.rb +++ b/app/helpers/work_packages_helper.rb @@ -169,11 +169,29 @@ def work_package_quick_info(work_package, only_path: true) end end + link = link_to_work_package(work_package, status: true, only_path: only_path) - link += " #{work_package.start_date.nil? ? '[?]' : work_package.start_date.to_s}" - link += changed_dates['start_date'] - link += " – #{work_package.due_date.nil? ? '[?]' : work_package.due_date.to_s}" - link += changed_dates['due_date'] + + # Don't print dates if neither start nor due set + start = work_package.start_date&.to_s + due = work_package.due_date&.to_s + + if start.nil? && due.nil? + return link + end + + # Otherwise, print concise + # (2018-01-01 -) + # (- 2018-01-01) + # (2018-01-01 - 2018-01-01) + link << + if start.nil? + " (- #{due})" + elsif due.nil? + " (#{start} -)" + else + " (#{start} - #{due})" + end link end diff --git a/app/models/custom_actions/actions/date.rb b/app/models/custom_actions/actions/date.rb index 1c4d096075..7440775d94 100644 --- a/app/models/custom_actions/actions/date.rb +++ b/app/models/custom_actions/actions/date.rb @@ -36,7 +36,7 @@ def self.key end def apply(work_package) - work_package.start_date = values.first - work_package.due_date = values.first + work_package.start_date = date_to_apply + work_package.due_date = date_to_apply end end diff --git a/app/models/custom_actions/actions/strategies/date.rb b/app/models/custom_actions/actions/strategies/date.rb index bf9e2e7077..c229345aad 100644 --- a/app/models/custom_actions/actions/strategies/date.rb +++ b/app/models/custom_actions/actions/strategies/date.rb @@ -37,10 +37,27 @@ def type :date_property end - def to_date_or_nil(value) - return nil if value.nil? + def apply(work_package) + work_package.send("#{self.class.key}=", date_to_apply) + end + + private - value.to_date + def date_to_apply + if values.first == '%CURRENT_DATE%' + Date.today + else + values.first + end + end + + def to_date_or_nil(value) + case value + when nil, '%CURRENT_DATE%' + value + else + value.to_date + end rescue TypeError, ArgumentError nil end diff --git a/app/models/custom_actions/actions/strategies/date_property.rb b/app/models/custom_actions/actions/strategies/date_property.rb index 138ca132a3..d8b9bcbb19 100644 --- a/app/models/custom_actions/actions/strategies/date_property.rb +++ b/app/models/custom_actions/actions/strategies/date_property.rb @@ -30,8 +30,4 @@ module CustomActions::Actions::Strategies::DateProperty include CustomActions::Actions::Strategies::Date - - def apply(work_package) - work_package.send("#{self.class.key}=", values.first) - end end diff --git a/app/models/queries/work_packages/columns/property_column.rb b/app/models/queries/work_packages/columns/property_column.rb index 7c903c9430..d67a150673 100644 --- a/app/models/queries/work_packages/columns/property_column.rb +++ b/app/models/queries/work_packages/columns/property_column.rb @@ -51,6 +51,7 @@ def caption type: { association: 'type', sortable: "position", + highlightable: true, groupable: true }, parent: { @@ -67,12 +68,14 @@ def caption status: { association: 'status', sortable: "position", + highlightable: true, groupable: true }, priority: { association: 'priority', sortable: "position", default_order: 'desc', + highlightable: true, groupable: true }, author: { @@ -119,6 +122,7 @@ def caption "#{WorkPackage.table_name}.start_date"] }, due_date: { + highlightable: true, # Put empty due_dates in the far future rather than in the far past sortable: ["CASE WHEN #{WorkPackage.table_name}.due_date IS NULL THEN 1 diff --git a/app/models/queries/work_packages/columns/work_package_column.rb b/app/models/queries/work_packages/columns/work_package_column.rb index 85587f3d43..078e3fee6c 100644 --- a/app/models/queries/work_packages/columns/work_package_column.rb +++ b/app/models/queries/work_packages/columns/work_package_column.rb @@ -29,6 +29,14 @@ #++ class Queries::WorkPackages::Columns::WorkPackageColumn < Queries::Columns::Base + attr_accessor :highlightable + alias_method :highlightable?, :highlightable + + def initialize(name, options = {}) + super(name, options) + self.highlightable = !!options.fetch(:highlightable, false) + end + def caption WorkPackage.human_attribute_name(name) end diff --git a/app/models/query/highlighting.rb b/app/models/query/highlighting.rb index d8dee44b2f..86fb9e3909 100644 --- a/app/models/query/highlighting.rb +++ b/app/models/query/highlighting.rb @@ -30,13 +30,56 @@ module Query::Highlighting extend ActiveSupport::Concern + module PrependValidHighlightingSubset + def valid_subset! + super + valid_highlighting_subset! + end + end + included do + prepend PrependValidHighlightingSubset + QUERY_HIGHLIGHTING_MODES = %i[inline none status type priority].freeze + + serialize :highlighted_attributes, Array + validates_inclusion_of :highlighting_mode, in: QUERY_HIGHLIGHTING_MODES, allow_nil: true, allow_blank: true + validate :attributes_highlightable? + + def valid_highlighting_subset! + self.highlighted_attributes = valid_highlighting_subset + end + + def available_highlighting_columns + @available_highlighting_columns ||= available_columns.select(&:highlightable?) + end + + def highlighted_columns + columns = available_highlighting_columns.group_by(&:name) + + valid_highlighting_subset + .map { |name| columns[name.to_sym] } + .flatten + .uniq + end + + def highlighted_attributes + return [] unless EnterpriseToken.allows_to?(:conditional_highlighting) + + val = super + + if val.present? + val.map(&:to_sym) + else + highlighted_attributes_from_setting + end + end + def highlighting_mode return :none unless EnterpriseToken.allows_to?(:conditional_highlighting) @@ -49,6 +92,35 @@ def highlighting_mode end end + def default_highlighting_mode + QUERY_HIGHLIGHTING_MODES.first + end + + def attributes_highlightable? + # Test that chosen attributes intersect with allowed columns + difference = highlighted_attributes - available_highlighting_columns.map { |col| col.name.to_sym } + if difference.any? + errors.add(:highlighted_attributes, + I18n.t(:error_attribute_not_highlightable, + attributes: difference.map(&:to_s).map(&:capitalize).join(', '))) + end + end + + private + + def valid_highlighting_subset + available_names = available_highlighting_columns.map(&:name) + + highlighted_attributes & available_names + end + + def highlighted_attributes_from_setting + settings = Setting.work_package_list_default_highlighted_attributes || [] + values = settings.map(&:to_sym) + available_names = available_highlighting_columns.map(&:name) + values & available_names + end + def highlighting_mode_from_setting value = Setting.work_package_list_default_highlighting_mode.to_sym @@ -58,9 +130,5 @@ def highlighting_mode_from_setting default_highlighting_mode end end - - def default_highlighting_mode - QUERY_HIGHLIGHTING_MODES.first - end end end diff --git a/app/models/setting.rb b/app/models/setting.rb index 319cf540a0..fef77da5b3 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -155,7 +155,7 @@ def formatted_value(value) # Returns the value of the setting named name def self.[](name) - cached_or_default(name) + filtered_cached_or_default(name) end def self.[]=(name, v) @@ -213,6 +213,22 @@ def self.clear_cache(key = cache_key) private + # Returns the Setting instance for the setting named name + # and allows to filter the returned value + def self.filtered_cached_or_default(name) + name = name.to_s + raise "There's no setting named #{name}" unless exists? name + + value = cached_or_default(name) + + case name + when "work_package_list_default_highlighting_mode" + value = "none" unless EnterpriseToken.allows_to? :conditional_highlighting + end + + value + end + # Returns the Setting instance for the setting named name # (record found in cache or default value) def self.cached_or_default(name) diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index 66056296e7..bbde5f9a27 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -62,7 +62,6 @@ class WikiPage < ActiveRecord::Base validate :validate_non_circular_dependency validate :validate_same_project - after_initialize :check_and_mark_as_protected before_save :update_redirects before_destroy :remove_redirects @@ -82,17 +81,8 @@ class WikiPage < ActiveRecord::Base .merge(Project.allowed_to(user, :view_wiki_pages)) } - # Wiki pages that are protected by default - DEFAULT_PROTECTED_PAGES = %w(sidebar) - after_destroy :delete_wiki_menu_item - def check_and_mark_as_protected - if new_record? && DEFAULT_PROTECTED_PAGES.include?(title.to_s.downcase) - self.protected = true - end - end - def slug read_attribute(:slug).presence || title.try(:to_url) end diff --git a/app/seeders/basic_data/color_seeder.rb b/app/seeders/basic_data/color_seeder.rb index 4da27488bf..a1925569c9 100644 --- a/app/seeders/basic_data/color_seeder.rb +++ b/app/seeders/basic_data/color_seeder.rb @@ -46,8 +46,8 @@ def not_applicable_message def data [ - { name: I18n.t(:default_color_blue_dark), hexcode: '#06799F' }, - { name: I18n.t(:default_color_blue), hexcode: '#3493B3' }, + { name: I18n.t(:default_color_blue_dark), hexcode: '#175A8E' }, + { name: I18n.t(:default_color_blue), hexcode: '#1A67A3' }, { name: I18n.t(:default_color_blue_light), hexcode: '#00B0F0' }, { name: I18n.t(:default_color_green_light), hexcode: '#35C53F' }, { name: I18n.t(:default_color_green_dark), hexcode: '#339933' }, diff --git a/app/seeders/demo_data/custom_field_seeder.rb b/app/seeders/demo_data/custom_field_seeder.rb index 0a738c9d8a..eb44476b5e 100644 --- a/app/seeders/demo_data/custom_field_seeder.rb +++ b/app/seeders/demo_data/custom_field_seeder.rb @@ -40,7 +40,7 @@ def seed_data! print ' ↳ Creating custom fields...' # create some custom fields and add them to the project - Array(I18n.t("seeders.demo_data.projects.#{key}")[:custom_fields]).each do |name| + Array(translate_with_base_url("seeders.demo_data.projects.#{key}")[:custom_fields]).each do |name| cf = WorkPackageCustomField.create!( name: name, regexp: '', diff --git a/app/seeders/demo_data/project_seeder.rb b/app/seeders/demo_data/project_seeder.rb index f37496f9b0..9e6f90d3e9 100644 --- a/app/seeders/demo_data/project_seeder.rb +++ b/app/seeders/demo_data/project_seeder.rb @@ -58,7 +58,12 @@ def seed_data! puts " -#{seeder.class.name.demodulize}" seeder.seed! end + + Setting.demo_projects_available = 'true' end + + puts ' ↳ Updating settings' + seed_settings end def applicable? @@ -75,6 +80,16 @@ def project_data_seeders(project, key) seeders.map { |seeder| seeder.new project, key } end + def seed_settings + welcome = translate_with_base_url("seeders.demo_data.welcome") + + if welcome.present? + Setting.welcome_title = welcome[:title] + Setting.welcome_text = welcome[:text] + Setting.welcome_on_homescreen = 1 + end + end + def reset_project(key) delete_project(key) create_project(key) @@ -91,44 +106,44 @@ def delete_project(key) end def set_members(project) - role = Role.find_by(name: I18n.t(:default_role_project_admin)) + role = Role.find_by(name: translate_with_base_url(:default_role_project_admin)) user = User.admin.first Member.create!( project: project, - user: user, - roles: [role] + user: user, + roles: [role] ) end def set_types(project, key) project.types.clear - Array(I18n.t("seeders.demo_data.projects.#{key}.types")).each do |type_name| - type = Type.find_by(name: I18n.t(type_name)) + Array(translate_with_base_url("seeders.demo_data.projects.#{key}.types")).each do |type_name| + type = Type.find_by(name: translate_with_base_url(type_name)) project.types << type end end def seed_categories(project, key) - Array(I18n.t("seeders.demo_data.projects.#{key}.categories")).each do |cat_name| + Array(translate_with_base_url("seeders.demo_data.projects.#{key}.categories")).each do |cat_name| project.categories.create name: cat_name end end def seed_news(project, key) - Array(I18n.t("seeders.demo_data.projects.#{key}")[:news]).each do |news| + Array(translate_with_base_url("seeders.demo_data.projects.#{key}")[:news]).each do |news| News.create! project: project, title: news[:title], summary: news[:summary], description: news[:description] end end def seed_queries(project, key) - Array(I18n.t("seeders.demo_data.projects.#{key}")[:queries]).each do |config| + Array(translate_with_base_url("seeders.demo_data.projects.#{key}")[:queries]).each do |config| QueryBuilder.new(config, project).create! end end def seed_versions(project, key) - version_data = I18n.t("seeders.demo_data.projects.#{key}.versions") + version_data = translate_with_base_url("seeders.demo_data.projects.#{key}.versions") return if version_data.is_a?(String) && version_data.start_with?("translation missing") @@ -139,9 +154,9 @@ def seed_versions(project, key) def seed_board(project) Board.create!( - project: project, - name: I18n.t('seeders.demo_data.board.name'), - description: I18n.t('seeders.demo_data.board.description') + project: project, + name: translate_with_base_url('seeders.demo_data.board.name'), + description: translate_with_base_url('seeders.demo_data.board.description') ) end @@ -150,24 +165,24 @@ module Data def project_data(key) { - name: project_name(key), - identifier: project_identifier(key), - description: project_description(key), + name: project_name(key), + identifier: project_identifier(key), + description: project_description(key), enabled_module_names: project_modules(key), - types: project_types + types: project_types } end def project_name(key) - I18n.t("seeders.demo_data.projects.#{key}.name") + translate_with_base_url("seeders.demo_data.projects.#{key}.name") end def project_identifier(key) - I18n.t("seeders.demo_data.projects.#{key}.identifier") + translate_with_base_url("seeders.demo_data.projects.#{key}.identifier") end def project_description(key) - I18n.t("seeders.demo_data.projects.#{key}.description") + translate_with_base_url("seeders.demo_data.projects.#{key}.description") end def project_types @@ -175,7 +190,7 @@ def project_types end def project_modules(key) - I18n.t("seeders.demo_data.projects.#{key}.modules") + translate_with_base_url("seeders.demo_data.projects.#{key}.modules") end def find_project(key) diff --git a/app/seeders/demo_data/query_builder.rb b/app/seeders/demo_data/query_builder.rb index 7a62073a08..d2e033f0b5 100644 --- a/app/seeders/demo_data/query_builder.rb +++ b/app/seeders/demo_data/query_builder.rb @@ -26,7 +26,7 @@ # # See doc/COPYRIGHT.rdoc for more details. module DemoData - class QueryBuilder + class QueryBuilder < ::Seeder attr_reader :config attr_reader :project @@ -134,7 +134,7 @@ def set_version_filter!(filters) def set_type_filter!(filters) types = Array(config[:type]).map do |name| - Type.find_by(name: I18n.t(name)) + Type.find_by(name: translate_with_base_url(name)) end if !types.empty? diff --git a/app/seeders/demo_data/version_builder.rb b/app/seeders/demo_data/version_builder.rb index 4cab9f0713..4233afa78b 100644 --- a/app/seeders/demo_data/version_builder.rb +++ b/app/seeders/demo_data/version_builder.rb @@ -27,6 +27,8 @@ # See doc/COPYRIGHT.rdoc for more details. module DemoData class VersionBuilder + include ::DemoData::References + attr_reader :config attr_reader :project @@ -68,7 +70,8 @@ def set_wiki!(version, config) version.wiki_page_title = config[:title] page = WikiPage.create! wiki: version.project.wiki, title: version.wiki_page_title - WikiContent.create! page: page, author: User.admin.first, text: config[:content] + content = with_references config[:content], project + WikiContent.create! page: page, author: User.admin.first, text: content version.save! end diff --git a/app/seeders/demo_data/wiki_seeder.rb b/app/seeders/demo_data/wiki_seeder.rb index e6407d2e6c..e62ad46340 100644 --- a/app/seeders/demo_data/wiki_seeder.rb +++ b/app/seeders/demo_data/wiki_seeder.rb @@ -35,27 +35,53 @@ def initialize(project, key) end def seed_data! - text = I18n.t("seeders.demo_data.projects.#{key}.wiki") + text = translate_with_base_url("seeders.demo_data.projects.#{key}.wiki") - return if text.start_with?("translation missing") + return if text.is_a?(String) && text.start_with?("translation missing") user = User.admin.first + if text.is_a? String + text = [{title: "Wiki", content: text}] + end + print ' ↳ Creating wikis' - print '.' + + Array(text).each do |data| + create_wiki_page!( + data, + project: project, + user: user + ) + end + + puts + end + + def create_wiki_page!(data, project:, user:, parent: nil) wiki_page = WikiPage.create!( wiki: project.wiki, - title: 'Wiki' + title: data[:title], + parent: parent ) print '.' WikiContent.create!( page: wiki_page, author: user, - text: text + text: data[:content] ) - puts + if data[:children] + Array(data[:children]).each do |child_data| + create_wiki_page!( + child_data, + project: project, + user: user, + parent: wiki_page + ) + end + end end end end diff --git a/app/seeders/demo_data/work_package_seeder.rb b/app/seeders/demo_data/work_package_seeder.rb index e0cf4c1370..aaf2f5e20c 100644 --- a/app/seeders/demo_data/work_package_seeder.rb +++ b/app/seeders/demo_data/work_package_seeder.rb @@ -54,7 +54,7 @@ def seed_data! private def seed_demo_work_packages - work_packages_data = I18n.t("seeders.demo_data.projects.#{key}.work_packages") + work_packages_data = translate_with_base_url("seeders.demo_data.projects.#{key}.work_packages") work_packages_data.each do |attributes| print '.' @@ -108,15 +108,15 @@ def base_work_package_attributes(attributes) end def find_priority(attributes) - IssuePriority.find_by(name: I18n.t(attributes[:priority])) + IssuePriority.find_by(name: translate_with_base_url(attributes[:priority])) end def find_status(attributes) - Status.find_by!(name: I18n.t(attributes[:status])) + Status.find_by!(name: translate_with_base_url(attributes[:status])) end def find_type(attributes) - Type.find_by!(name: I18n.t(attributes[:type])) + Type.find_by!(name: translate_with_base_url(attributes[:type])) end def set_version!(wp_attr, attributes) @@ -152,7 +152,7 @@ def create_attachments!(work_package, attributes) end def set_workpackage_relations - work_packages_data = I18n.t("seeders.demo_data.projects.#{key}.work_packages") + work_packages_data = translate_with_base_url("seeders.demo_data.projects.#{key}.work_packages") work_packages_data.each do |attributes| create_relations attributes diff --git a/app/seeders/seeder.rb b/app/seeders/seeder.rb index ce757026b3..7495f9296a 100644 --- a/app/seeders/seeder.rb +++ b/app/seeders/seeder.rb @@ -47,4 +47,13 @@ def applicable? def not_applicable_message "Skipping #{self.class.name}" end + + protected + + ## + # Translate the given string with the fixed interpolation for base_url + # Deep interpolation is required in order for interpolations on hashes to work! + def translate_with_base_url(string) + I18n.t(string, deep_interpolation: true, base_url: OpenProject::Configuration.rails_relative_url_root) + end end diff --git a/app/services/api/v3/parse_query_params_service.rb b/app/services/api/v3/parse_query_params_service.rb index 54c40b26c5..7d8427f311 100644 --- a/app/services/api/v3/parse_query_params_service.rb +++ b/app/services/api/v3/parse_query_params_service.rb @@ -54,6 +54,8 @@ def call(params) parsed_params[:highlighting_mode] = params[:highlightingMode] + parsed_params[:highlighted_attributes] = highlighted_attributes_from_params(params) + parsed_params[:show_hierarchies] = boolearize(params[:showHierarchies]) allow_empty = params.keys + skip_empty @@ -124,6 +126,16 @@ def columns_from_params(params) end end + def highlighted_attributes_from_params(params) + highlighted_attributes = params[:highlightedAttributes] + + return unless highlighted_attributes + + highlighted_attributes.map do |attr| + convert_attribute(attr) + end + end + def boolearize(value) if value == 'true' true diff --git a/app/services/planning_comparison_service.rb b/app/services/planning_comparison_service.rb deleted file mode 100644 index afce2324c3..0000000000 --- a/app/services/planning_comparison_service.rb +++ /dev/null @@ -1,133 +0,0 @@ -#-- encoding: UTF-8 -#-- copyright -# OpenProject is a project management system. -# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2017 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See docs/COPYRIGHT.rdoc for more details. -#++ - -class PlanningComparisonService - @@journal_sql = < <%= icon_wrapper("icon-context icon-#{event_type}", e.event_name) %> <%= format_time(e.event_datetime.to_time, false) %> - <%= content_tag('span', link_to(e.project.name, e.project), class: 'project') if (@project.nil? || @project != e.project) && e.project %> + <% if (@project.nil? || @project != e.project) && e.project %> + <%= content_tag('span', link_to(e.project.name, e.project), class: 'project') %> + - + <% end %> <%= link_to format_activity_title(e.event_title), e.event_path%>
<%= format_activity_description(e.event_description) %>
diff --git a/app/views/attachments/_links.html.erb b/app/views/attachments/_links.html.erb deleted file mode 100644 index c8b7aa798d..0000000000 --- a/app/views/attachments/_links.html.erb +++ /dev/null @@ -1,55 +0,0 @@ -<%#-- copyright -OpenProject is a project management system. -Copyright (C) 2012-2018 the OpenProject Foundation (OPF) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 3. - -OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -Copyright (C) 2006-2017 Jean-Philippe Lang -Copyright (C) 2010-2013 the ChiliProject Team - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -See docs/COPYRIGHT.rdoc for more details. - -++#%> - -
- - - <% for attachment in attachments %> - - - - <% end %> - -
- <%= link_to_attachment attachment, class: 'icon icon-attachment' -%> - <%= h(" - #{attachment.description}") unless attachment.description.blank? %> - (<%= number_to_human_size attachment.filesize, precision: 3 %>) - <% if options[:deletable] %> - <%= link_to icon_wrapper('icon-context icon-delete', l(:button_delete)), - attachment, - { data: { confirm: l(:text_are_you_sure) }, - method: :delete, - class: 'delete', - title: l(:button_delete) } %> - <% end %> - <% if options[:author] %> - <%= h(attachment.author) %>, <%= format_time(attachment.created_at) %> - <% end %> -
-
diff --git a/app/views/custom_actions/_form.html.erb b/app/views/custom_actions/_form.html.erb index 41de766233..a27bbaf79f 100644 --- a/app/views/custom_actions/_form.html.erb +++ b/app/views/custom_actions/_form.html.erb @@ -59,11 +59,9 @@
<% elsif %i(date_property).include?(action.type) %> - <%= styled_text_field_tag input_name, - action.values, - container_class: '-slim', - class: '-augmented-datepicker', - size: '10' %> + + <% elsif %i(string_property text_property).include?(action.type) %> <%= styled_text_field_tag input_name, action.values, diff --git a/app/views/homescreen/index.html.erb b/app/views/homescreen/index.html.erb index df6d26706c..998ff48860 100644 --- a/app/views/homescreen/index.html.erb +++ b/app/views/homescreen/index.html.erb @@ -27,12 +27,10 @@ See docs/COPYRIGHT.rdoc for more details. ++#%> <% breadcrumb_paths(nil) %> -
-

- <%= organization_icon %> - <%= organization_name %> -

-
+

+ <%= organization_icon %> + <%= organization_name %> +

<%= render partial: 'announcements/show' %> @@ -40,7 +38,7 @@ See docs/COPYRIGHT.rdoc for more details.
<% @homescreen[:blocks].each do |block| %> <% if block[:if].nil? || instance_eval(&block[:if]) %> -
+
<%= render partial: "homescreen/blocks/#{block[:partial]}", locals: (block[:locals] || {}) %>
<% end %> diff --git a/app/views/layouts/_action_menu_base.html.erb b/app/views/layouts/_action_menu_base.html.erb index 7807f5ef6f..ebcadcfb6d 100644 --- a/app/views/layouts/_action_menu_base.html.erb +++ b/app/views/layouts/_action_menu_base.html.erb @@ -28,12 +28,7 @@ See docs/COPYRIGHT.rdoc for more details. ++#%> <% action_menu_key = action_menu_key ? action_menu_key : :action_menu_main %> -<% - # TODO FIXME OMG! this is the ugliest hack I ever performed - # We need to hide the clearfix in the wiki to avoid additional spacing in the wiki - # THIS HACK NEEDS TO BE REPLACED BY AN ENGINEERS SOLUTION! - @no_clearfix ||= false -%> +
    @@ -53,7 +48,3 @@ See docs/COPYRIGHT.rdoc for more details.
- -<% unless @no_clearfix %> -
-<% end %> diff --git a/app/views/layouts/base.html.erb b/app/views/layouts/base.html.erb index c9744892ea..cbb70c6fb0 100644 --- a/app/views/layouts/base.html.erb +++ b/app/views/layouts/base.html.erb @@ -57,6 +57,7 @@ See docs/COPYRIGHT.rdoc for more details. data-default-locale="<%= I18n.default_locale %>" data-environment="<%= Rails.env %>"/> + <%= csrf_meta_tags %> <%= render 'common/favicons' %> <%= stylesheet_link_tag 'openproject', media: "all" %> @@ -68,6 +69,8 @@ See docs/COPYRIGHT.rdoc for more details. <%= javascript_include_tag "locales/#{I18n.locale}" %> <%= text_formatting_js_includes %> + + <%= javascript_include_tag 'vendor/enjoyhint.js'%> <%= call_hook :view_layouts_base_html_head %> diff --git a/app/views/messages/show.html.erb b/app/views/messages/show.html.erb index 5cd4607547..2732d9bdb8 100644 --- a/app/views/messages/show.html.erb +++ b/app/views/messages/show.html.erb @@ -31,46 +31,37 @@ See docs/COPYRIGHT.rdoc for more details. link_to(t(:label_board_plural), project_boards_path(@project)), link_to(h(@board.name), project_board_path(@project, @board))) %> - - -
-
-
-
-

<%= avatar(@topic.author) %><%=h @topic.subject %>

-
-
    -
  • - <%= watcher_link(@topic, User.current) %> -
  • -
  • - <% if !@topic.locked? && authorize_for('messages', 'reply') %> - <%= link_to({ action: 'quote', id: @topic }, class: 'boards--quote-button button') do %> +<% title avatar(@topic.author) + h(@topic.subject) %> +<%= toolbar title: title do %> +
  • + <%= watcher_link(@topic, User.current) %> +
  • +
  • + <% if !@topic.locked? && authorize_for('messages', 'reply') %> + <%= link_to({ action: 'quote', id: @topic }, class: 'boards--quote-button button') do %> <%= op_icon('button--icon icon-quote') %> <%= t(:button_quote) %> - <% end %> <% end %> -
  • -
  • - <% if @message.editable_by?(User.current) %> - <%= link_to(edit_topic_path(@topic), accesskey: accesskey(:edit), class: 'button') do %> + <% end %> +
  • +
  • + <% if @message.editable_by?(User.current) %> + <%= link_to(edit_topic_path(@topic), accesskey: accesskey(:edit), class: 'button') do %> <%= op_icon('button--icon icon-edit') %> <%= t(:button_edit) %> - <% end %> <% end %> -
  • -
  • - <% if @message.destroyable_by?(User.current) %> - <%= link_to(topic_path(@topic), method: :delete, data: { confirm: t(:text_are_you_sure) }, class: 'button') do %> + <% end %> +
  • +
  • + <% if @message.destroyable_by?(User.current) %> + <%= link_to(topic_path(@topic), method: :delete, data: { confirm: t(:text_are_you_sure) }, class: 'button') do %> <%= op_icon('button--icon icon-delete') %> <%= t(:button_delete) %> - <% end %> <% end %> -
  • -
-
-
-
+ <% end %> + +<% end %> +

<%= authoring @topic.created_on, @topic.author %>

@@ -86,14 +77,14 @@ See docs/COPYRIGHT.rdoc for more details.

<%= t(:label_reply_plural) %> (<%= @replies.count %>)

<% @replies.each do |message| %>
"> -

+

<%= avatar(message.author) %> <%= link_to h(message.subject), topic_path(@topic, r: message, anchor: "message-#{message.id}") %> - <%= authoring message.created_on, message.author %> -

+
<%= link_to(icon_wrapper('icon-quote', t(:button_quote)), { action: 'quote', id: message }, diff --git a/app/views/news/_form.html.erb b/app/views/news/_form.html.erb index b4a83e9667..46b975cda7 100644 --- a/app/views/news/_form.html.erb +++ b/app/views/news/_form.html.erb @@ -28,18 +28,18 @@ See docs/COPYRIGHT.rdoc for more details. ++#%> <%= error_messages_for 'news' %>
- <%= f.text_field :title, required: true, size: 60, container_class: '-wide' %> + <%= f.text_field :title, required: true, size: 60, container_class: '-xxwide' %>
<%= f.text_area :summary, cols: 60, rows: 4, class: 'wiki-edit wiki-toolbar -small', - container_class: '-wide' %> + container_class: '-xxwide' %>
<%= f.text_area :description, class: 'wiki-edit wiki-toolbar', - container_class: '-wide', + container_class: '-xxwide', with_text_formatting: true %>
diff --git a/app/views/onboarding/_configuration_modal.html.erb b/app/views/onboarding/_configuration_modal.html.erb index 7ea1c5c99b..6c8d0bd869 100644 --- a/app/views/onboarding/_configuration_modal.html.erb +++ b/app/views/onboarding/_configuration_modal.html.erb @@ -32,7 +32,7 @@ See docs/COPYRIGHT.rdoc for more details.
<%= homescreen_user_avatar %> -

<%= I18n.t('onboarding.welcome') %> , <%= current_user.name %>

+

<%= I18n.t('onboarding.welcome') %>, <%= current_user.name %>

diff --git a/app/views/search/index.html.erb b/app/views/search/index.html.erb index 694941f2b7..4436ec8481 100644 --- a/app/views/search/index.html.erb +++ b/app/views/search/index.html.erb @@ -91,6 +91,7 @@ See docs/COPYRIGHT.rdoc for more details. <%= icon_wrapper("icon-context icon-#{event_type}", e.event_name) %> <% if e.project != @project %> <%= e.project %> + - <% end %> <%= link_to highlight_tokens(truncate(e.event_title, escape: false, length: 255), @tokens), with_notes_anchor(e, @tokens) %> diff --git a/app/views/settings/_enterprise_feature_hint.html.erb b/app/views/settings/_enterprise_feature_hint.html.erb new file mode 100644 index 0000000000..0bb68a36e1 --- /dev/null +++ b/app/views/settings/_enterprise_feature_hint.html.erb @@ -0,0 +1,13 @@ +<% unless EnterpriseToken.allows_to?(ee_feature) %> + +
+
+

<%= title.present? ? title : t('js.upsale.ee_only') %>

+

<%= explanation %>

+

+ <%= link_to link_out[:caption], link_out[:href], target: 'blank' %> +

+
+
+
+<% end %> diff --git a/app/views/settings/_work_packages.html.erb b/app/views/settings/_work_packages.html.erb index 878570d1f1..496c14a723 100644 --- a/app/views/settings/_work_packages.html.erb +++ b/app/views/settings/_work_packages.html.erb @@ -34,14 +34,35 @@ See docs/COPYRIGHT.rdoc for more details.
<%= setting_check_box :work_package_startdate_is_adddate %>
<%= setting_select :work_package_done_ratio, WorkPackage::DONE_RATIO_OPTIONS.collect {|i| [t("setting_work_package_done_ratio_#{i}"), i]}, container_class: '-middle' %>
<%= setting_text_field :work_packages_export_limit, size: 6, container_class: '-xslim' %>
-
+
<%= setting_select :work_package_list_default_highlighting_mode, Query::Highlighting::QUERY_HIGHLIGHTING_MODES.map { |mode| - [t("js.work_packages.table_configuration.highlighting_mode.#{mode}"), mode] + [t("settings.highlighting.mode_long.#{mode}"), mode] }, - container_class: '-middle' + Hash.new.tap { |options| + options[:container_class] = '-middle' + options[:disabled] = 'disabled' unless EnterpriseToken.allows_to?(:conditional_highlighting) + } %> + <%= render partial: 'enterprise_feature_hint', + locals: { + ee_feature: :conditional_highlighting, + explanation: t('js.work_packages.table_configuration.upsale.attribute_highlighting'), + link_out: { + href: "https://www.openproject.org/enterprise-edition/?op_edtion=community-edition&op_referrer=settings-wp-attribute-highlighting#attribute-highlighting", + caption: t('js.work_packages.table_configuration.upsale.check_out_link') + } + } %>
+ <% if EnterpriseToken.allows_to? :conditional_highlighting %> +
+ <%= setting_multiselect :work_package_list_default_highlighted_attributes, + Query.available_columns(nil).select(&:highlightable).map { |column| + [column.caption, column.name.to_s] + } + %> +
+ <% end %>
<%= t(:setting_column_options) %> <% diff --git a/app/views/versions/_overview.html.erb b/app/views/versions/_overview.html.erb index 2dc6755fbe..fea77d56b7 100644 --- a/app/views/versions/_overview.html.erb +++ b/app/views/versions/_overview.html.erb @@ -31,7 +31,8 @@ See docs/COPYRIGHT.rdoc for more details. <% if version.start_date %> <%= Version.human_attribute_name(:start_date) %> <%= h(format_date(version.start_date)) %> <% end %> - <% if version.start_date %> + <% if version.due_date %> +
<%= Version.human_attribute_name(:due_date) %> <%= h(format_date(version.due_date)) %> <% end %>

diff --git a/app/views/versions/_work_package_counts.html.erb b/app/views/versions/_work_package_counts.html.erb deleted file mode 100644 index 7cdcf5ba22..0000000000 --- a/app/views/versions/_work_package_counts.html.erb +++ /dev/null @@ -1,77 +0,0 @@ -<%#-- copyright -OpenProject is a project management system. -Copyright (C) 2012-2018 the OpenProject Foundation (OPF) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 3. - -OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -Copyright (C) 2006-2017 Jean-Philippe Lang -Copyright (C) 2010-2013 the ChiliProject Team - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -See docs/COPYRIGHT.rdoc for more details. - -++#%> -<% tag_for_selection = select_tag('status_by', - status_by_options_for_select(criteria), - id: 'status_by_select', - class: 'form--select -narrow') %> - -<%= form_tag status_by_version_path(version), - id: "status_by_form" do %> - -
- - - <%= l(:label_work_package_plural) %> - - - - - <%= l(:label_group_by) %> - - <%= tag_for_selection %> - - <% if counts.empty? %> - -

- <%= l(:label_no_data) %> -

- <% else %> - - <% counts.each do |count| %> - - - - - - <% end %> - -
- <%= link_to h(count[:group]), - project_version_property_path(version, "#{criteria}_id", count[:group].id) %> - - <%= progress_bar((count[:closed].to_f / count[:total])*100, - legend: "#{count[:closed]}/#{count[:total]}", - hide_total_progress: true, - hide_percent_sign: true, - width: "#{(count[:total].to_f / max * 200).floor}px;") %> -
- - <% end %> -
-<% end %> diff --git a/app/views/versions/show.html.erb b/app/views/versions/show.html.erb index 2b01fa7dc6..148281a37b 100644 --- a/app/views/versions/show.html.erb +++ b/app/views/versions/show.html.erb @@ -28,67 +28,91 @@ See docs/COPYRIGHT.rdoc for more details. ++#%> <%= toolbar title: @version.name do %> - <% if authorize_for(:versions, :edit) %> -
  • - <%= link_to(edit_version_path(@version), class: 'button') do %> - <%= op_icon('button--icon icon-edit') %> - <%= l(:button_edit) %> - <% end %> -
  • - <% end %> - <% if authorize_for(:wiki, :edit) && !(@version.wiki_page_title.blank? || @version.project.wiki.nil?) %> -
  • - <%= link_to({controller: '/wiki', action: 'edit', - project_id: @version.project, - id: @version.wiki_page_title}, - class: 'button') do %> - <%= op_icon('button--icon icon-edit') %> - <%= l(:button_edit_associated_wikipage, page_title: truncate(@version.wiki_page_title, length: 50, separator: ' ')) %> - <% end %> -
  • - <% end %> - <%= call_hook(:view_versions_show_contextual, { version: @version, project: @project }) %> + <% if authorize_for(:versions, :edit) %> +
  • + <%= link_to(edit_version_path(@version), class: 'button') do %> + <%= op_icon('button--icon icon-edit') %> + <%= l(:button_edit) %> + <% end %> +
  • + <% end %> + <% if authorize_for(:wiki, :edit) && !(@version.wiki_page_title.blank? || @version.project.wiki.nil?) %> +
  • + <%= link_to({controller: '/wiki', action: 'edit', + project_id: @version.project, + id: @version.wiki_page_title}, + class: 'button') do %> + <%= op_icon('button--icon icon-edit') %> + <%= l(:button_edit_associated_wikipage, page_title: truncate(@version.wiki_page_title, length: 50, separator: ' ')) %> + <% end %> +
  • + <% end %> + <%= call_hook(:view_versions_show_contextual, { version: @version, project: @project }) %> <% end %> +
    +
    + <%= render partial: 'versions/overview', locals: { version: @version } %> +
    -
    - <% if @version.estimated_hours > 0 || User.current.allowed_to?(:view_time_entries, @project) %> -
    <%= l(:label_time_tracking) %> - - - - - - <% if User.current.allowed_to?(:view_time_entries, @project) %> - - - - - <% end %> -
    <%= Version.human_attribute_name(:estimated_hours) %><%= html_hours(l_hours(@version.estimated_hours)) %>
    <%= l(:label_spent_time) %><%= html_hours(l_hours(@version.spent_hours)) %>
    -
    - <% end %> +
    +
    +
    +
    + <% if @version.wiki_page %> +
    + <%= render(partial: "wiki/content", locals: {content: @version.wiki_page.content}) if @version.wiki_page %> +
    + <% end %> -
    - <%= render_status_by(@version, params[:status_by]) if @version.fixed_issues.count > 0 %> -
    -
    + <% if @issues.present? %> +
    + <% if @issues.present? %> + + <% end %> +
    + <% end %> +
    +
    -
    - <%= render partial: 'versions/overview', locals: {version: @version} %> - <%= render(partial: "wiki/content", locals: {content: @version.wiki_page.content}) if @version.wiki_page %> +
    +
    + <% if @version.estimated_hours > 0 || User.current.allowed_to?(:view_time_entries, @project) %> +
    +
    <%= l(:label_time_tracking) %> + + + + + + <% if User.current.allowed_to?(:view_time_entries, @project) %> + + + + + <% end %> +
    <%= Version.human_attribute_name(:estimated_hours) %><%= html_hours(l_hours(@version.estimated_hours)) %>
    <%= l(:label_spent_time) %><%= html_hours(l_hours(@version.spent_hours)) %>
    +
    +
    + <% end %> - <% if @issues.present? %> - - <% end %> + <% if @version.fixed_issues.count > 0 %> +
    + + +
    + <% end %> +
    +
    +
    +
    - <%= call_hook :view_versions_show_bottom, version: @version %> <% html_title h(@version.name) %> diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb deleted file mode 100644 index fc0fcfff26..0000000000 --- a/app/views/welcome/index.html.erb +++ /dev/null @@ -1,72 +0,0 @@ -<%#-- copyright -OpenProject is a project management system. -Copyright (C) 2012-2018 the OpenProject Foundation (OPF) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 3. - -OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -Copyright (C) 2006-2017 Jean-Philippe Lang -Copyright (C) 2010-2013 the ChiliProject Team - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -See docs/COPYRIGHT.rdoc for more details. - -++#%> - -<% breadcrumb_paths(nil) %> -
    -
    -
    <%= format_text Setting.welcome_text %>
    - <% if @news.any? %> -
    - <%= op_icon('icon-context icon-news') %> -

    <%=l(:label_news_latest)%>

    -
    - <%= render partial: 'news/news', collection: @news %> - <%= link_to l(:label_news_view_all), controller: '/news' %> -
    -
    - <% end %> - <%= call_hook(:view_welcome_index_left, projects: @projects) %> -
    - -
    - <% if @projects.any? %> -
    - <%= op_icon('icon-context icon-projects') %> -

    <%=l(:label_project_latest)%>

    -
      - <% for project in @projects %> - <% @project = project %> -
    • - <%= link_to_project project %> (<%= format_time(project.created_on) %>) - <%= format_text project.short_description, project: project %> -
    • - <% end %> - <% @project = nil %> -
    -
    - <% end %> - <%= call_hook(:view_welcome_index_right, projects: @projects) %> -
    -
    -<% content_for :header_tags do %> - <%= auto_discovery_link_tag(:atom, {controller: '/news', action: 'index', key: User.current.rss_key, format: 'atom'}, - title: "#{Setting.app_title}: #{l(:label_news_latest)}") %> - <%= auto_discovery_link_tag(:atom, {controller: '/activities', action: 'index', key: User.current.rss_key, format: 'atom'}, - title: "#{Setting.app_title}: #{l(:label_activity)}") %> -<% end %> diff --git a/app/views/wiki/_wiki_export_modal.html.erb b/app/views/wiki/_wiki_export_modal.html.erb new file mode 100644 index 0000000000..c9074d711a --- /dev/null +++ b/app/views/wiki/_wiki_export_modal.html.erb @@ -0,0 +1,65 @@ +<%#-- copyright +OpenProject is a project management system. +Copyright (C) 2012-2018 the OpenProject Foundation (OPF) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 3. + +OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +Copyright (C) 2006-2017 Jean-Philippe Lang +Copyright (C) 2010-2013 the ChiliProject Team + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +See docs/COPYRIGHT.rdoc for more details. + +++#%> + +
    + +<% content_for :header_tags do %> + <%= auto_discovery_link_tag(:atom, controller: '/activities', action: 'index', id: @project, show_wiki_edits: 1, format: 'atom', key: User.current.rss_key) %> +<% end %> diff --git a/app/views/wiki/date_index.html.erb b/app/views/wiki/date_index.html.erb index 1e5a7f0d22..938797410a 100644 --- a/app/views/wiki/date_index.html.erb +++ b/app/views/wiki/date_index.html.erb @@ -30,8 +30,10 @@ See docs/COPYRIGHT.rdoc for more details. <% content_for :action_menu_specific do %> <%= watcher_link(@wiki, User.current) %> <% end %> -

    <%= l(:label_index_by_date) %>

    -<%= render partial: 'layouts/action_menu_specific' %> + +<%= toolbar title: t(:label_index_by_date) %> +<%= render partial: "layouts/action_menu_specific" %> + <% if @pages.empty? %> <%= no_results_box %> <% end %> diff --git a/app/views/wiki/show.html.erb b/app/views/wiki/show.html.erb index 88395908c2..e336998009 100644 --- a/app/views/wiki/show.html.erb +++ b/app/views/wiki/show.html.erb @@ -91,6 +91,18 @@ See docs/COPYRIGHT.rdoc for more details. <% end %> <%= li_unless_nil(link_to_if_authorized(l(:label_history), {action: 'history', id: @page}, class: 'icon-context icon-wiki')) %> <%= li_unless_nil(link_to_if_authorized(l(:button_manage_menu_entry), {controller: '/wiki_menu_items', action: 'edit', project_id: @project.identifier, id: @page}, class: 'icon-context icon-settings')) %> + <% if User.current.allowed_to?(:export_wiki_pages, @project) %> +
    +
  • + <%= link_to I18n.t('js.label_export'), + '', + title: I18n.t('js.label_export'), + class: 'modal-wrapper--activation-link icon-context icon-export' %> +
  • + <%= render partial: 'wiki/wiki_export_modal' %> +
    + <% end %> <%= li_unless_nil(link_to_if_authorized(l(:label_table_of_contents), {controller: '/wiki', action: 'index', project_id: @project.identifier, id: @page}, class: 'icon-context icon-view-list')) %> @@ -116,17 +128,4 @@ See docs/COPYRIGHT.rdoc for more details. <% resource = ::API::V3::WikiPages::WikiPageRepresenter.new(@page, current_user: current_user, embed_links: true) %> <%= list_attachments(resource) %> -<%= other_formats_links do |f| %> - <%= f.link_to 'Atom', url: { controller: '/activities', - action: 'index', - show_wiki_edits: 1, - key: User.current.rss_key } %> - <%= f.link_to 'Markdown', url: { version: @content.version, id: @page, format: 'markdown' } %> - <%= call_hook(:view_wiki_show_other_formats, {link_builder: f, url_params: {id: @page, version: @content.version}}) %> -<% end if User.current.allowed_to?(:export_wiki_pages, @project) %> - -<% content_for :header_tags do %> - <%= auto_discovery_link_tag(:atom, controller: '/activities', action: 'index', id: @project, show_wiki_edits: 1, format: 'atom', key: User.current.rss_key) %> -<% end %> - <% html_title h(@page.title) %> diff --git a/app/workers/extract_fulltext_job.rb b/app/workers/extract_fulltext_job.rb index 026fbe24aa..2cdac62eda 100644 --- a/app/workers/extract_fulltext_job.rb +++ b/app/workers/extract_fulltext_job.rb @@ -44,6 +44,8 @@ def perform init update + ensure + FileUtils.rm @file.path if delete_file? end private @@ -79,4 +81,12 @@ def update def find_attachment(id) Attachment.find_by_id id end + + def remote_file? + !@attachment.file.is_a?(LocalFileUploader) + end + + def delete_file? + remote_file? && @file + end end diff --git a/config/application.rb b/config/application.rb index 01d43759aa..93a6e6b8ce 100644 --- a/config/application.rb +++ b/config/application.rb @@ -168,6 +168,8 @@ class Application < Rails::Application config.action_controller.asset_host = OpenProject::Configuration['rails_asset_host'] + config.log_level = OpenProject::Configuration['log_level'].to_sym + def self.root_url Setting.protocol + "://" + Setting.host_name end diff --git a/config/configuration.yml.example b/config/configuration.yml.example index 55d55e4a73..4c7d522434 100644 --- a/config/configuration.yml.example +++ b/config/configuration.yml.example @@ -165,6 +165,8 @@ # default configuration options for all environments default: + log_level: info + # Outgoing emails configuration (see examples above) email_delivery_method: :smtp smtp_address: smtp.example.net @@ -389,7 +391,8 @@ default: # specific configuration options for production environment # that overrides the default ones -# production: +production: + log_level: warn # specific configuration options for development environment # that overrides the default ones diff --git a/config/environments/production.rb b/config/environments/production.rb index 042710d23c..8526225fdc 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -87,7 +87,7 @@ } # Set to :debug to see everything in the log. - config.log_level = :warn + config.log_level = OpenProject::Configuration['log_level'].to_sym # Prepend all log lines with the following tags. # config.log_tags = [ :subdomain, :uuid ] diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 9b1b98c63b..dcb9b4f9bf 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -9,7 +9,6 @@ admin_users.js autocompleter.js calendar/lang/*.js - contextual_fieldset.js copy_issue_actions.js date-de-DE.js date-en-US.js @@ -27,6 +26,7 @@ types_checkboxes.js work_packages.js vendor/ckeditor/ckeditor.*js + vendor/enjoyhint.js bundles/openproject-legacy-app.js ) end diff --git a/config/locales/crowdin/af.yml b/config/locales/crowdin/af.yml index 4e09ad1452..665f76b824 100644 --- a/config/locales/crowdin/af.yml +++ b/config/locales/crowdin/af.yml @@ -1037,6 +1037,7 @@ af: ' error_external_authentication_failed: Daar was 'n probleem tydens eksterne waarmerking. Probeer asseblief weer. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projek geredigeer changeset: Veranderingstel geredigeer @@ -1086,7 +1087,7 @@ af: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1863,7 +1864,7 @@ af: team collaboration with OpenProject. text_show_again: You can restart this video from the help menu welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Add notes permission_add_work_packages: Add work packages permission_add_messages: Post messages @@ -2219,8 +2220,9 @@ af: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Wiki history compression setting_work_package_group_assignment: Allow assignment to groups - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Algemeen other: Ander @@ -2230,6 +2232,13 @@ af: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/ar.yml b/config/locales/crowdin/ar.yml index 1b764f4afd..f1a57046d8 100644 --- a/config/locales/crowdin/ar.yml +++ b/config/locales/crowdin/ar.yml @@ -1097,6 +1097,7 @@ ar: ' error_external_authentication_failed: حدث خطأ أثناء المصادقة الخارجية. الرجاء المحاولة مرة أخرى. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: تم تعديل المشروع changeset: تم تحرير مجموعة التغييرات @@ -1146,7 +1147,7 @@ ar: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1937,7 +1938,7 @@ ar: team collaboration with OpenProject. text_show_again: يمكنك إعادة تشغيل هذا الفيديو من قائمة المساعدة welcome: مرحبًا بكم في أوبِن بروجِكت - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: إضافة ملاحظات permission_add_work_packages: إضافة مجموعات عمل permission_add_messages: نشر الرسائل @@ -2287,8 +2288,9 @@ ar: setting_welcome_on_homescreen: كتلة الترحيب عرض على الشاشة الرئيسية setting_wiki_compression: ضغط تاريخ Wiki setting_work_package_group_assignment: السماح بالإحالة إلى مجموعات - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: عام other: اخرى @@ -2298,6 +2300,13 @@ ar: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/bg.yml b/config/locales/crowdin/bg.yml index f98216a794..dace7f0c99 100644 --- a/config/locales/crowdin/bg.yml +++ b/config/locales/crowdin/bg.yml @@ -1035,6 +1035,7 @@ bg: ' error_external_authentication_failed: Възникна грешка при външно удостовяряване. Моля, опитайте отново. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Проекта е редактиран changeset: Редактиран пакет промени @@ -1084,7 +1085,7 @@ bg: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1864,7 +1865,7 @@ bg: team collaboration with OpenProject. text_show_again: Можете да рестартирате това видео от менюто помощ welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Добавяне на бележки permission_add_work_packages: Add work packages permission_add_messages: Post messages @@ -2217,8 +2218,9 @@ bg: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Wiki history compression setting_work_package_group_assignment: Allow assignment to groups - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Общ other: Други @@ -2228,6 +2230,13 @@ bg: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/ca.yml b/config/locales/crowdin/ca.yml index e6ecdbe038..88733c5a09 100644 --- a/config/locales/crowdin/ca.yml +++ b/config/locales/crowdin/ca.yml @@ -1046,6 +1046,7 @@ ca: ' error_external_authentication_failed: S'ha produït un error durant l'autenticació externa. Torneu-ho a provar. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projecte editat changeset: Conjunt de canvis editat @@ -1095,7 +1096,7 @@ ca: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1885,7 +1886,7 @@ ca: team collaboration with OpenProject. text_show_again: Pot reprendre aquest vídeo des del menú d'ajuda welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Afegir notes permission_add_work_packages: Afegir paquets de treball permission_add_messages: Publicar missatges @@ -2265,8 +2266,9 @@ ca: setting_welcome_on_homescreen: Mostrar el bloc de benvinguda a la pàgina d'inici setting_wiki_compression: Compressió de l'historial de la wiki setting_work_package_group_assignment: Permeten l'assignació als grups - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: General other: Altres @@ -2276,6 +2278,13 @@ ca: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/cs.yml b/config/locales/crowdin/cs.yml index 550da31469..020c5a8062 100644 --- a/config/locales/crowdin/cs.yml +++ b/config/locales/crowdin/cs.yml @@ -1066,6 +1066,7 @@ cs: ' error_external_authentication_failed: An error occured during external authentication. Please try again. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projekt upraven changeset: Changeset edited @@ -1115,7 +1116,7 @@ cs: upsale: become_hero: Staň se hrdinou! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: Více informací additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1902,7 +1903,7 @@ cs: team collaboration with OpenProject. text_show_again: You can restart this video from the help menu welcome: Vítejte v OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Add notes permission_add_work_packages: Add work packages permission_add_messages: Post messages @@ -2259,8 +2260,9 @@ cs: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Wiki history compression setting_work_package_group_assignment: Povolit přiřazení do skupin - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Obecné other: Ostatní @@ -2270,6 +2272,13 @@ cs: user: default_preferences: Výchozí předvolby deletion: Odstranění + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Zmenšení plain: Obyčejný text diff --git a/config/locales/crowdin/da.yml b/config/locales/crowdin/da.yml index 02dcff9022..67d671727f 100644 --- a/config/locales/crowdin/da.yml +++ b/config/locales/crowdin/da.yml @@ -1031,6 +1031,7 @@ da: ' error_external_authentication_failed: Der opstod en fejl ved den eksterne godkendelse. Prøv venligst igen. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projekt er redigeret changeset: Pakke af ændringer er redigeret @@ -1080,7 +1081,7 @@ da: upsale: become_hero: Become a hero! title: Opgradér til Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1854,7 +1855,7 @@ da: team collaboration with OpenProject. text_show_again: You can restart this video from the help menu welcome: Velkommen til OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Tilføj noter permission_add_work_packages: Tilføj arbejdspakker permission_add_messages: Send beskeder @@ -2210,8 +2211,9 @@ da: setting_welcome_on_homescreen: Vis velkomstblok på hjemmeskærm setting_wiki_compression: Sammendrag af wiki-historie setting_work_package_group_assignment: Tillad tilknytning til grupper - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Generelle other: Andet @@ -2221,6 +2223,13 @@ da: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/de.yml b/config/locales/crowdin/de.yml index 23a2eb6195..88a2fd24ca 100644 --- a/config/locales/crowdin/de.yml +++ b/config/locales/crowdin/de.yml @@ -690,7 +690,7 @@ de: responsible: Verantwortlich role: Rolle roles: Rollen - start_date: Anfangstermin + start_date: Beginn status: Status subject: Thema summary: Zusammenfassung @@ -1067,6 +1067,7 @@ de: ' error_external_authentication_failed: Die externe Authentifizierung ist fehlgeschlagen. Bitte versuchen Sie es erneut. + error_attribute_not_highlightable: 'Nicht hervorhebbare Attribut(e): %{attributes}' events: project: Projekt bearbeitet changeset: Projektarchiv-Änderung bearbeitet @@ -1116,7 +1117,7 @@ de: upsale: become_hero: Werde zum Held! title: Auf Enterprise-Edition upgraden - description: Steigern Sie Ihre Produktivität mit der Enterprise-Edition + description: Was sind die Vorteile? more_info: Weitere Informationen additional_features: Zusätzliche mächtige Premium-Funktionen professional_support: Professioneller Support durch OpenProject Experten @@ -1907,7 +1908,7 @@ de: Projekt-Management und Zusammenarbeit in Teams mit OpenProject. text_show_again: Sie können dieses Video über das Hilfe-Menü erneut starten welcome: Willkommen bei OpenProject - select_language: Bitte wählen Sie Ihre Sprache für OpenProject + select_language: Please select your language permission_add_work_package_notes: Kommentare hinzufügen permission_add_work_packages: Arbeitspakete hinzufügen permission_add_messages: Forenbeiträge hinzufügen @@ -2282,7 +2283,9 @@ de: setting_welcome_on_homescreen: Willkommens-Block auf Startseite anzeigen setting_wiki_compression: Wiki-Historie komprimieren setting_work_package_group_assignment: Zuweisung zu Gruppen erlauben - setting_work_package_list_default_highlighting_mode: Standardwert für Arbeitspaket-Hervorherbung + setting_work_package_list_default_highlighting_mode: Standard Hervorhebung + setting_work_package_list_default_highlighted_attributes: Voreinstellung Inline + Hervorherbung settings: general: Allgemein other: Sonstiges @@ -2292,6 +2295,13 @@ de: user: default_preferences: Standardeinstellungen deletion: Löschen + highlighting: + mode_long: + inline: Inline hervorgehobene Attribute + none: Keine Hervorhebung + status: Ganze Zeile nach Status + type: Ganze Zeile nach Typ + priority: Ganze Zeile nach Priorität text_formatting: markdown: Markdown plain: Reiner Text @@ -2767,7 +2777,8 @@ de: korrekt. code_403: Sie sind nicht berechtigt auf diese Ressource zuzugreifen. code_404: Die angeforderte Ressource konnte nicht gefunden werden. - code_409: Could not update the resource because of conflicting modifications. + code_409: Die Ressource konnte wegen parallelen Zugriffs nicht aktualisiert + werden. code_500: Ein interner Fehler ist aufgetreten. expected: date: YYYY-MM-DD (Datum nach ISO 8601) diff --git a/config/locales/crowdin/es.yml b/config/locales/crowdin/es.yml index e8fd87fb3e..e089bb1f27 100644 --- a/config/locales/crowdin/es.yml +++ b/config/locales/crowdin/es.yml @@ -1064,6 +1064,7 @@ es: ' error_external_authentication_failed: Se ha producido un error durante la autenticación externa. Por favor inténtelo nuevamente. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Proyecto editado changeset: Set de cambios editado @@ -1113,7 +1114,7 @@ es: upsale: become_hero: "¡Conviértete en héroe!" title: Actualizar hasta versión corporativa - description: Aumente el rendimiento con la versión corporativa + description: What are the benefits? more_info: Más información additional_features: Características Premium avanzadas adicionales professional_support: Apoyo profesional de los expertos de OpenProject @@ -1907,7 +1908,7 @@ es: administración de proyectos y la colaboración en equipo con OpenProject. text_show_again: Puede reiniciar este vídeo en el menú ayuda welcome: Bienvenido a OpenProject - select_language: Seleccione el idioma de OpenProject + select_language: Please select your language permission_add_work_package_notes: Añadir notas permission_add_work_packages: Añadir paquetes de trabajo permission_add_messages: Publicar mensajes @@ -2288,8 +2289,9 @@ es: setting_welcome_on_homescreen: Mostrar bloque de bienvenida en la pagina de inicio setting_wiki_compression: Comprensión del historial del Wiki setting_work_package_group_assignment: Permite la asignación a grupos - setting_work_package_list_default_highlighting_mode: Modo predeterminado de resaltado - de paquete de trabajo + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: General other: Otros @@ -2299,6 +2301,13 @@ es: user: default_preferences: Preferencias predeterminadas deletion: Eliminación + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: Sin resaltado + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Texto sin formato diff --git a/config/locales/crowdin/et.yml b/config/locales/crowdin/et.yml index fb96854872..1719d39005 100644 --- a/config/locales/crowdin/et.yml +++ b/config/locales/crowdin/et.yml @@ -1031,6 +1031,7 @@ et: ' error_external_authentication_failed: Välisel autentimisel ilmnes tõrge. Palun proovi uuesti. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projekti on muudetud changeset: Toimikut on muudetud @@ -1080,7 +1081,7 @@ et: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1848,7 +1849,7 @@ et: team collaboration with OpenProject. text_show_again: You can restart this video from the help menu welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Märkusi lisada permission_add_work_packages: Teemasid lisada permission_add_messages: Postitusi lisada @@ -2206,8 +2207,9 @@ et: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Viki ajaloo tihendamine setting_work_package_group_assignment: Luba teemade andmine gruppidele - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Üldine other: Muu @@ -2217,6 +2219,13 @@ et: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/fa.yml b/config/locales/crowdin/fa.yml index 3d987898a1..bc7ad79596 100644 --- a/config/locales/crowdin/fa.yml +++ b/config/locales/crowdin/fa.yml @@ -1030,6 +1030,7 @@ fa: ' error_external_authentication_failed: An error occured during external authentication. Please try again. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Project edited changeset: Changeset edited @@ -1079,7 +1080,7 @@ fa: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1852,7 +1853,7 @@ fa: team collaboration with OpenProject. text_show_again: You can restart this video from the help menu welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Add notes permission_add_work_packages: Add work packages permission_add_messages: Post messages @@ -2207,8 +2208,9 @@ fa: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Wiki history compression setting_work_package_group_assignment: Allow assignment to groups - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: General other: Other @@ -2218,6 +2220,13 @@ fa: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/fi.yml b/config/locales/crowdin/fi.yml index 61ebd397fd..e430dbe97e 100644 --- a/config/locales/crowdin/fi.yml +++ b/config/locales/crowdin/fi.yml @@ -1029,6 +1029,7 @@ fi: ' error_external_authentication_failed: An error occured during external authentication. Please try again. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Project edited changeset: Changeset edited @@ -1078,7 +1079,7 @@ fi: upsale: become_hero: Ryhdy sankariksi! title: Päivitä yritysversioon - description: Tehosta tuottavuuttasi yritysversiolla + description: What are the benefits? more_info: Lisätietoja additional_features: Muita tehokkaita erikoisominaisuuksia professional_support: Professional support from the OpenProject experts @@ -1850,7 +1851,7 @@ fi: team collaboration with OpenProject. text_show_again: Voit käynnistää tämä videon uudelleen ohjeet-valikosta welcome: Tervetuloa OpenProjectiin - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Lisää muistiinpanoja permission_add_work_packages: Lisää työpaketteja permission_add_messages: Jätä viesti @@ -2204,8 +2205,9 @@ fi: setting_welcome_on_homescreen: Näytä tervehdyspalkki kotinäkymässä setting_wiki_compression: Wiki historian tiivistys setting_work_package_group_assignment: Allow assignment to groups - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Yleinen other: Muut @@ -2215,6 +2217,13 @@ fi: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/fil.yml b/config/locales/crowdin/fil.yml index 63059e07ba..6a3efcc76a 100644 --- a/config/locales/crowdin/fil.yml +++ b/config/locales/crowdin/fil.yml @@ -1067,6 +1067,7 @@ fil: ' error_external_authentication_failed: Isang error ang naganap habang nag-external authentication. Mangyaring subukan ulit. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Naka-edit ang proyekto changeset: Naka-edit ang changeset @@ -1116,7 +1117,7 @@ fil: upsale: become_hero: Maging isang bayani! title: I-upgrade sa Enterprise Edition - description: Palakasin ang itong productivity kasama ang Enterprise Edition + description: What are the benefits? more_info: Karagdagang impornasyon additional_features: Karagdagang tampok ng powerful premium professional_support: Propesyonal na suporta mula sa OpenProject eksperto @@ -1909,7 +1910,7 @@ fil: at pakikipagtulungan ng koponan sa OpenProject. text_show_again: Maari mong i-restart amg video na ito mula sa tulong ng pagpipilian welcome: Maligayang pagdating sa OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Magdagdag ng mga talaan permission_add_work_packages: Magdagdag ng mga work package permission_add_messages: Mga post na mensahe @@ -2293,8 +2294,9 @@ fil: setting_welcome_on_homescreen: I-display ang welcome block sa homescreen setting_wiki_compression: Pag-compress ng wiki na kasaysayan setting_work_package_group_assignment: Pinayagan ang gawain sa mga grupo - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Pangkalahatan other: Iba pa @@ -2304,6 +2306,13 @@ fil: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/fr.yml b/config/locales/crowdin/fr.yml index abca2c9995..100191e068 100644 --- a/config/locales/crowdin/fr.yml +++ b/config/locales/crowdin/fr.yml @@ -400,7 +400,7 @@ fr: mail_notification: Notifications par courriel new_password: Nouveau mot de passe password_confirmation: Confirmation - consented_at: Consented at + consented_at: Consenti à user_preference: comments_sorting: Afficher les commentaires hide_mail: Masquer mon adresse courriel @@ -755,7 +755,7 @@ fr: button_unlock: Déverrouiller button_unwatch: Ne plus suivre button_update: Mettre à jour - button_upgrade: Upgrade + button_upgrade: Mise à niveau button_upload: Charger button_view: Afficher button_watch: Suivre @@ -764,22 +764,25 @@ fr: button_configure_menu_entry: Configurer l'élément de menu button_delete_menu_entry: Supprimer l'élément de menu consent: - checkbox_label: I have noted and do consent to the above. - failure_message: Consent failed, cannot proceed. - title: User Consent - decline_warning_message: You have declined to consent and have been logged out. - user_has_consented: User has consented to your configured statement at the given - time. - not_yet_consented: User has not consented yet, will be requested upon next login. - contact_mail_instructions: Define the mail address that users can reach a data - controller to perform data change or removal requests. - contact_your_administrator: Please contact your administrator if you want to have - your account deleted. - contact_this_mail_address: Please contact %{mail_address} if you want to have - your account deleted. - text_update_consent_time: Check this box to force users to consent again. Enable - when you have changed the legal aspect of the consent information above. - update_consent_last_time: 'Last update of consent: %{update_time}' + checkbox_label: J'ai pris note de ce qui précède et je l'accepte. + failure_message: Échec de l'accord, impossible de continuer. + title: Accord de l'utilisateur + decline_warning_message: Vous avez refusé l'accord et avez été déconnecté. + user_has_consented: L'utilisateur a accepté votre déclaration configurée au moment + donné. + not_yet_consented: L'utilisateur n'a pas encore donné son accord, il sera demandé + lors de la prochaine connexion. + contact_mail_instructions: Définissez l'adresse mail à laquelle les utilisateurs + peuvent joindre un contrôleur de données pour effectuer des modifications de + données ou des demandes de suppression. + contact_your_administrator: Veuillez contacter votre administrateur si vous souhaitez + que votre compte soit supprimé. + contact_this_mail_address: Veuillez contacter %{mail_address} si vous voulez que + votre compte soit supprimé. + text_update_consent_time: Cochez cette case pour forcer les utilisateurs à accepter + à nouveau. Activer le lorsque vous avez modifié l'aspect juridique des informations + de l'accord ci-dessus. + update_consent_last_time: 'Dernière mise à jour de l''accord: %{update_time}' copy_project: started: La copie du projet "%{source_project_name}" vers "%{target_project_name}" a débuté. Vous serez informé par courriel dès que "%{target_project_name}" sera @@ -1007,10 +1010,11 @@ fr: error_cookie_missing: Le cookie OpenProject est manquant. Assurez-vous que les cookies sont activés, sans quoi cette application ne fonctionnera pas correctement. error_custom_option_not_found: L'option n'existe pas. - error_dependent_work_package: 'Error in dependent work package #%{related_id} %{related_subject}: - %{error}' - error_enterprise_activation_user_limit: Your account could not be activated (user - limit reached). Please contact your administrator to gain access. + error_dependent_work_package: 'Erreur dans le lot de travaux dépendants #%{related_id} + %{related_subject}: %{error}' + error_enterprise_activation_user_limit: Votre compte n'a pas pu être activé (limite + d'utilisateurs atteinte). Veuillez contacter votre administrateur pour obtenir + l'accès. error_failed_to_delete_entry: Échec lors de la suppression de cette entrée. error_invalid_selected_value: Valeur sélectionnée invalide. error_invalid_group_by: 'Impossible de grouper par : %{value}' @@ -1057,6 +1061,8 @@ fr: ' error_external_authentication_failed: Une erreur s'est produite lors de l'authentification externe. Veuillez essayer de nouveau. + error_attribute_not_highlightable: 'Attribut(s) ne pouvant pas être mis en surbrillance: + %{attributes}' events: project: Projet édité changeset: Lot de modification édité @@ -1106,7 +1112,7 @@ fr: upsale: become_hero: Devenez un héros ! title: Passer à la version Entreprise - description: Augmentez votre productivité avec la version Entreprise + description: Quels sont les avantages? more_info: Plus d'informations additional_features: Puissantes fonctionnalités premium additionnelles professional_support: Support professionnel d'experts OpenProject @@ -1207,7 +1213,7 @@ fr: label_calendar: Calendrier label_calendar_show: Afficher le calendrier label_category: Catégorie - label_consent_settings: User Consent + label_consent_settings: Accord de l'utilisateur label_wiki_menu_item: Élément de menu wiki label_select_main_menu_item: Sélectionner nouvel élément de menu principal label_select_project: Sélectionner un projet @@ -1296,7 +1302,7 @@ fr: label_enumeration_value: Valeur d'énumération label_enumerations: Énumérations label_enterprise: Entreprise - label_enterprise_active_users: "%{current}/%{limit} booked active users" + label_enterprise_active_users: "%{current}/%{limit} utilisateurs actifs inscrits" label_enterprise_edition: Version Entreprise label_environment: Environement label_estimates_and_time: Estimations et temps @@ -1759,7 +1765,7 @@ fr: à échéance dans les %{days} prochains jours:" mail_body_wiki_content_added: La page wiki '%{id}' a été ajouté par %{author}. mail_body_wiki_content_updated: La page wiki '%{id}' a été mise à jour par %{author}. - mail_subject_account_activation_request: Requête pour l'activation du compte %{value} + mail_subject_account_activation_request: Réquete pour l'activation du compte %{value} mail_subject_lost_password: Votre mot de passe %{value} mail_subject_register: Votre activation du compte %{value} mail_subject_reminder: "%{count} lot(s) de travaux à échéance dans les %{days} prochains @@ -1767,14 +1773,14 @@ fr: mail_subject_wiki_content_added: Page wiki '%{id}' a été ajouté mail_subject_wiki_content_updated: Page wiki '%{id}' a été mise à jour mail_user_activation_limit_reached: - subject: User activation limit reached + subject: Limite d'activation de l'utilisateur atteinte message: | - A new user (%{email}) tried to create an account on an OpenProject environment that you manage (%{host}). - The user cannot activate their account since the user limit has been reached. + Un nouvel utilisateur (%{email}) a essayé de créer un compte sur un environnement OpenProject que vous gérez (%{host}). + L'utilisateur ne peut pas activer son compte puisque la limite d'utilisateurs a été atteinte. steps: - label: 'To allow the user to sign in you can either: ' - a: Upgrade your payment plan ([here](upgrade_url)) - b: Lock or delete an existing user ([here](users_url)) + label: 'Pour permettre à l''utilisateur de se connecter, vous pouvez soit: ' + a: Mettez à jour votre plan de paiement ([here](upgrade_url)) + b: Verrouiller ou supprimer un utilisateur existant ([here](users_url)) more_actions: Plus de fonctions noscript_description: Vous devez activer JavaScript afin d'utiliser OpenProject! noscript_heading: JavaScript désactivé @@ -1897,7 +1903,7 @@ fr: et de la collaboration en équipe avec OpenProject. text_show_again: Vous pouvez relancer cette vidéo au départ du menu d'aide welcome: Bienvenue dans OpenProject - select_language: Veuillez sélectionner votre langue pour OpenProject + select_language: Please select your language permission_add_work_package_notes: Ajouter des notes permission_add_work_packages: Ajouter des lots de travaux permission_add_messages: Poster des messages @@ -2067,7 +2073,7 @@ fr: écrire dans ce dossier.' unauthorized: Vous n'êtes pas autorisé à accéder au dépôt ou les informations d'identification ne sont pas valides. - unavailable: Le dépôt n'est pas disponible. + unavailable: Le dépôt n'est èas disponible. exception_title: 'Ne peut pas accéder au dépôt: %{message}' disabled_or_unknown_type: Le type %{type} sélectionné est désactivé ou n'est plus disponible pour le fournisseur de gestion de contrôle de sources %{vendor}. @@ -2174,10 +2180,10 @@ fr: setting_commit_logtime_activity_id: Activité pour les « Logged Time » setting_commit_logtime_enabled: Activer « time logging » setting_commit_ref_keywords: Referencement des mots clés - setting_consent_time: Consent time - setting_consent_info: Consent information text - setting_consent_required: Consent required - setting_consent_decline_mail: Consent contact mail address + setting_consent_time: Moment de l'accord + setting_consent_info: Texte d'information sur l'accord + setting_consent_required: Accord requis + setting_consent_decline_mail: Adresse mail de contact de l'accord setting_cross_project_work_package_relations: Autoriser les relations entre lots de travaux de projets différents setting_date_format: Format de date @@ -2269,8 +2275,9 @@ fr: setting_welcome_on_homescreen: Afficher le bloc de bienvenue sur l'écran d'accueil setting_wiki_compression: Compression de l'historique du wiki setting_work_package_group_assignment: Autoriser l'assignation à des groupes - setting_work_package_list_default_highlighting_mode: Mode de surlignement des lots - de travaux par défaut + setting_work_package_list_default_highlighting_mode: Mode de surbrillance par défaut + setting_work_package_list_default_highlighted_attributes: Attributs en ligne mis + en surbrillance par défaut settings: general: Général other: Autre @@ -2280,6 +2287,13 @@ fr: user: default_preferences: Préférences par défaut deletion: Suppression + highlighting: + mode_long: + inline: Mettre en surbrillance le(s) attribut(s) en ligne + none: Pas de surlignement + status: Ligne entière par Statut + type: Ligne entière par Type + priority: Ligne entière par Priorité text_formatting: markdown: Markdown plain: Texte brut @@ -2629,7 +2643,7 @@ fr: quarters: Trimestres years: Années title_remove_and_delete_user: Retirer du projet l'utilisateur invité et le supprimer. - title_enterprise_upgrade: Upgrade to unlock more users. + title_enterprise_upgrade: Mettre à niveau pour débloquer plus d'utilisateurs. tooltip_user_default_timezone: 'Fuseau horaire par défaut des nouveaux utilisateurs. Il peut-être modifié dans les paramètres utilisateur. @@ -2705,10 +2719,11 @@ fr: par %{configuration}. warning: Attention warning_attachments_not_saved: "%{count} fichier(s) n'ont pu être sauvegardés." - warning_imminent_user_limit: 'You invited more users than are supported by your - current plan. Invited users may not be able to join your OpenProject environment. - Please
    upgrade your plan or block existing users - in order to allow invited and registered users to join. + warning_imminent_user_limit: 'Vous avez invité plus d''utilisateurs que ce qui est + prévu dans votre plan actuel. Les utilisateurs invités peuvent ne pas être en + mesure de rejoindre votre environnement OpenProject. Veuillez mettre + à jour votre plan ou bloquer les utilisateurs existants afin de permettre + aux utilisateurs invités et enregistrés de rejoindre votre environnement. ' warning_registration_token_expired: 'L’émail d’activation a expiré. Nous vous avons @@ -2716,14 +2731,14 @@ fr: activer votre compte. ' - warning_user_limit_reached: 'User limit reached. You cannot activate any more users. - Please upgrade your plan or block members to allow - for additional users. + warning_user_limit_reached: 'Limite d''utilisateur atteinte. Vous ne pouvez plus + activer d''autres utilisateurs. Veuillez mettre à jour + votre plan ou bloquez des membres pour permettre d''autres utilisateurs. ' - warning_user_limit_reached_instructions: 'You reached your user limit (%{current}/%{max} - active users). Please contact sales@openproject.com to upgrade your Enterprise - Edition plan and add additional users. + warning_user_limit_reached_instructions: 'Vous avez atteint votre limite d''utilisateurs + (%{current}/%{max} utilisateurs actifs). Veuillez contacter sales@openproject.com + pour mettre à jour votre plan Enterprise Edition et ajouter des utilisateurs supplémentaires. ' menu_item: Éléments de menu diff --git a/config/locales/crowdin/he.yml b/config/locales/crowdin/he.yml index 59d94e2370..4bdbfea8ca 100644 --- a/config/locales/crowdin/he.yml +++ b/config/locales/crowdin/he.yml @@ -1052,6 +1052,7 @@ he: ' error_external_authentication_failed: אירעה שגיאה בעת אימות חיצוני. נא נסה שוב. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: הפרויקט נערך changeset: אוסף שינוים נערך @@ -1101,7 +1102,7 @@ he: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1886,7 +1887,7 @@ he: team collaboration with OpenProject. text_show_again: You can restart this video from the help menu welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: הוסף הערות permission_add_work_packages: Add work packages permission_add_messages: Post messages @@ -2241,8 +2242,9 @@ he: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Wiki history compression setting_work_package_group_assignment: Allow assignment to groups - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: כללי other: אחר @@ -2252,6 +2254,13 @@ he: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/hi.yml b/config/locales/crowdin/hi.yml index b8e77fc790..90eec867f3 100644 --- a/config/locales/crowdin/hi.yml +++ b/config/locales/crowdin/hi.yml @@ -1034,6 +1034,7 @@ hi: ' error_external_authentication_failed: An error occured during external authentication. Please try again. + error_attribute_not_highlightable: 'गुण हाइलाइट नहीं करने लायक: %{attributes}' events: project: Project edited changeset: Changeset edited @@ -1083,7 +1084,7 @@ hi: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: लाभ क्या हैं? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1857,7 +1858,7 @@ hi: team collaboration with OpenProject. text_show_again: You can restart this video from the help menu welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Add notes permission_add_work_packages: Add work packages permission_add_messages: Post messages @@ -2212,8 +2213,9 @@ hi: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Wiki history compression setting_work_package_group_assignment: Allow assignment to groups - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: डिफ़ॉल्ट हाइलाइटिंग तरीका + setting_work_package_list_default_highlighted_attributes: डिफ़ॉल्ट पंक्ति ही में + हाइलाइट किए गए गुण settings: general: सामान्य other: अन्य @@ -2223,6 +2225,13 @@ hi: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: पंक्ति ही में गुण / गुणों को हाइलाइट करें + none: हाइलाइट नहीं है + status: स्थिति के अनुसार संपूर्ण पंक्ति + type: प्रकार के अनुसार संपूर्ण पंक्ति + priority: प्राथमिकता के अनुसार संपूर्ण पंक्ति text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/hr.yml b/config/locales/crowdin/hr.yml index e628c83fa5..a797acb373 100644 --- a/config/locales/crowdin/hr.yml +++ b/config/locales/crowdin/hr.yml @@ -1051,6 +1051,7 @@ hr: ' error_external_authentication_failed: Došlo je do greške tijekom izvođenja vanjske autentifikacije. Molim vas pokušajte opet. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projekt je uređivan changeset: Changeset uređen @@ -1100,7 +1101,7 @@ hr: upsale: become_hero: Postati heroj! title: Nadogradnja na izdanje Enterprise - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: Više informacija additional_features: Additional powerful premium features professional_support: Stručna podrška OpenProject stručnjaka @@ -1891,7 +1892,7 @@ hr: team collaboration with OpenProject. text_show_again: You can restart this video from the help menu welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Dodaj bilješke permission_add_work_packages: Dodaj radne pakete permission_add_messages: Pošalji poruke @@ -2250,8 +2251,9 @@ hr: setting_welcome_on_homescreen: Prikaži tekst dobrodošlice na početnoj stranici setting_wiki_compression: Kompresija Wiki povijesti setting_work_package_group_assignment: Allow assignment to groups - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Općenito other: Ostalo @@ -2261,6 +2263,13 @@ hr: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/hu.yml b/config/locales/crowdin/hu.yml index 515ac280ad..319b6cd80a 100644 --- a/config/locales/crowdin/hu.yml +++ b/config/locales/crowdin/hu.yml @@ -1037,6 +1037,7 @@ hu: ' error_external_authentication_failed: Hiba történt a külső hitelesítés során. Kérjük, próbálja meg újra. + error_attribute_not_highlightable: 'Tulajdonság(ok) nem kiemelhetők: %{attributes}' events: project: Projekt szerkesztve changeset: Commit szerkesztve @@ -1086,7 +1087,7 @@ hu: upsale: become_hero: Legyél egy hős! title: Frissítés a Vállalati Verzióra - description: Növeld a termelékenységedet a vállalati kiadással + description: Milyen előnyökkel jár? more_info: További információ additional_features: További erőteljes prémium funkciók professional_support: Professzionális támogatás az OpenProject szakértőktől @@ -1871,7 +1872,7 @@ hu: csapatmunkáról az OpenProjecttel. text_show_again: Újra tudod indítani ezt a videót a segítség menüből welcome: Üdvözöl az OpenProject - select_language: Kérjük, válassza ki az OpenProject nyelvét + select_language: Please select your language permission_add_work_package_notes: Megjegyzések hozzáadása permission_add_work_packages: feladatcsoport hozzáadása permission_add_messages: Elküldött üzenetek @@ -2227,8 +2228,9 @@ hu: setting_welcome_on_homescreen: Üdvözlő blokk megjelenítése a kezdőképernyőn setting_wiki_compression: Wiki előzmények tömörítése setting_work_package_group_assignment: Hozzárendelés engedélyezése csoportokhoz - setting_work_package_list_default_highlighting_mode: Alapértelmezett feladatcsoport - kiemelés mód + setting_work_package_list_default_highlighting_mode: Alapértelmezett kiemelési mód + setting_work_package_list_default_highlighted_attributes: Alapértelmezett kiemelt + attribútumok sorai settings: general: Általános other: Egyéb @@ -2238,6 +2240,13 @@ hu: user: default_preferences: Alapértelmezett preferenciák deletion: Törlés + highlighting: + mode_long: + inline: Kiemelt attribútum(ok) egy vonalban + none: Kiemelés nélkül + status: Teljes sor állapot szerint + type: Teljes sor típus szerint + priority: Teljes sor prioritás szerint text_formatting: markdown: Markdown plain: Egyszerű szöveg diff --git a/config/locales/crowdin/id.yml b/config/locales/crowdin/id.yml index 9d942b5f82..70303554b8 100644 --- a/config/locales/crowdin/id.yml +++ b/config/locales/crowdin/id.yml @@ -1027,6 +1027,7 @@ id: ' error_external_authentication_failed: Error selama otentikasi eksternal. Silakan coba lagi. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Project edited changeset: Set-Perubahan telah diedit @@ -1076,7 +1077,7 @@ id: upsale: become_hero: Menjadi seorang pahlawan! title: Tingkatkan ke edisi enterprise - description: Tingkatkan produktivitas Anda dengan Edisi Perusahaan + description: What are the benefits? more_info: Informasi lebih lanjut additional_features: Tambahan fitur premium yang sangat berdaya guna professional_support: Dukungan profesional dari para ahli OpenProject @@ -1849,7 +1850,7 @@ id: proyek dan tim kolaborasi bersama OpenProject. text_show_again: You can restart this video from the help menu welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Tambahkan catatan permission_add_work_packages: Tambah Paket-Penugasan permission_add_messages: Kirim pesan @@ -2203,8 +2204,9 @@ id: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Kompresi Wiki histori setting_work_package_group_assignment: Mungkinkan penugasan ke Grup - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Umum other: Lainnya @@ -2214,6 +2216,13 @@ id: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/it.yml b/config/locales/crowdin/it.yml index 3054d17da6..4811e66b49 100644 --- a/config/locales/crowdin/it.yml +++ b/config/locales/crowdin/it.yml @@ -1052,6 +1052,7 @@ it: ' error_external_authentication_failed: Si è verificato un errore durante l'autenticazione esterna. Per favore riprova. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Progetto modificato changeset: Changeset modificato @@ -1101,7 +1102,7 @@ it: upsale: become_hero: Diventa un eroe! title: Aggiorna ad Enterprise Edition - description: Incrementa la tua produttività con l'Enterprise Edition + description: What are the benefits? more_info: Altre informazioni additional_features: Funzionalità aggiuntive speciali professional_support: Assistenza professionale da parte degli esperti OpenProject @@ -1894,7 +1895,7 @@ it: e il lavoro di squadra in OpenProject. text_show_again: È possibile riavviare questo video dal menu Guida welcome: Benvenuto in OpenProject - select_language: Seleziona la lingua di OpenProject + select_language: Please select your language permission_add_work_package_notes: Aggiungi nota permission_add_work_packages: Aggiungere macro-attività (work package) permission_add_messages: Postare messaggi @@ -2280,8 +2281,9 @@ it: home setting_wiki_compression: Compressione del registro della wiki setting_work_package_group_assignment: Consentire l'assegnazione ai gruppi - setting_work_package_list_default_highlighting_mode: Modalità di evidenziazione - predefinita per le macro-attività + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Generale other: Altro @@ -2291,6 +2293,13 @@ it: user: default_preferences: Preferenze predefinite deletion: Eliminazione + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: Non evidenziare + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Testo semplice diff --git a/config/locales/crowdin/ja.yml b/config/locales/crowdin/ja.yml index 7d3bd97890..39a279a279 100644 --- a/config/locales/crowdin/ja.yml +++ b/config/locales/crowdin/ja.yml @@ -944,6 +944,7 @@ ja: ' error_external_authentication_failed: 外部認証中にエラーが発生しました。もう一度やり直してください。 + error_attribute_not_highlightable: '強調表示されない属性: %{attributes}' events: project: プロジェクトが編集されました。 changeset: 変更セットが編集されました。 @@ -993,7 +994,7 @@ ja: upsale: become_hero: ヒーローになる! title: エンタープライズ版にアップグレード - description: エンタープライズ版で生産性を向上します + description: メリットは何ですか? more_info: 詳細情報 additional_features: 強力なプレミアム機能 professional_support: OpenProject のエキスパートからのプロフェッショナル サポート @@ -1724,7 +1725,7 @@ ja: text_getting_started_description: OpenProject のプロジェクト管理とチームコラボレーションの簡単な概要を取得します。 text_show_again: ヘルプメニューからこのビデオを再度開始することができます。 welcome: OpenProjectへようこそ - select_language: OpenProjectの言語を選択してください + select_language: Please select your language permission_add_work_package_notes: 注記の追加 permission_add_work_packages: 作業項目の追加 permission_add_messages: メッセージの投稿 @@ -2043,7 +2044,8 @@ ja: setting_welcome_on_homescreen: ホーム画面にようこそブロックを表示 setting_wiki_compression: Wiki履歴を圧縮する setting_work_package_group_assignment: グループへの割り当てを許可する - setting_work_package_list_default_highlighting_mode: デフォルト作業項目のハイライトモード + setting_work_package_list_default_highlighting_mode: デフォルトの強調表示モード + setting_work_package_list_default_highlighted_attributes: デフォルトのインライン強調表示属性 settings: general: 概要 other: その他 @@ -2053,6 +2055,13 @@ ja: user: default_preferences: デフォルト設定 deletion: 削除 + highlighting: + mode_long: + inline: 属性をインラインで強調表示する + none: ハイライトなし + status: ステータス別の行全体 + type: タイプごとの行全体 + priority: 優先度別に行全体 text_formatting: markdown: Markdown plain: プレーンテキスト diff --git a/config/locales/crowdin/js-af.yml b/config/locales/crowdin/js-af.yml index aa08d2cbb9..dc25ca6082 100644 --- a/config/locales/crowdin/js-af.yml +++ b/config/locales/crowdin/js-af.yml @@ -107,6 +107,10 @@ af: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: 'on' + current_date: Current date error: internal: An internal error has occurred. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -470,6 +474,8 @@ af: to Microsoft Edge. learn_more: Learn more close_warning: Ignore this warning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Strong italic: Italic @@ -647,14 +653,15 @@ af: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Status priority: Prioriteit + type: Soort columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-ar.yml b/config/locales/crowdin/js-ar.yml index 3b229c3b82..405d669fdb 100644 --- a/config/locales/crowdin/js-ar.yml +++ b/config/locales/crowdin/js-ar.yml @@ -107,6 +107,10 @@ ar: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: في + current_date: Current date error: internal: حدث خطأ داخلي. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -469,6 +473,8 @@ ar: إلى مايكروسوفت إدج. learn_more: التعرف على المزيد close_warning: تجاهل هذا التحذير. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: قوي italic: مائل @@ -645,14 +651,15 @@ ar: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: الحالة priority: الأولوية + type: النّوع columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-bg.yml b/config/locales/crowdin/js-bg.yml index abda9a4ca7..cafaee05fc 100644 --- a/config/locales/crowdin/js-bg.yml +++ b/config/locales/crowdin/js-bg.yml @@ -107,6 +107,10 @@ bg: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: на + current_date: Current date error: internal: Възникна вътрешна грешка. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -472,6 +476,8 @@ bg: to Microsoft Edge. learn_more: Научете повече close_warning: Ignore this warning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Главни букви italic: Наклонени букви @@ -650,14 +656,15 @@ bg: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Състояние priority: Приоритет + type: Тип columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-ca.yml b/config/locales/crowdin/js-ca.yml index a02639b215..c30d31ec1e 100644 --- a/config/locales/crowdin/js-ca.yml +++ b/config/locales/crowdin/js-ca.yml @@ -107,6 +107,10 @@ ca: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: en + current_date: Current date error: internal: S'ha produït un error intern. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -473,6 +477,8 @@ ca: to Microsoft Edge. learn_more: Saber-ne més close_warning: Ignore this warning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Fort italic: Cursiva @@ -652,14 +658,15 @@ ca: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Estat priority: Prioritat + type: Tipus columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-cs.yml b/config/locales/crowdin/js-cs.yml index c9af5dc692..d595c25632 100644 --- a/config/locales/crowdin/js-cs.yml +++ b/config/locales/crowdin/js-cs.yml @@ -107,6 +107,10 @@ cs: embedded_table: button: Vložit tabulku pracovního balíčku text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: 'on' + current_date: Current date error: internal: Došlo k vnitřní chybě. cannot_save_changes_with_message: 'Nelze uložit změny kvůli následující chybě: @@ -474,6 +478,8 @@ cs: upgradujte na Microsoft Edge. learn_more: Více informací close_warning: Ignorovat toto upozornění. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Strong italic: Italic @@ -652,14 +658,15 @@ cs: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Stav priority: Priorita + type: Typ columns_help_text: Použijte vstup výše pro přidání nebo odebrání sloupců do tabulkového pohledu. Přetažením sloupců změníte jejich pořadí. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-da.yml b/config/locales/crowdin/js-da.yml index 80d05b527b..1a57be2e5b 100644 --- a/config/locales/crowdin/js-da.yml +++ b/config/locales/crowdin/js-da.yml @@ -107,6 +107,10 @@ da: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: på + current_date: Current date error: internal: En intern fejl opstod. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -468,6 +472,8 @@ da: to Microsoft Edge. learn_more: Få mere at vide close_warning: Ignore this warning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Fed italic: Kursiv @@ -645,14 +651,15 @@ da: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Status priority: Prioritet + type: Type columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-de.yml b/config/locales/crowdin/js-de.yml index 3c28b7169e..73612214ed 100644 --- a/config/locales/crowdin/js-de.yml +++ b/config/locales/crowdin/js-de.yml @@ -112,6 +112,10 @@ de: embedded_table: button: Arbeitspaket-Tabelle einbetten text: "[Platzhalter] Eingebette Arbeitspaket-Tabelle" + custom_actions: + date: + specific: am + current_date: Aktuelles Datum error: internal: Ein interner Fehler ist aufgetreten. cannot_save_changes_with_message: 'Ihre Änderungen können nicht gespeichert @@ -481,6 +485,8 @@ de: führen ein Upgrade auf Microsoft Edge durch. learn_more: Weitere Informationen close_warning: Diese Warnung ignorieren. + upsale: + ee_only: Enterprise-Edition Feature wiki_formatting: strong: Fett italic: Kursiv @@ -664,15 +670,16 @@ de: highlighting_mode: description: Farbliche Hervorherbung none: Keine Hervorhebung - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Hervorgehobene Attribute + inline_all: Alle Attribute entire_row_by: Gesamte Zeile durch status: Status priority: Priorität + type: Typ columns_help_text: Verwenden Sie die Eingabe oben um Spalten zur Tabellenansicht hinzuzufügen oder zu entfernen. Sie können die Reihenfolge der Spalten über Drag & Drop verändern. upsale: - ee_only: Enterprise-Edition Feature attribute_highlighting: Sollen bestimmte Arbeitspakete aus der Menge herausstechen? relation_columns: Möchten Sie Zusammenhänge in der Arbeitspaketliste anzeigen? check_out_link: Testen Sie die Enterprise Edition. @@ -710,7 +717,7 @@ de: modals: label_settings: Ansicht umbenennen label_name: Name - label_delete_page: Aktuelle Ansicht löschen + label_delete_page: Aktuelle Seite löschen button_apply: Anwenden button_save: Speichern button_submit: OK diff --git a/config/locales/crowdin/js-es.yml b/config/locales/crowdin/js-es.yml index dfa4d72f57..278bfd7f88 100644 --- a/config/locales/crowdin/js-es.yml +++ b/config/locales/crowdin/js-es.yml @@ -109,6 +109,10 @@ es: embedded_table: button: Insertar tabla de paquetes de trabajo text: "[Placeholder] Tabla de paquetes de trabajo insertada" + custom_actions: + date: + specific: en + current_date: Current date error: internal: Ha ocurrido un error interno. cannot_save_changes_with_message: 'No se pueden guardar los cambios debido al @@ -477,6 +481,8 @@ es: a Microsoft Edge. learn_more: Saber más close_warning: Ignore esta advertencia. + upsale: + ee_only: Característica exclusiva de Enterprise Edition wiki_formatting: strong: Negrita italic: Cursiva @@ -657,15 +663,16 @@ es: highlighting_mode: description: Resaltar con color none: Sin resaltado - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Toda la fila por status: Estado priority: Prioridad + type: Tipo columns_help_text: Use los datos anteriores para agregar o quitar columnas de la vista de tabla. Puede arrastrar y colocar las columnas para cambiar el orden. upsale: - ee_only: Característica exclusiva de Enterprise Edition attribute_highlighting: "¿Necesita que algunos paquetes de trabajo destaquen del resto?" relation_columns: "¿Necesita ver las relaciones en la lista del paquete diff --git a/config/locales/crowdin/js-et.yml b/config/locales/crowdin/js-et.yml index fa0d9b61d0..05079eb4db 100644 --- a/config/locales/crowdin/js-et.yml +++ b/config/locales/crowdin/js-et.yml @@ -107,6 +107,10 @@ et: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: 'on' + current_date: Current date error: internal: An internal error has occurred. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -470,6 +474,8 @@ et: to Microsoft Edge. learn_more: Loe rohkem close_warning: Ignore this warning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Strong italic: Krusiiv @@ -648,14 +654,15 @@ et: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Olek priority: Prioriteet + type: Liik columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-fa.yml b/config/locales/crowdin/js-fa.yml index 77d698a148..29aead0dc9 100644 --- a/config/locales/crowdin/js-fa.yml +++ b/config/locales/crowdin/js-fa.yml @@ -107,6 +107,10 @@ fa: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: برخط + current_date: Current date error: internal: An internal error has occurred. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -472,6 +476,8 @@ fa: to Microsoft Edge. learn_more: Learn more close_warning: Ignore this warning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: ضخیم italic: مورب @@ -650,14 +656,15 @@ fa: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Status priority: اولويت + type: نوع columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: آیا نیاز به مشاهده روابط در بسته کاری را دارید؟ diff --git a/config/locales/crowdin/js-fi.yml b/config/locales/crowdin/js-fi.yml index 91077bc58a..5f8cf7163f 100644 --- a/config/locales/crowdin/js-fi.yml +++ b/config/locales/crowdin/js-fi.yml @@ -107,6 +107,10 @@ fi: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: päälle + current_date: Current date error: internal: Tapahtui sisäinen virhe. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -468,6 +472,8 @@ fi: Microsoft Edge. learn_more: Learn more close_warning: Ohita tämä varoitus. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Lihavoitu italic: Kursivoitu @@ -643,14 +649,15 @@ fi: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Tila priority: Tärkeys + type: Tyyppi columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Täytyy nähdä suhteet toimia paketti lista? diff --git a/config/locales/crowdin/js-fil.yml b/config/locales/crowdin/js-fil.yml index 371acb13c0..52e6c0c9b0 100644 --- a/config/locales/crowdin/js-fil.yml +++ b/config/locales/crowdin/js-fil.yml @@ -107,6 +107,10 @@ fil: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: sa + current_date: Current date error: internal: Isang internal error ang naganap. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -477,6 +481,8 @@ fil: sa Microsoft Edge. learn_more: Matuto ng higit pa close_warning: Huwag pansinin ang babala ito. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Malakas italic: Italic @@ -661,14 +667,15 @@ fil: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Estado priority: Ang prayoridad + type: Uri columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Kailangan tingnan ang mga relasyon sa listahan ng work diff --git a/config/locales/crowdin/js-fr.yml b/config/locales/crowdin/js-fr.yml index 2949eb0acf..52281a73b1 100644 --- a/config/locales/crowdin/js-fr.yml +++ b/config/locales/crowdin/js-fr.yml @@ -110,6 +110,10 @@ fr: embedded_table: button: Intégrer le tableau du lot de travaux text: "[Placeholder] Tableau du lot de travaux intégré" + custom_actions: + date: + specific: le + current_date: Date actuelle error: internal: Une erreur interne s'est produite. cannot_save_changes_with_message: 'Impossible d’enregistrer vos modifications @@ -481,6 +485,8 @@ fr: à niveau vers Microsoft Edge. learn_more: En savoir plus close_warning: Ignorer cet avertissement. + upsale: + ee_only: Fonctionnalité exclusive Version Entreprise wiki_formatting: strong: Gras italic: Italique @@ -663,15 +669,16 @@ fr: highlighting_mode: description: Surligner avec de la couleur none: Pas de surlignement - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Attribut(s) en surbrillance + inline_all: Tous les attributs entire_row_by: Ligne entière par status: Statut priority: Priorité + type: Type columns_help_text: Utilisez l’entrée ci-dessus pour ajouter ou supprimer des colonnes à votre vue du tableau. Vous pouvez déplacer les colonnes par glisser/déposer pour les réorganiser. upsale: - ee_only: Fonctionnalité exclusive Version Entreprise attribute_highlighting: Vous avez besoin de lots de travaux qui sortent du lot ? relation_columns: Besoin de voir les relations sur la liste des lots de diff --git a/config/locales/crowdin/js-he.yml b/config/locales/crowdin/js-he.yml index 0f5f498da7..662ea1d748 100644 --- a/config/locales/crowdin/js-he.yml +++ b/config/locales/crowdin/js-he.yml @@ -107,6 +107,10 @@ he: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: פועל + current_date: Current date error: internal: An internal error has occurred. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -473,6 +477,8 @@ he: to Microsoft Edge. learn_more: למידע נוסף close_warning: Ignore this warning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: חזק italic: נטוי קו @@ -650,14 +656,15 @@ he: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: מצב priority: עדיפות + type: סוג columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-hi.yml b/config/locales/crowdin/js-hi.yml index dbcbae4107..6100762087 100644 --- a/config/locales/crowdin/js-hi.yml +++ b/config/locales/crowdin/js-hi.yml @@ -107,6 +107,10 @@ hi: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: पर + current_date: वर्तमान दिनांक error: internal: An internal error has occurred. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -471,6 +475,8 @@ hi: to Microsoft Edge. learn_more: Learn more close_warning: Ignore this warning. + upsale: + ee_only: केवल एंटरप्राइज संस्करण में सुविधा wiki_formatting: strong: Strong italic: Italic @@ -650,14 +656,15 @@ hi: highlighting_mode: description: रंग से हाइलाइट करें none: हाइलाइट नहीं है - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: हाइलाइट की गई विशेषता (यां) + inline_all: सभी गुण entire_row_by: प्रकार के अनुसार संपूर्ण पंक्ति status: अवस्था priority: वरीयता + type: प्रकार columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: केवल एंटरप्राइज संस्करण में सुविधा attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-hr.yml b/config/locales/crowdin/js-hr.yml index e6d49e8c33..75c46bec19 100644 --- a/config/locales/crowdin/js-hr.yml +++ b/config/locales/crowdin/js-hr.yml @@ -107,6 +107,10 @@ hr: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: na + current_date: Current date error: internal: Dogodila se interna greška. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -472,6 +476,8 @@ hr: to Microsoft Edge. learn_more: Saznaj više close_warning: Ignorirati ovo upozorenje. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Strong italic: Italic @@ -650,14 +656,15 @@ hr: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Status priority: Prioritet + type: Tip columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-hu.yml b/config/locales/crowdin/js-hu.yml index 31ad5676b3..ae146f646d 100644 --- a/config/locales/crowdin/js-hu.yml +++ b/config/locales/crowdin/js-hu.yml @@ -108,6 +108,10 @@ hu: embedded_table: button: Munkacsomag táblázat beágyazás text: "[Placeholder] Beágyazott munkacsomag táblázat" + custom_actions: + date: + specific: be + current_date: Current date error: internal: Belső hiba történt. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -470,6 +474,8 @@ hu: vagy Microsoft Edge-re. learn_more: További információ close_warning: Figyelmeztetés figyelmen kívül hagyása. + upsale: + ee_only: Ez csak az Enterprise Edition-ban elérhető wiki_formatting: strong: Erős italic: Dőlt betű @@ -648,14 +654,15 @@ hu: highlighting_mode: description: Kiemelés szinnel none: Kiemelés nélkül - inline: Lejárt dátumok, a "Státusz", "Típus" és "Prioritás" attribútummal + inline: Kiemelt attribútum(ok) + inline_all: Attribútumok entire_row_by: Egész sor alapján status: Állapot priority: Fontosság + type: Típus columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Ez csak az Enterprise Edition-ban elérhető attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Szeretné látni a munkacsomag kapcsolatait? diff --git a/config/locales/crowdin/js-id.yml b/config/locales/crowdin/js-id.yml index 1dbc043a7f..4f36d9a593 100644 --- a/config/locales/crowdin/js-id.yml +++ b/config/locales/crowdin/js-id.yml @@ -107,6 +107,10 @@ id: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: pada + current_date: Current date error: internal: An internal error has occurred. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -470,6 +474,8 @@ id: Edge. learn_more: Pelajari lebih lanjut close_warning: Abaikan peringatan ini. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Tebal italic: Miring @@ -648,14 +654,15 @@ id: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Status priority: Prioritas + type: Tipe columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Apakah perlu untuk melihat hubungan dalam daftar paker diff --git a/config/locales/crowdin/js-it.yml b/config/locales/crowdin/js-it.yml index ba44516c69..18eaa0dc37 100644 --- a/config/locales/crowdin/js-it.yml +++ b/config/locales/crowdin/js-it.yml @@ -109,6 +109,10 @@ it: embedded_table: button: Incorpora la tabella della macro-attività text: "[Placeholder] Tabella della macro-attività incorporata" + custom_actions: + date: + specific: il + current_date: Current date error: internal: Si è verificato un errore interno. cannot_save_changes_with_message: 'Impossibile salvare le modifiche a causa @@ -476,6 +480,8 @@ it: a Microsoft Edge. learn_more: Scopri di più close_warning: Ignora questo avviso. + upsale: + ee_only: Funzionalità esclusiva della Versione Enterprise wiki_formatting: strong: Grassetto italic: Corsivo @@ -657,15 +663,16 @@ it: highlighting_mode: description: Evidenzia con colore none: Non evidenziare - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Tutta la riga per status: Stato priority: Priorità + type: Tipo columns_help_text: Utilizza l'input sopra per aggiungere o rimuovere colonne alla visualizzazione della tabella. È possibile trascinare e rilasciare le colonne per riordinarle. upsale: - ee_only: Funzionalità esclusiva della Versione Enterprise attribute_highlighting: Vuoi che alcune macro-attività si distinguano dalla massa? relation_columns: Vuoi visualizzare le relazioni nell'elenco di macro-attività? diff --git a/config/locales/crowdin/js-ja.yml b/config/locales/crowdin/js-ja.yml index be72a2d316..7a1b811ef6 100644 --- a/config/locales/crowdin/js-ja.yml +++ b/config/locales/crowdin/js-ja.yml @@ -101,6 +101,10 @@ ja: embedded_table: button: 作業項目表を埋め込む text: "[Placeholder] 埋め込まれた作業項目表" + custom_actions: + date: + specific: オン + current_date: 現在の日付 error: internal: 内部エラーが発生しました。 cannot_save_changes_with_message: '次のエラーのために変更を保存できません: %{error}' @@ -441,6 +445,8 @@ ja: update_ie_user: Mozilla FirefoxまたはGoogle Chromeに切り替えるか、Microsoft Edgeにアップグレードしてください。 learn_more: もっと詳しく close_warning: この警告を無視する。 + upsale: + ee_only: Enterprise Editionのみの機能 wiki_formatting: strong: 強調 italic: 斜体字 @@ -601,13 +607,14 @@ ja: highlighting_mode: description: 色付きでハイライト none: ハイライトなし - inline: 期限切れ日付、「状態」、「タイプ」、「優先度」の属性 + inline: 強調表示された属性 + inline_all: 全ての属性 entire_row_by: 全体の行 status: ステータス priority: 優先度 + type: 種別 columns_help_text: テーブルビューに列を追加または削除するには上記の入力を使用します。列をドラッグ&ドロップして並べ替えることができます。 upsale: - ee_only: Enterprise Editionのみの機能 attribute_highlighting: 全体から目立つように特定の作業項目が必要ですか? relation_columns: ワークパッケージリストに関係を表示する必要がありますか? check_out_link: エンタープライズ版をチェックしてください。 diff --git a/config/locales/crowdin/js-ko.yml b/config/locales/crowdin/js-ko.yml index e620d91c12..ea18c728ef 100644 --- a/config/locales/crowdin/js-ko.yml +++ b/config/locales/crowdin/js-ko.yml @@ -103,6 +103,10 @@ ko: embedded_table: button: 작업 패키지 테이블 포함 text: "[Placeholder] 포함 작업 패키지 테이블" + custom_actions: + date: + specific: 에 + current_date: Current date error: internal: 내부 오류가 발생하였습니다. cannot_save_changes_with_message: '다음 오류로 인해 변경 사항을 저장할 수 없습니다: %{error}' @@ -447,6 +451,8 @@ ko: update_ie_user: Mozilla Firefox 또는 Google Chrome으로 전환하거나, Microsoft Edge로 업그레이드하십시오. learn_more: 자세히 알아보기 close_warning: 이 경고를 무시하십시오. + upsale: + ee_only: Enterprise Edition 전용 기능 wiki_formatting: strong: 굵게 italic: 기울임꼴 @@ -608,13 +614,14 @@ ko: highlighting_mode: description: 색상으로 강조 표시 none: 강조 표시 없음 - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: 전체 행 기준 status: 상태 priority: 우선 순위 + type: 타입 columns_help_text: 위 입력을 사용하여 테이블 보기에 열을 추가하거나 제거하세요. 열을 끌어다 놓아 순서를 바꿀 수 있습니다. upsale: - ee_only: Enterprise Edition 전용 기능 attribute_highlighting: 나머지 작업 중에 확연히 두드러지는 특정 작업 패키지가 필요합니까? relation_columns: 작업 패키지 목록에서 관계를 표시해야 합니까? check_out_link: Enterprise Edition을 체크아웃하세요. diff --git a/config/locales/crowdin/js-lol.yml b/config/locales/crowdin/js-lol.yml index c927679b14..ab5b087960 100644 --- a/config/locales/crowdin/js-lol.yml +++ b/config/locales/crowdin/js-lol.yml @@ -2,698 +2,705 @@ lol: js: ajax: - hide: crwdns98333:0crwdne98333:0 - loading: crwdns98334:0crwdne98334:0 + hide: crwdns101434:0crwdne101434:0 + loading: crwdns101435:0crwdne101435:0 attachments: - draggable_hint: 'crwdns99081:0crwdne99081:0 + draggable_hint: 'crwdns101436:0crwdne101436:0 ' autocomplete_select: placeholder: - multi: crwdns98881:0%{name}crwdne98881:0 - single: crwdns98882:0%{name}crwdne98882:0 - remove: crwdns98883:0%{name}crwdne98883:0 - active: crwdns98884:0%{label}crwdnd98884:0%{name}crwdne98884:0 - close_popup_title: crwdns98335:0crwdne98335:0 - close_filter_title: crwdns98336:0crwdne98336:0 - close_form_title: crwdns98337:0crwdne98337:0 + multi: crwdns101437:0%{name}crwdne101437:0 + single: crwdns101438:0%{name}crwdne101438:0 + remove: crwdns101439:0%{name}crwdne101439:0 + active: crwdns101440:0%{label}crwdnd101440:0%{name}crwdne101440:0 + close_popup_title: crwdns101441:0crwdne101441:0 + close_filter_title: crwdns101442:0crwdne101442:0 + close_form_title: crwdns101443:0crwdne101443:0 clipboard: - browser_error: crwdns98338:0crwdne98338:0 - copied_successful: crwdns98339:0crwdne98339:0 - button_add_watcher: crwdns98340:0crwdne98340:0 - button_back_to_list_view: crwdns98341:0crwdne98341:0 - button_cancel: crwdns98342:0crwdne98342:0 - button_close: crwdns98343:0crwdne98343:0 - button_check_all: crwdns98344:0crwdne98344:0 - button_configure-form: crwdns98345:0crwdne98345:0 - button_confirm: crwdns98346:0crwdne98346:0 - button_continue: crwdns98347:0crwdne98347:0 - button_copy: crwdns98348:0crwdne98348:0 - button_custom-fields: crwdns98349:0crwdne98349:0 - button_delete: crwdns98350:0crwdne98350:0 - button_delete_watcher: crwdns98351:0crwdne98351:0 - button_details_view: crwdns98352:0crwdne98352:0 - button_duplicate: crwdns98353:0crwdne98353:0 - button_edit: crwdns98354:0crwdne98354:0 - button_filter: crwdns98355:0crwdne98355:0 - button_list_view: crwdns98356:0crwdne98356:0 - button_show_view: crwdns98357:0crwdne98357:0 - button_log_time: crwdns98358:0crwdne98358:0 - button_more: crwdns98359:0crwdne98359:0 - button_move: crwdns98360:0crwdne98360:0 - button_open_details: crwdns98361:0crwdne98361:0 - button_close_details: crwdns98362:0crwdne98362:0 - button_open_fullscreen: crwdns98363:0crwdne98363:0 - button_quote: crwdns98364:0crwdne98364:0 - button_save: crwdns98365:0crwdne98365:0 - button_settings: crwdns98366:0crwdne98366:0 - button_uncheck_all: crwdns98367:0crwdne98367:0 - button_update: crwdns98368:0crwdne98368:0 - button_export-pdf: crwdns98369:0crwdne98369:0 - button_export-atom: crwdns98370:0crwdne98370:0 - description_available_columns: crwdns98371:0crwdne98371:0 - description_current_position: crwdns98372:0crwdne98372:0 - description_select_work_package: crwdns98373:0%{id}crwdne98373:0 - description_selected_columns: crwdns98374:0crwdne98374:0 - description_subwork_package: crwdns98375:0%{id}crwdne98375:0 + browser_error: crwdns101444:0crwdne101444:0 + copied_successful: crwdns101445:0crwdne101445:0 + button_add_watcher: crwdns101446:0crwdne101446:0 + button_back_to_list_view: crwdns101447:0crwdne101447:0 + button_cancel: crwdns101448:0crwdne101448:0 + button_close: crwdns101449:0crwdne101449:0 + button_check_all: crwdns101450:0crwdne101450:0 + button_configure-form: crwdns101451:0crwdne101451:0 + button_confirm: crwdns101452:0crwdne101452:0 + button_continue: crwdns101453:0crwdne101453:0 + button_copy: crwdns101454:0crwdne101454:0 + button_custom-fields: crwdns101455:0crwdne101455:0 + button_delete: crwdns101456:0crwdne101456:0 + button_delete_watcher: crwdns101457:0crwdne101457:0 + button_details_view: crwdns101458:0crwdne101458:0 + button_duplicate: crwdns101459:0crwdne101459:0 + button_edit: crwdns101460:0crwdne101460:0 + button_filter: crwdns101461:0crwdne101461:0 + button_list_view: crwdns101462:0crwdne101462:0 + button_show_view: crwdns101463:0crwdne101463:0 + button_log_time: crwdns101464:0crwdne101464:0 + button_more: crwdns101465:0crwdne101465:0 + button_move: crwdns101466:0crwdne101466:0 + button_open_details: crwdns101467:0crwdne101467:0 + button_close_details: crwdns101468:0crwdne101468:0 + button_open_fullscreen: crwdns101469:0crwdne101469:0 + button_quote: crwdns101470:0crwdne101470:0 + button_save: crwdns101471:0crwdne101471:0 + button_settings: crwdns101472:0crwdne101472:0 + button_uncheck_all: crwdns101473:0crwdne101473:0 + button_update: crwdns101474:0crwdne101474:0 + button_export-pdf: crwdns101475:0crwdne101475:0 + button_export-atom: crwdns101476:0crwdne101476:0 + description_available_columns: crwdns101477:0crwdne101477:0 + description_current_position: crwdns101478:0crwdne101478:0 + description_select_work_package: crwdns101479:0%{id}crwdne101479:0 + description_selected_columns: crwdns101480:0crwdne101480:0 + description_subwork_package: crwdns101481:0%{id}crwdne101481:0 editor: - preview: crwdns99062:0crwdne99062:0 - source_code: crwdns102025:0crwdne102025:0 - error_saving_failed: crwdns102026:0%{error}crwdne102026:0 + preview: crwdns101482:0crwdne101482:0 + source_code: crwdns101483:0crwdne101483:0 + error_saving_failed: crwdns101484:0%{error}crwdne101484:0 mode: - manual: crwdns102027:0crwdne102027:0 - wysiwyg: crwdns102028:0crwdne102028:0 + manual: crwdns101485:0crwdne101485:0 + wysiwyg: crwdns101486:0crwdne101486:0 macro: child_pages: - button: crwdns99052:0crwdne99052:0 - include_parent: crwdns99053:0crwdne99053:0 - text: crwdns99054:0[Placeholder]crwdne99054:0 - page: crwdns99055:0crwdne99055:0 - this_page: crwdns99056:0crwdne99056:0 - hint: 'crwdns99057:0crwdne99057:0 + button: crwdns101487:0crwdne101487:0 + include_parent: crwdns101488:0crwdne101488:0 + text: crwdns101489:0[Placeholder]crwdne101489:0 + page: crwdns101490:0crwdne101490:0 + this_page: crwdns101491:0crwdne101491:0 + hint: 'crwdns101492:0crwdne101492:0 ' code_block: - button: crwdns99045:0crwdne99045:0 - title: crwdns99046:0crwdne99046:0 - language: crwdns99047:0crwdne99047:0 - language_hint: crwdns99048:0crwdne99048:0 + button: crwdns101493:0crwdne101493:0 + title: crwdns101494:0crwdne101494:0 + language: crwdns101495:0crwdne101495:0 + language_hint: crwdns101496:0crwdne101496:0 dropdown: - macros: crwdns99063:0crwdne99063:0 - chose_macro: crwdns99064:0crwdne99064:0 - toc: crwdns99007:0crwdne99007:0 - toolbar_help: crwdns99044:0crwdne99044:0 + macros: crwdns101497:0crwdne101497:0 + chose_macro: crwdns101498:0crwdne101498:0 + toc: crwdns101499:0crwdne101499:0 + toolbar_help: crwdns101500:0crwdne101500:0 wiki_page_include: - button: crwdns99018:0crwdne99018:0 - text: crwdns99065:0[Placeholder]crwdne99065:0 - page: crwdns99020:0crwdne99020:0 - not_set: crwdns99128:0crwdne99128:0 - hint: 'crwdns99021:0crwdne99021:0 + button: crwdns101501:0crwdne101501:0 + text: crwdns101502:0[Placeholder]crwdne101502:0 + page: crwdns101503:0crwdne101503:0 + not_set: crwdns101504:0crwdne101504:0 + hint: 'crwdns101505:0crwdne101505:0 ' work_package_button: - button: crwdns99022:0crwdne99022:0 - type: crwdns99023:0crwdne99023:0 - button_style: crwdns99024:0crwdne99024:0 - button_style_hint: crwdns99025:0crwdne99025:0 - without_type: crwdns99026:0crwdne99026:0 - with_type: crwdns99027:0%{typename}crwdne99027:0 + button: crwdns101506:0crwdne101506:0 + type: crwdns101507:0crwdne101507:0 + button_style: crwdns101508:0crwdne101508:0 + button_style_hint: crwdns101509:0crwdne101509:0 + without_type: crwdns101510:0crwdne101510:0 + with_type: crwdns101511:0%{typename}crwdne101511:0 embedded_table: - button: crwdns99009:0crwdne99009:0 - text: crwdns99069:0[Placeholder]crwdne99069:0 + button: crwdns101512:0crwdne101512:0 + text: crwdns101513:0[Placeholder]crwdne101513:0 + custom_actions: + date: + specific: crwdns102564:0crwdne102564:0 + current_date: crwdns102566:0crwdne102566:0 error: - internal: crwdns98376:0crwdne98376:0 - cannot_save_changes_with_message: crwdns99001:0%{error}crwdne99001:0 - query_saving: crwdns99083:0crwdne99083:0 - embedded_table_loading: crwdns99123:0%{message}crwdne99123:0 + internal: crwdns101514:0crwdne101514:0 + cannot_save_changes_with_message: crwdns101515:0%{error}crwdne101515:0 + query_saving: crwdns101516:0crwdne101516:0 + embedded_table_loading: crwdns101517:0%{message}crwdne101517:0 filter: description: - text_open_filter: crwdns98377:0crwdne98377:0 - text_close_filter: crwdns98378:0crwdne98378:0 - noneElement: crwdns98379:0crwdne98379:0 + text_open_filter: crwdns101518:0crwdne101518:0 + text_close_filter: crwdns101519:0crwdne101519:0 + noneElement: crwdns101520:0crwdne101520:0 time_zone_converted: - two_values: crwdns98380:0%{from}crwdnd98380:0%{to}crwdne98380:0 - only_start: crwdns98381:0%{from}crwdne98381:0 - only_end: crwdns98382:0%{to}crwdne98382:0 - value_spacer: crwdns98383:0crwdne98383:0 + two_values: crwdns101521:0%{from}crwdnd101521:0%{to}crwdne101521:0 + only_start: crwdns101522:0%{from}crwdne101522:0 + only_end: crwdns101523:0%{to}crwdne101523:0 + value_spacer: crwdns101524:0crwdne101524:0 sorting: criteria: - one: crwdns98384:0crwdne98384:0 - two: crwdns98385:0crwdne98385:0 - three: crwdns98386:0crwdne98386:0 - upsale_for_more: crwdns98868:0crwdne98868:0 - upsale_link: crwdns98869:0crwdne98869:0 - general_text_no: crwdns98387:0crwdne98387:0 - general_text_yes: crwdns98388:0crwdne98388:0 - general_text_No: crwdns98389:0crwdne98389:0 - general_text_Yes: crwdns98390:0crwdne98390:0 - label_activate: crwdns98391:0crwdne98391:0 - label_activity_no: crwdns98392:0%{activityNo}crwdne98392:0 - label_activity_with_comment_no: crwdns98393:0%{activityNo}crwdne98393:0 - label_add_columns: crwdns98394:0crwdne98394:0 - label_add_comment: crwdns98395:0crwdne98395:0 - label_add_comment_title: crwdns98396:0crwdne98396:0 - label_add_selected_columns: crwdns98397:0crwdne98397:0 - label_added_by: crwdns98398:0crwdne98398:0 - label_added_time_by: crwdns98399:0%{author}crwdnd98399:0%{age}crwdne98399:0 - label_ago: crwdns98400:0crwdne98400:0 - label_all: crwdns98401:0crwdne98401:0 - label_all_work_packages: crwdns98402:0crwdne98402:0 - label_and: crwdns98403:0crwdne98403:0 - label_ascending: crwdns98404:0crwdne98404:0 - label_author: crwdns98405:0%{user}crwdne98405:0 - label_between: crwdns98406:0crwdne98406:0 - label_board_locked: crwdns98407:0crwdne98407:0 - label_board_sticky: crwdns98408:0crwdne98408:0 - label_create_work_package: crwdns98409:0crwdne98409:0 - label_created_by: crwdns98410:0crwdne98410:0 - label_date: crwdns98411:0crwdne98411:0 - label_date_with_format: crwdns98412:0%{date_attribute}crwdnd98412:0%{format}crwdne98412:0 - label_deactivate: crwdns98413:0crwdne98413:0 - label_descending: crwdns98414:0crwdne98414:0 - label_description: crwdns98415:0crwdne98415:0 - label_cancel_comment: crwdns98416:0crwdne98416:0 - label_closed_work_packages: crwdns98417:0crwdne98417:0 - label_collapse: crwdns98418:0crwdne98418:0 - label_collapsed: crwdns98419:0crwdne98419:0 - label_collapse_all: crwdns98420:0crwdne98420:0 - label_comment: crwdns98421:0crwdne98421:0 - label_committed_at: crwdns98422:0%{committed_revision_link}crwdnd98422:0%{date}crwdne98422:0 - label_committed_link: crwdns98423:0%{revision_identifier}crwdne98423:0 - label_contains: crwdns98424:0crwdne98424:0 - label_created_on: crwdns98425:0crwdne98425:0 - label_edit_comment: crwdns98426:0crwdne98426:0 - label_edit_status: crwdns98427:0crwdne98427:0 - label_equals: crwdns98428:0crwdne98428:0 - label_expand: crwdns98429:0crwdne98429:0 - label_expanded: crwdns98430:0crwdne98430:0 - label_expand_all: crwdns98431:0crwdne98431:0 - label_expand_project_menu: crwdns98988:0crwdne98988:0 - label_export: crwdns98432:0crwdne98432:0 - label_filename: crwdns98433:0crwdne98433:0 - label_filesize: crwdns98434:0crwdne98434:0 - label_greater_or_equal: crwdns98435:0crwdne98435:0 - label_group_by: crwdns98436:0crwdne98436:0 - label_hide_attributes: crwdns98437:0crwdne98437:0 - label_hide_column: crwdns98438:0crwdne98438:0 - label_hide_project_menu: crwdns98989:0crwdne98989:0 - label_in: crwdns98439:0crwdne98439:0 - label_in_less_than: crwdns98440:0crwdne98440:0 - label_in_more_than: crwdns98441:0crwdne98441:0 - label_latest_activity: crwdns99084:0crwdne99084:0 - label_last_updated_on: crwdns98443:0crwdne98443:0 - label_less_or_equal: crwdns98444:0crwdne98444:0 - label_less_than_ago: crwdns98445:0crwdne98445:0 - label_loading: crwdns98446:0crwdne98446:0 - label_me: crwdns98447:0crwdne98447:0 - label_menu_collapse: crwdns98448:0crwdne98448:0 - label_menu_expand: crwdns98449:0crwdne98449:0 - label_more_than_ago: crwdns98450:0crwdne98450:0 - label_next: crwdns98451:0crwdne98451:0 - label_no_data: crwdns98452:0crwdne98452:0 - label_no_due_date: crwdns98453:0crwdne98453:0 - label_no_start_date: crwdns98454:0crwdne98454:0 - label_none: crwdns98455:0crwdne98455:0 - label_not_contains: crwdns98456:0crwdne98456:0 - label_not_equals: crwdns98457:0crwdne98457:0 - label_on: crwdns98458:0crwdne98458:0 - label_open_menu: crwdns98459:0crwdne98459:0 - label_open_context_menu: crwdns98901:0crwdne98901:0 - label_open_work_packages: crwdns98460:0crwdne98460:0 - label_password: crwdns98461:0crwdne98461:0 - label_previous: crwdns98462:0crwdne98462:0 - label_per_page: crwdns98463:0crwdne98463:0 - label_please_wait: crwdns98464:0crwdne98464:0 - label_visibility_settings: crwdns98465:0crwdne98465:0 - label_quote_comment: crwdns98466:0crwdne98466:0 - label_reset: crwdns98467:0crwdne98467:0 - label_remove_columns: crwdns98468:0crwdne98468:0 - label_save_as: crwdns98469:0crwdne98469:0 - label_select_watcher: crwdns98470:0crwdne98470:0 - label_selected_filter_list: crwdns98471:0crwdne98471:0 - label_show_attributes: crwdns98472:0crwdne98472:0 - label_show_in_menu: crwdns99003:0crwdne99003:0 - label_sort_by: crwdns98474:0crwdne98474:0 - label_sorted_by: crwdns98475:0crwdne98475:0 - label_sort_higher: crwdns98476:0crwdne98476:0 - label_sort_lower: crwdns98477:0crwdne98477:0 - label_sorting: crwdns98478:0crwdne98478:0 - label_star_query: crwdns99085:0crwdne99085:0 - label_press_enter_to_save: crwdns99086:0crwdne99086:0 - label_public_query: crwdns99087:0crwdne99087:0 - label_sum_for: crwdns98479:0crwdne98479:0 - label_subject: crwdns98480:0crwdne98480:0 - label_this_week: crwdns98481:0crwdne98481:0 - label_today: crwdns98482:0crwdne98482:0 - label_up: crwdns98946:0crwdne98946:0 - label_activity_show_only_comments: crwdns98483:0crwdne98483:0 - label_activity_show_all: crwdns98484:0crwdne98484:0 - label_total_progress: crwdns98485:0%{percent}crwdne98485:0 - label_updated_on: crwdns98487:0crwdne98487:0 - label_warning: crwdns98488:0crwdne98488:0 - label_work_package: crwdns98489:0crwdne98489:0 - label_work_package_plural: crwdns98490:0crwdne98490:0 - label_watch: crwdns98491:0crwdne98491:0 - label_watch_work_package: crwdns98492:0crwdne98492:0 - label_watcher_added_successfully: crwdns98493:0crwdne98493:0 - label_watcher_deleted_successfully: crwdns98494:0crwdne98494:0 - label_work_package_details_you_are_here: crwdns98495:0%{tab}crwdnd98495:0%{type}crwdnd98495:0%{subject}crwdne98495:0 - label_unwatch: crwdns98496:0crwdne98496:0 - label_unwatch_work_package: crwdns98497:0crwdne98497:0 - label_uploaded_by: crwdns98498:0crwdne98498:0 - label_default_queries: crwdns99088:0crwdne99088:0 - label_starred_queries: crwdns99089:0crwdne99089:0 - label_global_queries: crwdns99090:0crwdne99090:0 - label_custom_queries: crwdns99091:0crwdne99091:0 - label_columns: crwdns98501:0crwdne98501:0 - label_attachments: crwdns98502:0crwdne98502:0 - label_drop_files: crwdns98503:0crwdne98503:0 - label_drop_files_hint: crwdns98504:0crwdne98504:0 - label_add_attachments: crwdns98505:0crwdne98505:0 - label_formattable_attachment_hint: crwdns98506:0crwdne98506:0 - label_remove_file: crwdns98507:0%{fileName}crwdne98507:0 - label_remove_watcher: crwdns98508:0%{name}crwdne98508:0 - label_remove_all_files: crwdns98509:0crwdne98509:0 - label_add_description: crwdns98510:0%{file}crwdne98510:0 - label_upload_notification: crwdns99058:0crwdne99058:0 - label_work_package_upload_notification: crwdns99059:0%{id}crwdnd99059:0%{subject}crwdne99059:0 - label_files_to_upload: crwdns98512:0crwdne98512:0 - label_rejected_files: crwdns98513:0crwdne98513:0 - label_rejected_files_reason: crwdns98514:0%{maximumFilesize}crwdne98514:0 - label_wait: crwdns98515:0crwdne98515:0 - label_upload_counter: crwdns98516:0%{done}crwdnd98516:0%{count}crwdne98516:0 - label_validation_error: crwdns98517:0crwdne98517:0 + one: crwdns101525:0crwdne101525:0 + two: crwdns101526:0crwdne101526:0 + three: crwdns101527:0crwdne101527:0 + upsale_for_more: crwdns101528:0crwdne101528:0 + upsale_link: crwdns101529:0crwdne101529:0 + general_text_no: crwdns101530:0crwdne101530:0 + general_text_yes: crwdns101531:0crwdne101531:0 + general_text_No: crwdns101532:0crwdne101532:0 + general_text_Yes: crwdns101533:0crwdne101533:0 + label_activate: crwdns101534:0crwdne101534:0 + label_activity_no: crwdns101535:0%{activityNo}crwdne101535:0 + label_activity_with_comment_no: crwdns101536:0%{activityNo}crwdne101536:0 + label_add_columns: crwdns101537:0crwdne101537:0 + label_add_comment: crwdns101538:0crwdne101538:0 + label_add_comment_title: crwdns101539:0crwdne101539:0 + label_add_selected_columns: crwdns101540:0crwdne101540:0 + label_added_by: crwdns101541:0crwdne101541:0 + label_added_time_by: crwdns101542:0%{author}crwdnd101542:0%{age}crwdne101542:0 + label_ago: crwdns101543:0crwdne101543:0 + label_all: crwdns101544:0crwdne101544:0 + label_all_work_packages: crwdns101545:0crwdne101545:0 + label_and: crwdns101546:0crwdne101546:0 + label_ascending: crwdns101547:0crwdne101547:0 + label_author: crwdns101548:0%{user}crwdne101548:0 + label_between: crwdns101549:0crwdne101549:0 + label_board_locked: crwdns101550:0crwdne101550:0 + label_board_sticky: crwdns101551:0crwdne101551:0 + label_create_work_package: crwdns101552:0crwdne101552:0 + label_created_by: crwdns101553:0crwdne101553:0 + label_date: crwdns101554:0crwdne101554:0 + label_date_with_format: crwdns101555:0%{date_attribute}crwdnd101555:0%{format}crwdne101555:0 + label_deactivate: crwdns101556:0crwdne101556:0 + label_descending: crwdns101557:0crwdne101557:0 + label_description: crwdns101558:0crwdne101558:0 + label_cancel_comment: crwdns101559:0crwdne101559:0 + label_closed_work_packages: crwdns101560:0crwdne101560:0 + label_collapse: crwdns101561:0crwdne101561:0 + label_collapsed: crwdns101562:0crwdne101562:0 + label_collapse_all: crwdns101563:0crwdne101563:0 + label_comment: crwdns101564:0crwdne101564:0 + label_committed_at: crwdns101565:0%{committed_revision_link}crwdnd101565:0%{date}crwdne101565:0 + label_committed_link: crwdns101566:0%{revision_identifier}crwdne101566:0 + label_contains: crwdns101567:0crwdne101567:0 + label_created_on: crwdns101568:0crwdne101568:0 + label_edit_comment: crwdns101569:0crwdne101569:0 + label_edit_status: crwdns101570:0crwdne101570:0 + label_equals: crwdns101571:0crwdne101571:0 + label_expand: crwdns101572:0crwdne101572:0 + label_expanded: crwdns101573:0crwdne101573:0 + label_expand_all: crwdns101574:0crwdne101574:0 + label_expand_project_menu: crwdns101575:0crwdne101575:0 + label_export: crwdns101576:0crwdne101576:0 + label_filename: crwdns101577:0crwdne101577:0 + label_filesize: crwdns101578:0crwdne101578:0 + label_greater_or_equal: crwdns101579:0crwdne101579:0 + label_group_by: crwdns101580:0crwdne101580:0 + label_hide_attributes: crwdns101581:0crwdne101581:0 + label_hide_column: crwdns101582:0crwdne101582:0 + label_hide_project_menu: crwdns101583:0crwdne101583:0 + label_in: crwdns101584:0crwdne101584:0 + label_in_less_than: crwdns101585:0crwdne101585:0 + label_in_more_than: crwdns101586:0crwdne101586:0 + label_latest_activity: crwdns101587:0crwdne101587:0 + label_last_updated_on: crwdns101588:0crwdne101588:0 + label_less_or_equal: crwdns101589:0crwdne101589:0 + label_less_than_ago: crwdns101590:0crwdne101590:0 + label_loading: crwdns101591:0crwdne101591:0 + label_me: crwdns101592:0crwdne101592:0 + label_menu_collapse: crwdns101593:0crwdne101593:0 + label_menu_expand: crwdns101594:0crwdne101594:0 + label_more_than_ago: crwdns101595:0crwdne101595:0 + label_next: crwdns101596:0crwdne101596:0 + label_no_data: crwdns101597:0crwdne101597:0 + label_no_due_date: crwdns101598:0crwdne101598:0 + label_no_start_date: crwdns101599:0crwdne101599:0 + label_none: crwdns101600:0crwdne101600:0 + label_not_contains: crwdns101601:0crwdne101601:0 + label_not_equals: crwdns101602:0crwdne101602:0 + label_on: crwdns101603:0crwdne101603:0 + label_open_menu: crwdns101604:0crwdne101604:0 + label_open_context_menu: crwdns101605:0crwdne101605:0 + label_open_work_packages: crwdns101606:0crwdne101606:0 + label_password: crwdns101607:0crwdne101607:0 + label_previous: crwdns101608:0crwdne101608:0 + label_per_page: crwdns101609:0crwdne101609:0 + label_please_wait: crwdns101610:0crwdne101610:0 + label_visibility_settings: crwdns101611:0crwdne101611:0 + label_quote_comment: crwdns101612:0crwdne101612:0 + label_reset: crwdns101613:0crwdne101613:0 + label_remove_columns: crwdns101614:0crwdne101614:0 + label_save_as: crwdns101615:0crwdne101615:0 + label_select_watcher: crwdns101616:0crwdne101616:0 + label_selected_filter_list: crwdns101617:0crwdne101617:0 + label_show_attributes: crwdns101618:0crwdne101618:0 + label_show_in_menu: crwdns101619:0crwdne101619:0 + label_sort_by: crwdns101620:0crwdne101620:0 + label_sorted_by: crwdns101621:0crwdne101621:0 + label_sort_higher: crwdns101622:0crwdne101622:0 + label_sort_lower: crwdns101623:0crwdne101623:0 + label_sorting: crwdns101624:0crwdne101624:0 + label_star_query: crwdns101625:0crwdne101625:0 + label_press_enter_to_save: crwdns101626:0crwdne101626:0 + label_public_query: crwdns101627:0crwdne101627:0 + label_sum_for: crwdns101628:0crwdne101628:0 + label_subject: crwdns101629:0crwdne101629:0 + label_this_week: crwdns101630:0crwdne101630:0 + label_today: crwdns101631:0crwdne101631:0 + label_up: crwdns101632:0crwdne101632:0 + label_activity_show_only_comments: crwdns101633:0crwdne101633:0 + label_activity_show_all: crwdns101634:0crwdne101634:0 + label_total_progress: crwdns101635:0%{percent}crwdne101635:0 + label_updated_on: crwdns101636:0crwdne101636:0 + label_warning: crwdns101637:0crwdne101637:0 + label_work_package: crwdns101638:0crwdne101638:0 + label_work_package_plural: crwdns101639:0crwdne101639:0 + label_watch: crwdns101640:0crwdne101640:0 + label_watch_work_package: crwdns101641:0crwdne101641:0 + label_watcher_added_successfully: crwdns101642:0crwdne101642:0 + label_watcher_deleted_successfully: crwdns101643:0crwdne101643:0 + label_work_package_details_you_are_here: crwdns101644:0%{tab}crwdnd101644:0%{type}crwdnd101644:0%{subject}crwdne101644:0 + label_unwatch: crwdns101645:0crwdne101645:0 + label_unwatch_work_package: crwdns101646:0crwdne101646:0 + label_uploaded_by: crwdns101647:0crwdne101647:0 + label_default_queries: crwdns101648:0crwdne101648:0 + label_starred_queries: crwdns101649:0crwdne101649:0 + label_global_queries: crwdns101650:0crwdne101650:0 + label_custom_queries: crwdns101651:0crwdne101651:0 + label_columns: crwdns101652:0crwdne101652:0 + label_attachments: crwdns101653:0crwdne101653:0 + label_drop_files: crwdns101654:0crwdne101654:0 + label_drop_files_hint: crwdns101655:0crwdne101655:0 + label_add_attachments: crwdns101656:0crwdne101656:0 + label_formattable_attachment_hint: crwdns101657:0crwdne101657:0 + label_remove_file: crwdns101658:0%{fileName}crwdne101658:0 + label_remove_watcher: crwdns101659:0%{name}crwdne101659:0 + label_remove_all_files: crwdns101660:0crwdne101660:0 + label_add_description: crwdns101661:0%{file}crwdne101661:0 + label_upload_notification: crwdns101662:0crwdne101662:0 + label_work_package_upload_notification: crwdns101663:0%{id}crwdnd101663:0%{subject}crwdne101663:0 + label_files_to_upload: crwdns101664:0crwdne101664:0 + label_rejected_files: crwdns101665:0crwdne101665:0 + label_rejected_files_reason: crwdns101666:0%{maximumFilesize}crwdne101666:0 + label_wait: crwdns101667:0crwdne101667:0 + label_upload_counter: crwdns101668:0%{done}crwdnd101668:0%{count}crwdne101668:0 + label_validation_error: crwdns101669:0crwdne101669:0 help_texts: - show_modal: crwdns98518:0crwdne98518:0 + show_modal: crwdns101670:0crwdne101670:0 password_confirmation: - field_description: crwdns98519:0crwdne98519:0 - title: crwdns98520:0crwdne98520:0 + field_description: crwdns101671:0crwdne101671:0 + title: crwdns101672:0crwdne101672:0 pagination: - no_other_page: crwdns98521:0crwdne98521:0 + no_other_page: crwdns101673:0crwdne101673:0 pages: - next: crwdns98522:0crwdne98522:0 - previous: crwdns98523:0crwdne98523:0 + next: crwdns101674:0crwdne101674:0 + previous: crwdns101675:0crwdne101675:0 placeholders: - default: crwdns98524:0crwdne98524:0 - subject: crwdns98525:0crwdne98525:0 - selection: crwdns98526:0crwdne98526:0 - relation_description: crwdns98527:0crwdne98527:0 + default: crwdns101676:0crwdne101676:0 + subject: crwdns101677:0crwdne101677:0 + selection: crwdns101678:0crwdne101678:0 + relation_description: crwdns101679:0crwdne101679:0 project: - required_outside_context: crwdns98528:0crwdne98528:0 - context: crwdns98529:0crwdne98529:0 - work_package_belongs_to: crwdns98530:0%{projectname}crwdne98530:0 - click_to_switch_context: crwdns98531:0crwdne98531:0 + required_outside_context: crwdns101680:0crwdne101680:0 + context: crwdns101681:0crwdne101681:0 + work_package_belongs_to: crwdns101682:0%{projectname}crwdne101682:0 + click_to_switch_context: crwdns101683:0crwdne101683:0 autocompleter: - label: crwdns98532:0crwdne98532:0 - text_are_you_sure: crwdns98533:0crwdne98533:0 + label: crwdns101684:0crwdne101684:0 + text_are_you_sure: crwdns101685:0crwdne101685:0 types: attribute_groups: - error_duplicate_group_name: crwdns98534:0%{group}crwdne98534:0 - reset_title: crwdns98535:0crwdne98535:0 - confirm_reset: 'crwdns99066:0crwdne99066:0 + error_duplicate_group_name: crwdns101686:0%{group}crwdne101686:0 + reset_title: crwdns101687:0crwdne101687:0 + confirm_reset: 'crwdns101688:0crwdne101688:0 ' - upgrade_to_ee: crwdns98537:0crwdne98537:0 - upgrade_to_ee_text: crwdns98538:0crwdne98538:0 - more_information: crwdns98539:0crwdne98539:0 - nevermind: crwdns98540:0crwdne98540:0 + upgrade_to_ee: crwdns101689:0crwdne101689:0 + upgrade_to_ee_text: crwdns101690:0crwdne101690:0 + more_information: crwdns101691:0crwdne101691:0 + nevermind: crwdns101692:0crwdne101692:0 watchers: - label_loading: crwdns98541:0crwdne98541:0 - label_error_loading: crwdns98542:0crwdne98542:0 - label_search_watchers: crwdns98543:0crwdne98543:0 - label_add: crwdns98544:0crwdne98544:0 - label_discard: crwdns98545:0crwdne98545:0 - typeahead_placeholder: crwdns98546:0crwdne98546:0 + label_loading: crwdns101693:0crwdne101693:0 + label_error_loading: crwdns101694:0crwdne101694:0 + label_search_watchers: crwdns101695:0crwdne101695:0 + label_add: crwdns101696:0crwdne101696:0 + label_discard: crwdns101697:0crwdne101697:0 + typeahead_placeholder: crwdns101698:0crwdne101698:0 relation_labels: - parent: crwdns98547:0crwdne98547:0 - children: crwdns98548:0crwdne98548:0 - relates: crwdns98549:0crwdne98549:0 - duplicates: crwdns98550:0crwdne98550:0 - duplicated: crwdns98551:0crwdne98551:0 - blocks: crwdns98552:0crwdne98552:0 - blocked: crwdns98553:0crwdne98553:0 - precedes: crwdns98554:0crwdne98554:0 - follows: crwdns98555:0crwdne98555:0 - includes: crwdns98556:0crwdne98556:0 - partof: crwdns98557:0crwdne98557:0 - requires: crwdns98558:0crwdne98558:0 - required: crwdns98559:0crwdne98559:0 - relation_type: crwdns98560:0crwdne98560:0 + parent: crwdns101699:0crwdne101699:0 + children: crwdns101700:0crwdne101700:0 + relates: crwdns101701:0crwdne101701:0 + duplicates: crwdns101702:0crwdne101702:0 + duplicated: crwdns101703:0crwdne101703:0 + blocks: crwdns101704:0crwdne101704:0 + blocked: crwdns101705:0crwdne101705:0 + precedes: crwdns101706:0crwdne101706:0 + follows: crwdns101707:0crwdne101707:0 + includes: crwdns101708:0crwdne101708:0 + partof: crwdns101709:0crwdne101709:0 + requires: crwdns101710:0crwdne101710:0 + required: crwdns101711:0crwdne101711:0 + relation_type: crwdns101712:0crwdne101712:0 relations_hierarchy: - parent_headline: crwdns98902:0crwdne98902:0 - children_headline: crwdns98903:0crwdne98903:0 + parent_headline: crwdns101713:0crwdne101713:0 + children_headline: crwdns101714:0crwdne101714:0 relation_buttons: - change_parent: crwdns98562:0crwdne98562:0 - remove_parent: crwdns98563:0crwdne98563:0 - group_by_wp_type: crwdns98564:0crwdne98564:0 - group_by_relation_type: crwdns98565:0crwdne98565:0 - add_parent: crwdns98566:0crwdne98566:0 - add_new_child: crwdns98567:0crwdne98567:0 - add_existing_child: crwdns98568:0crwdne98568:0 - remove_child: crwdns98569:0crwdne98569:0 - add_new_relation: crwdns98570:0crwdne98570:0 - update_description: crwdns98571:0crwdne98571:0 - toggle_description: crwdns98572:0crwdne98572:0 - update_relation: crwdns98573:0crwdne98573:0 - add_follower: crwdns98574:0crwdne98574:0 - add_predecessor: crwdns98575:0crwdne98575:0 - remove: crwdns98576:0crwdne98576:0 - save: crwdns98577:0crwdne98577:0 - abort: crwdns98578:0crwdne98578:0 + change_parent: crwdns101715:0crwdne101715:0 + remove_parent: crwdns101716:0crwdne101716:0 + group_by_wp_type: crwdns101717:0crwdne101717:0 + group_by_relation_type: crwdns101718:0crwdne101718:0 + add_parent: crwdns101719:0crwdne101719:0 + add_new_child: crwdns101720:0crwdne101720:0 + add_existing_child: crwdns101721:0crwdne101721:0 + remove_child: crwdns101722:0crwdne101722:0 + add_new_relation: crwdns101723:0crwdne101723:0 + update_description: crwdns101724:0crwdne101724:0 + toggle_description: crwdns101725:0crwdne101725:0 + update_relation: crwdns101726:0crwdne101726:0 + add_follower: crwdns101727:0crwdne101727:0 + add_predecessor: crwdns101728:0crwdne101728:0 + remove: crwdns101729:0crwdne101729:0 + save: crwdns101730:0crwdne101730:0 + abort: crwdns101731:0crwdne101731:0 relations_autocomplete: - placeholder: crwdns98579:0crwdne98579:0 + placeholder: crwdns101732:0crwdne101732:0 repositories: - select_tag: crwdns98580:0crwdne98580:0 - select_branch: crwdns98581:0crwdne98581:0 - field_value_enter_prompt: crwdns98582:0%{field}crwdne98582:0 + select_tag: crwdns101733:0crwdne101733:0 + select_branch: crwdns101734:0crwdne101734:0 + field_value_enter_prompt: crwdns101735:0%{field}crwdne101735:0 select2: input_too_short: - one: crwdns98583:1crwdne98583:1 - other: crwdns98583:5{{count}}crwdne98583:5 + one: crwdns101736:1crwdne101736:1 + other: crwdns101736:5{{count}}crwdne101736:5 zero: Please enter more characters - load_more: crwdns98584:0crwdne98584:0 - no_matches: crwdns98585:0crwdne98585:0 - searching: crwdns98586:0crwdne98586:0 + load_more: crwdns101737:0crwdne101737:0 + no_matches: crwdns101738:0crwdne101738:0 + searching: crwdns101739:0crwdne101739:0 selection_too_big: - one: crwdns98587:1crwdne98587:1 - other: crwdns98587:5{{limit}}crwdne98587:5 + one: crwdns101740:1crwdne101740:1 + other: crwdns101740:5{{limit}}crwdne101740:5 zero: You cannot select any items - project_menu_details: crwdns98971:0crwdne98971:0 + project_menu_details: crwdns101741:0crwdne101741:0 sort: - sorted_asc: crwdns98588:0crwdne98588:0 - sorted_dsc: crwdns98589:0crwdne98589:0 - sorted_no: crwdns98590:0crwdne98590:0 - sorting_disabled: crwdns98591:0crwdne98591:0 - activate_asc: crwdns98592:0crwdne98592:0 - activate_dsc: crwdns98593:0crwdne98593:0 - activate_no: crwdns98594:0crwdne98594:0 - text_work_packages_destroy_confirmation: crwdns98595:0crwdne98595:0 - text_query_destroy_confirmation: crwdns99092:0crwdne99092:0 - text_attachment_destroy_confirmation: crwdns98597:0crwdne98597:0 + sorted_asc: crwdns101742:0crwdne101742:0 + sorted_dsc: crwdns101743:0crwdne101743:0 + sorted_no: crwdns101744:0crwdne101744:0 + sorting_disabled: crwdns101745:0crwdne101745:0 + activate_asc: crwdns101746:0crwdne101746:0 + activate_dsc: crwdns101747:0crwdne101747:0 + activate_no: crwdns101748:0crwdne101748:0 + text_work_packages_destroy_confirmation: crwdns101749:0crwdne101749:0 + text_query_destroy_confirmation: crwdns101750:0crwdne101750:0 + text_attachment_destroy_confirmation: crwdns101751:0crwdne101751:0 timelines: - gantt_chart: crwdns98598:0crwdne98598:0 + gantt_chart: crwdns101752:0crwdne101752:0 labels: - title: crwdns98904:0crwdne98904:0 - bar: crwdns98599:0crwdne98599:0 - left: crwdns98600:0crwdne98600:0 - right: crwdns98601:0crwdne98601:0 - farRight: crwdns98602:0crwdne98602:0 - showNone: crwdns98603:0crwdne98603:0 - description: 'crwdns98604:0crwdne98604:0 + title: crwdns101753:0crwdne101753:0 + bar: crwdns101754:0crwdne101754:0 + left: crwdns101755:0crwdne101755:0 + right: crwdns101756:0crwdne101756:0 + farRight: crwdns101757:0crwdne101757:0 + showNone: crwdns101758:0crwdne101758:0 + description: 'crwdns101759:0crwdne101759:0 ' - button_activate: crwdns99070:0crwdne99070:0 - button_deactivate: crwdns99129:0crwdne99129:0 - cancel: crwdns98607:0crwdne98607:0 - change: crwdns98608:0crwdne98608:0 - due_date: crwdns99247:0crwdne99247:0 - empty: crwdns98610:0crwdne98610:0 - error: crwdns98611:0crwdne98611:0 + button_activate: crwdns101760:0crwdne101760:0 + button_deactivate: crwdns101761:0crwdne101761:0 + cancel: crwdns101762:0crwdne101762:0 + change: crwdns101763:0crwdne101763:0 + due_date: crwdns101764:0crwdne101764:0 + empty: crwdns101765:0crwdne101765:0 + error: crwdns101766:0crwdne101766:0 errors: - not_implemented: crwdns98612:0crwdne98612:0 - report_comparison: crwdns98613:0crwdne98613:0 - report_epicfail: crwdns98614:0crwdne98614:0 - report_timeout: crwdns98615:0crwdne98615:0 + not_implemented: crwdns101767:0crwdne101767:0 + report_comparison: crwdns101768:0crwdne101768:0 + report_epicfail: crwdns101769:0crwdne101769:0 + report_timeout: crwdns101770:0crwdne101770:0 filter: - grouping_other: crwdns98623:0crwdne98623:0 - noneSelection: crwdns98624:0crwdne98624:0 - name: crwdns98625:0crwdne98625:0 - outline: crwdns98627:0crwdne98627:0 + grouping_other: crwdns101771:0crwdne101771:0 + noneSelection: crwdns101772:0crwdne101772:0 + name: crwdns101773:0crwdne101773:0 + outline: crwdns101774:0crwdne101774:0 outlines: - aggregation: crwdns98628:0crwdne98628:0 - level1: crwdns98629:0crwdne98629:0 - level2: crwdns98630:0crwdne98630:0 - level3: crwdns98631:0crwdne98631:0 - level4: crwdns98632:0crwdne98632:0 - level5: crwdns98633:0crwdne98633:0 - all: crwdns98634:0crwdne98634:0 - project_status: crwdns98635:0crwdne98635:0 - really_close_dialog: crwdns98637:0crwdne98637:0 - responsible: crwdns98638:0crwdne98638:0 - save: crwdns98639:0crwdne98639:0 - start_date: crwdns98640:0crwdne98640:0 - tooManyProjects: crwdns98641:0%{count}crwdne98641:0 + aggregation: crwdns101775:0crwdne101775:0 + level1: crwdns101776:0crwdne101776:0 + level2: crwdns101777:0crwdne101777:0 + level3: crwdns101778:0crwdne101778:0 + level4: crwdns101779:0crwdne101779:0 + level5: crwdns101780:0crwdne101780:0 + all: crwdns101781:0crwdne101781:0 + project_status: crwdns101782:0crwdne101782:0 + really_close_dialog: crwdns101783:0crwdne101783:0 + responsible: crwdns101784:0crwdne101784:0 + save: crwdns101785:0crwdne101785:0 + start_date: crwdns101786:0crwdne101786:0 + tooManyProjects: crwdns101787:0%{count}crwdne101787:0 selection_mode: - notification: crwdns98642:0crwdne98642:0 + notification: crwdns101788:0crwdne101788:0 zoom: - in: crwdns98643:0crwdne98643:0 - out: crwdns98644:0crwdne98644:0 - auto: crwdns98645:0crwdne98645:0 - days: crwdns98646:0crwdne98646:0 - weeks: crwdns98647:0crwdne98647:0 - months: crwdns98648:0crwdne98648:0 - quarters: crwdns98649:0crwdne98649:0 - years: crwdns98650:0crwdne98650:0 - slider: crwdns98651:0crwdne98651:0 - description: 'crwdns99133:0crwdne99133:0 + in: crwdns101789:0crwdne101789:0 + out: crwdns101790:0crwdne101790:0 + auto: crwdns101791:0crwdne101791:0 + days: crwdns101792:0crwdne101792:0 + weeks: crwdns101793:0crwdne101793:0 + months: crwdns101794:0crwdne101794:0 + quarters: crwdns101795:0crwdne101795:0 + years: crwdns101796:0crwdne101796:0 + slider: crwdns101797:0crwdne101797:0 + description: 'crwdns101798:0crwdne101798:0 ' tl_toolbar: - zooms: crwdns98652:0crwdne98652:0 - outlines: crwdns98653:0crwdne98653:0 + zooms: crwdns101799:0crwdne101799:0 + outlines: crwdns101800:0crwdne101800:0 unsupported_browser: - title: crwdns98654:0crwdne98654:0 - message: crwdns98655:0crwdne98655:0 - update_message: crwdns98656:0crwdne98656:0 - update_ie_user: crwdns98657:0crwdne98657:0 - learn_more: crwdns98658:0crwdne98658:0 - close_warning: crwdns98659:0crwdne98659:0 + title: crwdns101801:0crwdne101801:0 + message: crwdns101802:0crwdne101802:0 + update_message: crwdns101803:0crwdne101803:0 + update_ie_user: crwdns101804:0crwdne101804:0 + learn_more: crwdns101805:0crwdne101805:0 + close_warning: crwdns101806:0crwdne101806:0 + upsale: + ee_only: crwdns102556:0crwdne102556:0 wiki_formatting: - strong: crwdns98660:0crwdne98660:0 - italic: crwdns98661:0crwdne98661:0 - underline: crwdns98662:0crwdne98662:0 - deleted: crwdns98663:0crwdne98663:0 - code: crwdns98664:0crwdne98664:0 - heading1: crwdns98665:0crwdne98665:0 - heading2: crwdns98666:0crwdne98666:0 - heading3: crwdns98667:0crwdne98667:0 - unordered_list: crwdns98668:0crwdne98668:0 - ordered_list: crwdns98669:0crwdne98669:0 - quote: crwdns98670:0crwdne98670:0 - unquote: crwdns98671:0crwdne98671:0 - preformatted_text: crwdns98672:0crwdne98672:0 - wiki_link: crwdns98673:0crwdne98673:0 - image: crwdns98674:0crwdne98674:0 + strong: crwdns101807:0crwdne101807:0 + italic: crwdns101808:0crwdne101808:0 + underline: crwdns101809:0crwdne101809:0 + deleted: crwdns101810:0crwdne101810:0 + code: crwdns101811:0crwdne101811:0 + heading1: crwdns101812:0crwdne101812:0 + heading2: crwdns101813:0crwdne101813:0 + heading3: crwdns101814:0crwdne101814:0 + unordered_list: crwdns101815:0crwdne101815:0 + ordered_list: crwdns101816:0crwdne101816:0 + quote: crwdns101817:0crwdne101817:0 + unquote: crwdns101818:0crwdne101818:0 + preformatted_text: crwdns101819:0crwdne101819:0 + wiki_link: crwdns101820:0crwdne101820:0 + image: crwdns101821:0crwdne101821:0 work_packages: bulk_actions: - move: crwdns98675:0crwdne98675:0 - edit: crwdns98676:0crwdne98676:0 - copy: crwdns98677:0crwdne98677:0 - delete: crwdns98678:0crwdne98678:0 - button_clear: crwdns98679:0crwdne98679:0 - comment_added: crwdns98680:0crwdne98680:0 - comment_send_failed: crwdns98681:0crwdne98681:0 - comment_updated: crwdns98682:0crwdne98682:0 - confirm_edit_cancel: crwdns98683:0crwdne98683:0 - description_filter: crwdns98684:0crwdne98684:0 - description_enter_text: crwdns98685:0crwdne98685:0 - description_options_hide: crwdns98686:0crwdne98686:0 - description_options_show: crwdns98687:0crwdne98687:0 + move: crwdns101822:0crwdne101822:0 + edit: crwdns101823:0crwdne101823:0 + copy: crwdns101824:0crwdne101824:0 + delete: crwdns101825:0crwdne101825:0 + button_clear: crwdns101826:0crwdne101826:0 + comment_added: crwdns101827:0crwdne101827:0 + comment_send_failed: crwdns101828:0crwdne101828:0 + comment_updated: crwdns101829:0crwdne101829:0 + confirm_edit_cancel: crwdns101830:0crwdne101830:0 + description_filter: crwdns101831:0crwdne101831:0 + description_enter_text: crwdns101832:0crwdne101832:0 + description_options_hide: crwdns101833:0crwdne101833:0 + description_options_show: crwdns101834:0crwdne101834:0 error: - edit_prohibited: crwdns98688:0%{attribute}crwdne98688:0 + edit_prohibited: crwdns101835:0%{attribute}crwdne101835:0 format: - date: crwdns98689:0%{attribute}crwdne98689:0 - general: crwdns98690:0crwdne98690:0 - edit_attribute: crwdns98691:0%{attribute}crwdne98691:0 - key_value: crwdns98692:0%{key}crwdnd98692:0%{value}crwdne98692:0 - label_enable_multi_select: crwdns98693:0crwdne98693:0 - label_disable_multi_select: crwdns98694:0crwdne98694:0 - label_filter_add: crwdns98695:0crwdne98695:0 - label_options: crwdns98696:0crwdne98696:0 - label_column_multiselect: crwdns98697:0crwdne98697:0 - label_switch_to_single_select: crwdns98698:0crwdne98698:0 - label_switch_to_multi_select: crwdns98699:0crwdne98699:0 - message_error_during_bulk_delete: crwdns98700:0crwdne98700:0 - message_successful_bulk_delete: crwdns98701:0crwdne98701:0 - message_successful_show_in_fullscreen: crwdns98702:0crwdne98702:0 - message_view_spent_time: crwdns98703:0crwdne98703:0 - no_value: crwdns98704:0crwdne98704:0 + date: crwdns101836:0%{attribute}crwdne101836:0 + general: crwdns101837:0crwdne101837:0 + edit_attribute: crwdns101838:0%{attribute}crwdne101838:0 + key_value: crwdns101839:0%{key}crwdnd101839:0%{value}crwdne101839:0 + label_enable_multi_select: crwdns101840:0crwdne101840:0 + label_disable_multi_select: crwdns101841:0crwdne101841:0 + label_filter_add: crwdns101842:0crwdne101842:0 + label_options: crwdns101843:0crwdne101843:0 + label_column_multiselect: crwdns101844:0crwdne101844:0 + label_switch_to_single_select: crwdns101845:0crwdne101845:0 + label_switch_to_multi_select: crwdns101846:0crwdne101846:0 + message_error_during_bulk_delete: crwdns101847:0crwdne101847:0 + message_successful_bulk_delete: crwdns101848:0crwdne101848:0 + message_successful_show_in_fullscreen: crwdns101849:0crwdne101849:0 + message_view_spent_time: crwdns101850:0crwdne101850:0 + no_value: crwdns101851:0crwdne101851:0 inline_create: - title: crwdns98705:0crwdne98705:0 + title: crwdns101852:0crwdne101852:0 create: - title: crwdns98905:0crwdne98905:0 - header: crwdns98706:0%{type}crwdne98706:0 - header_no_type: crwdns98707:0crwdne98707:0 - header_with_parent: crwdns98708:0%{type}crwdnd98708:0%{parent_type}crwdnd98708:0%{id}crwdne98708:0 - button: crwdns98709:0crwdne98709:0 + title: crwdns101853:0crwdne101853:0 + header: crwdns101854:0%{type}crwdne101854:0 + header_no_type: crwdns101855:0crwdne101855:0 + header_with_parent: crwdns101856:0%{type}crwdnd101856:0%{parent_type}crwdnd101856:0%{id}crwdne101856:0 + button: crwdns101857:0crwdne101857:0 copy: - title: crwdns98906:0crwdne98906:0 + title: crwdns101858:0crwdne101858:0 hierarchy: - show: crwdns98710:0crwdne98710:0 - hide: crwdns98711:0crwdne98711:0 - toggle_button: crwdns98712:0crwdne98712:0 - leaf: crwdns98713:0%{level}crwdne98713:0 - children_collapsed: crwdns98714:0%{level}crwdne98714:0 - children_expanded: crwdns98715:0%{level}crwdne98715:0 + show: crwdns101859:0crwdne101859:0 + hide: crwdns101860:0crwdne101860:0 + toggle_button: crwdns101861:0crwdne101861:0 + leaf: crwdns101862:0%{level}crwdne101862:0 + children_collapsed: crwdns101863:0%{level}crwdne101863:0 + children_expanded: crwdns101864:0%{level}crwdne101864:0 faulty_query: - title: crwdns98716:0crwdne98716:0 - description: crwdns99093:0crwdne99093:0 + title: crwdns101865:0crwdne101865:0 + description: crwdns101866:0crwdne101866:0 no_results: - title: crwdns98718:0crwdne98718:0 - description: crwdns98719:0crwdne98719:0 + title: crwdns101867:0crwdne101867:0 + description: crwdns101868:0crwdne101868:0 property_groups: - details: crwdns98720:0crwdne98720:0 - people: crwdns98721:0crwdne98721:0 - estimatesAndTime: crwdns98722:0crwdne98722:0 - other: crwdns98723:0crwdne98723:0 + details: crwdns101869:0crwdne101869:0 + people: crwdns101870:0crwdne101870:0 + estimatesAndTime: crwdns101871:0crwdne101871:0 + other: crwdns101872:0crwdne101872:0 properties: - assignee: crwdns98724:0crwdne98724:0 - author: crwdns98725:0crwdne98725:0 - createdAt: crwdns98726:0crwdne98726:0 - description: crwdns98727:0crwdne98727:0 - date: crwdns98728:0crwdne98728:0 - dueDate: crwdns99248:0crwdne99248:0 - estimatedTime: crwdns98730:0crwdne98730:0 - spentTime: crwdns98731:0crwdne98731:0 - category: crwdns98732:0crwdne98732:0 - percentageDone: crwdns98733:0crwdne98733:0 - priority: crwdns98734:0crwdne98734:0 - projectName: crwdns98735:0crwdne98735:0 - responsible: crwdns98736:0crwdne98736:0 - startDate: crwdns98737:0crwdne98737:0 - status: crwdns98738:0crwdne98738:0 - subject: crwdns98739:0crwdne98739:0 - title: crwdns98740:0crwdne98740:0 - type: crwdns98741:0crwdne98741:0 - updatedAt: crwdns98742:0crwdne98742:0 - versionName: crwdns98743:0crwdne98743:0 - version: crwdns98744:0crwdne98744:0 + assignee: crwdns101873:0crwdne101873:0 + author: crwdns101874:0crwdne101874:0 + createdAt: crwdns101875:0crwdne101875:0 + description: crwdns101876:0crwdne101876:0 + date: crwdns101877:0crwdne101877:0 + dueDate: crwdns101878:0crwdne101878:0 + estimatedTime: crwdns101879:0crwdne101879:0 + spentTime: crwdns101880:0crwdne101880:0 + category: crwdns101881:0crwdne101881:0 + percentageDone: crwdns101882:0crwdne101882:0 + priority: crwdns101883:0crwdne101883:0 + projectName: crwdns101884:0crwdne101884:0 + responsible: crwdns101885:0crwdne101885:0 + startDate: crwdns101886:0crwdne101886:0 + status: crwdns101887:0crwdne101887:0 + subject: crwdns101888:0crwdne101888:0 + title: crwdns101889:0crwdne101889:0 + type: crwdns101890:0crwdne101890:0 + updatedAt: crwdns101891:0crwdne101891:0 + versionName: crwdns101892:0crwdne101892:0 + version: crwdns101893:0crwdne101893:0 default_queries: - latest_activity: crwdns99094:0crwdne99094:0 - created_by_me: crwdns99095:0crwdne99095:0 - assigned_to_me: crwdns99096:0crwdne99096:0 - recently_created: crwdns99097:0crwdne99097:0 - all_open: crwdns99098:0crwdne99098:0 - summary: crwdns99099:0crwdne99099:0 + latest_activity: crwdns101894:0crwdne101894:0 + created_by_me: crwdns101895:0crwdne101895:0 + assigned_to_me: crwdns101896:0crwdne101896:0 + recently_created: crwdns101897:0crwdne101897:0 + all_open: crwdns101898:0crwdne101898:0 + summary: crwdns101899:0crwdne101899:0 jump_marks: - pagination: crwdns98745:0crwdne98745:0 - label_pagination: crwdns98746:0crwdne98746:0 - content: crwdns98747:0crwdne98747:0 - label_content: crwdns98748:0crwdne98748:0 + pagination: crwdns101900:0crwdne101900:0 + label_pagination: crwdns101901:0crwdne101901:0 + content: crwdns101902:0crwdne101902:0 + label_content: crwdns101903:0crwdne101903:0 placeholders: - default: crwdns98749:0crwdne98749:0 - description: crwdns98750:0crwdne98750:0 + default: crwdns101904:0crwdne101904:0 + description: crwdns101905:0crwdne101905:0 query: - column_names: crwdns98751:0crwdne98751:0 - group_by: crwdns98752:0crwdne98752:0 - group: crwdns98753:0crwdne98753:0 - group_by_disabled_by_hierarchy: crwdns98754:0crwdne98754:0 - hierarchy_disabled_by_group_by: crwdns98755:0%{column}crwdne98755:0 - sort_ascending: crwdns98757:0crwdne98757:0 - sort_descending: crwdns98758:0crwdne98758:0 - move_column_left: crwdns98759:0crwdne98759:0 - move_column_right: crwdns98760:0crwdne98760:0 - hide_column: crwdns98761:0crwdne98761:0 - insert_columns: crwdns98762:0crwdne98762:0 - filters: crwdns98763:0crwdne98763:0 - display_sums: crwdns98764:0crwdne98764:0 - confirm_edit_cancel: crwdns99100:0crwdne99100:0 - click_to_edit_query_name: crwdns99101:0crwdne99101:0 - rename_query_placeholder: crwdns99102:0crwdne99102:0 + column_names: crwdns101906:0crwdne101906:0 + group_by: crwdns101907:0crwdne101907:0 + group: crwdns101908:0crwdne101908:0 + group_by_disabled_by_hierarchy: crwdns101909:0crwdne101909:0 + hierarchy_disabled_by_group_by: crwdns101910:0%{column}crwdne101910:0 + sort_ascending: crwdns101911:0crwdne101911:0 + sort_descending: crwdns101912:0crwdne101912:0 + move_column_left: crwdns101913:0crwdne101913:0 + move_column_right: crwdns101914:0crwdne101914:0 + hide_column: crwdns101915:0crwdne101915:0 + insert_columns: crwdns101916:0crwdne101916:0 + filters: crwdns101917:0crwdne101917:0 + display_sums: crwdns101918:0crwdne101918:0 + confirm_edit_cancel: crwdns101919:0crwdne101919:0 + click_to_edit_query_name: crwdns101920:0crwdne101920:0 + rename_query_placeholder: crwdns101921:0crwdne101921:0 errors: - unretrievable_query: crwdns99103:0crwdne99103:0 - not_found: crwdns99104:0crwdne99104:0 - duplicate_query_title: crwdns99105:0crwdne99105:0 - text_no_results: crwdns99106:0crwdne99106:0 + unretrievable_query: crwdns101922:0crwdne101922:0 + not_found: crwdns101923:0crwdne101923:0 + duplicate_query_title: crwdns101924:0crwdne101924:0 + text_no_results: crwdns101925:0crwdne101925:0 table: - configure_button: crwdns98907:0crwdne98907:0 - summary: crwdns98768:0crwdne98768:0 - text_inline_edit: crwdns98769:0crwdne98769:0 - text_sort_hint: crwdns98770:0crwdne98770:0 - text_select_hint: crwdns98771:0crwdne98771:0 + configure_button: crwdns101926:0crwdne101926:0 + summary: crwdns101927:0crwdne101927:0 + text_inline_edit: crwdns101928:0crwdne101928:0 + text_sort_hint: crwdns101929:0crwdne101929:0 + text_select_hint: crwdns101930:0crwdne101930:0 table_configuration: - button: crwdns98908:0crwdne98908:0 - choose_display_mode: crwdns99232:0crwdne99232:0 - modal_title: crwdns98909:0crwdne98909:0 - embedded_tab_disabled: crwdns99107:0crwdne99107:0 - default: crwdns99233:0crwdne99233:0 - display_settings: crwdns98911:0crwdne98911:0 - default_mode: crwdns99234:0crwdne99234:0 - hierarchy_mode: crwdns99235:0crwdne99235:0 - hierarchy_hint: crwdns98916:0crwdne98916:0 - display_sums_hint: crwdns98917:0crwdne98917:0 - show_timeline_hint: crwdns98918:0crwdne98918:0 - highlighting: crwdns99222:0crwdne99222:0 + button: crwdns101931:0crwdne101931:0 + choose_display_mode: crwdns101932:0crwdne101932:0 + modal_title: crwdns101933:0crwdne101933:0 + embedded_tab_disabled: crwdns101934:0crwdne101934:0 + default: crwdns101935:0crwdne101935:0 + display_settings: crwdns101936:0crwdne101936:0 + default_mode: crwdns101937:0crwdne101937:0 + hierarchy_mode: crwdns101938:0crwdne101938:0 + hierarchy_hint: crwdns101939:0crwdne101939:0 + display_sums_hint: crwdns101940:0crwdne101940:0 + show_timeline_hint: crwdns101941:0crwdne101941:0 + highlighting: crwdns101942:0crwdne101942:0 highlighting_mode: - description: crwdns99236:0crwdne99236:0 - none: crwdns99237:0crwdne99237:0 - inline: crwdns102533:0crwdne102533:0 - entire_row_by: crwdns99239:0crwdne99239:0 - status: crwdns99228:0crwdne99228:0 - priority: crwdns99230:0crwdne99230:0 - columns_help_text: crwdns99008:0crwdne99008:0 + description: crwdns101943:0crwdne101943:0 + none: crwdns101944:0crwdne101944:0 + inline: crwdns102558:0crwdne102558:0 + inline_all: crwdns102560:0crwdne102560:0 + entire_row_by: crwdns101946:0crwdne101946:0 + status: crwdns101947:0crwdne101947:0 + priority: crwdns101948:0crwdne101948:0 + type: crwdns102562:0crwdne102562:0 + columns_help_text: crwdns101949:0crwdne101949:0 upsale: - ee_only: crwdns99250:0crwdne99250:0 - attribute_highlighting: crwdns99251:0crwdne99251:0 - relation_columns: crwdns99252:0crwdne99252:0 - check_out_link: crwdns99253:0crwdne99253:0 + attribute_highlighting: crwdns101951:0crwdne101951:0 + relation_columns: crwdns101952:0crwdne101952:0 + check_out_link: crwdns101953:0crwdne101953:0 tabs: - overview: crwdns98772:0crwdne98772:0 - activity: crwdns98773:0crwdne98773:0 - relations: crwdns98774:0crwdne98774:0 - watchers: crwdns98775:0crwdne98775:0 - attachments: crwdns98776:0crwdne98776:0 + overview: crwdns101954:0crwdne101954:0 + activity: crwdns101955:0crwdne101955:0 + relations: crwdns101956:0crwdne101956:0 + watchers: crwdns101957:0crwdne101957:0 + attachments: crwdns101958:0crwdne101958:0 time_relative: - days: crwdns98777:0crwdne98777:0 - weeks: crwdns98778:0crwdne98778:0 - months: crwdns98779:0crwdne98779:0 + days: crwdns101959:0crwdne101959:0 + weeks: crwdns101960:0crwdne101960:0 + months: crwdns101961:0crwdne101961:0 toolbar: settings: - configure_view: crwdns99071:0crwdne99071:0 - columns: crwdns98780:0crwdne98780:0 - sort_by: crwdns98781:0crwdne98781:0 - group_by: crwdns98782:0crwdne98782:0 - display_sums: crwdns98783:0crwdne98783:0 - display_hierarchy: crwdns98784:0crwdne98784:0 - hide_hierarchy: crwdns98785:0crwdne98785:0 - hide_sums: crwdns98786:0crwdne98786:0 - save: crwdns98787:0crwdne98787:0 - save_as: crwdns98788:0crwdne98788:0 - export: crwdns98789:0crwdne98789:0 - visibility_settings: crwdns99108:0crwdne99108:0 - page_settings: crwdns99067:0crwdne99067:0 - delete: crwdns98792:0crwdne98792:0 - filter: crwdns98793:0crwdne98793:0 - unselected_title: crwdns98794:0crwdne98794:0 - search_query_label: crwdns99109:0crwdne99109:0 - search_query_title: crwdns99110:0crwdne99110:0 - placeholder_query_title: crwdns99111:0crwdne99111:0 + configure_view: crwdns101962:0crwdne101962:0 + columns: crwdns101963:0crwdne101963:0 + sort_by: crwdns101964:0crwdne101964:0 + group_by: crwdns101965:0crwdne101965:0 + display_sums: crwdns101966:0crwdne101966:0 + display_hierarchy: crwdns101967:0crwdne101967:0 + hide_hierarchy: crwdns101968:0crwdne101968:0 + hide_sums: crwdns101969:0crwdne101969:0 + save: crwdns101970:0crwdne101970:0 + save_as: crwdns101971:0crwdne101971:0 + export: crwdns101972:0crwdne101972:0 + visibility_settings: crwdns101973:0crwdne101973:0 + page_settings: crwdns101974:0crwdne101974:0 + delete: crwdns101975:0crwdne101975:0 + filter: crwdns101976:0crwdne101976:0 + unselected_title: crwdns101977:0crwdne101977:0 + search_query_label: crwdns101978:0crwdne101978:0 + search_query_title: crwdns101979:0crwdne101979:0 + placeholder_query_title: crwdns101980:0crwdne101980:0 modals: - label_settings: crwdns99068:0crwdne99068:0 - label_name: crwdns98798:0crwdne98798:0 - label_delete_page: crwdns98799:0crwdne98799:0 - button_apply: crwdns98800:0crwdne98800:0 - button_save: crwdns98801:0crwdne98801:0 - button_submit: crwdns98802:0crwdne98802:0 - button_cancel: crwdns98803:0crwdne98803:0 + label_settings: crwdns101981:0crwdne101981:0 + label_name: crwdns101982:0crwdne101982:0 + label_delete_page: crwdns101983:0crwdne101983:0 + button_apply: crwdns101984:0crwdne101984:0 + button_save: crwdns101985:0crwdne101985:0 + button_submit: crwdns101986:0crwdne101986:0 + button_cancel: crwdns101987:0crwdne101987:0 form_submit: - title: crwdns98804:0crwdne98804:0 - text: crwdns98805:0crwdne98805:0 + title: crwdns101988:0crwdne101988:0 + text: crwdns101989:0crwdne101989:0 destroy_work_package: - title: crwdns98808:0%{label}crwdne98808:0 - text: crwdns98809:0%{label}crwdne98809:0 - has_children: crwdns98810:0%{childUnits}crwdne98810:0 - confirm_deletion_children: crwdns102029:0crwdne102029:0 - deletes_children: crwdns99130:0crwdne99130:0 - notice_successful_create: crwdns98812:0crwdne98812:0 - notice_successful_delete: crwdns98813:0crwdne98813:0 - notice_successful_update: crwdns98814:0crwdne98814:0 - notice_bad_request: crwdns98815:0crwdne98815:0 + title: crwdns101990:0%{label}crwdne101990:0 + text: crwdns101991:0%{label}crwdne101991:0 + has_children: crwdns101992:0%{childUnits}crwdne101992:0 + confirm_deletion_children: crwdns102528:0crwdne102528:0 + deletes_children: crwdns101994:0crwdne101994:0 + notice_successful_create: crwdns101995:0crwdne101995:0 + notice_successful_delete: crwdns101996:0crwdne101996:0 + notice_successful_update: crwdns101997:0crwdne101997:0 + notice_bad_request: crwdns101998:0crwdne101998:0 relations: - empty: crwdns98816:0crwdne98816:0 - remove: crwdns98817:0crwdne98817:0 + empty: crwdns101999:0crwdne101999:0 + remove: crwdns102000:0crwdne102000:0 inplace: - button_edit: crwdns98818:0%{attribute}crwdne98818:0 - button_save: crwdns98819:0%{attribute}crwdne98819:0 - button_cancel: crwdns98820:0%{attribute}crwdne98820:0 - button_save_all: crwdns98821:0crwdne98821:0 - button_cancel_all: crwdns98822:0crwdne98822:0 - link_formatting_help: crwdns98823:0crwdne98823:0 - btn_preview_enable: crwdns98824:0crwdne98824:0 - btn_preview_disable: crwdns98825:0crwdne98825:0 - null_value_label: crwdns98826:0crwdne98826:0 - clear_value_label: crwdns98827:0crwdne98827:0 + button_edit: crwdns102001:0%{attribute}crwdne102001:0 + button_save: crwdns102002:0%{attribute}crwdne102002:0 + button_cancel: crwdns102003:0%{attribute}crwdne102003:0 + button_save_all: crwdns102004:0crwdne102004:0 + button_cancel_all: crwdns102005:0crwdne102005:0 + link_formatting_help: crwdns102006:0crwdne102006:0 + btn_preview_enable: crwdns102007:0crwdne102007:0 + btn_preview_disable: crwdns102008:0crwdne102008:0 + null_value_label: crwdns102009:0crwdne102009:0 + clear_value_label: crwdns102010:0crwdne102010:0 errors: - required: crwdns98828:0%{field}crwdne98828:0 - number: crwdns98829:0%{field}crwdne98829:0 - maxlength: crwdns98830:0%{field}crwdnd98830:0%{maxLength}crwdne98830:0 - minlength: crwdns98831:0%{field}crwdnd98831:0%{minLength}crwdne98831:0 - messages_on_field: crwdns98832:0%{messages}crwdne98832:0 - error_could_not_resolve_version_name: crwdns98833:0crwdne98833:0 - error_could_not_resolve_user_name: crwdns98834:0crwdne98834:0 - error_attachment_upload: crwdns98990:0%{name}crwdnd98990:0%{error}crwdne98990:0 - error_attachment_upload_permission: crwdns99060:0crwdne99060:0 + required: crwdns102011:0%{field}crwdne102011:0 + number: crwdns102012:0%{field}crwdne102012:0 + maxlength: crwdns102013:0%{field}crwdnd102013:0%{maxLength}crwdne102013:0 + minlength: crwdns102014:0%{field}crwdnd102014:0%{minLength}crwdne102014:0 + messages_on_field: crwdns102015:0%{messages}crwdne102015:0 + error_could_not_resolve_version_name: crwdns102016:0crwdne102016:0 + error_could_not_resolve_user_name: crwdns102017:0crwdne102017:0 + error_attachment_upload: crwdns102018:0%{name}crwdnd102018:0%{error}crwdne102018:0 + error_attachment_upload_permission: crwdns102019:0crwdne102019:0 units: workPackage: - one: crwdns98835:1crwdne98835:1 - other: crwdns98835:5crwdne98835:5 + one: crwdns102020:1crwdne102020:1 + other: crwdns102020:5crwdne102020:5 child_work_packages: - one: crwdns98836:1crwdne98836:1 - other: crwdns98836:5%{count}crwdne98836:5 + one: crwdns102021:1crwdne102021:1 + other: crwdns102021:5%{count}crwdne102021:5 hour: - one: crwdns98837:1crwdne98837:1 - other: crwdns98837:5%{count}crwdne98837:5 + one: crwdns102022:1crwdne102022:1 + other: crwdns102022:5%{count}crwdne102022:5 zero: 0 hours zen_mode: - button_activate: crwdns98838:0crwdne98838:0 - button_deactivate: crwdns98839:0crwdne98839:0 + button_activate: crwdns102023:0crwdne102023:0 + button_deactivate: crwdns102024:0crwdne102024:0 diff --git a/config/locales/crowdin/js-lt.yml b/config/locales/crowdin/js-lt.yml index 06d0e21091..f9552ef6a6 100644 --- a/config/locales/crowdin/js-lt.yml +++ b/config/locales/crowdin/js-lt.yml @@ -107,6 +107,10 @@ lt: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: įjungta + current_date: Current date error: internal: Įvyko vidinė klaida. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -473,6 +477,8 @@ lt: į Microsoft Edge. learn_more: Sužinoti daugiau close_warning: Ignoruoti šį perspėjimą. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Paryškintas italic: Pasvirasis @@ -653,14 +659,15 @@ lt: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Būsena priority: Pirmenybė + type: Tipas columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Ar reikia matyti ryšius darbų paketų sąraše? diff --git a/config/locales/crowdin/js-lv.yml b/config/locales/crowdin/js-lv.yml index 78af6f6cbe..1e7dd70eda 100644 --- a/config/locales/crowdin/js-lv.yml +++ b/config/locales/crowdin/js-lv.yml @@ -107,6 +107,10 @@ lv: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: " " + current_date: Current date error: internal: Radusies iekšēja kļūda. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -469,6 +473,8 @@ lv: to Microsoft Edge. learn_more: Uzzināt vairāk close_warning: Ignore this warning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Trekns italic: Slīps @@ -647,14 +653,15 @@ lv: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Statuss priority: Prioritāte + type: Veids columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-nl.yml b/config/locales/crowdin/js-nl.yml index 6441925c56..20a6305954 100644 --- a/config/locales/crowdin/js-nl.yml +++ b/config/locales/crowdin/js-nl.yml @@ -109,6 +109,10 @@ nl: embedded_table: button: Werk pakket tabel insluiten text: "[Placeholder] ingesloten werkpakket tabel" + custom_actions: + date: + specific: op + current_date: Current date error: internal: Een interne fout is opgetreden. cannot_save_changes_with_message: 'Uw wijzigingen vanwege de volgende fout niet @@ -478,6 +482,8 @@ nl: Edge. learn_more: Leer meer close_warning: Negeer deze waarschuwing. + upsale: + ee_only: Functie alleen voor de Enterprise Editie wiki_formatting: strong: Vet italic: Schuingedrukt @@ -658,15 +664,16 @@ nl: highlighting_mode: description: Markeren met kleur none: Geen markering - inline: Achterstallige datums, 'Status',”Type” en 'Prioriteit' kenmerk + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Hele rij door status: Status priority: Prioriteit + type: Type columns_help_text: Gebruik de bovenstaande toegang voor het toevoegen of verwijderen van kolommen aan uw tabelweergave. U kunt de kolommen slepen en neerzetten om deze te rangschikken. upsale: - ee_only: Functie alleen voor de Enterprise Editie attribute_highlighting: Moeten bepaalde werkpakketten te onderscheiden zijn van de massa? relation_columns: Nodig om te zien van betrekkingen in de pakketlijst werk? diff --git a/config/locales/crowdin/js-no.yml b/config/locales/crowdin/js-no.yml index 2fedaa5b8d..43a954ab44 100644 --- a/config/locales/crowdin/js-no.yml +++ b/config/locales/crowdin/js-no.yml @@ -107,6 +107,10 @@ embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: på + current_date: Current date error: internal: An internal error has occurred. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -468,6 +472,8 @@ to Microsoft Edge. learn_more: Mer informasjon close_warning: Ignore this warning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Halvfet italic: Kursiv @@ -645,14 +651,15 @@ highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Status priority: Prioritet + type: Type columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-pl.yml b/config/locales/crowdin/js-pl.yml index 112021b451..a33f1c6839 100644 --- a/config/locales/crowdin/js-pl.yml +++ b/config/locales/crowdin/js-pl.yml @@ -108,6 +108,10 @@ pl: embedded_table: button: Osadź tabelę pakietów roboczych text: "[Placeholder] Osadzona tabela pakietów roboczych" + custom_actions: + date: + specific: wł + current_date: Aktualna data error: internal: Wystąpił błąd wewnętrzny. cannot_save_changes_with_message: 'Nie można zapisać zmian ze względu na następujący @@ -471,6 +475,8 @@ pl: lub zaistalować przeglądarkę Microsoft Edge. learn_more: Dowiedz się więcej close_warning: Zignoruj to ostrzeżenie. + upsale: + ee_only: Funkcja dostępna tylko w wersji Enterprise wiki_formatting: strong: Pogrubienie italic: Kursywa @@ -648,15 +654,16 @@ pl: highlighting_mode: description: Wyróżniaj kolorem none: Bez wyróżniania - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Cały wiersz wg status: Status priority: Priorytet + type: Typ columns_help_text: Użyj powyższych danych wejściowych, aby dodać lub usunąć kolumny w widoku tabeli. Możesz przeciągać i upuszczać kolumny, aby zmienić ich kolejność. upsale: - ee_only: Funkcja dostępna tylko w wersji Enterprise attribute_highlighting: Czy określone pakiety robocze trzeba wyróżnić? relation_columns: Chcesz zobaczyć relacje w tej liście pakietów roboczych? check_out_link: Sprawdź wersję Enterprise. diff --git a/config/locales/crowdin/js-pt-BR.yml b/config/locales/crowdin/js-pt-BR.yml index 6eccb84833..bb60472427 100644 --- a/config/locales/crowdin/js-pt-BR.yml +++ b/config/locales/crowdin/js-pt-BR.yml @@ -112,6 +112,10 @@ pt-BR: embedded_table: button: Embutir tabela de pacote de trabalho text: "[Placeholder] Embutida tabela de pacote de trabalho" + custom_actions: + date: + specific: ligado + current_date: Current date error: internal: Ocorreu um erro interno. cannot_save_changes_with_message: 'Não foi possível salvar as alterações devido @@ -476,6 +480,8 @@ pt-BR: para o Microsoft Edge. learn_more: Saiba mais close_warning: Ignorar este aviso. + upsale: + ee_only: Recurso exclusivo da Enterprise Edition wiki_formatting: strong: Negrito italic: Itálico @@ -497,7 +503,7 @@ pt-BR: move: Mover vários edit: Editar vários copy: Copiar vários - delete: Excluir vários + delete: Remover vários button_clear: Limpar comment_added: O comentário foi adicionado com sucesso. comment_send_failed: Ocorreu um erro. Não foi possível enviar o comentário. @@ -654,14 +660,15 @@ pt-BR: highlighting_mode: description: Destacar com cor none: Sem destaque - inline: Datas atrasadas, "Situação", "Tipo" e atributo "Prioridade" + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Toda linha por status: Situação priority: Prioridade + type: Tipo columns_help_text: Use a entrada acima para adicionar ou remover colunas à sua exibição de tabela. Você pode arrastar e soltar as colunas para reordená-las. upsale: - ee_only: Recurso exclusivo da Enterprise Edition attribute_highlighting: Precisa de certos pacotes de trabalho para se destacar da massa? relation_columns: Necessário ver as relações na lista de pacote de trabalho? diff --git a/config/locales/crowdin/js-pt.yml b/config/locales/crowdin/js-pt.yml index c81be26366..369f81ca0f 100644 --- a/config/locales/crowdin/js-pt.yml +++ b/config/locales/crowdin/js-pt.yml @@ -109,6 +109,10 @@ pt: embedded_table: button: Incorporar a tabela de pacote de trabalho text: "[Placeholder] Tabela de pacote de trabalho incorporada" + custom_actions: + date: + specific: 'on' + current_date: Current date error: internal: Ocorreu um erro interno. cannot_save_changes_with_message: 'Não é possível guardar as alterações devido @@ -301,7 +305,7 @@ pt: work_package_belongs_to: Este pacote de trabalho pertence ao projeto %{projectname}. click_to_switch_context: Abra este pacote de trabalho nesse projeto. autocompleter: - label: Autocompletar Projeto + label: Conclusão automática do Projecto text_are_you_sure: Tem a certeza? types: attribute_groups: @@ -470,6 +474,8 @@ pt: para o Microsoft Edge. learn_more: Saber mais close_warning: Ignore este aviso. + upsale: + ee_only: Recurso exclusivo da Edição Empresarial wiki_formatting: strong: Negrito italic: Itálico @@ -647,15 +653,16 @@ pt: highlighting_mode: description: Destaque com cor none: Sem destaque - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Toda a linha por status: Situação priority: Prioridade + type: Tipo columns_help_text: Utilize a entrada acima para adicionar ou remover colunas ao seu modo de vista de tabela. Pode arrastar e soltar as colunas para as reordenar. upsale: - ee_only: Recurso exclusivo da Edição Empresarial attribute_highlighting: Precisa de certos pacotes de trabalho para se destacar do resto? relation_columns: Precisa de ver as relações na lista do pacote de trabalho? diff --git a/config/locales/crowdin/js-ro.yml b/config/locales/crowdin/js-ro.yml index 48e00df431..44a2437bfc 100644 --- a/config/locales/crowdin/js-ro.yml +++ b/config/locales/crowdin/js-ro.yml @@ -109,6 +109,10 @@ ro: embedded_table: button: Inserați tabel pachet de lucru text: "[Placeholder] Tabelul pachetului de lucru inserat" + custom_actions: + date: + specific: pe + current_date: Current date error: internal: A apărut o eroare internă. cannot_save_changes_with_message: 'Schimbările nu pot fi salvate datorită acestei @@ -478,6 +482,8 @@ ro: faceți un upgrade către Microsoft Edge. learn_more: Aflați mai multe close_warning: Ignoră acest avertisment. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Aldin italic: Italic @@ -658,14 +664,15 @@ ro: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Stare priority: Prioritate + type: Tip columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-ru.yml b/config/locales/crowdin/js-ru.yml index e9e86d4c43..92c43e69d7 100644 --- a/config/locales/crowdin/js-ru.yml +++ b/config/locales/crowdin/js-ru.yml @@ -110,6 +110,10 @@ ru: embedded_table: button: Вложить таблицу пакетов работ text: "[Placeholder] Таблица внедренных пакетов работ" + custom_actions: + date: + specific: на + current_date: Текущая дата error: internal: Произошла внутренняя ошибка. cannot_save_changes_with_message: 'Не удается сохранить изменения из-за следующей @@ -473,6 +477,8 @@ ru: обновитесь до Microsoft Edge. learn_more: Узнать больше close_warning: Игнорировать это предупреждение. + upsale: + ee_only: Эта функция есть только в корпоративной версии wiki_formatting: strong: Выделение жирным italic: Курсив @@ -653,15 +659,16 @@ ru: highlighting_mode: description: Цветной подсветки none: Без подсветки - inline: Просроченные даты, атрибуты «Статус», «Тип» и «Приоритет» + inline: Выделенные атрибуты + inline_all: Все атрибуты entire_row_by: Вся строка по status: Состояние priority: Приоритет + type: Тип columns_help_text: Используйте ввод выше для добавления или удаления столбцов в табличном представлении. Вы можете перетаскивать столбцы для изменения их порядка. upsale: - ee_only: Эта функция есть только в корпоративной версии attribute_highlighting: Хотите выделить некоторые пакеты работ из общей массы? relation_columns: Нужно видеть отношения в списке пакетов работ? diff --git a/config/locales/crowdin/js-sk.yml b/config/locales/crowdin/js-sk.yml index 2e034e0f3e..eccf2db244 100644 --- a/config/locales/crowdin/js-sk.yml +++ b/config/locales/crowdin/js-sk.yml @@ -107,6 +107,10 @@ sk: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: dňa + current_date: Current date error: internal: Vyskytla sa vnútorná chyba. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -474,6 +478,8 @@ sk: to Microsoft Edge. learn_more: Zistiť viac close_warning: Ignore this warning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Tučné italic: Kurzíva @@ -652,14 +658,15 @@ sk: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Stav priority: Priorita + type: Typ columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Potrebujete vidieť vzťahy v zozname pracovných balíčkov? diff --git a/config/locales/crowdin/js-sv-SE.yml b/config/locales/crowdin/js-sv-SE.yml index e31474d018..ca1322470d 100644 --- a/config/locales/crowdin/js-sv-SE.yml +++ b/config/locales/crowdin/js-sv-SE.yml @@ -110,6 +110,10 @@ sv-SE: embedded_table: button: Bädda in arbetspaket-tabell text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: på + current_date: Current date error: internal: Ett internt fel har inträffat. cannot_save_changes_with_message: 'Kan inte spara dina ändringar på grund av @@ -471,6 +475,8 @@ sv-SE: uppgradera till Microsoft Edge. learn_more: Lär dig mer close_warning: Bortse från denna varning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Fetstil italic: Kursiv @@ -646,15 +652,16 @@ sv-SE: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Status priority: Prioritet + type: Typ columns_help_text: Använd inmatningen ovan för att lägga till eller ta bort kolumner i din tabellvy. Du kan dra och släppa kolumnerna för att omordna dem. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-th.yml b/config/locales/crowdin/js-th.yml index d5e6f1258c..bad22659b5 100644 --- a/config/locales/crowdin/js-th.yml +++ b/config/locales/crowdin/js-th.yml @@ -106,6 +106,10 @@ th: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: 'on' + current_date: Current date error: internal: An internal error has occurred. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -467,6 +471,8 @@ th: Microsoft Edge learn_more: เรียนรู้เพิ่มเติม close_warning: ไม่สนใจคำเตือนนี้ + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Strong italic: ตัวเอียง @@ -645,14 +651,15 @@ th: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: สถานะ priority: ระดับความสำคัญ + type: ประเภท columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-tr.yml b/config/locales/crowdin/js-tr.yml index 7e68f84f6f..dd7e82c4ba 100644 --- a/config/locales/crowdin/js-tr.yml +++ b/config/locales/crowdin/js-tr.yml @@ -60,7 +60,7 @@ tr: description_subwork_package: "#%{id} nolu iş paketinin alt parçası" editor: preview: Önizleme modunu aç/kapat - source_code: İşaretleme kaynak modunu değiştir + source_code: Markdown kaynak modunu değiştir error_saving_failed: 'Aşağıdaki nedenden dolayı belge kayıt edilemedi: %{error}' mode: manual: Markdown kaynağına geç @@ -107,6 +107,10 @@ tr: embedded_table: button: Gömülü iş paketi tablosu text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: açık + current_date: Geçerli tarih error: internal: İç hata oluştu. cannot_save_changes_with_message: 'Değişikliklerinizin kaydedilememesine sebep @@ -471,6 +475,8 @@ tr: da Microsoft Edge'e yükseltin. learn_more: Daha fazla bilgi edin close_warning: Bu uyarıyı yoksay. + upsale: + ee_only: Enterprise Edition özelliği wiki_formatting: strong: Kalın italic: İtalik @@ -648,14 +654,15 @@ tr: highlighting_mode: description: Rekle vurgula none: Vurgulama - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Vurgulanan öznitelik(ler) + inline_all: Tüm öznitelikler entire_row_by: Entire row by status: Durum priority: Öncelik + type: Tür columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition özelliği attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: İş paketleri listesindeki ilişkileri görmek ister misiniz? diff --git a/config/locales/crowdin/js-uk.yml b/config/locales/crowdin/js-uk.yml index 69d0c4af8b..9b28558936 100644 --- a/config/locales/crowdin/js-uk.yml +++ b/config/locales/crowdin/js-uk.yml @@ -107,6 +107,10 @@ uk: embedded_table: button: Embed work package table text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: на + current_date: Current date error: internal: Сталася внутрішня помилка. cannot_save_changes_with_message: 'Cannot save your changes due to the following @@ -476,6 +480,8 @@ uk: оновіться до Microsoft Edge. learn_more: Learn more close_warning: Ігнорувати це попередження. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Жирний italic: Курсив @@ -654,14 +660,15 @@ uk: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Status priority: Priority + type: Type columns_help_text: Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-vi.yml b/config/locales/crowdin/js-vi.yml index af5b23049c..b0e2d732fa 100644 --- a/config/locales/crowdin/js-vi.yml +++ b/config/locales/crowdin/js-vi.yml @@ -110,6 +110,10 @@ vi: embedded_table: button: Nhúng danh sách gói công việc dưới dạng bảng text: "[Placeholder] gói công việc nhúng" + custom_actions: + date: + specific: 'on' + current_date: Current date error: internal: Lỗi nội bộ đã xảy ra. cannot_save_changes_with_message: 'Không thể lưu thay đổi của bạn do lỗi sau: @@ -471,6 +475,8 @@ vi: to Microsoft Edge. learn_more: Learn more close_warning: Ignore this warning. + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: Strong italic: Italic @@ -647,14 +653,15 @@ vi: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: Trạng thái priority: Độ ưu tiên + type: Kiểu columns_help_text: Sử dụng ô nhập liệu trên đây để thêm hoặc bớt cột vào bảng của bạn. Bạn có thể kéo thả cột để thay đổi trật tự của nó. upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: Need to see relations in the work package list? diff --git a/config/locales/crowdin/js-zh-TW.yml b/config/locales/crowdin/js-zh-TW.yml index 9dbbabafb3..f4f470af74 100644 --- a/config/locales/crowdin/js-zh-TW.yml +++ b/config/locales/crowdin/js-zh-TW.yml @@ -106,6 +106,10 @@ zh-TW: embedded_table: button: 嵌入工作包表 text: "[Placeholder] Embedded work package table" + custom_actions: + date: + specific: 開啟 + current_date: Current date error: internal: 發生內部錯誤。 cannot_save_changes_with_message: '由於以下錯誤, 無法保存所做的更改: %{error}' @@ -447,6 +451,8 @@ zh-TW: update_ie_user: 請改用Mozilla Firefox或Google Chrome,或者升級到Microsoft Edge。 learn_more: 了解更多 close_warning: 忽略此警告。 + upsale: + ee_only: Enterprise Edition only feature wiki_formatting: strong: 粗體 italic: 斜體 @@ -608,13 +614,14 @@ zh-TW: highlighting_mode: description: Highlight with color none: No highlighting - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: Entire row by status: 狀態 priority: 優先等級 + type: 類型 columns_help_text: 使用上面的輸入在表視圖中添加或移除列。可以拖放列以對其進行重新排序。 upsale: - ee_only: Enterprise Edition only feature attribute_highlighting: Need certain work packages to stand out from the mass? relation_columns: 需要檢視工作項目清單的關係嗎 diff --git a/config/locales/crowdin/js-zh.yml b/config/locales/crowdin/js-zh.yml index 445f770750..1b76ced8a9 100644 --- a/config/locales/crowdin/js-zh.yml +++ b/config/locales/crowdin/js-zh.yml @@ -101,6 +101,10 @@ zh: embedded_table: button: 嵌入工作包表 text: "[Placeholder] 嵌入式工作包表" + custom_actions: + date: + specific: 于 + current_date: Current date error: internal: 发生了内部错误。 cannot_save_changes_with_message: 由于%{error} 原因,无法保存您的更改。 @@ -438,6 +442,8 @@ zh: update_ie_user: 请使用Mozilla Firefox或者Google Chrome浏览器,或者升级到Microsoft Edge浏览器。 learn_more: 了解更多信息 close_warning: 请忽略这个警告。 + upsale: + ee_only: 企业版特定功能 wiki_formatting: strong: 加强 italic: 斜体 @@ -597,13 +603,14 @@ zh: highlighting_mode: description: 使用颜色突出显示 none: 无突出显示 - inline: Overdue dates, "Status", "Type", and "Priority" attribute + inline: Highlighted attribute(s) + inline_all: All attributes entire_row_by: 整行 status: 状态 priority: 优先级 + type: 类型 columns_help_text: 使用上面的输入向表视图添加或删除列。 您可以拖放列以重新排序它们。 upsale: - ee_only: 企业版特定功能 attribute_highlighting: 需要特定的工作包以脱颖而出? relation_columns: 需要查看工作包列表中的关系吗? check_out_link: 签出企业版。 diff --git a/config/locales/crowdin/ko.yml b/config/locales/crowdin/ko.yml index f45f249fe1..c6f3b0da01 100644 --- a/config/locales/crowdin/ko.yml +++ b/config/locales/crowdin/ko.yml @@ -995,6 +995,7 @@ ko: ' error_external_authentication_failed: 외부 인증 중에 오류가 발생했습니다. 다시 시도하세요. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: 프로젝트 편집됨 changeset: 변경 집합 편집됨 @@ -1044,7 +1045,7 @@ ko: upsale: become_hero: 영웅이 되세요! title: Enterprise Edition으로 업그레이드 하세요. - description: Enterprise Edition으로 당신의 생산성을 끌어올리세요. + description: What are the benefits? more_info: 더보기 additional_features: 추가적인 강력한 프리미엄 기능들 professional_support: OpenProject 전문가들의 전문적인 지원 @@ -1797,7 +1798,7 @@ ko: 수 있습니다. text_show_again: 도움말 메뉴에서 이 비디오를 다시 시작할 수 있습니다. welcome: OpenProject에 오신 것을 환영합니다. - select_language: OpenProject에 대한 해당 언어를 선택하세요. + select_language: Please select your language permission_add_work_package_notes: 메모 추가 permission_add_work_packages: 작업 패키지 추가 permission_add_messages: 메시지 게시 @@ -2121,7 +2122,9 @@ ko: setting_welcome_on_homescreen: 홈 화면에 환영 블록 표시 setting_wiki_compression: 위키 기록 압축 setting_work_package_group_assignment: 그룹에 할당 허용 - setting_work_package_list_default_highlighting_mode: 기본 작업 패키지 강조 표시 모드 + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: 일반 other: 기타 @@ -2131,6 +2134,13 @@ ko: user: default_preferences: 기본 설정 deletion: 삭제 + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: 강조 표시 없음 + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: 일반 텍스트 diff --git a/config/locales/crowdin/lol.yml b/config/locales/crowdin/lol.yml index 05ff138dad..5659df6630 100644 --- a/config/locales/crowdin/lol.yml +++ b/config/locales/crowdin/lol.yml @@ -1,2434 +1,2443 @@ --- lol: - no_results_title_text: crwdns96368:0crwdne96368:0 + no_results_title_text: crwdns99385:0crwdne99385:0 activities: index: - no_results_title_text: crwdns99113:0crwdne99113:0 + no_results_title_text: crwdns99386:0crwdne99386:0 admin: plugins: - no_results_title_text: crwdns96370:0crwdne96370:0 + no_results_title_text: crwdns99387:0crwdne99387:0 custom_styles: - custom_colors: crwdns96371:0crwdne96371:0 - customize: crwdns96372:0crwdne96372:0 - enterprise_notice: crwdns96373:0crwdne96373:0 - manage_colors: crwdns96374:0crwdne96374:0 + custom_colors: crwdns99388:0crwdne99388:0 + customize: crwdns99389:0crwdne99389:0 + enterprise_notice: crwdns99390:0crwdne99390:0 + manage_colors: crwdns99391:0crwdne99391:0 instructions: - alternative_color: crwdns96375:0crwdne96375:0 - content_link_color: crwdns96376:0crwdne96376:0 - primary_color: crwdns96377:0crwdne96377:0 - primary_color_dark: crwdns96378:0crwdne96378:0 - header_bg_color: crwdns96379:0crwdne96379:0 - header_item_bg_hover_color: crwdns96380:0crwdne96380:0 - header_item_font_color: crwdns96381:0crwdne96381:0 - header_item_font_hover_color: crwdns96382:0crwdne96382:0 - header_border_bottom_color: crwdns96383:0crwdne96383:0 - main_menu_bg_color: crwdns96384:0crwdne96384:0 + alternative_color: crwdns99392:0crwdne99392:0 + content_link_color: crwdns99393:0crwdne99393:0 + primary_color: crwdns99394:0crwdne99394:0 + primary_color_dark: crwdns99395:0crwdne99395:0 + header_bg_color: crwdns99396:0crwdne99396:0 + header_item_bg_hover_color: crwdns99397:0crwdne99397:0 + header_item_font_color: crwdns99398:0crwdne99398:0 + header_item_font_hover_color: crwdns99399:0crwdne99399:0 + header_border_bottom_color: crwdns99400:0crwdne99400:0 + main_menu_bg_color: crwdns99401:0crwdne99401:0 enterprise: - upgrade_to_ee: crwdns96385:0crwdne96385:0 - add_token: crwdns96386:0crwdne96386:0 - replace_token: crwdns96387:0crwdne96387:0 - order: crwdns96388:0crwdne96388:0 - paste: crwdns96389:0crwdne96389:0 - required_for_feature: crwdns96390:0crwdne96390:0 - enterprise_link: crwdns96391:0crwdne96391:0 + upgrade_to_ee: crwdns99402:0crwdne99402:0 + add_token: crwdns99403:0crwdne99403:0 + replace_token: crwdns99404:0crwdne99404:0 + order: crwdns99405:0crwdne99405:0 + paste: crwdns99406:0crwdne99406:0 + required_for_feature: crwdns99407:0crwdne99407:0 + enterprise_link: crwdns99408:0crwdne99408:0 announcements: - show_until: crwdns96392:0crwdne96392:0 - is_active: crwdns96393:0crwdne96393:0 - is_inactive: crwdns96394:0crwdne96394:0 + show_until: crwdns99409:0crwdne99409:0 + is_active: crwdns99410:0crwdne99410:0 + is_inactive: crwdns99411:0crwdne99411:0 attribute_help_texts: - text_overview: crwdns96395:0crwdne96395:0 - label_plural: crwdns96396:0crwdne96396:0 - show_preview: crwdns96397:0crwdne96397:0 - add_new: crwdns96398:0crwdne96398:0 - edit: crwdns96399:0%{attribute_caption}crwdne96399:0 + text_overview: crwdns99412:0crwdne99412:0 + label_plural: crwdns99413:0crwdne99413:0 + show_preview: crwdns99414:0crwdne99414:0 + add_new: crwdns99415:0crwdne99415:0 + edit: crwdns99416:0%{attribute_caption}crwdne99416:0 auth_sources: index: - no_results_content_title: crwdns96400:0crwdne96400:0 - no_results_content_text: crwdns96401:0crwdne96401:0 + no_results_content_title: crwdns99417:0crwdne99417:0 + no_results_content_text: crwdns99418:0crwdne99418:0 boards: show: - no_results_title_text: crwdns96402:0crwdne96402:0 + no_results_title_text: crwdns99419:0crwdne99419:0 colors: index: - no_results_title_text: crwdns99215:0crwdne99215:0 - no_results_content_text: crwdns99216:0crwdne99216:0 - label_no_color: crwdns99217:0crwdne99217:0 + no_results_title_text: crwdns99420:0crwdne99420:0 + no_results_content_text: crwdns99421:0crwdne99421:0 + label_no_color: crwdns99422:0crwdne99422:0 custom_actions: actions: - name: crwdns98840:0crwdne98840:0 - add: crwdns98841:0crwdne98841:0 + name: crwdns99423:0crwdne99423:0 + add: crwdns99424:0crwdne99424:0 assigned_to: - executing_user_value: crwdns99169:0crwdne99169:0 - conditions: crwdns98842:0crwdne98842:0 - plural: crwdns98843:0crwdne98843:0 - new: crwdns98844:0crwdne98844:0 - edit: crwdns98845:0%{name}crwdne98845:0 - execute: crwdns98870:0%{name}crwdne98870:0 + executing_user_value: crwdns99425:0crwdne99425:0 + conditions: crwdns99426:0crwdne99426:0 + plural: crwdns99427:0crwdne99427:0 + new: crwdns99428:0crwdne99428:0 + edit: crwdns99429:0%{name}crwdne99429:0 + execute: crwdns99430:0%{name}crwdne99430:0 upsale: - title: crwdns98846:0crwdne98846:0 - description: crwdns98847:0crwdne98847:0 + title: crwdns99431:0crwdne99431:0 + description: crwdns99432:0crwdne99432:0 custom_fields: - text_add_new_custom_field: 'crwdns96403:0crwdne96403:0 + text_add_new_custom_field: 'crwdns99433:0crwdne99433:0 ' - is_enabled_globally: crwdns96404:0crwdne96404:0 - enabled_in_project: crwdns96405:0crwdne96405:0 - contained_in_type: crwdns96406:0crwdne96406:0 - confirm_destroy_option: crwdns96407:0crwdne96407:0 + is_enabled_globally: crwdns99434:0crwdne99434:0 + enabled_in_project: crwdns99435:0crwdne99435:0 + contained_in_type: crwdns99436:0crwdne99436:0 + confirm_destroy_option: crwdns99437:0crwdne99437:0 tab: - no_results_title_text: crwdns96408:0crwdne96408:0 - no_results_content_text: crwdns96409:0crwdne96409:0 + no_results_title_text: crwdns99438:0crwdne99438:0 + no_results_content_text: crwdns99439:0crwdne99439:0 concatenation: - single: crwdns99119:0crwdne99119:0 + single: crwdns99440:0crwdne99440:0 deprecations: old_timeline: - replacement: crwdns96410:0crwdne96410:0 - removal: crwdns96411:0crwdne96411:0 - further_information_before: crwdns96412:0crwdne96412:0 - link_name: crwdns96413:0crwdne96413:0 - further_information_after: crwdns96414:0crwdne96414:0 + replacement: crwdns99441:0crwdne99441:0 + removal: crwdns99442:0crwdne99442:0 + further_information_before: crwdns99443:0crwdne99443:0 + link_name: crwdns99444:0crwdne99444:0 + further_information_after: crwdns99445:0crwdne99445:0 calendar: - removal: crwdns96415:0crwdne96415:0 + removal: crwdns99446:0crwdne99446:0 groups: index: - no_results_title_text: crwdns96416:0crwdne96416:0 - no_results_content_text: crwdns96417:0crwdne96417:0 + no_results_title_text: crwdns99447:0crwdne99447:0 + no_results_content_text: crwdns99448:0crwdne99448:0 users: - no_results_title_text: crwdns96418:0crwdne96418:0 + no_results_title_text: crwdns99449:0crwdne99449:0 memberships: - no_results_title_text: crwdns96419:0crwdne96419:0 + no_results_title_text: crwdns99450:0crwdne99450:0 projects: index: - no_results_title_text: crwdns96422:0crwdne96422:0 - no_results_content_text: crwdns96423:0crwdne96423:0 + no_results_title_text: crwdns99451:0crwdne99451:0 + no_results_content_text: crwdns99452:0crwdne99452:0 settings: activities: - no_results_title_text: crwdns96424:0crwdne96424:0 + no_results_title_text: crwdns99453:0crwdne99453:0 boards: - no_results_title_text: crwdns96425:0crwdne96425:0 - no_results_content_text: crwdns96426:0crwdne96426:0 + no_results_title_text: crwdns99454:0crwdne99454:0 + no_results_content_text: crwdns99455:0crwdne99455:0 categories: - no_results_title_text: crwdns96427:0crwdne96427:0 - no_results_content_text: crwdns96428:0crwdne96428:0 + no_results_title_text: crwdns99456:0crwdne99456:0 + no_results_content_text: crwdns99457:0crwdne99457:0 custom_fields: - no_results_title_text: crwdns96429:0crwdne96429:0 + no_results_title_text: crwdns99458:0crwdne99458:0 types: - no_results_title_text: crwdns96430:0crwdne96430:0 + no_results_title_text: crwdns99459:0crwdne99459:0 versions: - no_results_title_text: crwdns96431:0crwdne96431:0 - no_results_content_text: crwdns96432:0crwdne96432:0 + no_results_title_text: crwdns99460:0crwdne99460:0 + no_results_content_text: crwdns99461:0crwdne99461:0 members: index: - no_results_title_text: crwdns96435:0crwdne96435:0 - no_results_content_text: crwdns96436:0crwdne96436:0 + no_results_title_text: crwdns99462:0crwdne99462:0 + no_results_content_text: crwdns99463:0crwdne99463:0 my: access_token: - failed_to_reset_token: crwdns96437:0%{error}crwdne96437:0 - notice_reset_token: crwdns96438:0%{type}crwdne96438:0 - token_value_warning: crwdns96439:0crwdne96439:0 - no_results_title_text: crwdns96440:0crwdne96440:0 + failed_to_reset_token: crwdns99464:0%{error}crwdne99464:0 + notice_reset_token: crwdns99465:0%{type}crwdne99465:0 + token_value_warning: crwdns99466:0crwdne99466:0 + no_results_title_text: crwdns99467:0crwdne99467:0 news: index: - no_results_title_text: crwdns96441:0crwdne96441:0 - no_results_content_text: crwdns96442:0crwdne96442:0 + no_results_title_text: crwdns99468:0crwdne99468:0 + no_results_content_text: crwdns99469:0crwdne99469:0 my_page: - no_results_title_text: crwdns96443:0crwdne96443:0 + no_results_title_text: crwdns99470:0crwdne99470:0 users: memberships: - no_results_title_text: crwdns96444:0crwdne96444:0 + no_results_title_text: crwdns99471:0crwdne99471:0 prioritiies: edit: - priority_color_text: 'crwdns99218:0crwdne99218:0 + priority_color_text: 'crwdns99472:0crwdne99472:0 ' reportings: index: - no_results_title_text: crwdns96445:0crwdne96445:0 - no_results_content_text: crwdns96446:0crwdne96446:0 + no_results_title_text: crwdns99473:0crwdne99473:0 + no_results_content_text: crwdns99474:0crwdne99474:0 statuses: edit: - status_color_text: 'crwdns99219:0crwdne99219:0 + status_color_text: 'crwdns99475:0crwdne99475:0 ' index: - no_results_title_text: crwdns96447:0crwdne96447:0 - no_results_content_text: crwdns96448:0crwdne96448:0 + no_results_title_text: crwdns99476:0crwdne99476:0 + no_results_content_text: crwdns99477:0crwdne99477:0 types: index: - no_results_title_text: crwdns96449:0crwdne96449:0 - no_results_content_text: crwdns96450:0crwdne96450:0 + no_results_title_text: crwdns99478:0crwdne99478:0 + no_results_content_text: crwdns99479:0crwdne99479:0 edit: - settings: crwdns96451:0crwdne96451:0 - form_configuration: crwdns96452:0crwdne96452:0 - projects: crwdns96453:0crwdne96453:0 - enabled_projects: crwdns96454:0crwdne96454:0 - add_group: crwdns98887:0crwdne98887:0 - add_subelements: crwdns98888:0crwdne98888:0 - edit_query: crwdns98889:0crwdne98889:0 - reset: crwdns96456:0crwdne96456:0 - type_color_text: 'crwdns99241:0crwdne99241:0 + settings: crwdns99480:0crwdne99480:0 + form_configuration: crwdns99481:0crwdne99481:0 + projects: crwdns99482:0crwdne99482:0 + enabled_projects: crwdns99483:0crwdne99483:0 + add_group: crwdns99484:0crwdne99484:0 + add_subelements: crwdns99485:0crwdne99485:0 + edit_query: crwdns99486:0crwdne99486:0 + reset: crwdns99487:0crwdne99487:0 + type_color_text: 'crwdns99488:0crwdne99488:0 ' versions: overview: - no_results_title_text: crwdns96457:0crwdne96457:0 + no_results_title_text: crwdns99489:0crwdne99489:0 wiki: - no_results_title_text: crwdns96458:0crwdne96458:0 + no_results_title_text: crwdns99490:0crwdne99490:0 index: - no_results_content_text: crwdns96459:0crwdne96459:0 + no_results_content_text: crwdns99491:0crwdne99491:0 work_flows: index: - no_results_title_text: crwdns96460:0crwdne96460:0 + no_results_title_text: crwdns99492:0crwdne99492:0 work_packages: x_descendants: - one: crwdns99125:1crwdne99125:1 - other: crwdns99125:5%{count}crwdne99125:5 + one: crwdns99493:1crwdne99493:1 + other: crwdns99493:5%{count}crwdne99493:5 move: - no_common_statuses_exists: crwdns99037:0crwdne99037:0 - unsupported_for_multiple_projects: crwdns96461:0crwdne96461:0 + no_common_statuses_exists: crwdns99494:0crwdne99494:0 + unsupported_for_multiple_projects: crwdns99495:0crwdne99495:0 list_simple: assigned: - no_results_title_text: crwdns96462:0crwdne96462:0 + no_results_title_text: crwdns99496:0crwdne99496:0 reported: - no_results_title_text: crwdns96463:0crwdne96463:0 + no_results_title_text: crwdns99497:0crwdne99497:0 responsible: - no_results_title_text: crwdns99072:0crwdne99072:0 + no_results_title_text: crwdns99498:0crwdne99498:0 watched: - no_results_title_text: crwdns96465:0crwdne96465:0 + no_results_title_text: crwdns99499:0crwdne99499:0 summary: reports: category: - no_results_title_text: crwdns96466:0crwdne96466:0 + no_results_title_text: crwdns99500:0crwdne99500:0 assigned_to: - no_results_title_text: crwdns96467:0crwdne96467:0 + no_results_title_text: crwdns99501:0crwdne99501:0 responsible: - no_results_title_text: crwdns96468:0crwdne96468:0 + no_results_title_text: crwdns99502:0crwdne99502:0 author: - no_results_title_text: crwdns96469:0crwdne96469:0 + no_results_title_text: crwdns99503:0crwdne99503:0 priority: - no_results_title_text: crwdns96470:0crwdne96470:0 + no_results_title_text: crwdns99504:0crwdne99504:0 type: - no_results_title_text: crwdns96471:0crwdne96471:0 + no_results_title_text: crwdns99505:0crwdne99505:0 version: - no_results_title_text: crwdns96472:0crwdne96472:0 - label_invitation: crwdns96473:0crwdne96473:0 + no_results_title_text: crwdns99506:0crwdne99506:0 + label_invitation: crwdns99507:0crwdne99507:0 account: - delete: crwdns96474:0crwdne96474:0 - delete_confirmation: crwdns96475:0crwdne96475:0 - deleted: crwdns96476:0crwdne96476:0 + delete: crwdns99508:0crwdne99508:0 + delete_confirmation: crwdns99509:0crwdne99509:0 + deleted: crwdns99510:0crwdne99510:0 deletion_info: data_consequences: - other: crwdns96477:0crwdne96477:0 - self: crwdns96478:0crwdne96478:0 - heading: crwdns96479:0%{name}crwdne96479:0 + other: crwdns99511:0crwdne99511:0 + self: crwdns99512:0crwdne99512:0 + heading: crwdns99513:0%{name}crwdne99513:0 info: - other: crwdns96480:0crwdne96480:0 - self: crwdns96481:0crwdne96481:0 + other: crwdns99514:0crwdne99514:0 + self: crwdns99515:0crwdne99515:0 login_consequences: - other: crwdns96482:0crwdne96482:0 - self: crwdns96483:0crwdne96483:0 + other: crwdns99516:0crwdne99516:0 + self: crwdns99517:0crwdne99517:0 login_verification: - other: crwdns98986:0%{name}crwdne98986:0 - self: crwdns98987:0%{name}crwdne98987:0 - error_inactive_activation_by_mail: 'crwdns96486:0crwdne96486:0 + other: crwdns99518:0%{name}crwdne99518:0 + self: crwdns99519:0%{name}crwdne99519:0 + error_inactive_activation_by_mail: 'crwdns99520:0crwdne99520:0 ' - error_inactive_manual_activation: 'crwdns96487:0crwdne96487:0 + error_inactive_manual_activation: 'crwdns99521:0crwdne99521:0 ' - error_self_registration_disabled: 'crwdns96488:0crwdne96488:0 + error_self_registration_disabled: 'crwdns99522:0crwdne99522:0 ' - login_with_auth_provider: crwdns96489:0crwdne96489:0 - signup_with_auth_provider: crwdns96490:0crwdne96490:0 - auth_source_login: crwdns96491:0%{login}crwdne96491:0 - omniauth_login: crwdns96492:0crwdne96492:0 - actionview_instancetag_blank_option: crwdns96493:0crwdne96493:0 + login_with_auth_provider: crwdns99523:0crwdne99523:0 + signup_with_auth_provider: crwdns99524:0crwdne99524:0 + auth_source_login: crwdns99525:0%{login}crwdne99525:0 + omniauth_login: crwdns99526:0crwdne99526:0 + actionview_instancetag_blank_option: crwdns99527:0crwdne99527:0 activerecord: attributes: announcements: - show_until: crwdns96494:0crwdne96494:0 + show_until: crwdns99528:0crwdne99528:0 attachment: - attachment_content: crwdns98857:0crwdne98857:0 - attachment_file_name: crwdns98858:0crwdne98858:0 - downloads: crwdns96495:0crwdne96495:0 - file: crwdns96496:0crwdne96496:0 - filename: crwdns96497:0crwdne96497:0 - filesize: crwdns96498:0crwdne96498:0 + attachment_content: crwdns99529:0crwdne99529:0 + attachment_file_name: crwdns99530:0crwdne99530:0 + downloads: crwdns99531:0crwdne99531:0 + file: crwdns99532:0crwdne99532:0 + filename: crwdns99533:0crwdne99533:0 + filesize: crwdns99534:0crwdne99534:0 attribute_help_text: - attribute_name: crwdns96499:0crwdne96499:0 - help_text: crwdns96500:0crwdne96500:0 + attribute_name: crwdns99535:0crwdne99535:0 + help_text: crwdns99536:0crwdne99536:0 auth_source: - account: crwdns96501:0crwdne96501:0 - attr_firstname: crwdns96502:0crwdne96502:0 - attr_lastname: crwdns96503:0crwdne96503:0 - attr_login: crwdns96504:0crwdne96504:0 - attr_mail: crwdns96505:0crwdne96505:0 - base_dn: crwdns96506:0crwdne96506:0 - host: crwdns96507:0crwdne96507:0 - onthefly: crwdns96508:0crwdne96508:0 - port: crwdns96509:0crwdne96509:0 + account: crwdns99537:0crwdne99537:0 + attr_firstname: crwdns99538:0crwdne99538:0 + attr_lastname: crwdns99539:0crwdne99539:0 + attr_login: crwdns99540:0crwdne99540:0 + attr_mail: crwdns99541:0crwdne99541:0 + base_dn: crwdns99542:0crwdne99542:0 + host: crwdns99543:0crwdne99543:0 + onthefly: crwdns99544:0crwdne99544:0 + port: crwdns99545:0crwdne99545:0 changeset: - repository: crwdns96510:0crwdne96510:0 + repository: crwdns99546:0crwdne99546:0 comment: - commented: crwdns96511:0crwdne96511:0 + commented: crwdns99547:0crwdne99547:0 custom_action: - actions: crwdns99126:0crwdne99126:0 + actions: crwdns99548:0crwdne99548:0 custom_field: - default_value: crwdns96512:0crwdne96512:0 - editable: crwdns96513:0crwdne96513:0 - field_format: crwdns96514:0crwdne96514:0 - is_filter: crwdns96515:0crwdne96515:0 - is_required: crwdns96516:0crwdne96516:0 - max_length: crwdns96517:0crwdne96517:0 - min_length: crwdns96518:0crwdne96518:0 - multi_value: crwdns96519:0crwdne96519:0 - possible_values: crwdns96520:0crwdne96520:0 - regexp: crwdns96521:0crwdne96521:0 - searchable: crwdns96522:0crwdne96522:0 - visible: crwdns96523:0crwdne96523:0 + default_value: crwdns99549:0crwdne99549:0 + editable: crwdns99550:0crwdne99550:0 + field_format: crwdns99551:0crwdne99551:0 + is_filter: crwdns99552:0crwdne99552:0 + is_required: crwdns99553:0crwdne99553:0 + max_length: crwdns99554:0crwdne99554:0 + min_length: crwdns99555:0crwdne99555:0 + multi_value: crwdns99556:0crwdne99556:0 + possible_values: crwdns99557:0crwdne99557:0 + regexp: crwdns99558:0crwdne99558:0 + searchable: crwdns99559:0crwdne99559:0 + visible: crwdns99560:0crwdne99560:0 custom_value: - value: crwdns96524:0crwdne96524:0 + value: crwdns99561:0crwdne99561:0 enterprise_token: - starts_at: crwdns96525:0crwdne96525:0 - expires_at: crwdns96526:0crwdne96526:0 - subscriber: crwdns96527:0crwdne96527:0 - encoded_token: crwdns96528:0crwdne96528:0 - active_user_count_restriction: crwdns98980:0crwdne98980:0 + starts_at: crwdns99562:0crwdne99562:0 + expires_at: crwdns99563:0crwdne99563:0 + subscriber: crwdns99564:0crwdne99564:0 + encoded_token: crwdns99565:0crwdne99565:0 + active_user_count_restriction: crwdns99566:0crwdne99566:0 relation: - delay: crwdns96529:0crwdne96529:0 - from: crwdns96530:0crwdne96530:0 - to: crwdns96531:0crwdne96531:0 + delay: crwdns99567:0crwdne99567:0 + from: crwdns99568:0crwdne99568:0 + to: crwdns99569:0crwdne99569:0 status: - is_closed: crwdns96532:0crwdne96532:0 + is_closed: crwdns99570:0crwdne99570:0 journal: - notes: crwdns96533:0crwdne96533:0 + notes: crwdns99571:0crwdne99571:0 member: - roles: crwdns96534:0crwdne96534:0 + roles: crwdns99572:0crwdne99572:0 project: - identifier: crwdns96535:0crwdne96535:0 - latest_activity_at: crwdns96536:0crwdne96536:0 - parent: crwdns96537:0crwdne96537:0 - queries: crwdns96539:0crwdne96539:0 - types: crwdns96541:0crwdne96541:0 - versions: crwdns96542:0crwdne96542:0 - work_packages: crwdns96543:0crwdne96543:0 + identifier: crwdns99573:0crwdne99573:0 + latest_activity_at: crwdns99574:0crwdne99574:0 + parent: crwdns99575:0crwdne99575:0 + queries: crwdns99576:0crwdne99576:0 + types: crwdns99577:0crwdne99577:0 + versions: crwdns99578:0crwdne99578:0 + work_packages: crwdns99579:0crwdne99579:0 query: - column_names: crwdns96544:0crwdne96544:0 - relations_to_type_column: crwdns96545:0%{type}crwdne96545:0 - relations_of_type_column: crwdns96546:0%{type}crwdne96546:0 - group_by: crwdns96547:0crwdne96547:0 - filters: crwdns96548:0crwdne96548:0 - timeline_labels: crwdns96549:0crwdne96549:0 + column_names: crwdns99580:0crwdne99580:0 + relations_to_type_column: crwdns99581:0%{type}crwdne99581:0 + relations_of_type_column: crwdns99582:0%{type}crwdne99582:0 + group_by: crwdns99583:0crwdne99583:0 + filters: crwdns99584:0crwdne99584:0 + timeline_labels: crwdns99585:0crwdne99585:0 repository: - url: crwdns96550:0crwdne96550:0 + url: crwdns99586:0crwdne99586:0 role: - assignable: crwdns96551:0crwdne96551:0 + assignable: crwdns99587:0crwdne99587:0 time_entry: - activity: crwdns96552:0crwdne96552:0 - hours: crwdns96553:0crwdne96553:0 - spent_on: crwdns96554:0crwdne96554:0 - type: crwdns96555:0crwdne96555:0 + activity: crwdns99588:0crwdne99588:0 + hours: crwdns99589:0crwdne99589:0 + spent_on: crwdns99590:0crwdne99590:0 + type: crwdns99591:0crwdne99591:0 type: - attribute_groups: crwdns99049:0crwdne99049:0 - is_in_roadmap: crwdns99131:0crwdne99131:0 - is_default: crwdns99132:0crwdne99132:0 - is_milestone: crwdns96558:0crwdne96558:0 - color: crwdns96559:0crwdne96559:0 + attribute_groups: crwdns99592:0crwdne99592:0 + is_in_roadmap: crwdns99593:0crwdne99593:0 + is_default: crwdns99594:0crwdne99594:0 + is_milestone: crwdns99595:0crwdne99595:0 + color: crwdns99596:0crwdne99596:0 user: - admin: crwdns96560:0crwdne96560:0 - auth_source: crwdns96561:0crwdne96561:0 - current_password: crwdns96562:0crwdne96562:0 - force_password_change: crwdns96563:0crwdne96563:0 - language: crwdns96564:0crwdne96564:0 - last_login_on: crwdns96565:0crwdne96565:0 - mail_notification: crwdns96566:0crwdne96566:0 - new_password: crwdns96567:0crwdne96567:0 - password_confirmation: crwdns96568:0crwdne96568:0 - consented_at: crwdns98948:0crwdne98948:0 + admin: crwdns99597:0crwdne99597:0 + auth_source: crwdns99598:0crwdne99598:0 + current_password: crwdns99599:0crwdne99599:0 + force_password_change: crwdns99600:0crwdne99600:0 + language: crwdns99601:0crwdne99601:0 + last_login_on: crwdns99602:0crwdne99602:0 + mail_notification: crwdns99603:0crwdne99603:0 + new_password: crwdns99604:0crwdne99604:0 + password_confirmation: crwdns99605:0crwdne99605:0 + consented_at: crwdns99606:0crwdne99606:0 user_preference: - comments_sorting: crwdns96569:0crwdne96569:0 - hide_mail: crwdns96570:0crwdne96570:0 - impaired: crwdns96571:0crwdne96571:0 - time_zone: crwdns96572:0crwdne96572:0 - auto_hide_popups: crwdns96573:0crwdne96573:0 - warn_on_leaving_unsaved: crwdns96574:0crwdne96574:0 + comments_sorting: crwdns99607:0crwdne99607:0 + hide_mail: crwdns99608:0crwdne99608:0 + impaired: crwdns99609:0crwdne99609:0 + time_zone: crwdns99610:0crwdne99610:0 + auto_hide_popups: crwdns99611:0crwdne99611:0 + warn_on_leaving_unsaved: crwdns99612:0crwdne99612:0 version: - effective_date: crwdns99242:0crwdne99242:0 - sharing: crwdns96576:0crwdne96576:0 + effective_date: crwdns99613:0crwdne99613:0 + sharing: crwdns99614:0crwdne99614:0 wiki_content: - text: crwdns96578:0crwdne96578:0 + text: crwdns99615:0crwdne99615:0 wiki_page: - parent_title: crwdns96579:0crwdne96579:0 - redirect_existing_links: crwdns96580:0crwdne96580:0 + parent_title: crwdns99616:0crwdne99616:0 + redirect_existing_links: crwdns99617:0crwdne99617:0 planning_element_type_color: - hexcode: crwdns96581:0crwdne96581:0 + hexcode: crwdns99618:0crwdne99618:0 work_package: - begin_insertion: crwdns96583:0crwdne96583:0 - begin_deletion: crwdns96584:0crwdne96584:0 - children: crwdns98890:0crwdne98890:0 - done_ratio: crwdns96585:0crwdne96585:0 - end_insertion: crwdns96586:0crwdne96586:0 - end_deletion: crwdns96587:0crwdne96587:0 - fixed_version: crwdns96588:0crwdne96588:0 - parent: crwdns96589:0crwdne96589:0 - parent_issue: crwdns96590:0crwdne96590:0 - parent_work_package: crwdns96591:0crwdne96591:0 - priority: crwdns96592:0crwdne96592:0 - progress: crwdns96593:0crwdne96593:0 - spent_hours: crwdns96595:0crwdne96595:0 - spent_time: crwdns96596:0crwdne96596:0 - subproject: crwdns96597:0crwdne96597:0 - time_entries: crwdns96598:0crwdne96598:0 - type: crwdns96599:0crwdne96599:0 - watcher: crwdns96600:0crwdne96600:0 + begin_insertion: crwdns99619:0crwdne99619:0 + begin_deletion: crwdns99620:0crwdne99620:0 + children: crwdns99621:0crwdne99621:0 + done_ratio: crwdns99622:0crwdne99622:0 + end_insertion: crwdns99623:0crwdne99623:0 + end_deletion: crwdns99624:0crwdne99624:0 + fixed_version: crwdns99625:0crwdne99625:0 + parent: crwdns99626:0crwdne99626:0 + parent_issue: crwdns99627:0crwdne99627:0 + parent_work_package: crwdns99628:0crwdne99628:0 + priority: crwdns99629:0crwdne99629:0 + progress: crwdns99630:0crwdne99630:0 + spent_hours: crwdns99631:0crwdne99631:0 + spent_time: crwdns99632:0crwdne99632:0 + subproject: crwdns99633:0crwdne99633:0 + time_entries: crwdns99634:0crwdne99634:0 + type: crwdns99635:0crwdne99635:0 + watcher: crwdns99636:0crwdne99636:0 errors: messages: - accepted: crwdns96601:0crwdne96601:0 - after: crwdns96632:0%{date}crwdne96632:0 - after_or_equal_to: crwdns96633:0%{date}crwdne96633:0 - before: crwdns96634:0%{date}crwdne96634:0 - before_or_equal_to: crwdns96635:0%{date}crwdne96635:0 - blank: crwdns96602:0crwdne96602:0 - cant_link_a_work_package_with_a_descendant: crwdns96603:0crwdne96603:0 - circular_dependency: crwdns96604:0crwdne96604:0 - confirmation: crwdns96605:0%{attribute}crwdne96605:0 - could_not_be_copied: crwdns96636:0crwdne96636:0 - does_not_exist: crwdns96606:0crwdne96606:0 - empty: crwdns96607:0crwdne96607:0 - even: crwdns96608:0crwdne96608:0 - exclusion: crwdns96609:0crwdne96609:0 - file_too_large: crwdns96610:0%{count}crwdne96610:0 - greater_than: crwdns96611:0%{count}crwdne96611:0 - greater_than_or_equal_to: crwdns96612:0%{count}crwdne96612:0 - greater_than_or_equal_to_start_date: crwdns96615:0crwdne96615:0 - greater_than_start_date: crwdns96614:0crwdne96614:0 - inclusion: crwdns96616:0crwdne96616:0 - invalid: crwdns96617:0crwdne96617:0 - invalid_url: crwdns96618:0crwdne96618:0 - invalid_url_scheme: crwdns96619:0%{allowed_schemes}crwdne96619:0 - less_than_or_equal_to: crwdns96620:0%{count}crwdne96620:0 - not_a_date: crwdns96621:0crwdne96621:0 - not_a_datetime: crwdns96622:0crwdne96622:0 - not_a_number: crwdns96624:0crwdne96624:0 - not_allowed: crwdns99073:0crwdne99073:0 - not_an_integer: crwdns96625:0crwdne96625:0 - not_an_iso_date: crwdns96623:0crwdne96623:0 - not_same_project: crwdns96626:0crwdne96626:0 - odd: crwdns96627:0crwdne96627:0 - regex_invalid: crwdns96637:0crwdne96637:0 - smaller_than_or_equal_to_max_length: crwdns96613:0crwdne96613:0 - taken: crwdns96628:0crwdne96628:0 - too_long: crwdns96629:0%{count}crwdne96629:0 - too_short: crwdns96630:0%{count}crwdne96630:0 - unchangeable: crwdns98978:0crwdne98978:0 - wrong_length: crwdns96631:0%{count}crwdne96631:0 + accepted: crwdns99637:0crwdne99637:0 + after: crwdns99638:0%{date}crwdne99638:0 + after_or_equal_to: crwdns99639:0%{date}crwdne99639:0 + before: crwdns99640:0%{date}crwdne99640:0 + before_or_equal_to: crwdns99641:0%{date}crwdne99641:0 + blank: crwdns99642:0crwdne99642:0 + cant_link_a_work_package_with_a_descendant: crwdns99643:0crwdne99643:0 + circular_dependency: crwdns99644:0crwdne99644:0 + confirmation: crwdns99645:0%{attribute}crwdne99645:0 + could_not_be_copied: crwdns99646:0crwdne99646:0 + does_not_exist: crwdns99647:0crwdne99647:0 + empty: crwdns99648:0crwdne99648:0 + even: crwdns99649:0crwdne99649:0 + exclusion: crwdns99650:0crwdne99650:0 + file_too_large: crwdns99651:0%{count}crwdne99651:0 + greater_than: crwdns99652:0%{count}crwdne99652:0 + greater_than_or_equal_to: crwdns99653:0%{count}crwdne99653:0 + greater_than_or_equal_to_start_date: crwdns99654:0crwdne99654:0 + greater_than_start_date: crwdns99655:0crwdne99655:0 + inclusion: crwdns99656:0crwdne99656:0 + invalid: crwdns99657:0crwdne99657:0 + invalid_url: crwdns99658:0crwdne99658:0 + invalid_url_scheme: crwdns99659:0%{allowed_schemes}crwdne99659:0 + less_than_or_equal_to: crwdns99660:0%{count}crwdne99660:0 + not_a_date: crwdns99661:0crwdne99661:0 + not_a_datetime: crwdns99662:0crwdne99662:0 + not_a_number: crwdns99663:0crwdne99663:0 + not_allowed: crwdns99664:0crwdne99664:0 + not_an_integer: crwdns99665:0crwdne99665:0 + not_an_iso_date: crwdns99666:0crwdne99666:0 + not_same_project: crwdns99667:0crwdne99667:0 + odd: crwdns99668:0crwdne99668:0 + regex_invalid: crwdns99669:0crwdne99669:0 + smaller_than_or_equal_to_max_length: crwdns99670:0crwdne99670:0 + taken: crwdns99671:0crwdne99671:0 + too_long: crwdns99672:0%{count}crwdne99672:0 + too_short: crwdns99673:0%{count}crwdne99673:0 + unchangeable: crwdns99674:0crwdne99674:0 + wrong_length: crwdns99675:0%{count}crwdne99675:0 models: custom_field: - at_least_one_custom_option: crwdns96638:0crwdne96638:0 + at_least_one_custom_option: crwdns99676:0crwdne99676:0 custom_actions: - only_one_allowed: crwdns98848:0%{name}crwdne98848:0 - empty: crwdns98849:0%{name}crwdne98849:0 - inclusion: crwdns98850:0%{name}crwdne98850:0 - not_logged_in: crwdns99171:0%{name}crwdne99171:0 - not_an_integer: crwdns98851:0%{name}crwdne98851:0 - smaller_than_or_equal_to: crwdns98871:0%{name}crwdnd98871:0%{count}crwdne98871:0 - greater_than_or_equal_to: crwdns98872:0%{name}crwdnd98872:0%{count}crwdne98872:0 + only_one_allowed: crwdns99677:0%{name}crwdne99677:0 + empty: crwdns99678:0%{name}crwdne99678:0 + inclusion: crwdns99679:0%{name}crwdne99679:0 + not_logged_in: crwdns99680:0%{name}crwdne99680:0 + not_an_integer: crwdns99681:0%{name}crwdne99681:0 + smaller_than_or_equal_to: crwdns99682:0%{name}crwdnd99682:0%{count}crwdne99682:0 + greater_than_or_equal_to: crwdns99683:0%{name}crwdnd99683:0%{count}crwdne99683:0 enterprise_token: - unreadable: crwdns96639:0crwdne96639:0 + unreadable: crwdns99684:0crwdne99684:0 parse_schema_filter_params_service: attributes: base: - unsupported_operator: crwdns96640:0crwdne96640:0 - invalid_values: crwdns96641:0crwdne96641:0 - id_filter_required: crwdns96642:0crwdne96642:0 + unsupported_operator: crwdns99685:0crwdne99685:0 + invalid_values: crwdns99686:0crwdne99686:0 + id_filter_required: crwdns99687:0crwdne99687:0 project: attributes: types: - in_use_by_work_packages: crwdns96643:0%{types}crwdne96643:0 + in_use_by_work_packages: crwdns99688:0%{types}crwdne99688:0 query: attributes: project: - error_not_found: crwdns96644:0crwdne96644:0 + error_not_found: crwdns99689:0crwdne99689:0 public: - error_unauthorized: crwdns99120:0crwdne99120:0 - group_by_hierarchies_exclusive: crwdns96646:0%{group_by}crwdne96646:0 + error_unauthorized: crwdns99690:0crwdne99690:0 + group_by_hierarchies_exclusive: crwdns99691:0%{group_by}crwdne99691:0 filters: custom_fields: - inexistent: crwdns96647:0crwdne96647:0 - invalid: crwdns96648:0crwdne96648:0 + inexistent: crwdns99692:0crwdne99692:0 + invalid: crwdns99693:0crwdne99693:0 relation: typed_dag: - circular_dependency: crwdns96649:0crwdne96649:0 + circular_dependency: crwdns99694:0crwdne99694:0 attributes: to: - error_not_found: crwdns96650:0crwdne96650:0 - error_readonly: crwdns96651:0crwdne96651:0 + error_not_found: crwdns99695:0crwdne99695:0 + error_readonly: crwdns99696:0crwdne99696:0 from: - error_not_found: crwdns96652:0crwdne96652:0 - error_readonly: crwdns96653:0crwdne96653:0 + error_not_found: crwdns99697:0crwdne99697:0 + error_readonly: crwdns99698:0crwdne99698:0 repository: - not_available: crwdns96654:0crwdne96654:0 - not_whitelisted: crwdns96655:0crwdne96655:0 - invalid_url: crwdns96656:0crwdne96656:0 - must_not_be_ssh: crwdns96657:0crwdne96657:0 - no_directory: crwdns96658:0crwdne96658:0 + not_available: crwdns99699:0crwdne99699:0 + not_whitelisted: crwdns99700:0crwdne99700:0 + invalid_url: crwdns99701:0crwdne99701:0 + must_not_be_ssh: crwdns99702:0crwdne99702:0 + no_directory: crwdns99703:0crwdne99703:0 work_package: - is_not_a_valid_target_for_time_entries: crwdns96659:0%{id}crwdne96659:0 + is_not_a_valid_target_for_time_entries: crwdns99704:0%{id}crwdne99704:0 attributes: due_date: - not_start_date: crwdns96660:0crwdne96660:0 + not_start_date: crwdns99705:0crwdne99705:0 parent: - cannot_be_milestone: crwdns96661:0crwdne96661:0 - cannot_be_in_another_project: crwdns96662:0crwdne96662:0 - not_a_valid_parent: crwdns96663:0crwdne96663:0 + cannot_be_milestone: crwdns99706:0crwdne99706:0 + cannot_be_in_another_project: crwdns99707:0crwdne99707:0 + not_a_valid_parent: crwdns99708:0crwdne99708:0 start_date: - violates_relationships: crwdns96664:0%{soonest_start}crwdne96664:0 + violates_relationships: crwdns99709:0%{soonest_start}crwdne99709:0 status_id: - status_transition_invalid: crwdns96665:0crwdne96665:0 - status_invalid_in_type: crwdns98891:0crwdne98891:0 + status_transition_invalid: crwdns99710:0crwdne99710:0 + status_invalid_in_type: crwdns99711:0crwdne99711:0 type: - cannot_be_milestone_due_to_children: crwdns99172:0crwdne99172:0 + cannot_be_milestone_due_to_children: crwdns99712:0crwdne99712:0 priority_id: - only_active_priorities_allowed: crwdns96666:0crwdne96666:0 + only_active_priorities_allowed: crwdns99713:0crwdne99713:0 category: - only_same_project_categories_allowed: crwdns96667:0crwdne96667:0 - does_not_exist: crwdns96668:0crwdne96668:0 + only_same_project_categories_allowed: crwdns99714:0crwdne99714:0 + does_not_exist: crwdns99715:0crwdne99715:0 estimated_hours: - only_values_greater_or_equal_zeroes_allowed: crwdns96669:0crwdne96669:0 + only_values_greater_or_equal_zeroes_allowed: crwdns99716:0crwdne99716:0 type: attributes: attribute_groups: - attribute_unknown: crwdns96672:0crwdne96672:0 - duplicate_group: crwdns99050:0%{group}crwdne99050:0 - query_invalid: crwdns99051:0%{group}crwdnd99051:0%{details}crwdne99051:0 - group_without_name: crwdns96670:0crwdne96670:0 + attribute_unknown: crwdns99717:0crwdne99717:0 + duplicate_group: crwdns99718:0%{group}crwdne99718:0 + query_invalid: crwdns99719:0%{group}crwdnd99719:0%{details}crwdne99719:0 + group_without_name: crwdns99720:0crwdne99720:0 user: attributes: password: - weak: crwdns96673:0%{min_count}crwdnd96673:0%{all_count}crwdnd96673:0%{rules}crwdne96673:0 - lowercase: crwdns96674:0crwdne96674:0 - uppercase: crwdns96675:0crwdne96675:0 - numeric: crwdns96676:0crwdne96676:0 - special: crwdns96677:0crwdne96677:0 + weak: crwdns99721:0%{min_count}crwdnd99721:0%{all_count}crwdnd99721:0%{rules}crwdne99721:0 + lowercase: crwdns99722:0crwdne99722:0 + uppercase: crwdns99723:0crwdne99723:0 + numeric: crwdns99724:0crwdne99724:0 + special: crwdns99725:0crwdne99725:0 reused: - one: crwdns96678:1crwdne96678:1 - other: crwdns96678:5%{count}crwdne96678:5 + one: crwdns99726:1crwdne99726:1 + other: crwdns99726:5%{count}crwdne99726:5 match: - confirm: crwdns96679:0crwdne96679:0 - description: crwdns96680:0crwdne96680:0 + confirm: crwdns99727:0crwdne99727:0 + description: crwdns99728:0crwdne99728:0 status: - invalid_on_create: crwdns96681:0crwdne96681:0 + invalid_on_create: crwdns99729:0crwdne99729:0 auth_source: - error_not_found: crwdns96682:0crwdne96682:0 + error_not_found: crwdns99730:0crwdne99730:0 member: - principal_blank: crwdns96683:0crwdne96683:0 - role_blank: crwdns96684:0crwdne96684:0 + principal_blank: crwdns99731:0crwdne99731:0 + role_blank: crwdns99732:0crwdne99732:0 template: - body: crwdns96685:0crwdne96685:0 + body: crwdns99733:0crwdne99733:0 header: - one: crwdns96686:1%{model}crwdne96686:1 - other: crwdns96686:5%{count}crwdnd96686:5%{model}crwdne96686:5 + one: crwdns99734:1%{model}crwdne99734:1 + other: crwdns99734:5%{count}crwdnd99734:5%{model}crwdne99734:5 models: - attachment: crwdns96687:0crwdne96687:0 - attribute_help_text: crwdns96688:0crwdne96688:0 - board: crwdns96689:0crwdne96689:0 - comment: crwdns96690:0crwdne96690:0 - custom_action: crwdns98852:0crwdne98852:0 - custom_field: crwdns96691:0crwdne96691:0 - group: crwdns96692:0crwdne96692:0 - category: crwdns96693:0crwdne96693:0 - status: crwdns96694:0crwdne96694:0 - member: crwdns96695:0crwdne96695:0 - news: crwdns96696:0crwdne96696:0 - project: crwdns96697:0crwdne96697:0 - query: crwdns96698:0crwdne96698:0 + attachment: crwdns99735:0crwdne99735:0 + attribute_help_text: crwdns99736:0crwdne99736:0 + board: crwdns99737:0crwdne99737:0 + comment: crwdns99738:0crwdne99738:0 + custom_action: crwdns99739:0crwdne99739:0 + custom_field: crwdns99740:0crwdne99740:0 + group: crwdns99741:0crwdne99741:0 + category: crwdns99742:0crwdne99742:0 + status: crwdns99743:0crwdne99743:0 + member: crwdns99744:0crwdne99744:0 + news: crwdns99745:0crwdne99745:0 + project: crwdns99746:0crwdne99746:0 + query: crwdns99747:0crwdne99747:0 role: - one: crwdns96699:1crwdne96699:1 - other: crwdns96699:5crwdne96699:5 - type: crwdns96700:0crwdne96700:0 - user: crwdns96702:0crwdne96702:0 - version: crwdns96703:0crwdne96703:0 - wiki: crwdns96704:0crwdne96704:0 - wiki_page: crwdns96705:0crwdne96705:0 - workflow: crwdns96706:0crwdne96706:0 - work_package: crwdns96707:0crwdne96707:0 + one: crwdns99748:1crwdne99748:1 + other: crwdns99748:5crwdne99748:5 + type: crwdns99749:0crwdne99749:0 + user: crwdns99750:0crwdne99750:0 + version: crwdns99751:0crwdne99751:0 + wiki: crwdns99752:0crwdne99752:0 + wiki_page: crwdns99753:0crwdne99753:0 + workflow: crwdns99754:0crwdne99754:0 + work_package: crwdns99755:0crwdne99755:0 errors: - header_invalid_fields: crwdns96708:0crwdne96708:0 - field_erroneous_label: crwdns96709:0%{full_errors}crwdne96709:0 + header_invalid_fields: crwdns99756:0crwdne99756:0 + field_erroneous_label: crwdns99757:0%{full_errors}crwdne99757:0 activity: - created: crwdns96710:0%{title}crwdne96710:0 - updated: crwdns96711:0%{title}crwdne96711:0 + created: crwdns99758:0%{title}crwdne99758:0 + updated: crwdns99759:0%{title}crwdne99759:0 attributes: - active: crwdns96712:0crwdne96712:0 - assigned_to: crwdns96713:0crwdne96713:0 - assignee: crwdns96714:0crwdne96714:0 - attachments: crwdns96715:0crwdne96715:0 - author: crwdns96716:0crwdne96716:0 - base: crwdns96717:0crwdne96717:0 - blocks_ids: crwdns96718:0crwdne96718:0 - category: crwdns96719:0crwdne96719:0 - comment: crwdns96720:0crwdne96720:0 - comments: crwdns96721:0crwdne96721:0 - content: crwdns96722:0crwdne96722:0 - color: crwdns99221:0crwdne99221:0 - created_at: crwdns96723:0crwdne96723:0 - created_on: crwdns96724:0crwdne96724:0 - custom_options: crwdns96725:0crwdne96725:0 - custom_values: crwdns96726:0crwdne96726:0 - date: crwdns96727:0crwdne96727:0 - default_columns: crwdns96728:0crwdne96728:0 - description: crwdns96729:0crwdne96729:0 - display_sums: crwdns96730:0crwdne96730:0 - due_date: crwdns99243:0crwdne99243:0 - estimated_hours: crwdns96732:0crwdne96732:0 - estimated_time: crwdns96733:0crwdne96733:0 - firstname: crwdns96734:0crwdne96734:0 - group: crwdns96735:0crwdne96735:0 - groups: crwdns96736:0crwdne96736:0 - groupname: crwdns96737:0crwdne96737:0 - id: crwdns96738:0crwdne96738:0 - is_default: crwdns96739:0crwdne96739:0 - is_for_all: crwdns96740:0crwdne96740:0 - is_public: crwdns96741:0crwdne96741:0 - issue: crwdns96742:0crwdne96742:0 - lastname: crwdns96743:0crwdne96743:0 - login: crwdns96744:0crwdne96744:0 - mail: crwdns96745:0crwdne96745:0 - name: crwdns96746:0crwdne96746:0 - password: crwdns96747:0crwdne96747:0 - priority: crwdns96748:0crwdne96748:0 - project: crwdns96749:0crwdne96749:0 - responsible: crwdns99074:0crwdne99074:0 - role: crwdns96751:0crwdne96751:0 - roles: crwdns96752:0crwdne96752:0 - start_date: crwdns96753:0crwdne96753:0 - status: crwdns96754:0crwdne96754:0 - subject: crwdns96755:0crwdne96755:0 - summary: crwdns96756:0crwdne96756:0 - title: crwdns96757:0crwdne96757:0 - type: crwdns96758:0crwdne96758:0 - updated_at: crwdns96759:0crwdne96759:0 - updated_on: crwdns96760:0crwdne96760:0 - user: crwdns96761:0crwdne96761:0 - version: crwdns96762:0crwdne96762:0 - work_package: crwdns96763:0crwdne96763:0 - button_add: crwdns96764:0crwdne96764:0 - button_add_member: crwdns96765:0crwdne96765:0 - button_add_watcher: crwdns96766:0crwdne96766:0 - button_annotate: crwdns96767:0crwdne96767:0 - button_apply: crwdns96768:0crwdne96768:0 - button_archive: crwdns96769:0crwdne96769:0 - button_back: crwdns96770:0crwdne96770:0 - button_cancel: crwdns96771:0crwdne96771:0 - button_change: crwdns96772:0crwdne96772:0 - button_change_parent_page: crwdns96773:0crwdne96773:0 - button_change_password: crwdns96774:0crwdne96774:0 - button_check_all: crwdns96775:0crwdne96775:0 - button_clear: crwdns96776:0crwdne96776:0 - button_close: crwdns96777:0crwdne96777:0 - button_collapse_all: crwdns96778:0crwdne96778:0 - button_configure: crwdns96779:0crwdne96779:0 - button_continue: crwdns98949:0crwdne98949:0 - button_copy: crwdns96780:0crwdne96780:0 - button_copy_and_follow: crwdns96781:0crwdne96781:0 - button_create: crwdns96782:0crwdne96782:0 - button_create_and_continue: crwdns96783:0crwdne96783:0 - button_delete: crwdns96784:0crwdne96784:0 - button_decline: crwdns98950:0crwdne98950:0 - button_delete_watcher: crwdns96785:0%{name}crwdne96785:0 - button_download: crwdns96786:0crwdne96786:0 - button_duplicate: crwdns96787:0crwdne96787:0 - button_edit: crwdns96788:0crwdne96788:0 - button_edit_associated_wikipage: crwdns96789:0%{page_title}crwdne96789:0 - button_expand_all: crwdns96790:0crwdne96790:0 - button_filter: crwdns96791:0crwdne96791:0 - button_generate: crwdns96792:0crwdne96792:0 - button_list: crwdns96793:0crwdne96793:0 - button_lock: crwdns96794:0crwdne96794:0 - button_log_time: crwdns96795:0crwdne96795:0 - button_login: crwdns96796:0crwdne96796:0 - button_move: crwdns96797:0crwdne96797:0 - button_move_and_follow: crwdns96798:0crwdne96798:0 - button_print: crwdns96799:0crwdne96799:0 - button_quote: crwdns96800:0crwdne96800:0 - button_remove: crwdns96801:0crwdne96801:0 - button_remove_widget: crwdns96802:0crwdne96802:0 - button_rename: crwdns96803:0crwdne96803:0 - button_replace: crwdns96804:0crwdne96804:0 - button_reply: crwdns96805:0crwdne96805:0 - button_reset: crwdns96806:0crwdne96806:0 - button_rollback: crwdns96807:0crwdne96807:0 - button_save: crwdns96808:0crwdne96808:0 - button_save_back: crwdns96809:0crwdne96809:0 - button_show: crwdns96810:0crwdne96810:0 - button_sort: crwdns96811:0crwdne96811:0 - button_submit: crwdns96812:0crwdne96812:0 - button_test: crwdns96813:0crwdne96813:0 - button_unarchive: crwdns96814:0crwdne96814:0 - button_uncheck_all: crwdns96815:0crwdne96815:0 - button_unlock: crwdns96816:0crwdne96816:0 - button_unwatch: crwdns96817:0crwdne96817:0 - button_update: crwdns96818:0crwdne96818:0 - button_upgrade: crwdns98981:0crwdne98981:0 - button_upload: crwdns96819:0crwdne96819:0 - button_view: crwdns96820:0crwdne96820:0 - button_watch: crwdns96821:0crwdne96821:0 - button_manage_menu_entry: crwdns96822:0crwdne96822:0 - button_add_menu_entry: crwdns96823:0crwdne96823:0 - button_configure_menu_entry: crwdns96824:0crwdne96824:0 - button_delete_menu_entry: crwdns96825:0crwdne96825:0 + active: crwdns99760:0crwdne99760:0 + assigned_to: crwdns99761:0crwdne99761:0 + assignee: crwdns99762:0crwdne99762:0 + attachments: crwdns99763:0crwdne99763:0 + author: crwdns99764:0crwdne99764:0 + base: crwdns99765:0crwdne99765:0 + blocks_ids: crwdns99766:0crwdne99766:0 + category: crwdns99767:0crwdne99767:0 + comment: crwdns99768:0crwdne99768:0 + comments: crwdns99769:0crwdne99769:0 + content: crwdns99770:0crwdne99770:0 + color: crwdns99771:0crwdne99771:0 + created_at: crwdns99772:0crwdne99772:0 + created_on: crwdns99773:0crwdne99773:0 + custom_options: crwdns99774:0crwdne99774:0 + custom_values: crwdns99775:0crwdne99775:0 + date: crwdns99776:0crwdne99776:0 + default_columns: crwdns99777:0crwdne99777:0 + description: crwdns99778:0crwdne99778:0 + display_sums: crwdns99779:0crwdne99779:0 + due_date: crwdns99780:0crwdne99780:0 + estimated_hours: crwdns99781:0crwdne99781:0 + estimated_time: crwdns99782:0crwdne99782:0 + firstname: crwdns99783:0crwdne99783:0 + group: crwdns99784:0crwdne99784:0 + groups: crwdns99785:0crwdne99785:0 + groupname: crwdns99786:0crwdne99786:0 + id: crwdns99787:0crwdne99787:0 + is_default: crwdns99788:0crwdne99788:0 + is_for_all: crwdns99789:0crwdne99789:0 + is_public: crwdns99790:0crwdne99790:0 + issue: crwdns99791:0crwdne99791:0 + lastname: crwdns99792:0crwdne99792:0 + login: crwdns99793:0crwdne99793:0 + mail: crwdns99794:0crwdne99794:0 + name: crwdns99795:0crwdne99795:0 + password: crwdns99796:0crwdne99796:0 + priority: crwdns99797:0crwdne99797:0 + project: crwdns99798:0crwdne99798:0 + responsible: crwdns99799:0crwdne99799:0 + role: crwdns99800:0crwdne99800:0 + roles: crwdns99801:0crwdne99801:0 + start_date: crwdns99802:0crwdne99802:0 + status: crwdns99803:0crwdne99803:0 + subject: crwdns99804:0crwdne99804:0 + summary: crwdns99805:0crwdne99805:0 + title: crwdns99806:0crwdne99806:0 + type: crwdns99807:0crwdne99807:0 + updated_at: crwdns99808:0crwdne99808:0 + updated_on: crwdns99809:0crwdne99809:0 + user: crwdns99810:0crwdne99810:0 + version: crwdns99811:0crwdne99811:0 + work_package: crwdns99812:0crwdne99812:0 + button_add: crwdns99813:0crwdne99813:0 + button_add_member: crwdns99814:0crwdne99814:0 + button_add_watcher: crwdns99815:0crwdne99815:0 + button_annotate: crwdns99816:0crwdne99816:0 + button_apply: crwdns99817:0crwdne99817:0 + button_archive: crwdns99818:0crwdne99818:0 + button_back: crwdns99819:0crwdne99819:0 + button_cancel: crwdns99820:0crwdne99820:0 + button_change: crwdns99821:0crwdne99821:0 + button_change_parent_page: crwdns99822:0crwdne99822:0 + button_change_password: crwdns99823:0crwdne99823:0 + button_check_all: crwdns99824:0crwdne99824:0 + button_clear: crwdns99825:0crwdne99825:0 + button_close: crwdns99826:0crwdne99826:0 + button_collapse_all: crwdns99827:0crwdne99827:0 + button_configure: crwdns99828:0crwdne99828:0 + button_continue: crwdns99829:0crwdne99829:0 + button_copy: crwdns99830:0crwdne99830:0 + button_copy_and_follow: crwdns99831:0crwdne99831:0 + button_create: crwdns99832:0crwdne99832:0 + button_create_and_continue: crwdns99833:0crwdne99833:0 + button_delete: crwdns99834:0crwdne99834:0 + button_decline: crwdns99835:0crwdne99835:0 + button_delete_watcher: crwdns99836:0%{name}crwdne99836:0 + button_download: crwdns99837:0crwdne99837:0 + button_duplicate: crwdns99838:0crwdne99838:0 + button_edit: crwdns99839:0crwdne99839:0 + button_edit_associated_wikipage: crwdns99840:0%{page_title}crwdne99840:0 + button_expand_all: crwdns99841:0crwdne99841:0 + button_filter: crwdns99842:0crwdne99842:0 + button_generate: crwdns99843:0crwdne99843:0 + button_list: crwdns99844:0crwdne99844:0 + button_lock: crwdns99845:0crwdne99845:0 + button_log_time: crwdns99846:0crwdne99846:0 + button_login: crwdns99847:0crwdne99847:0 + button_move: crwdns99848:0crwdne99848:0 + button_move_and_follow: crwdns99849:0crwdne99849:0 + button_print: crwdns99850:0crwdne99850:0 + button_quote: crwdns99851:0crwdne99851:0 + button_remove: crwdns99852:0crwdne99852:0 + button_remove_widget: crwdns99853:0crwdne99853:0 + button_rename: crwdns99854:0crwdne99854:0 + button_replace: crwdns99855:0crwdne99855:0 + button_reply: crwdns99856:0crwdne99856:0 + button_reset: crwdns99857:0crwdne99857:0 + button_rollback: crwdns99858:0crwdne99858:0 + button_save: crwdns99859:0crwdne99859:0 + button_save_back: crwdns99860:0crwdne99860:0 + button_show: crwdns99861:0crwdne99861:0 + button_sort: crwdns99862:0crwdne99862:0 + button_submit: crwdns99863:0crwdne99863:0 + button_test: crwdns99864:0crwdne99864:0 + button_unarchive: crwdns99865:0crwdne99865:0 + button_uncheck_all: crwdns99866:0crwdne99866:0 + button_unlock: crwdns99867:0crwdne99867:0 + button_unwatch: crwdns99868:0crwdne99868:0 + button_update: crwdns99869:0crwdne99869:0 + button_upgrade: crwdns99870:0crwdne99870:0 + button_upload: crwdns99871:0crwdne99871:0 + button_view: crwdns99872:0crwdne99872:0 + button_watch: crwdns99873:0crwdne99873:0 + button_manage_menu_entry: crwdns99874:0crwdne99874:0 + button_add_menu_entry: crwdns99875:0crwdne99875:0 + button_configure_menu_entry: crwdns99876:0crwdne99876:0 + button_delete_menu_entry: crwdns99877:0crwdne99877:0 consent: - checkbox_label: crwdns98951:0crwdne98951:0 - failure_message: crwdns98952:0crwdne98952:0 - title: crwdns98953:0crwdne98953:0 - decline_warning_message: crwdns98954:0crwdne98954:0 - user_has_consented: crwdns98955:0crwdne98955:0 - not_yet_consented: crwdns98956:0crwdne98956:0 - contact_mail_instructions: crwdns98957:0crwdne98957:0 - contact_your_administrator: crwdns98958:0crwdne98958:0 - contact_this_mail_address: crwdns98959:0%{mail_address}crwdne98959:0 - text_update_consent_time: crwdns98960:0crwdne98960:0 - update_consent_last_time: crwdns98961:0%{update_time}crwdne98961:0 + checkbox_label: crwdns99878:0crwdne99878:0 + failure_message: crwdns99879:0crwdne99879:0 + title: crwdns99880:0crwdne99880:0 + decline_warning_message: crwdns99881:0crwdne99881:0 + user_has_consented: crwdns99882:0crwdne99882:0 + not_yet_consented: crwdns99883:0crwdne99883:0 + contact_mail_instructions: crwdns99884:0crwdne99884:0 + contact_your_administrator: crwdns99885:0crwdne99885:0 + contact_this_mail_address: crwdns99886:0%{mail_address}crwdne99886:0 + text_update_consent_time: crwdns99887:0crwdne99887:0 + update_consent_last_time: crwdns99888:0%{update_time}crwdne99888:0 copy_project: - started: crwdns96826:0%{source_project_name}crwdnd96826:0%{target_project_name}crwdnd96826:0%{target_project_name}crwdne96826:0 - failed: crwdns96827:0%{source_project_name}crwdne96827:0 - succeeded: crwdns96828:0%{target_project_name}crwdne96828:0 - errors: crwdns96829:0crwdne96829:0 - project_custom_fields: crwdns96830:0crwdne96830:0 + started: crwdns99889:0%{source_project_name}crwdnd99889:0%{target_project_name}crwdnd99889:0%{target_project_name}crwdne99889:0 + failed: crwdns99890:0%{source_project_name}crwdne99890:0 + succeeded: crwdns99891:0%{target_project_name}crwdne99891:0 + errors: crwdns99892:0crwdne99892:0 + project_custom_fields: crwdns99893:0crwdne99893:0 text: - failed: crwdns96831:0%{source_project_name}crwdnd96831:0%{target_project_name}crwdne96831:0 - succeeded: crwdns96832:0%{source_project_name}crwdnd96832:0%{target_project_name}crwdne96832:0 - create_new_page: crwdns96833:0crwdne96833:0 + failed: crwdns99894:0%{source_project_name}crwdnd99894:0%{target_project_name}crwdne99894:0 + succeeded: crwdns99895:0%{source_project_name}crwdnd99895:0%{target_project_name}crwdne99895:0 + create_new_page: crwdns99896:0crwdne99896:0 date: abbr_day_names: - - crwdns96834:0crwdne96834:0 - - crwdns96835:0crwdne96835:0 - - crwdns96836:0crwdne96836:0 - - crwdns96837:0crwdne96837:0 - - crwdns96838:0crwdne96838:0 - - crwdns96839:0crwdne96839:0 - - crwdns96840:0crwdne96840:0 + - crwdns99897:0crwdne99897:0 + - crwdns99898:0crwdne99898:0 + - crwdns99899:0crwdne99899:0 + - crwdns99900:0crwdne99900:0 + - crwdns99901:0crwdne99901:0 + - crwdns99902:0crwdne99902:0 + - crwdns99903:0crwdne99903:0 abbr_month_names: - - - crwdns96841:0crwdne96841:0 - - crwdns96842:0crwdne96842:0 - - crwdns96843:0crwdne96843:0 - - crwdns96844:0crwdne96844:0 - - crwdns96845:0crwdne96845:0 - - crwdns96846:0crwdne96846:0 - - crwdns96847:0crwdne96847:0 - - crwdns96848:0crwdne96848:0 - - crwdns96849:0crwdne96849:0 - - crwdns96850:0crwdne96850:0 - - crwdns96851:0crwdne96851:0 - - crwdns96852:0crwdne96852:0 + - crwdns99904:0crwdne99904:0 + - crwdns99905:0crwdne99905:0 + - crwdns99906:0crwdne99906:0 + - crwdns99907:0crwdne99907:0 + - crwdns99908:0crwdne99908:0 + - crwdns99909:0crwdne99909:0 + - crwdns99910:0crwdne99910:0 + - crwdns99911:0crwdne99911:0 + - crwdns99912:0crwdne99912:0 + - crwdns99913:0crwdne99913:0 + - crwdns99914:0crwdne99914:0 + - crwdns99915:0crwdne99915:0 day_names: - - crwdns96853:0crwdne96853:0 - - crwdns96854:0crwdne96854:0 - - crwdns96855:0crwdne96855:0 - - crwdns96856:0crwdne96856:0 - - crwdns96857:0crwdne96857:0 - - crwdns96858:0crwdne96858:0 - - crwdns96859:0crwdne96859:0 + - crwdns99916:0crwdne99916:0 + - crwdns99917:0crwdne99917:0 + - crwdns99918:0crwdne99918:0 + - crwdns99919:0crwdne99919:0 + - crwdns99920:0crwdne99920:0 + - crwdns99921:0crwdne99921:0 + - crwdns99922:0crwdne99922:0 formats: - default: crwdns96860:0%mcrwdnd96860:0%dcrwdnd96860:0%Ycrwdne96860:0 - long: crwdns96861:0%Bcrwdnd96861:0%dcrwdnd96861:0%Ycrwdne96861:0 - short: crwdns96862:0%bcrwdnd96862:0%dcrwdne96862:0 + default: crwdns99923:0%mcrwdnd99923:0%dcrwdnd99923:0%Ycrwdne99923:0 + long: crwdns99924:0%Bcrwdnd99924:0%dcrwdnd99924:0%Ycrwdne99924:0 + short: crwdns99925:0%bcrwdnd99925:0%dcrwdne99925:0 month_names: - - - crwdns96863:0crwdne96863:0 - - crwdns96864:0crwdne96864:0 - - crwdns96865:0crwdne96865:0 - - crwdns96866:0crwdne96866:0 - - crwdns96867:0crwdne96867:0 - - crwdns96868:0crwdne96868:0 - - crwdns96869:0crwdne96869:0 - - crwdns96870:0crwdne96870:0 - - crwdns96871:0crwdne96871:0 - - crwdns96872:0crwdne96872:0 - - crwdns96873:0crwdne96873:0 - - crwdns96874:0crwdne96874:0 + - crwdns99926:0crwdne99926:0 + - crwdns99927:0crwdne99927:0 + - crwdns99928:0crwdne99928:0 + - crwdns99929:0crwdne99929:0 + - crwdns99930:0crwdne99930:0 + - crwdns99931:0crwdne99931:0 + - crwdns99932:0crwdne99932:0 + - crwdns99933:0crwdne99933:0 + - crwdns99934:0crwdne99934:0 + - crwdns99935:0crwdne99935:0 + - crwdns99936:0crwdne99936:0 + - crwdns99937:0crwdne99937:0 order: - - crwdns96875:0crwdne96875:0 - - crwdns96876:0crwdne96876:0 - - crwdns96877:0crwdne96877:0 + - crwdns99938:0crwdne99938:0 + - crwdns99939:0crwdne99939:0 + - crwdns99940:0crwdne99940:0 datetime: distance_in_words: about_x_hours: - one: crwdns96878:1crwdne96878:1 - other: crwdns96878:5%{count}crwdne96878:5 + one: crwdns99941:1crwdne99941:1 + other: crwdns99941:5%{count}crwdne99941:5 about_x_months: - one: crwdns96879:1crwdne96879:1 - other: crwdns96879:5%{count}crwdne96879:5 + one: crwdns99942:1crwdne99942:1 + other: crwdns99942:5%{count}crwdne99942:5 about_x_years: - one: crwdns96880:1crwdne96880:1 - other: crwdns96880:5%{count}crwdne96880:5 + one: crwdns99943:1crwdne99943:1 + other: crwdns99943:5%{count}crwdne99943:5 almost_x_years: - one: crwdns96881:1crwdne96881:1 - other: crwdns96881:5%{count}crwdne96881:5 - half_a_minute: crwdns96882:0crwdne96882:0 + one: crwdns99944:1crwdne99944:1 + other: crwdns99944:5%{count}crwdne99944:5 + half_a_minute: crwdns99945:0crwdne99945:0 less_than_x_minutes: - one: crwdns96883:1crwdne96883:1 - other: crwdns96883:5%{count}crwdne96883:5 + one: crwdns99946:1crwdne99946:1 + other: crwdns99946:5%{count}crwdne99946:5 less_than_x_seconds: - one: crwdns96884:1crwdne96884:1 - other: crwdns96884:5%{count}crwdne96884:5 + one: crwdns99947:1crwdne99947:1 + other: crwdns99947:5%{count}crwdne99947:5 over_x_years: - one: crwdns96885:1crwdne96885:1 - other: crwdns96885:5%{count}crwdne96885:5 + one: crwdns99948:1crwdne99948:1 + other: crwdns99948:5%{count}crwdne99948:5 x_days: - one: crwdns96886:1crwdne96886:1 - other: crwdns96886:5%{count}crwdne96886:5 + one: crwdns99949:1crwdne99949:1 + other: crwdns99949:5%{count}crwdne99949:5 x_minutes: - one: crwdns96887:1crwdne96887:1 - other: crwdns96887:5%{count}crwdne96887:5 + one: crwdns99950:1crwdne99950:1 + other: crwdns99950:5%{count}crwdne99950:5 x_months: - one: crwdns96888:1crwdne96888:1 - other: crwdns96888:5%{count}crwdne96888:5 + one: crwdns99951:1crwdne99951:1 + other: crwdns99951:5%{count}crwdne99951:5 x_seconds: - one: crwdns96889:1crwdne96889:1 - other: crwdns96889:5%{count}crwdne96889:5 + one: crwdns99952:1crwdne99952:1 + other: crwdns99952:5%{count}crwdne99952:5 units: hour: - one: crwdns96890:1crwdne96890:1 - other: crwdns96890:5crwdne96890:5 - default_activity_development: crwdns96891:0crwdne96891:0 - default_activity_management: crwdns96892:0crwdne96892:0 - default_activity_other: crwdns96893:0crwdne96893:0 - default_activity_specification: crwdns96894:0crwdne96894:0 - default_activity_support: crwdns96895:0crwdne96895:0 - default_activity_testing: crwdns96896:0crwdne96896:0 - default_color_black: crwdns96897:0crwdne96897:0 - default_color_blue: crwdns96898:0crwdne96898:0 - default_color_blue_dark: crwdns96899:0crwdne96899:0 - default_color_blue_light: crwdns96900:0crwdne96900:0 - default_color_green_dark: crwdns96901:0crwdne96901:0 - default_color_green_light: crwdns96902:0crwdne96902:0 - default_color_grey_dark: crwdns96903:0crwdne96903:0 - default_color_grey_light: crwdns96904:0crwdne96904:0 - default_color_grey: crwdns96905:0crwdne96905:0 - default_color_magenta: crwdns96906:0crwdne96906:0 - default_color_orange: crwdns96907:0crwdne96907:0 - default_color_red: crwdns96908:0crwdne96908:0 - default_color_white: crwdns96909:0crwdne96909:0 - default_color_yellow: crwdns96910:0crwdne96910:0 - default_status_closed: crwdns96911:0crwdne96911:0 - default_status_confirmed: crwdns96912:0crwdne96912:0 - default_status_developed: crwdns96913:0crwdne96913:0 - default_status_in_development: crwdns96914:0crwdne96914:0 - default_status_in_progress: crwdns96915:0crwdne96915:0 - default_status_in_specification: crwdns96916:0crwdne96916:0 - default_status_in_testing: crwdns96917:0crwdne96917:0 - default_status_new: crwdns96918:0crwdne96918:0 - default_status_on_hold: crwdns96919:0crwdne96919:0 - default_status_rejected: crwdns96920:0crwdne96920:0 - default_status_scheduled: crwdns96921:0crwdne96921:0 - default_status_specified: crwdns96922:0crwdne96922:0 - default_status_tested: crwdns96923:0crwdne96923:0 - default_status_test_failed: crwdns96924:0crwdne96924:0 - default_status_to_be_scheduled: crwdns96925:0crwdne96925:0 - default_priority_low: crwdns96926:0crwdne96926:0 - default_priority_normal: crwdns96927:0crwdne96927:0 - default_priority_high: crwdns96928:0crwdne96928:0 - default_priority_immediate: crwdns96929:0crwdne96929:0 - default_role_anonymous: crwdns96935:0crwdne96935:0 - default_role_developer: crwdns96936:0crwdne96936:0 - default_role_project_admin: crwdns96937:0crwdne96937:0 - default_role_non_member: crwdns96938:0crwdne96938:0 - default_role_reader: crwdns96939:0crwdne96939:0 - default_role_member: crwdns96940:0crwdne96940:0 - default_type: crwdns96941:0crwdne96941:0 - default_type_bug: crwdns96942:0crwdne96942:0 - default_type_deliverable: crwdns96943:0crwdne96943:0 - default_type_epic: crwdns96944:0crwdne96944:0 - default_type_feature: crwdns96945:0crwdne96945:0 - default_type_milestone: crwdns96946:0crwdne96946:0 - default_type_phase: crwdns96947:0crwdne96947:0 - default_type_task: crwdns96948:0crwdne96948:0 - default_type_user_story: crwdns96949:0crwdne96949:0 - description_active: crwdns96950:0crwdne96950:0 - description_attachment_toggle: crwdns96951:0crwdne96951:0 - description_autocomplete: 'crwdns96952:0crwdne96952:0 + one: crwdns99953:1crwdne99953:1 + other: crwdns99953:5crwdne99953:5 + default_activity_development: crwdns99954:0crwdne99954:0 + default_activity_management: crwdns99955:0crwdne99955:0 + default_activity_other: crwdns99956:0crwdne99956:0 + default_activity_specification: crwdns99957:0crwdne99957:0 + default_activity_support: crwdns99958:0crwdne99958:0 + default_activity_testing: crwdns99959:0crwdne99959:0 + default_color_black: crwdns99960:0crwdne99960:0 + default_color_blue: crwdns99961:0crwdne99961:0 + default_color_blue_dark: crwdns99962:0crwdne99962:0 + default_color_blue_light: crwdns99963:0crwdne99963:0 + default_color_green_dark: crwdns99964:0crwdne99964:0 + default_color_green_light: crwdns99965:0crwdne99965:0 + default_color_grey_dark: crwdns99966:0crwdne99966:0 + default_color_grey_light: crwdns99967:0crwdne99967:0 + default_color_grey: crwdns99968:0crwdne99968:0 + default_color_magenta: crwdns99969:0crwdne99969:0 + default_color_orange: crwdns99970:0crwdne99970:0 + default_color_red: crwdns99971:0crwdne99971:0 + default_color_white: crwdns99972:0crwdne99972:0 + default_color_yellow: crwdns99973:0crwdne99973:0 + default_status_closed: crwdns99974:0crwdne99974:0 + default_status_confirmed: crwdns99975:0crwdne99975:0 + default_status_developed: crwdns99976:0crwdne99976:0 + default_status_in_development: crwdns99977:0crwdne99977:0 + default_status_in_progress: crwdns99978:0crwdne99978:0 + default_status_in_specification: crwdns99979:0crwdne99979:0 + default_status_in_testing: crwdns99980:0crwdne99980:0 + default_status_new: crwdns99981:0crwdne99981:0 + default_status_on_hold: crwdns99982:0crwdne99982:0 + default_status_rejected: crwdns99983:0crwdne99983:0 + default_status_scheduled: crwdns99984:0crwdne99984:0 + default_status_specified: crwdns99985:0crwdne99985:0 + default_status_tested: crwdns99986:0crwdne99986:0 + default_status_test_failed: crwdns99987:0crwdne99987:0 + default_status_to_be_scheduled: crwdns99988:0crwdne99988:0 + default_priority_low: crwdns99989:0crwdne99989:0 + default_priority_normal: crwdns99990:0crwdne99990:0 + default_priority_high: crwdns99991:0crwdne99991:0 + default_priority_immediate: crwdns99992:0crwdne99992:0 + default_role_anonymous: crwdns99993:0crwdne99993:0 + default_role_developer: crwdns99994:0crwdne99994:0 + default_role_project_admin: crwdns99995:0crwdne99995:0 + default_role_non_member: crwdns99996:0crwdne99996:0 + default_role_reader: crwdns99997:0crwdne99997:0 + default_role_member: crwdns99998:0crwdne99998:0 + default_type: crwdns99999:0crwdne99999:0 + default_type_bug: crwdns100000:0crwdne100000:0 + default_type_deliverable: crwdns100001:0crwdne100001:0 + default_type_epic: crwdns100002:0crwdne100002:0 + default_type_feature: crwdns100003:0crwdne100003:0 + default_type_milestone: crwdns100004:0crwdne100004:0 + default_type_phase: crwdns100005:0crwdne100005:0 + default_type_task: crwdns100006:0crwdne100006:0 + default_type_user_story: crwdns100007:0crwdne100007:0 + description_active: crwdns100008:0crwdne100008:0 + description_attachment_toggle: crwdns100009:0crwdne100009:0 + description_autocomplete: 'crwdns100010:0crwdne100010:0 ' - description_available_columns: crwdns96953:0crwdne96953:0 - description_choose_project: crwdns96954:0crwdne96954:0 - description_compare_from: crwdns96955:0crwdne96955:0 - description_compare_to: crwdns96956:0crwdne96956:0 - description_current_position: crwdns96957:0crwdne96957:0 - description_date_from: crwdns96958:0crwdne96958:0 - description_date_range_interval: crwdns96959:0crwdne96959:0 - description_date_range_list: crwdns96960:0crwdne96960:0 - description_date_to: crwdns96961:0crwdne96961:0 - description_enter_number: crwdns96962:0crwdne96962:0 - description_enter_text: crwdns96963:0crwdne96963:0 - description_filter: crwdns96964:0crwdne96964:0 - description_filter_toggle: crwdns96965:0crwdne96965:0 - description_category_reassign: crwdns96966:0crwdne96966:0 - description_message_content: crwdns96967:0crwdne96967:0 - description_my_project: crwdns96968:0crwdne96968:0 - description_notes: crwdns96969:0crwdne96969:0 - description_parent_work_package: crwdns96970:0crwdne96970:0 - description_project_scope: crwdns96971:0crwdne96971:0 - description_query_sort_criteria_attribute: crwdns96972:0crwdne96972:0 - description_query_sort_criteria_direction: crwdns96973:0crwdne96973:0 - description_search: crwdns96974:0crwdne96974:0 - description_select_work_package: crwdns96975:0crwdne96975:0 - description_selected_columns: crwdns96976:0crwdne96976:0 - description_sub_work_package: crwdns96977:0crwdne96977:0 - description_toc_toggle: crwdns96978:0crwdne96978:0 - description_wiki_subpages_reassign: crwdns96979:0crwdne96979:0 - direction: crwdns96980:0crwdne96980:0 + description_available_columns: crwdns100011:0crwdne100011:0 + description_choose_project: crwdns100012:0crwdne100012:0 + description_compare_from: crwdns100013:0crwdne100013:0 + description_compare_to: crwdns100014:0crwdne100014:0 + description_current_position: crwdns100015:0crwdne100015:0 + description_date_from: crwdns100016:0crwdne100016:0 + description_date_range_interval: crwdns100017:0crwdne100017:0 + description_date_range_list: crwdns100018:0crwdne100018:0 + description_date_to: crwdns100019:0crwdne100019:0 + description_enter_number: crwdns100020:0crwdne100020:0 + description_enter_text: crwdns100021:0crwdne100021:0 + description_filter: crwdns100022:0crwdne100022:0 + description_filter_toggle: crwdns100023:0crwdne100023:0 + description_category_reassign: crwdns100024:0crwdne100024:0 + description_message_content: crwdns100025:0crwdne100025:0 + description_my_project: crwdns100026:0crwdne100026:0 + description_notes: crwdns100027:0crwdne100027:0 + description_parent_work_package: crwdns100028:0crwdne100028:0 + description_project_scope: crwdns100029:0crwdne100029:0 + description_query_sort_criteria_attribute: crwdns100030:0crwdne100030:0 + description_query_sort_criteria_direction: crwdns100031:0crwdne100031:0 + description_search: crwdns100032:0crwdne100032:0 + description_select_work_package: crwdns100033:0crwdne100033:0 + description_selected_columns: crwdns100034:0crwdne100034:0 + description_sub_work_package: crwdns100035:0crwdne100035:0 + description_toc_toggle: crwdns100036:0crwdne100036:0 + description_wiki_subpages_reassign: crwdns100037:0crwdne100037:0 + direction: crwdns100038:0crwdne100038:0 ee: upsale: form_configuration: - description: crwdns96981:0crwdne96981:0 - add_groups: crwdns96982:0crwdne96982:0 - rename_groups: crwdns96983:0crwdne96983:0 + description: crwdns100039:0crwdne100039:0 + add_groups: crwdns100040:0crwdne100040:0 + rename_groups: crwdns100041:0crwdne100041:0 project_filters: - description_html: crwdns96984:0%{link}crwdne96984:0 - enumeration_activities: crwdns96985:0crwdne96985:0 - enumeration_work_package_priorities: crwdns96986:0crwdne96986:0 - enumeration_system_activity: crwdns96987:0crwdne96987:0 - enumeration_reported_project_statuses: crwdns96988:0crwdne96988:0 - error_auth_source_sso_failed: crwdns96989:0%{value}crwdne96989:0 - error_can_not_archive_project: crwdns99127:0crwdne99127:0 - error_can_not_delete_entry: crwdns96991:0crwdne96991:0 - error_can_not_delete_custom_field: crwdns96992:0crwdne96992:0 - error_can_not_delete_type: crwdns96993:0crwdne96993:0 - error_can_not_delete_standard_type: crwdns96994:0crwdne96994:0 - error_can_not_invite_user: crwdns96995:0crwdne96995:0 - error_can_not_remove_role: crwdns96996:0crwdne96996:0 - error_can_not_reopen_work_package_on_closed_version: crwdns96997:0crwdne96997:0 - error_check_user_and_role: crwdns96998:0crwdne96998:0 - error_cookie_missing: crwdns96999:0crwdne96999:0 - error_custom_option_not_found: crwdns97000:0crwdne97000:0 - error_dependent_work_package: crwdns98962:0%{related_id}crwdnd98962:0%{related_subject}crwdnd98962:0%{error}crwdne98962:0 - error_enterprise_activation_user_limit: crwdns98982:0crwdne98982:0 - error_failed_to_delete_entry: crwdns97001:0crwdne97001:0 - error_invalid_selected_value: crwdns99082:0crwdne99082:0 - error_invalid_group_by: crwdns97002:0%{value}crwdne97002:0 - error_invalid_query_column: crwdns97003:0%{value}crwdne97003:0 - error_invalid_sort_criterion: crwdns97004:0%{value}crwdne97004:0 - error_journal_attribute_not_present: crwdns99173:0%{attribute}crwdne99173:0 - error_pdf_export_too_many_columns: crwdns97005:0crwdne97005:0 - error_pdf_failed_to_export: crwdns99041:0%{error}crwdne99041:0 - error_token_authenticity: crwdns99174:0crwdne99174:0 - error_work_package_done_ratios_not_updated: crwdns97007:0crwdne97007:0 - error_work_package_not_found_in_project: crwdns97008:0crwdne97008:0 - error_must_be_project_member: crwdns97009:0crwdne97009:0 - error_no_default_work_package_status: crwdns97010:0crwdne97010:0 - error_no_type_in_project: crwdns97011:0crwdne97011:0 - error_omniauth_registration_timed_out: crwdns97012:0crwdne97012:0 - error_scm_command_failed: crwdns97013:0%{value}crwdne97013:0 - error_scm_not_found: crwdns97014:0crwdne97014:0 - error_unable_delete_status: crwdns97015:0crwdne97015:0 - error_unable_delete_default_status: crwdns97016:0crwdne97016:0 - error_unable_to_connect: crwdns97017:0%{value}crwdne97017:0 - error_unable_delete_wiki: crwdns97018:0crwdne97018:0 - error_unable_update_wiki: crwdns97019:0crwdne97019:0 - error_workflow_copy_source: crwdns97020:0crwdne97020:0 - error_workflow_copy_target: crwdns97021:0crwdne97021:0 - error_menu_item_not_created: crwdns97022:0crwdne97022:0 - error_menu_item_not_saved: crwdns97023:0crwdne97023:0 - error_wiki_root_menu_item_conflict: 'crwdns97024:0%{old_name}crwdnd97024:0%{new_name}crwdnd97024:0%{existing_caption}crwdnd97024:0%{existing_identifier}crwdne97024:0 + description_html: crwdns100042:0%{link}crwdne100042:0 + enumeration_activities: crwdns100043:0crwdne100043:0 + enumeration_work_package_priorities: crwdns100044:0crwdne100044:0 + enumeration_system_activity: crwdns100045:0crwdne100045:0 + enumeration_reported_project_statuses: crwdns100046:0crwdne100046:0 + error_auth_source_sso_failed: crwdns100047:0%{value}crwdne100047:0 + error_can_not_archive_project: crwdns100048:0crwdne100048:0 + error_can_not_delete_entry: crwdns100049:0crwdne100049:0 + error_can_not_delete_custom_field: crwdns100050:0crwdne100050:0 + error_can_not_delete_type: crwdns100051:0crwdne100051:0 + error_can_not_delete_standard_type: crwdns100052:0crwdne100052:0 + error_can_not_invite_user: crwdns100053:0crwdne100053:0 + error_can_not_remove_role: crwdns100054:0crwdne100054:0 + error_can_not_reopen_work_package_on_closed_version: crwdns100055:0crwdne100055:0 + error_check_user_and_role: crwdns100056:0crwdne100056:0 + error_cookie_missing: crwdns100057:0crwdne100057:0 + error_custom_option_not_found: crwdns100058:0crwdne100058:0 + error_dependent_work_package: crwdns100059:0%{related_id}crwdnd100059:0%{related_subject}crwdnd100059:0%{error}crwdne100059:0 + error_enterprise_activation_user_limit: crwdns100060:0crwdne100060:0 + error_failed_to_delete_entry: crwdns100061:0crwdne100061:0 + error_invalid_selected_value: crwdns100062:0crwdne100062:0 + error_invalid_group_by: crwdns100063:0%{value}crwdne100063:0 + error_invalid_query_column: crwdns100064:0%{value}crwdne100064:0 + error_invalid_sort_criterion: crwdns100065:0%{value}crwdne100065:0 + error_journal_attribute_not_present: crwdns100066:0%{attribute}crwdne100066:0 + error_pdf_export_too_many_columns: crwdns100067:0crwdne100067:0 + error_pdf_failed_to_export: crwdns100068:0%{error}crwdne100068:0 + error_token_authenticity: crwdns100069:0crwdne100069:0 + error_work_package_done_ratios_not_updated: crwdns100070:0crwdne100070:0 + error_work_package_not_found_in_project: crwdns100071:0crwdne100071:0 + error_must_be_project_member: crwdns100072:0crwdne100072:0 + error_no_default_work_package_status: crwdns100073:0crwdne100073:0 + error_no_type_in_project: crwdns100074:0crwdne100074:0 + error_omniauth_registration_timed_out: crwdns100075:0crwdne100075:0 + error_scm_command_failed: crwdns100076:0%{value}crwdne100076:0 + error_scm_not_found: crwdns100077:0crwdne100077:0 + error_unable_delete_status: crwdns100078:0crwdne100078:0 + error_unable_delete_default_status: crwdns100079:0crwdne100079:0 + error_unable_to_connect: crwdns100080:0%{value}crwdne100080:0 + error_unable_delete_wiki: crwdns100081:0crwdne100081:0 + error_unable_update_wiki: crwdns100082:0crwdne100082:0 + error_workflow_copy_source: crwdns100083:0crwdne100083:0 + error_workflow_copy_target: crwdns100084:0crwdne100084:0 + error_menu_item_not_created: crwdns100085:0crwdne100085:0 + error_menu_item_not_saved: crwdns100086:0crwdne100086:0 + error_wiki_root_menu_item_conflict: 'crwdns100087:0%{old_name}crwdnd100087:0%{new_name}crwdnd100087:0%{existing_caption}crwdnd100087:0%{existing_identifier}crwdne100087:0 ' - error_external_authentication_failed: crwdns97025:0crwdne97025:0 + error_external_authentication_failed: crwdns100088:0crwdne100088:0 + error_attribute_not_highlightable: crwdns102540:0%{attributes}crwdne102540:0 events: - project: crwdns97026:0crwdne97026:0 - changeset: crwdns97027:0crwdne97027:0 - message: crwdns97028:0crwdne97028:0 - news: crwdns97029:0crwdne97029:0 - reply: crwdns97030:0crwdne97030:0 - time_entry: crwdns97031:0crwdne97031:0 - wiki_page: crwdns97032:0crwdne97032:0 - work_package_closed: crwdns97033:0crwdne97033:0 - work_package_edit: crwdns97034:0crwdne97034:0 - work_package_note: crwdns97035:0crwdne97035:0 + project: crwdns100089:0crwdne100089:0 + changeset: crwdns100090:0crwdne100090:0 + message: crwdns100091:0crwdne100091:0 + news: crwdns100092:0crwdne100092:0 + reply: crwdns100093:0crwdne100093:0 + time_entry: crwdns100094:0crwdne100094:0 + wiki_page: crwdns100095:0crwdne100095:0 + work_package_closed: crwdns100096:0crwdne100096:0 + work_package_edit: crwdns100097:0crwdne100097:0 + work_package_note: crwdns100098:0crwdne100098:0 export: format: - atom: crwdns97036:0crwdne97036:0 - csv: crwdns97037:0crwdne97037:0 - pdf: crwdns97038:0crwdne97038:0 - pdf_with_descriptions: crwdns97039:0crwdne97039:0 - pdf_with_descriptions_and_attachments: crwdns99042:0crwdne99042:0 - pdf_with_attachments: crwdns99043:0crwdne99043:0 + atom: crwdns100099:0crwdne100099:0 + csv: crwdns100100:0crwdne100100:0 + pdf: crwdns100101:0crwdne100101:0 + pdf_with_descriptions: crwdns100102:0crwdne100102:0 + pdf_with_descriptions_and_attachments: crwdns100103:0crwdne100103:0 + pdf_with_attachments: crwdns100104:0crwdne100104:0 extraction: available: - pdftotext: crwdns98859:0crwdne98859:0 - unrtf: crwdns98860:0crwdne98860:0 - catdoc: crwdns98861:0crwdne98861:0 - xls2csv: crwdns98862:0crwdne98862:0 - catppt: crwdns98863:0crwdne98863:0 - tesseract: crwdns98864:0crwdne98864:0 - general_csv_decimal_separator: crwdns97040:0crwdne97040:0 - general_csv_encoding: crwdns97041:0crwdne97041:0 - general_csv_separator: crwdns97042:0crwdne97042:0 - general_first_day_of_week: crwdns97043:0crwdne97043:0 - general_lang_name: crwdns97044:0crwdne97044:0 - general_pdf_encoding: crwdns97045:0crwdne97045:0 - general_text_no: crwdns97046:0crwdne97046:0 - general_text_yes: crwdns97047:0crwdne97047:0 - general_text_No: crwdns97048:0crwdne97048:0 - general_text_Yes: crwdns97049:0crwdne97049:0 - gui_validation_error: crwdns97050:0crwdne97050:0 - gui_validation_error_plural: crwdns97051:0%{count}crwdne97051:0 + pdftotext: crwdns100105:0crwdne100105:0 + unrtf: crwdns100106:0crwdne100106:0 + catdoc: crwdns100107:0crwdne100107:0 + xls2csv: crwdns100108:0crwdne100108:0 + catppt: crwdns100109:0crwdne100109:0 + tesseract: crwdns100110:0crwdne100110:0 + general_csv_decimal_separator: crwdns100111:0crwdne100111:0 + general_csv_encoding: crwdns100112:0crwdne100112:0 + general_csv_separator: crwdns100113:0crwdne100113:0 + general_first_day_of_week: crwdns100114:0crwdne100114:0 + general_lang_name: crwdns100115:0crwdne100115:0 + general_pdf_encoding: crwdns100116:0crwdne100116:0 + general_text_no: crwdns100117:0crwdne100117:0 + general_text_yes: crwdns100118:0crwdne100118:0 + general_text_No: crwdns100119:0crwdne100119:0 + general_text_Yes: crwdns100120:0crwdne100120:0 + gui_validation_error: crwdns100121:0crwdne100121:0 + gui_validation_error_plural: crwdns100122:0%{count}crwdne100122:0 homescreen: additional: - projects: crwdns97052:0crwdne97052:0 - no_visible_projects: crwdns99116:0crwdne99116:0 - users: crwdns97053:0crwdne97053:0 + projects: crwdns100123:0crwdne100123:0 + no_visible_projects: crwdns100124:0crwdne100124:0 + users: crwdns100125:0crwdne100125:0 blocks: - community: crwdns97054:0crwdne97054:0 + community: crwdns100126:0crwdne100126:0 upsale: - become_hero: crwdns97055:0crwdne97055:0 - title: crwdns97056:0crwdne97056:0 - description: crwdns97057:0crwdne97057:0 - more_info: crwdns97058:0crwdne97058:0 - additional_features: crwdns97059:0crwdne97059:0 - professional_support: crwdns97060:0crwdne97060:0 - you_contribute: crwdns97061:0crwdne97061:0 + become_hero: crwdns100127:0crwdne100127:0 + title: crwdns100128:0crwdne100128:0 + description: crwdns102536:0crwdne102536:0 + more_info: crwdns100130:0crwdne100130:0 + additional_features: crwdns100131:0crwdne100131:0 + professional_support: crwdns100132:0crwdne100132:0 + you_contribute: crwdns100133:0crwdne100133:0 links: - upgrade_enterprise_edition: crwdns97062:0crwdne97062:0 - user_guides: crwdns97063:0crwdne97063:0 - faq: crwdns97064:0crwdne97064:0 - glossary: crwdns97065:0crwdne97065:0 - shortcuts: crwdns97066:0crwdne97066:0 - forums: crwdns97067:0crwdne97067:0 - blog: crwdns97068:0crwdne97068:0 - boards: crwdns97069:0crwdne97069:0 - newsletter: crwdns97070:0crwdne97070:0 + upgrade_enterprise_edition: crwdns100134:0crwdne100134:0 + user_guides: crwdns100135:0crwdne100135:0 + faq: crwdns100136:0crwdne100136:0 + glossary: crwdns100137:0crwdne100137:0 + shortcuts: crwdns100138:0crwdne100138:0 + forums: crwdns100139:0crwdne100139:0 + blog: crwdns100140:0crwdne100140:0 + boards: crwdns100141:0crwdne100141:0 + newsletter: crwdns100142:0crwdne100142:0 links: - configuration_guide: crwdns97071:0crwdne97071:0 - instructions_after_registration: crwdns97072:0%{signin}crwdne97072:0 - instructions_after_logout: crwdns97073:0%{signin}crwdne97073:0 - instructions_after_error: crwdns97074:0%{signin}crwdne97074:0 + configuration_guide: crwdns100143:0crwdne100143:0 + instructions_after_registration: crwdns100144:0%{signin}crwdne100144:0 + instructions_after_logout: crwdns100145:0%{signin}crwdne100145:0 + instructions_after_error: crwdns100146:0%{signin}crwdne100146:0 my_account: access_tokens: no_results: - title: crwdns97075:0crwdne97075:0 - description: crwdns97076:0crwdne97076:0 - access_token: crwdns97077:0crwdne97077:0 + title: crwdns100147:0crwdne100147:0 + description: crwdns100148:0crwdne100148:0 + access_token: crwdns100149:0crwdne100149:0 headers: - action: crwdns97078:0crwdne97078:0 - expiration: crwdns97079:0crwdne97079:0 - indefinite_expiration: crwdns97080:0crwdne97080:0 - label_accessibility: crwdns97081:0crwdne97081:0 - label_account: crwdns97082:0crwdne97082:0 - label_active: crwdns97083:0crwdne97083:0 - label_activate_user: crwdns97084:0crwdne97084:0 - label_active_in_new_projects: crwdns97085:0crwdne97085:0 - label_activity: crwdns97086:0crwdne97086:0 - label_add_edit_translations: crwdns97087:0crwdne97087:0 - label_add_another_file: crwdns97088:0crwdne97088:0 - label_add_columns: crwdns97089:0crwdne97089:0 - label_add_note: crwdns97090:0crwdne97090:0 - label_add_related_work_packages: crwdns97091:0crwdne97091:0 - label_add_subtask: crwdns97092:0crwdne97092:0 - label_added: crwdns97093:0crwdne97093:0 - label_added_time_by: crwdns97094:0%{author}crwdnd97094:0%{age}crwdne97094:0 - label_additional_workflow_transitions_for_assignee: crwdns97095:0crwdne97095:0 - label_additional_workflow_transitions_for_author: crwdns97096:0crwdne97096:0 - label_administration: crwdns97097:0crwdne97097:0 - label_advanced_settings: crwdns97098:0crwdne97098:0 - label_age: crwdns97099:0crwdne97099:0 - label_ago: crwdns97100:0crwdne97100:0 - label_all: crwdns97101:0crwdne97101:0 - label_all_time: crwdns97102:0crwdne97102:0 - label_all_words: crwdns97103:0crwdne97103:0 - label_all_open_wps: crwdns98940:0crwdne98940:0 - label_always_visible: crwdns97104:0crwdne97104:0 - label_announcement: crwdns97105:0crwdne97105:0 - label_and_its_subprojects: crwdns97106:0%{value}crwdne97106:0 - label_api_access_key: crwdns97107:0crwdne97107:0 - label_api_access_key_created_on: crwdns97108:0%{value}crwdne97108:0 - label_api_access_key_type: crwdns97109:0crwdne97109:0 - label_applied_status: crwdns97110:0crwdne97110:0 - label_archive_project: crwdns97111:0crwdne97111:0 - label_ascending: crwdns97112:0crwdne97112:0 - label_assigned_to_me_work_packages: crwdns97113:0crwdne97113:0 - label_associated_revisions: crwdns97114:0crwdne97114:0 - label_attachment_delete: crwdns97115:0crwdne97115:0 - label_attachment_new: crwdns97116:0crwdne97116:0 - label_attachment_plural: crwdns97117:0crwdne97117:0 - label_attribute: crwdns97118:0crwdne97118:0 - label_attribute_plural: crwdns97119:0crwdne97119:0 - label_auth_source: crwdns97120:0crwdne97120:0 - label_auth_source_new: crwdns97121:0crwdne97121:0 - label_auth_source_plural: crwdns97122:0crwdne97122:0 - label_authentication: crwdns97123:0crwdne97123:0 - label_available_project_work_package_categories: crwdns97124:0crwdne97124:0 - label_available_project_boards: crwdns97125:0crwdne97125:0 - label_available_project_versions: crwdns97126:0crwdne97126:0 - label_available_project_repositories: crwdns97127:0crwdne97127:0 - label_api_documentation: crwdns97128:0crwdne97128:0 - label_between: crwdns97129:0crwdne97129:0 - label_blocked_by: crwdns97130:0crwdne97130:0 - label_blocks: crwdns97131:0crwdne97131:0 - label_blog: crwdns97132:0crwdne97132:0 - label_board_locked: crwdns97133:0crwdne97133:0 - label_board_new: crwdns97134:0crwdne97134:0 - label_board_plural: crwdns97135:0crwdne97135:0 - label_board_sticky: crwdns97136:0crwdne97136:0 - label_boolean: crwdns97137:0crwdne97137:0 - label_branch: crwdns97138:0crwdne97138:0 - label_browse: crwdns97139:0crwdne97139:0 - label_bulk_edit_selected_work_packages: crwdns97140:0crwdne97140:0 - label_calendar: crwdns97141:0crwdne97141:0 - label_calendar_show: crwdns97142:0crwdne97142:0 - label_category: crwdns97143:0crwdne97143:0 - label_consent_settings: crwdns98963:0crwdne98963:0 - label_wiki_menu_item: crwdns97144:0crwdne97144:0 - label_select_main_menu_item: crwdns97145:0crwdne97145:0 - label_select_project: crwdns97146:0crwdne97146:0 - label_required_disk_storage: crwdns97147:0crwdne97147:0 - label_send_invitation: crwdns97148:0crwdne97148:0 - label_change_plural: crwdns97149:0crwdne97149:0 - label_change_properties: crwdns97150:0crwdne97150:0 - label_change_status: crwdns97151:0crwdne97151:0 - label_change_status_of_user: crwdns97152:0#{username}crwdne97152:0 - label_change_view_all: crwdns97153:0crwdne97153:0 - label_changes_details: crwdns97154:0crwdne97154:0 - label_changeset: crwdns97155:0crwdne97155:0 - label_changeset_id: crwdns97156:0crwdne97156:0 - label_changeset_plural: crwdns97157:0crwdne97157:0 - label_checked: crwdns97158:0crwdne97158:0 - label_check_uncheck_all_in_column: crwdns97159:0crwdne97159:0 - label_check_uncheck_all_in_row: crwdns97160:0crwdne97160:0 - label_child_element: crwdns97161:0crwdne97161:0 - label_chronological_order: crwdns97162:0crwdne97162:0 - label_close_versions: crwdns97163:0crwdne97163:0 - label_closed_work_packages: crwdns97164:0crwdne97164:0 - label_collapse: crwdns97165:0crwdne97165:0 - label_collapsed_click_to_show: crwdns98941:0crwdne98941:0 - label_configuration: crwdns97166:0crwdne97166:0 - label_comment_add: crwdns97167:0crwdne97167:0 - label_comment_added: crwdns97168:0crwdne97168:0 - label_comment_delete: crwdns97169:0crwdne97169:0 - label_comment_plural: crwdns97170:0crwdne97170:0 - label_commits_per_author: crwdns97171:0crwdne97171:0 - label_commits_per_month: crwdns97172:0crwdne97172:0 - label_confirmation: crwdns97173:0crwdne97173:0 - label_contains: crwdns97174:0crwdne97174:0 - label_content: crwdns97175:0crwdne97175:0 - label_copied: crwdns97176:0crwdne97176:0 - label_copy_to_clipboard: crwdns97177:0crwdne97177:0 - label_copy_same_as_target: crwdns97178:0crwdne97178:0 - label_copy_source: crwdns97179:0crwdne97179:0 - label_copy_target: crwdns97180:0crwdne97180:0 - label_copy_workflow_from: crwdns97181:0crwdne97181:0 - label_copy_project: crwdns97182:0crwdne97182:0 - label_core_version: crwdns97183:0crwdne97183:0 - label_current_status: crwdns97184:0crwdne97184:0 - label_current_version: crwdns97185:0crwdne97185:0 - label_custom_field_add_no_type: crwdns97186:0crwdne97186:0 - label_custom_field_new: crwdns97187:0crwdne97187:0 - label_custom_field_plural: crwdns97188:0crwdne97188:0 - label_custom_field_default_type: crwdns97189:0crwdne97189:0 - label_custom_style: crwdns97190:0crwdne97190:0 - label_date: crwdns97191:0crwdne97191:0 - label_date_and_time: crwdns97192:0crwdne97192:0 - label_date_from: crwdns97193:0crwdne97193:0 - label_date_from_to: crwdns97194:0%{start}crwdnd97194:0%{end}crwdne97194:0 - label_date_range: crwdns97195:0crwdne97195:0 - label_date_to: crwdns97196:0crwdne97196:0 - label_day_plural: crwdns97197:0crwdne97197:0 - label_default: crwdns97198:0crwdne97198:0 - label_delete_user: crwdns97199:0crwdne97199:0 - label_delete_project: crwdns97200:0crwdne97200:0 - label_deleted: crwdns97201:0crwdne97201:0 - label_deleted_custom_field: crwdns97202:0crwdne97202:0 - label_descending: crwdns97203:0crwdne97203:0 - label_details: crwdns97204:0crwdne97204:0 - label_development_roadmap: crwdns97205:0crwdne97205:0 - label_diff: crwdns97206:0crwdne97206:0 - label_diff_inline: crwdns97207:0crwdne97207:0 - label_diff_side_by_side: crwdns97208:0crwdne97208:0 - label_disabled: crwdns97209:0crwdne97209:0 - label_display: crwdns97210:0crwdne97210:0 - label_display_per_page: crwdns97211:0%{value}crwdne97211:0 - label_display_used_statuses_only: crwdns97212:0crwdne97212:0 - label_download: crwdns97213:0%{count}crwdne97213:0 - label_download_plural: crwdns97214:0%{count}crwdne97214:0 - label_downloads_abbr: crwdns97215:0crwdne97215:0 - label_duplicated_by: crwdns97216:0crwdne97216:0 - label_duplicate: crwdns97217:0crwdne97217:0 - label_duplicates: crwdns97218:0crwdne97218:0 - label_edit: crwdns97219:0crwdne97219:0 - label_enable_multi_select: crwdns97220:0crwdne97220:0 - label_enabled_project_custom_fields: crwdns97221:0crwdne97221:0 - label_enabled_project_modules: crwdns97223:0crwdne97223:0 - label_enabled_project_activities: crwdns97224:0crwdne97224:0 - label_end_to_end: crwdns97225:0crwdne97225:0 - label_end_to_start: crwdns97226:0crwdne97226:0 - label_enumeration_new: crwdns97227:0crwdne97227:0 - label_enumeration_value: crwdns97228:0crwdne97228:0 - label_enumerations: crwdns97229:0crwdne97229:0 - label_enterprise: crwdns97230:0crwdne97230:0 - label_enterprise_active_users: crwdns98983:0%{current}crwdnd98983:0%{limit}crwdne98983:0 - label_enterprise_edition: crwdns97231:0crwdne97231:0 - label_environment: crwdns97232:0crwdne97232:0 - label_estimates_and_time: crwdns97233:0crwdne97233:0 - label_equals: crwdns97234:0crwdne97234:0 - label_example: crwdns97235:0crwdne97235:0 - label_export_to: crwdns97236:0crwdne97236:0 - label_expanded_click_to_collapse: crwdns98943:0crwdne98943:0 - label_f_hour: crwdns97237:0%{value}crwdne97237:0 - label_f_hour_plural: crwdns97238:0%{value}crwdne97238:0 - label_feed_plural: crwdns97239:0crwdne97239:0 - label_feeds_access_key: crwdns97240:0crwdne97240:0 - label_feeds_access_key_created_on: crwdns97241:0%{value}crwdne97241:0 - label_feeds_access_key_type: crwdns97242:0crwdne97242:0 - label_file_added: crwdns97243:0crwdne97243:0 - label_file_plural: crwdns97244:0crwdne97244:0 - label_filter_add: crwdns97245:0crwdne97245:0 - label_filter_plural: crwdns97246:0crwdne97246:0 - label_filters_toggle: crwdns97247:0crwdne97247:0 - label_float: crwdns97248:0crwdne97248:0 - label_folder: crwdns97249:0crwdne97249:0 - label_follows: crwdns97250:0crwdne97250:0 - label_force_user_language_to_default: crwdns97251:0crwdne97251:0 - label_form_configuration: crwdns97252:0crwdne97252:0 - label_gantt: crwdns98997:0crwdne98997:0 - label_gantt_chart: crwdns98998:0crwdne98998:0 - label_general: crwdns97253:0crwdne97253:0 - label_generate_key: crwdns97254:0crwdne97254:0 - label_git_path: crwdns97255:0crwdne97255:0 - label_greater_or_equal: crwdns97256:0crwdne97256:0 - label_group_by: crwdns97257:0crwdne97257:0 - label_group_new: crwdns97258:0crwdne97258:0 - label_group: crwdns97259:0crwdne97259:0 - label_group_named: crwdns99244:0%{name}crwdne99244:0 - label_group_plural: crwdns97260:0crwdne97260:0 - label_help: crwdns97261:0crwdne97261:0 - label_here: crwdns97262:0crwdne97262:0 - label_hide: crwdns97263:0crwdne97263:0 - label_history: crwdns97264:0crwdne97264:0 - label_hierarchy_leaf: crwdns98944:0crwdne98944:0 - label_home: crwdns97265:0crwdne97265:0 - label_in: crwdns97266:0crwdne97266:0 - label_in_less_than: crwdns97267:0crwdne97267:0 - label_in_more_than: crwdns97268:0crwdne97268:0 - label_inactive: crwdns97269:0crwdne97269:0 - label_incoming_emails: crwdns97270:0crwdne97270:0 - label_includes: crwdns97271:0crwdne97271:0 - label_index_by_date: crwdns97272:0crwdne97272:0 - label_index_by_title: crwdns97273:0crwdne97273:0 - label_information: crwdns97274:0crwdne97274:0 - label_information_plural: crwdns97275:0crwdne97275:0 - label_integer: crwdns97276:0crwdne97276:0 - label_internal: crwdns97277:0crwdne97277:0 - label_introduction_video: crwdns98892:0crwdne98892:0 - label_invite_user: crwdns97278:0crwdne97278:0 - label_show_hide: crwdns97279:0crwdne97279:0 - label_show_all_registered_users: crwdns97280:0crwdne97280:0 - label_journal: crwdns97281:0crwdne97281:0 - label_journal_diff: crwdns97282:0crwdne97282:0 - label_language: crwdns97283:0crwdne97283:0 - label_jump_to_a_project: crwdns97284:0crwdne97284:0 - label_language_based: crwdns97285:0crwdne97285:0 - label_last_activity: crwdns97286:0crwdne97286:0 - label_last_change_on: crwdns97287:0crwdne97287:0 - label_last_changes: crwdns97288:0%{count}crwdne97288:0 - label_last_login: crwdns97289:0crwdne97289:0 - label_last_month: crwdns97290:0crwdne97290:0 - label_last_n_days: crwdns97291:0%{count}crwdne97291:0 - label_last_week: crwdns97292:0crwdne97292:0 - label_latest_revision: crwdns97293:0crwdne97293:0 - label_latest_revision_plural: crwdns97294:0crwdne97294:0 - label_ldap_authentication: crwdns97295:0crwdne97295:0 - label_less_or_equal: crwdns97296:0crwdne97296:0 - label_less_than_ago: crwdns97297:0crwdne97297:0 - label_list: crwdns97298:0crwdne97298:0 - label_loading: crwdns97299:0crwdne97299:0 - label_lock_user: crwdns97300:0crwdne97300:0 - label_logged_as: crwdns97301:0crwdne97301:0 - label_login: crwdns97302:0crwdne97302:0 - label_custom_logo: crwdns97303:0crwdne97303:0 - label_custom_favicon: crwdns97304:0crwdne97304:0 - label_custom_touch_icon: crwdns97305:0crwdne97305:0 - label_logout: crwdns97306:0crwdne97306:0 - label_main_menu: crwdns97307:0crwdne97307:0 - label_manage_groups: crwdns97308:0crwdne97308:0 - label_managed_repositories_vendor: crwdns97309:0%{vendor}crwdne97309:0 - label_max_size: crwdns97310:0crwdne97310:0 - label_me: crwdns97311:0crwdne97311:0 - label_member_new: crwdns97312:0crwdne97312:0 - label_member_plural: crwdns97313:0crwdne97313:0 - label_view_all_members: crwdns97314:0crwdne97314:0 - label_menu_item_name: crwdns97315:0crwdne97315:0 - label_message: crwdns97316:0crwdne97316:0 - label_message_last: crwdns97317:0crwdne97317:0 - label_message_new: crwdns97318:0crwdne97318:0 - label_message_plural: crwdns97319:0crwdne97319:0 - label_message_posted: crwdns97320:0crwdne97320:0 - label_min_max_length: crwdns97321:0crwdne97321:0 - label_minute_plural: crwdns97322:0crwdne97322:0 - label_missing_api_access_key: crwdns97323:0crwdne97323:0 - label_missing_feeds_access_key: crwdns97324:0crwdne97324:0 - label_modification: crwdns97325:0%{count}crwdne97325:0 - label_modified: crwdns97326:0crwdne97326:0 - label_module_plural: crwdns97327:0crwdne97327:0 - label_modules: crwdns97328:0crwdne97328:0 - label_month: crwdns97329:0crwdne97329:0 - label_months_from: crwdns97330:0crwdne97330:0 - label_more: crwdns97331:0crwdne97331:0 - label_more_than_ago: crwdns97332:0crwdne97332:0 - label_move_work_package: crwdns97333:0crwdne97333:0 - label_my_account: crwdns97334:0crwdne97334:0 - label_my_account_data: crwdns97335:0crwdne97335:0 - label_my_page: crwdns97336:0crwdne97336:0 - label_my_page_block: crwdns97337:0crwdne97337:0 - label_my_projects: crwdns97338:0crwdne97338:0 - label_my_queries: crwdns97339:0crwdne97339:0 - label_never: crwdns98964:0crwdne98964:0 - label_new: crwdns97340:0crwdne97340:0 - label_new_statuses_allowed: crwdns97341:0crwdne97341:0 - label_news_added: crwdns97342:0crwdne97342:0 - label_news_comment_added: crwdns97343:0crwdne97343:0 - label_news_latest: crwdns97344:0crwdne97344:0 - label_news_new: crwdns97345:0crwdne97345:0 - label_news_edit: crwdns97346:0crwdne97346:0 - label_news_plural: crwdns97347:0crwdne97347:0 - label_news_view_all: crwdns97348:0crwdne97348:0 - label_next: crwdns97349:0crwdne97349:0 - label_next_week: crwdns97350:0crwdne97350:0 - label_no_change_option: crwdns97351:0crwdne97351:0 - label_no_data: crwdns97352:0crwdne97352:0 - label_no_parent_page: crwdns99002:0crwdne99002:0 - label_nothing_display: crwdns97353:0crwdne97353:0 - label_nobody: crwdns97354:0crwdne97354:0 - label_none: crwdns97355:0crwdne97355:0 - label_none_parentheses: crwdns97356:0crwdne97356:0 - label_not_contains: crwdns97357:0crwdne97357:0 - label_not_equals: crwdns97358:0crwdne97358:0 - label_notify_member_plural: crwdns97359:0crwdne97359:0 - label_on: crwdns97360:0crwdne97360:0 - label_open_menu: crwdns97361:0crwdne97361:0 - label_open_work_packages: crwdns97362:0crwdne97362:0 - label_open_work_packages_plural: crwdns97363:0crwdne97363:0 - label_openproject_website: crwdns98893:0crwdne98893:0 - label_optional_description: crwdns97364:0crwdne97364:0 - label_options: crwdns97365:0crwdne97365:0 - label_other: crwdns97366:0crwdne97366:0 - label_overall_activity: crwdns97367:0crwdne97367:0 - label_overall_spent_time: crwdns97368:0crwdne97368:0 - label_overview: crwdns97369:0crwdne97369:0 - label_page_title: crwdns99005:0crwdne99005:0 - label_part_of: crwdns97370:0crwdne97370:0 - label_password_lost: crwdns97371:0crwdne97371:0 - label_password_rule_lowercase: crwdns97372:0crwdne97372:0 - label_password_rule_numeric: crwdns97373:0crwdne97373:0 - label_password_rule_special: crwdns97374:0crwdne97374:0 - label_password_rule_uppercase: crwdns97375:0crwdne97375:0 - label_path_encoding: crwdns97376:0crwdne97376:0 - label_pdf_with_descriptions: crwdns97377:0crwdne97377:0 - label_per_page: crwdns97378:0crwdne97378:0 - label_people: crwdns97379:0crwdne97379:0 - label_permissions: crwdns97380:0crwdne97380:0 - label_permissions_report: crwdns97381:0crwdne97381:0 - label_personalize_page: crwdns97382:0crwdne97382:0 - label_planning: crwdns97383:0crwdne97383:0 - label_please_login: crwdns97384:0crwdne97384:0 - label_plugins: crwdns97385:0crwdne97385:0 - label_precedes: crwdns97386:0crwdne97386:0 - label_preferences: crwdns97387:0crwdne97387:0 - label_preview: crwdns97388:0crwdne97388:0 - label_previous: crwdns97389:0crwdne97389:0 - label_previous_week: crwdns97390:0crwdne97390:0 - label_principal_invite_via_email: crwdns97391:0crwdne97391:0 - label_principal_search: crwdns97392:0crwdne97392:0 - label_product_version: crwdns97393:0crwdne97393:0 - label_professional_support: crwdns97394:0crwdne97394:0 - label_profile: crwdns97395:0crwdne97395:0 - label_project_all: crwdns97396:0crwdne97396:0 - label_project_count: crwdns97397:0crwdne97397:0 - label_project_copy_notifications: crwdns97398:0crwdne97398:0 - label_project_latest: crwdns97399:0crwdne97399:0 - label_project_default_type: crwdns97400:0crwdne97400:0 - label_project_hierarchy: crwdns97401:0crwdne97401:0 - label_project_new: crwdns97402:0crwdne97402:0 - label_project_plural: crwdns97403:0crwdne97403:0 - label_project_settings: crwdns97404:0crwdne97404:0 - label_projects_storage_information: crwdns97405:0%{count}crwdnd97405:0%{storage}crwdne97405:0 - label_project_view_all: crwdns97406:0crwdne97406:0 - label_project_show_details: crwdns97407:0crwdne97407:0 - label_project_hide_details: crwdns97408:0crwdne97408:0 - label_public_projects: crwdns97409:0crwdne97409:0 - label_query_new: crwdns97410:0crwdne97410:0 - label_query_plural: crwdns97411:0crwdne97411:0 - label_query_menu_item: crwdns97412:0crwdne97412:0 - label_read: crwdns97413:0crwdne97413:0 - label_register: crwdns97414:0crwdne97414:0 - label_register_with_developer: crwdns97415:0crwdne97415:0 - label_registered_on: crwdns97416:0crwdne97416:0 - label_registration_activation_by_email: crwdns97417:0crwdne97417:0 - label_registration_automatic_activation: crwdns97418:0crwdne97418:0 - label_registration_manual_activation: crwdns97419:0crwdne97419:0 - label_related_work_packages: crwdns97420:0crwdne97420:0 - label_relates: crwdns97421:0crwdne97421:0 - label_relates_to: crwdns97422:0crwdne97422:0 - label_relation_delete: crwdns97423:0crwdne97423:0 - label_relation_new: crwdns97424:0crwdne97424:0 - label_release_notes: crwdns97425:0crwdne97425:0 - label_remove_columns: crwdns97426:0crwdne97426:0 - label_renamed: crwdns97427:0crwdne97427:0 - label_reply_plural: crwdns97428:0crwdne97428:0 - label_report: crwdns97429:0crwdne97429:0 - label_report_bug: crwdns97430:0crwdne97430:0 - label_report_plural: crwdns97431:0crwdne97431:0 - label_reported_work_packages: crwdns97432:0crwdne97432:0 - label_reporting: crwdns97433:0crwdne97433:0 - label_reporting_plural: crwdns97434:0crwdne97434:0 - label_repository: crwdns97435:0crwdne97435:0 - label_repository_root: crwdns97436:0crwdne97436:0 - label_repository_plural: crwdns97437:0crwdne97437:0 - label_required: crwdns97438:0crwdne97438:0 - label_requires: crwdns97439:0crwdne97439:0 - label_responsible_for_work_packages: crwdns99075:0crwdne99075:0 - label_result_plural: crwdns97441:0crwdne97441:0 - label_reverse_chronological_order: crwdns97442:0crwdne97442:0 - label_revision: crwdns97443:0crwdne97443:0 - label_revision_id: crwdns97444:0%{value}crwdne97444:0 - label_revision_plural: crwdns97445:0crwdne97445:0 - label_roadmap: crwdns97446:0crwdne97446:0 - label_roadmap_edit: crwdns97447:0%{name}crwdne97447:0 - label_roadmap_due_in: crwdns97448:0%{value}crwdne97448:0 - label_roadmap_no_work_packages: crwdns97449:0crwdne97449:0 - label_roadmap_overdue: crwdns97450:0%{value}crwdne97450:0 - label_role_and_permissions: crwdns97451:0crwdne97451:0 - label_role_new: crwdns97452:0crwdne97452:0 - label_role_plural: crwdns97453:0crwdne97453:0 - label_role_search: crwdns97454:0crwdne97454:0 - label_scm: crwdns97455:0crwdne97455:0 - label_search: crwdns97456:0crwdne97456:0 - label_search_titles_only: crwdns97457:0crwdne97457:0 - label_send_information: crwdns97458:0crwdne97458:0 - label_send_test_email: crwdns97459:0crwdne97459:0 - label_settings: crwdns97460:0crwdne97460:0 - label_system_settings: crwdns97461:0crwdne97461:0 - label_show_completed_versions: crwdns97462:0crwdne97462:0 - label_sort: crwdns97463:0crwdne97463:0 - label_sort_by: crwdns97464:0%{value}crwdne97464:0 - label_sorted_by: crwdns97465:0%{value}crwdne97465:0 - label_sort_higher: crwdns97466:0crwdne97466:0 - label_sort_highest: crwdns97467:0crwdne97467:0 - label_sort_lower: crwdns97468:0crwdne97468:0 - label_sort_lowest: crwdns97469:0crwdne97469:0 - label_spent_time: crwdns97470:0crwdne97470:0 - label_start_to_end: crwdns97471:0crwdne97471:0 - label_start_to_start: crwdns97472:0crwdne97472:0 - label_statistics: crwdns97473:0crwdne97473:0 - label_status: crwdns97474:0crwdne97474:0 - label_status_updated: crwdns97475:0crwdne97475:0 - label_stay_logged_in: crwdns97476:0crwdne97476:0 - label_storage_free_space: crwdns97477:0crwdne97477:0 - label_storage_used_space: crwdns97478:0crwdne97478:0 - label_storage_group: crwdns97479:0%{identifier}crwdne97479:0 - label_storage_for: crwdns97480:0crwdne97480:0 - label_string: crwdns97481:0crwdne97481:0 - label_subproject: crwdns97482:0crwdne97482:0 - label_subproject_new: crwdns97483:0crwdne97483:0 - label_subproject_plural: crwdns97484:0crwdne97484:0 - label_subtask_plural: crwdns97485:0crwdne97485:0 - label_summary: crwdns97486:0crwdne97486:0 - label_system: crwdns97487:0crwdne97487:0 - label_system_storage: crwdns97488:0crwdne97488:0 - label_table_of_contents: crwdns99006:0crwdne99006:0 - label_tag: crwdns97490:0crwdne97490:0 - label_text: crwdns97491:0crwdne97491:0 - label_this_month: crwdns97492:0crwdne97492:0 - label_this_week: crwdns97493:0crwdne97493:0 - label_this_year: crwdns97494:0crwdne97494:0 - label_time_entry_plural: crwdns97495:0crwdne97495:0 - label_time_sheet_menu: crwdns97496:0crwdne97496:0 - label_time_tracking: crwdns97497:0crwdne97497:0 - label_today: crwdns97498:0crwdne97498:0 - label_top_menu: crwdns97499:0crwdne97499:0 - label_topic_plural: crwdns97500:0crwdne97500:0 - label_total: crwdns97501:0crwdne97501:0 - label_type_new: crwdns97502:0crwdne97502:0 - label_type_plural: crwdns97503:0crwdne97503:0 - label_ui: crwdns97505:0crwdne97505:0 - label_update_work_package_done_ratios: crwdns97506:0crwdne97506:0 - label_updated_time: crwdns97507:0%{value}crwdne97507:0 - label_updated_time_at: crwdns97508:0%{author}crwdnd97508:0%{age}crwdne97508:0 - label_updated_time_by: crwdns97509:0%{author}crwdnd97509:0%{age}crwdne97509:0 - label_used_by: crwdns97510:0crwdne97510:0 - label_used_by_types: crwdns97511:0crwdne97511:0 - label_used_in_projects: crwdns97512:0crwdne97512:0 - label_user: crwdns97513:0crwdne97513:0 - label_user_named: crwdns99245:0%{name}crwdne99245:0 - label_user_activity: crwdns97514:0%{value}crwdne97514:0 - label_user_anonymous: crwdns97515:0crwdne97515:0 - label_user_mail_option_all: crwdns97516:0crwdne97516:0 - label_user_mail_option_none: crwdns97517:0crwdne97517:0 - label_user_mail_option_only_assigned: crwdns97518:0crwdne97518:0 - label_user_mail_option_only_my_events: crwdns97519:0crwdne97519:0 - label_user_mail_option_only_owner: crwdns97520:0crwdne97520:0 - label_user_mail_option_selected: crwdns97521:0crwdne97521:0 - label_user_new: crwdns97522:0crwdne97522:0 - label_user_plural: crwdns97523:0crwdne97523:0 - label_user_search: crwdns97524:0crwdne97524:0 - label_version_new: crwdns97525:0crwdne97525:0 - label_version_plural: crwdns97526:0crwdne97526:0 - label_version_sharing_descendants: crwdns97527:0crwdne97527:0 - label_version_sharing_hierarchy: crwdns97528:0crwdne97528:0 - label_version_sharing_none: crwdns97529:0crwdne97529:0 - label_version_sharing_system: crwdns97530:0crwdne97530:0 - label_version_sharing_tree: crwdns97531:0crwdne97531:0 - label_videos: crwdns98894:0crwdne98894:0 - label_view_all_revisions: crwdns97533:0crwdne97533:0 - label_view_diff: crwdns97534:0crwdne97534:0 - label_view_revisions: crwdns97535:0crwdne97535:0 - label_watched_work_packages: crwdns97536:0crwdne97536:0 - label_week: crwdns97537:0crwdne97537:0 - label_wiki_content_added: crwdns97538:0crwdne97538:0 - label_wiki_content_updated: crwdns97539:0crwdne97539:0 - label_wiki_toc: crwdns97540:0crwdne97540:0 - label_wiki_dont_show_menu_item: crwdns97541:0crwdne97541:0 - label_wiki_edit: crwdns97542:0crwdne97542:0 - label_wiki_edit_plural: crwdns97543:0crwdne97543:0 - label_wiki_page_attachments: crwdns97544:0crwdne97544:0 - label_wiki_page_id: crwdns97545:0crwdne97545:0 - label_wiki_navigation: crwdns97546:0crwdne97546:0 - label_wiki_page: crwdns97547:0crwdne97547:0 - label_wiki_page_plural: crwdns97548:0crwdne97548:0 - label_wiki_show_index_page_link: crwdns97549:0crwdne97549:0 - label_wiki_show_menu_item: crwdns97550:0crwdne97550:0 - label_wiki_show_new_page_link: crwdns97551:0crwdne97551:0 - label_wiki_show_submenu_item: crwdns97552:0crwdne97552:0 - label_wiki_start: crwdns98945:0crwdne98945:0 - label_work_package: crwdns97553:0crwdne97553:0 - label_work_package_added: crwdns97554:0crwdne97554:0 - label_work_package_attachments: crwdns97555:0crwdne97555:0 - label_work_package_category_new: crwdns97556:0crwdne97556:0 - label_work_package_category_plural: crwdns97557:0crwdne97557:0 - label_work_package_hierarchy: crwdns97558:0crwdne97558:0 - label_work_package_new: crwdns97559:0crwdne97559:0 - label_work_package_note_added: crwdns97560:0crwdne97560:0 - label_work_package_edit: crwdns97561:0%{name}crwdne97561:0 - label_work_package_plural: crwdns97562:0crwdne97562:0 - label_work_package_priority_updated: crwdns97563:0crwdne97563:0 - label_work_package_status: crwdns97564:0crwdne97564:0 - label_work_package_status_new: crwdns97565:0crwdne97565:0 - label_work_package_status_plural: crwdns97566:0crwdne97566:0 - label_work_package_types: crwdns97567:0crwdne97567:0 - label_work_package_updated: crwdns97568:0crwdne97568:0 - label_work_package_tracking: crwdns97569:0crwdne97569:0 - label_work_package_view_all: crwdns97570:0crwdne97570:0 - label_work_package_view_all_assigned_to_me: crwdns97571:0crwdne97571:0 - label_work_package_view_all_reported_by_me: crwdns97572:0crwdne97572:0 - label_work_package_view_all_responsible_for: crwdns99076:0crwdne99076:0 - label_work_package_view_all_watched: crwdns97574:0crwdne97574:0 - label_work_package_watchers: crwdns97575:0crwdne97575:0 - label_workflow: crwdns97576:0crwdne97576:0 - label_workflow_plural: crwdns97577:0crwdne97577:0 - label_workflow_summary: crwdns97578:0crwdne97578:0 + action: crwdns100150:0crwdne100150:0 + expiration: crwdns100151:0crwdne100151:0 + indefinite_expiration: crwdns100152:0crwdne100152:0 + label_accessibility: crwdns100153:0crwdne100153:0 + label_account: crwdns100154:0crwdne100154:0 + label_active: crwdns100155:0crwdne100155:0 + label_activate_user: crwdns100156:0crwdne100156:0 + label_active_in_new_projects: crwdns100157:0crwdne100157:0 + label_activity: crwdns100158:0crwdne100158:0 + label_add_edit_translations: crwdns100159:0crwdne100159:0 + label_add_another_file: crwdns100160:0crwdne100160:0 + label_add_columns: crwdns100161:0crwdne100161:0 + label_add_note: crwdns100162:0crwdne100162:0 + label_add_related_work_packages: crwdns100163:0crwdne100163:0 + label_add_subtask: crwdns100164:0crwdne100164:0 + label_added: crwdns100165:0crwdne100165:0 + label_added_time_by: crwdns100166:0%{author}crwdnd100166:0%{age}crwdne100166:0 + label_additional_workflow_transitions_for_assignee: crwdns100167:0crwdne100167:0 + label_additional_workflow_transitions_for_author: crwdns100168:0crwdne100168:0 + label_administration: crwdns100169:0crwdne100169:0 + label_advanced_settings: crwdns100170:0crwdne100170:0 + label_age: crwdns100171:0crwdne100171:0 + label_ago: crwdns100172:0crwdne100172:0 + label_all: crwdns100173:0crwdne100173:0 + label_all_time: crwdns100174:0crwdne100174:0 + label_all_words: crwdns100175:0crwdne100175:0 + label_all_open_wps: crwdns100176:0crwdne100176:0 + label_always_visible: crwdns100177:0crwdne100177:0 + label_announcement: crwdns100178:0crwdne100178:0 + label_and_its_subprojects: crwdns100179:0%{value}crwdne100179:0 + label_api_access_key: crwdns100180:0crwdne100180:0 + label_api_access_key_created_on: crwdns100181:0%{value}crwdne100181:0 + label_api_access_key_type: crwdns100182:0crwdne100182:0 + label_applied_status: crwdns100183:0crwdne100183:0 + label_archive_project: crwdns100184:0crwdne100184:0 + label_ascending: crwdns100185:0crwdne100185:0 + label_assigned_to_me_work_packages: crwdns100186:0crwdne100186:0 + label_associated_revisions: crwdns100187:0crwdne100187:0 + label_attachment_delete: crwdns100188:0crwdne100188:0 + label_attachment_new: crwdns100189:0crwdne100189:0 + label_attachment_plural: crwdns100190:0crwdne100190:0 + label_attribute: crwdns100191:0crwdne100191:0 + label_attribute_plural: crwdns100192:0crwdne100192:0 + label_auth_source: crwdns100193:0crwdne100193:0 + label_auth_source_new: crwdns100194:0crwdne100194:0 + label_auth_source_plural: crwdns100195:0crwdne100195:0 + label_authentication: crwdns100196:0crwdne100196:0 + label_available_project_work_package_categories: crwdns100197:0crwdne100197:0 + label_available_project_boards: crwdns100198:0crwdne100198:0 + label_available_project_versions: crwdns100199:0crwdne100199:0 + label_available_project_repositories: crwdns100200:0crwdne100200:0 + label_api_documentation: crwdns100201:0crwdne100201:0 + label_between: crwdns100202:0crwdne100202:0 + label_blocked_by: crwdns100203:0crwdne100203:0 + label_blocks: crwdns100204:0crwdne100204:0 + label_blog: crwdns100205:0crwdne100205:0 + label_board_locked: crwdns100206:0crwdne100206:0 + label_board_new: crwdns100207:0crwdne100207:0 + label_board_plural: crwdns100208:0crwdne100208:0 + label_board_sticky: crwdns100209:0crwdne100209:0 + label_boolean: crwdns100210:0crwdne100210:0 + label_branch: crwdns100211:0crwdne100211:0 + label_browse: crwdns100212:0crwdne100212:0 + label_bulk_edit_selected_work_packages: crwdns100213:0crwdne100213:0 + label_calendar: crwdns100214:0crwdne100214:0 + label_calendar_show: crwdns100215:0crwdne100215:0 + label_category: crwdns100216:0crwdne100216:0 + label_consent_settings: crwdns100217:0crwdne100217:0 + label_wiki_menu_item: crwdns100218:0crwdne100218:0 + label_select_main_menu_item: crwdns100219:0crwdne100219:0 + label_select_project: crwdns100220:0crwdne100220:0 + label_required_disk_storage: crwdns100221:0crwdne100221:0 + label_send_invitation: crwdns100222:0crwdne100222:0 + label_change_plural: crwdns100223:0crwdne100223:0 + label_change_properties: crwdns100224:0crwdne100224:0 + label_change_status: crwdns100225:0crwdne100225:0 + label_change_status_of_user: crwdns100226:0#{username}crwdne100226:0 + label_change_view_all: crwdns100227:0crwdne100227:0 + label_changes_details: crwdns100228:0crwdne100228:0 + label_changeset: crwdns100229:0crwdne100229:0 + label_changeset_id: crwdns100230:0crwdne100230:0 + label_changeset_plural: crwdns100231:0crwdne100231:0 + label_checked: crwdns100232:0crwdne100232:0 + label_check_uncheck_all_in_column: crwdns100233:0crwdne100233:0 + label_check_uncheck_all_in_row: crwdns100234:0crwdne100234:0 + label_child_element: crwdns100235:0crwdne100235:0 + label_chronological_order: crwdns100236:0crwdne100236:0 + label_close_versions: crwdns100237:0crwdne100237:0 + label_closed_work_packages: crwdns100238:0crwdne100238:0 + label_collapse: crwdns100239:0crwdne100239:0 + label_collapsed_click_to_show: crwdns100240:0crwdne100240:0 + label_configuration: crwdns100241:0crwdne100241:0 + label_comment_add: crwdns100242:0crwdne100242:0 + label_comment_added: crwdns100243:0crwdne100243:0 + label_comment_delete: crwdns100244:0crwdne100244:0 + label_comment_plural: crwdns100245:0crwdne100245:0 + label_commits_per_author: crwdns100246:0crwdne100246:0 + label_commits_per_month: crwdns100247:0crwdne100247:0 + label_confirmation: crwdns100248:0crwdne100248:0 + label_contains: crwdns100249:0crwdne100249:0 + label_content: crwdns100250:0crwdne100250:0 + label_copied: crwdns100251:0crwdne100251:0 + label_copy_to_clipboard: crwdns100252:0crwdne100252:0 + label_copy_same_as_target: crwdns100253:0crwdne100253:0 + label_copy_source: crwdns100254:0crwdne100254:0 + label_copy_target: crwdns100255:0crwdne100255:0 + label_copy_workflow_from: crwdns100256:0crwdne100256:0 + label_copy_project: crwdns100257:0crwdne100257:0 + label_core_version: crwdns100258:0crwdne100258:0 + label_current_status: crwdns100259:0crwdne100259:0 + label_current_version: crwdns100260:0crwdne100260:0 + label_custom_field_add_no_type: crwdns100261:0crwdne100261:0 + label_custom_field_new: crwdns100262:0crwdne100262:0 + label_custom_field_plural: crwdns100263:0crwdne100263:0 + label_custom_field_default_type: crwdns100264:0crwdne100264:0 + label_custom_style: crwdns100265:0crwdne100265:0 + label_date: crwdns100266:0crwdne100266:0 + label_date_and_time: crwdns100267:0crwdne100267:0 + label_date_from: crwdns100268:0crwdne100268:0 + label_date_from_to: crwdns100269:0%{start}crwdnd100269:0%{end}crwdne100269:0 + label_date_range: crwdns100270:0crwdne100270:0 + label_date_to: crwdns100271:0crwdne100271:0 + label_day_plural: crwdns100272:0crwdne100272:0 + label_default: crwdns100273:0crwdne100273:0 + label_delete_user: crwdns100274:0crwdne100274:0 + label_delete_project: crwdns100275:0crwdne100275:0 + label_deleted: crwdns100276:0crwdne100276:0 + label_deleted_custom_field: crwdns100277:0crwdne100277:0 + label_descending: crwdns100278:0crwdne100278:0 + label_details: crwdns100279:0crwdne100279:0 + label_development_roadmap: crwdns100280:0crwdne100280:0 + label_diff: crwdns100281:0crwdne100281:0 + label_diff_inline: crwdns100282:0crwdne100282:0 + label_diff_side_by_side: crwdns100283:0crwdne100283:0 + label_disabled: crwdns100284:0crwdne100284:0 + label_display: crwdns100285:0crwdne100285:0 + label_display_per_page: crwdns100286:0%{value}crwdne100286:0 + label_display_used_statuses_only: crwdns100287:0crwdne100287:0 + label_download: crwdns100288:0%{count}crwdne100288:0 + label_download_plural: crwdns100289:0%{count}crwdne100289:0 + label_downloads_abbr: crwdns100290:0crwdne100290:0 + label_duplicated_by: crwdns100291:0crwdne100291:0 + label_duplicate: crwdns100292:0crwdne100292:0 + label_duplicates: crwdns100293:0crwdne100293:0 + label_edit: crwdns100294:0crwdne100294:0 + label_enable_multi_select: crwdns100295:0crwdne100295:0 + label_enabled_project_custom_fields: crwdns100296:0crwdne100296:0 + label_enabled_project_modules: crwdns100297:0crwdne100297:0 + label_enabled_project_activities: crwdns100298:0crwdne100298:0 + label_end_to_end: crwdns100299:0crwdne100299:0 + label_end_to_start: crwdns100300:0crwdne100300:0 + label_enumeration_new: crwdns100301:0crwdne100301:0 + label_enumeration_value: crwdns100302:0crwdne100302:0 + label_enumerations: crwdns100303:0crwdne100303:0 + label_enterprise: crwdns100304:0crwdne100304:0 + label_enterprise_active_users: crwdns100305:0%{current}crwdnd100305:0%{limit}crwdne100305:0 + label_enterprise_edition: crwdns100306:0crwdne100306:0 + label_environment: crwdns100307:0crwdne100307:0 + label_estimates_and_time: crwdns100308:0crwdne100308:0 + label_equals: crwdns100309:0crwdne100309:0 + label_example: crwdns100310:0crwdne100310:0 + label_export_to: crwdns100311:0crwdne100311:0 + label_expanded_click_to_collapse: crwdns100312:0crwdne100312:0 + label_f_hour: crwdns100313:0%{value}crwdne100313:0 + label_f_hour_plural: crwdns100314:0%{value}crwdne100314:0 + label_feed_plural: crwdns100315:0crwdne100315:0 + label_feeds_access_key: crwdns100316:0crwdne100316:0 + label_feeds_access_key_created_on: crwdns100317:0%{value}crwdne100317:0 + label_feeds_access_key_type: crwdns100318:0crwdne100318:0 + label_file_added: crwdns100319:0crwdne100319:0 + label_file_plural: crwdns100320:0crwdne100320:0 + label_filter_add: crwdns100321:0crwdne100321:0 + label_filter_plural: crwdns100322:0crwdne100322:0 + label_filters_toggle: crwdns100323:0crwdne100323:0 + label_float: crwdns100324:0crwdne100324:0 + label_folder: crwdns100325:0crwdne100325:0 + label_follows: crwdns100326:0crwdne100326:0 + label_force_user_language_to_default: crwdns100327:0crwdne100327:0 + label_form_configuration: crwdns100328:0crwdne100328:0 + label_gantt: crwdns100329:0crwdne100329:0 + label_gantt_chart: crwdns100330:0crwdne100330:0 + label_general: crwdns100331:0crwdne100331:0 + label_generate_key: crwdns100332:0crwdne100332:0 + label_git_path: crwdns100333:0crwdne100333:0 + label_greater_or_equal: crwdns100334:0crwdne100334:0 + label_group_by: crwdns100335:0crwdne100335:0 + label_group_new: crwdns100336:0crwdne100336:0 + label_group: crwdns100337:0crwdne100337:0 + label_group_named: crwdns100338:0%{name}crwdne100338:0 + label_group_plural: crwdns100339:0crwdne100339:0 + label_help: crwdns100340:0crwdne100340:0 + label_here: crwdns100341:0crwdne100341:0 + label_hide: crwdns100342:0crwdne100342:0 + label_history: crwdns100343:0crwdne100343:0 + label_hierarchy_leaf: crwdns100344:0crwdne100344:0 + label_home: crwdns100345:0crwdne100345:0 + label_in: crwdns100346:0crwdne100346:0 + label_in_less_than: crwdns100347:0crwdne100347:0 + label_in_more_than: crwdns100348:0crwdne100348:0 + label_inactive: crwdns100349:0crwdne100349:0 + label_incoming_emails: crwdns100350:0crwdne100350:0 + label_includes: crwdns100351:0crwdne100351:0 + label_index_by_date: crwdns100352:0crwdne100352:0 + label_index_by_title: crwdns100353:0crwdne100353:0 + label_information: crwdns100354:0crwdne100354:0 + label_information_plural: crwdns100355:0crwdne100355:0 + label_integer: crwdns100356:0crwdne100356:0 + label_internal: crwdns100357:0crwdne100357:0 + label_introduction_video: crwdns100358:0crwdne100358:0 + label_invite_user: crwdns100359:0crwdne100359:0 + label_show_hide: crwdns100360:0crwdne100360:0 + label_show_all_registered_users: crwdns100361:0crwdne100361:0 + label_journal: crwdns100362:0crwdne100362:0 + label_journal_diff: crwdns100363:0crwdne100363:0 + label_language: crwdns100364:0crwdne100364:0 + label_jump_to_a_project: crwdns100365:0crwdne100365:0 + label_language_based: crwdns100366:0crwdne100366:0 + label_last_activity: crwdns100367:0crwdne100367:0 + label_last_change_on: crwdns100368:0crwdne100368:0 + label_last_changes: crwdns100369:0%{count}crwdne100369:0 + label_last_login: crwdns100370:0crwdne100370:0 + label_last_month: crwdns100371:0crwdne100371:0 + label_last_n_days: crwdns100372:0%{count}crwdne100372:0 + label_last_week: crwdns100373:0crwdne100373:0 + label_latest_revision: crwdns100374:0crwdne100374:0 + label_latest_revision_plural: crwdns100375:0crwdne100375:0 + label_ldap_authentication: crwdns100376:0crwdne100376:0 + label_less_or_equal: crwdns100377:0crwdne100377:0 + label_less_than_ago: crwdns100378:0crwdne100378:0 + label_list: crwdns100379:0crwdne100379:0 + label_loading: crwdns100380:0crwdne100380:0 + label_lock_user: crwdns100381:0crwdne100381:0 + label_logged_as: crwdns100382:0crwdne100382:0 + label_login: crwdns100383:0crwdne100383:0 + label_custom_logo: crwdns100384:0crwdne100384:0 + label_custom_favicon: crwdns100385:0crwdne100385:0 + label_custom_touch_icon: crwdns100386:0crwdne100386:0 + label_logout: crwdns100387:0crwdne100387:0 + label_main_menu: crwdns100388:0crwdne100388:0 + label_manage_groups: crwdns100389:0crwdne100389:0 + label_managed_repositories_vendor: crwdns100390:0%{vendor}crwdne100390:0 + label_max_size: crwdns100391:0crwdne100391:0 + label_me: crwdns100392:0crwdne100392:0 + label_member_new: crwdns100393:0crwdne100393:0 + label_member_plural: crwdns100394:0crwdne100394:0 + label_view_all_members: crwdns100395:0crwdne100395:0 + label_menu_item_name: crwdns100396:0crwdne100396:0 + label_message: crwdns100397:0crwdne100397:0 + label_message_last: crwdns100398:0crwdne100398:0 + label_message_new: crwdns100399:0crwdne100399:0 + label_message_plural: crwdns100400:0crwdne100400:0 + label_message_posted: crwdns100401:0crwdne100401:0 + label_min_max_length: crwdns100402:0crwdne100402:0 + label_minute_plural: crwdns100403:0crwdne100403:0 + label_missing_api_access_key: crwdns100404:0crwdne100404:0 + label_missing_feeds_access_key: crwdns100405:0crwdne100405:0 + label_modification: crwdns100406:0%{count}crwdne100406:0 + label_modified: crwdns100407:0crwdne100407:0 + label_module_plural: crwdns100408:0crwdne100408:0 + label_modules: crwdns100409:0crwdne100409:0 + label_month: crwdns100410:0crwdne100410:0 + label_months_from: crwdns100411:0crwdne100411:0 + label_more: crwdns100412:0crwdne100412:0 + label_more_than_ago: crwdns100413:0crwdne100413:0 + label_move_work_package: crwdns100414:0crwdne100414:0 + label_my_account: crwdns100415:0crwdne100415:0 + label_my_account_data: crwdns100416:0crwdne100416:0 + label_my_page: crwdns100417:0crwdne100417:0 + label_my_page_block: crwdns100418:0crwdne100418:0 + label_my_projects: crwdns100419:0crwdne100419:0 + label_my_queries: crwdns100420:0crwdne100420:0 + label_never: crwdns100421:0crwdne100421:0 + label_new: crwdns100422:0crwdne100422:0 + label_new_statuses_allowed: crwdns100423:0crwdne100423:0 + label_news_added: crwdns100424:0crwdne100424:0 + label_news_comment_added: crwdns100425:0crwdne100425:0 + label_news_latest: crwdns100426:0crwdne100426:0 + label_news_new: crwdns100427:0crwdne100427:0 + label_news_edit: crwdns100428:0crwdne100428:0 + label_news_plural: crwdns100429:0crwdne100429:0 + label_news_view_all: crwdns100430:0crwdne100430:0 + label_next: crwdns100431:0crwdne100431:0 + label_next_week: crwdns100432:0crwdne100432:0 + label_no_change_option: crwdns100433:0crwdne100433:0 + label_no_data: crwdns100434:0crwdne100434:0 + label_no_parent_page: crwdns100435:0crwdne100435:0 + label_nothing_display: crwdns100436:0crwdne100436:0 + label_nobody: crwdns100437:0crwdne100437:0 + label_none: crwdns100438:0crwdne100438:0 + label_none_parentheses: crwdns100439:0crwdne100439:0 + label_not_contains: crwdns100440:0crwdne100440:0 + label_not_equals: crwdns100441:0crwdne100441:0 + label_notify_member_plural: crwdns100442:0crwdne100442:0 + label_on: crwdns100443:0crwdne100443:0 + label_open_menu: crwdns100444:0crwdne100444:0 + label_open_work_packages: crwdns100445:0crwdne100445:0 + label_open_work_packages_plural: crwdns100446:0crwdne100446:0 + label_openproject_website: crwdns100447:0crwdne100447:0 + label_optional_description: crwdns100448:0crwdne100448:0 + label_options: crwdns100449:0crwdne100449:0 + label_other: crwdns100450:0crwdne100450:0 + label_overall_activity: crwdns100451:0crwdne100451:0 + label_overall_spent_time: crwdns100452:0crwdne100452:0 + label_overview: crwdns100453:0crwdne100453:0 + label_page_title: crwdns100454:0crwdne100454:0 + label_part_of: crwdns100455:0crwdne100455:0 + label_password_lost: crwdns100456:0crwdne100456:0 + label_password_rule_lowercase: crwdns100457:0crwdne100457:0 + label_password_rule_numeric: crwdns100458:0crwdne100458:0 + label_password_rule_special: crwdns100459:0crwdne100459:0 + label_password_rule_uppercase: crwdns100460:0crwdne100460:0 + label_path_encoding: crwdns100461:0crwdne100461:0 + label_pdf_with_descriptions: crwdns100462:0crwdne100462:0 + label_per_page: crwdns100463:0crwdne100463:0 + label_people: crwdns100464:0crwdne100464:0 + label_permissions: crwdns100465:0crwdne100465:0 + label_permissions_report: crwdns100466:0crwdne100466:0 + label_personalize_page: crwdns100467:0crwdne100467:0 + label_planning: crwdns100468:0crwdne100468:0 + label_please_login: crwdns100469:0crwdne100469:0 + label_plugins: crwdns100470:0crwdne100470:0 + label_precedes: crwdns100471:0crwdne100471:0 + label_preferences: crwdns100472:0crwdne100472:0 + label_preview: crwdns100473:0crwdne100473:0 + label_previous: crwdns100474:0crwdne100474:0 + label_previous_week: crwdns100475:0crwdne100475:0 + label_principal_invite_via_email: crwdns100476:0crwdne100476:0 + label_principal_search: crwdns100477:0crwdne100477:0 + label_product_version: crwdns100478:0crwdne100478:0 + label_professional_support: crwdns100479:0crwdne100479:0 + label_profile: crwdns100480:0crwdne100480:0 + label_project_all: crwdns100481:0crwdne100481:0 + label_project_count: crwdns100482:0crwdne100482:0 + label_project_copy_notifications: crwdns100483:0crwdne100483:0 + label_project_latest: crwdns100484:0crwdne100484:0 + label_project_default_type: crwdns100485:0crwdne100485:0 + label_project_hierarchy: crwdns100486:0crwdne100486:0 + label_project_new: crwdns100487:0crwdne100487:0 + label_project_plural: crwdns100488:0crwdne100488:0 + label_project_settings: crwdns100489:0crwdne100489:0 + label_projects_storage_information: crwdns100490:0%{count}crwdnd100490:0%{storage}crwdne100490:0 + label_project_view_all: crwdns100491:0crwdne100491:0 + label_project_show_details: crwdns100492:0crwdne100492:0 + label_project_hide_details: crwdns100493:0crwdne100493:0 + label_public_projects: crwdns100494:0crwdne100494:0 + label_query_new: crwdns100495:0crwdne100495:0 + label_query_plural: crwdns100496:0crwdne100496:0 + label_query_menu_item: crwdns100497:0crwdne100497:0 + label_read: crwdns100498:0crwdne100498:0 + label_register: crwdns100499:0crwdne100499:0 + label_register_with_developer: crwdns100500:0crwdne100500:0 + label_registered_on: crwdns100501:0crwdne100501:0 + label_registration_activation_by_email: crwdns100502:0crwdne100502:0 + label_registration_automatic_activation: crwdns100503:0crwdne100503:0 + label_registration_manual_activation: crwdns100504:0crwdne100504:0 + label_related_work_packages: crwdns100505:0crwdne100505:0 + label_relates: crwdns100506:0crwdne100506:0 + label_relates_to: crwdns100507:0crwdne100507:0 + label_relation_delete: crwdns100508:0crwdne100508:0 + label_relation_new: crwdns100509:0crwdne100509:0 + label_release_notes: crwdns100510:0crwdne100510:0 + label_remove_columns: crwdns100511:0crwdne100511:0 + label_renamed: crwdns100512:0crwdne100512:0 + label_reply_plural: crwdns100513:0crwdne100513:0 + label_report: crwdns100514:0crwdne100514:0 + label_report_bug: crwdns100515:0crwdne100515:0 + label_report_plural: crwdns100516:0crwdne100516:0 + label_reported_work_packages: crwdns100517:0crwdne100517:0 + label_reporting: crwdns100518:0crwdne100518:0 + label_reporting_plural: crwdns100519:0crwdne100519:0 + label_repository: crwdns100520:0crwdne100520:0 + label_repository_root: crwdns100521:0crwdne100521:0 + label_repository_plural: crwdns100522:0crwdne100522:0 + label_required: crwdns100523:0crwdne100523:0 + label_requires: crwdns100524:0crwdne100524:0 + label_responsible_for_work_packages: crwdns100525:0crwdne100525:0 + label_result_plural: crwdns100526:0crwdne100526:0 + label_reverse_chronological_order: crwdns100527:0crwdne100527:0 + label_revision: crwdns100528:0crwdne100528:0 + label_revision_id: crwdns100529:0%{value}crwdne100529:0 + label_revision_plural: crwdns100530:0crwdne100530:0 + label_roadmap: crwdns100531:0crwdne100531:0 + label_roadmap_edit: crwdns100532:0%{name}crwdne100532:0 + label_roadmap_due_in: crwdns100533:0%{value}crwdne100533:0 + label_roadmap_no_work_packages: crwdns100534:0crwdne100534:0 + label_roadmap_overdue: crwdns100535:0%{value}crwdne100535:0 + label_role_and_permissions: crwdns100536:0crwdne100536:0 + label_role_new: crwdns100537:0crwdne100537:0 + label_role_plural: crwdns100538:0crwdne100538:0 + label_role_search: crwdns100539:0crwdne100539:0 + label_scm: crwdns100540:0crwdne100540:0 + label_search: crwdns100541:0crwdne100541:0 + label_search_titles_only: crwdns100542:0crwdne100542:0 + label_send_information: crwdns100543:0crwdne100543:0 + label_send_test_email: crwdns100544:0crwdne100544:0 + label_settings: crwdns100545:0crwdne100545:0 + label_system_settings: crwdns100546:0crwdne100546:0 + label_show_completed_versions: crwdns100547:0crwdne100547:0 + label_sort: crwdns100548:0crwdne100548:0 + label_sort_by: crwdns100549:0%{value}crwdne100549:0 + label_sorted_by: crwdns100550:0%{value}crwdne100550:0 + label_sort_higher: crwdns100551:0crwdne100551:0 + label_sort_highest: crwdns100552:0crwdne100552:0 + label_sort_lower: crwdns100553:0crwdne100553:0 + label_sort_lowest: crwdns100554:0crwdne100554:0 + label_spent_time: crwdns100555:0crwdne100555:0 + label_start_to_end: crwdns100556:0crwdne100556:0 + label_start_to_start: crwdns100557:0crwdne100557:0 + label_statistics: crwdns100558:0crwdne100558:0 + label_status: crwdns100559:0crwdne100559:0 + label_status_updated: crwdns100560:0crwdne100560:0 + label_stay_logged_in: crwdns100561:0crwdne100561:0 + label_storage_free_space: crwdns100562:0crwdne100562:0 + label_storage_used_space: crwdns100563:0crwdne100563:0 + label_storage_group: crwdns100564:0%{identifier}crwdne100564:0 + label_storage_for: crwdns100565:0crwdne100565:0 + label_string: crwdns100566:0crwdne100566:0 + label_subproject: crwdns100567:0crwdne100567:0 + label_subproject_new: crwdns100568:0crwdne100568:0 + label_subproject_plural: crwdns100569:0crwdne100569:0 + label_subtask_plural: crwdns100570:0crwdne100570:0 + label_summary: crwdns100571:0crwdne100571:0 + label_system: crwdns100572:0crwdne100572:0 + label_system_storage: crwdns100573:0crwdne100573:0 + label_table_of_contents: crwdns100574:0crwdne100574:0 + label_tag: crwdns100575:0crwdne100575:0 + label_text: crwdns100576:0crwdne100576:0 + label_this_month: crwdns100577:0crwdne100577:0 + label_this_week: crwdns100578:0crwdne100578:0 + label_this_year: crwdns100579:0crwdne100579:0 + label_time_entry_plural: crwdns100580:0crwdne100580:0 + label_time_sheet_menu: crwdns100581:0crwdne100581:0 + label_time_tracking: crwdns100582:0crwdne100582:0 + label_today: crwdns100583:0crwdne100583:0 + label_top_menu: crwdns100584:0crwdne100584:0 + label_topic_plural: crwdns100585:0crwdne100585:0 + label_total: crwdns100586:0crwdne100586:0 + label_type_new: crwdns100587:0crwdne100587:0 + label_type_plural: crwdns100588:0crwdne100588:0 + label_ui: crwdns100589:0crwdne100589:0 + label_update_work_package_done_ratios: crwdns100590:0crwdne100590:0 + label_updated_time: crwdns100591:0%{value}crwdne100591:0 + label_updated_time_at: crwdns100592:0%{author}crwdnd100592:0%{age}crwdne100592:0 + label_updated_time_by: crwdns100593:0%{author}crwdnd100593:0%{age}crwdne100593:0 + label_used_by: crwdns100594:0crwdne100594:0 + label_used_by_types: crwdns100595:0crwdne100595:0 + label_used_in_projects: crwdns100596:0crwdne100596:0 + label_user: crwdns100597:0crwdne100597:0 + label_user_named: crwdns100598:0%{name}crwdne100598:0 + label_user_activity: crwdns100599:0%{value}crwdne100599:0 + label_user_anonymous: crwdns100600:0crwdne100600:0 + label_user_mail_option_all: crwdns100601:0crwdne100601:0 + label_user_mail_option_none: crwdns100602:0crwdne100602:0 + label_user_mail_option_only_assigned: crwdns100603:0crwdne100603:0 + label_user_mail_option_only_my_events: crwdns100604:0crwdne100604:0 + label_user_mail_option_only_owner: crwdns100605:0crwdne100605:0 + label_user_mail_option_selected: crwdns100606:0crwdne100606:0 + label_user_new: crwdns100607:0crwdne100607:0 + label_user_plural: crwdns100608:0crwdne100608:0 + label_user_search: crwdns100609:0crwdne100609:0 + label_version_new: crwdns100610:0crwdne100610:0 + label_version_plural: crwdns100611:0crwdne100611:0 + label_version_sharing_descendants: crwdns100612:0crwdne100612:0 + label_version_sharing_hierarchy: crwdns100613:0crwdne100613:0 + label_version_sharing_none: crwdns100614:0crwdne100614:0 + label_version_sharing_system: crwdns100615:0crwdne100615:0 + label_version_sharing_tree: crwdns100616:0crwdne100616:0 + label_videos: crwdns100617:0crwdne100617:0 + label_view_all_revisions: crwdns100618:0crwdne100618:0 + label_view_diff: crwdns100619:0crwdne100619:0 + label_view_revisions: crwdns100620:0crwdne100620:0 + label_watched_work_packages: crwdns100621:0crwdne100621:0 + label_week: crwdns100622:0crwdne100622:0 + label_wiki_content_added: crwdns100623:0crwdne100623:0 + label_wiki_content_updated: crwdns100624:0crwdne100624:0 + label_wiki_toc: crwdns100625:0crwdne100625:0 + label_wiki_dont_show_menu_item: crwdns100626:0crwdne100626:0 + label_wiki_edit: crwdns100627:0crwdne100627:0 + label_wiki_edit_plural: crwdns100628:0crwdne100628:0 + label_wiki_page_attachments: crwdns100629:0crwdne100629:0 + label_wiki_page_id: crwdns100630:0crwdne100630:0 + label_wiki_navigation: crwdns100631:0crwdne100631:0 + label_wiki_page: crwdns100632:0crwdne100632:0 + label_wiki_page_plural: crwdns100633:0crwdne100633:0 + label_wiki_show_index_page_link: crwdns100634:0crwdne100634:0 + label_wiki_show_menu_item: crwdns100635:0crwdne100635:0 + label_wiki_show_new_page_link: crwdns100636:0crwdne100636:0 + label_wiki_show_submenu_item: crwdns100637:0crwdne100637:0 + label_wiki_start: crwdns100638:0crwdne100638:0 + label_work_package: crwdns100639:0crwdne100639:0 + label_work_package_added: crwdns100640:0crwdne100640:0 + label_work_package_attachments: crwdns100641:0crwdne100641:0 + label_work_package_category_new: crwdns100642:0crwdne100642:0 + label_work_package_category_plural: crwdns100643:0crwdne100643:0 + label_work_package_hierarchy: crwdns100644:0crwdne100644:0 + label_work_package_new: crwdns100645:0crwdne100645:0 + label_work_package_note_added: crwdns100646:0crwdne100646:0 + label_work_package_edit: crwdns100647:0%{name}crwdne100647:0 + label_work_package_plural: crwdns100648:0crwdne100648:0 + label_work_package_priority_updated: crwdns100649:0crwdne100649:0 + label_work_package_status: crwdns100650:0crwdne100650:0 + label_work_package_status_new: crwdns100651:0crwdne100651:0 + label_work_package_status_plural: crwdns100652:0crwdne100652:0 + label_work_package_types: crwdns100653:0crwdne100653:0 + label_work_package_updated: crwdns100654:0crwdne100654:0 + label_work_package_tracking: crwdns100655:0crwdne100655:0 + label_work_package_view_all: crwdns100656:0crwdne100656:0 + label_work_package_view_all_assigned_to_me: crwdns100657:0crwdne100657:0 + label_work_package_view_all_reported_by_me: crwdns100658:0crwdne100658:0 + label_work_package_view_all_responsible_for: crwdns100659:0crwdne100659:0 + label_work_package_view_all_watched: crwdns100660:0crwdne100660:0 + label_work_package_watchers: crwdns100661:0crwdne100661:0 + label_workflow: crwdns100662:0crwdne100662:0 + label_workflow_plural: crwdns100663:0crwdne100663:0 + label_workflow_summary: crwdns100664:0crwdne100664:0 label_x_closed_work_packages_abbr: - one: crwdns97579:1crwdne97579:1 - other: crwdns97579:5%{count}crwdne97579:5 + one: crwdns100665:1crwdne100665:1 + other: crwdns100665:5%{count}crwdne100665:5 zero: 0 closed label_x_comments: - one: crwdns97580:1crwdne97580:1 - other: crwdns97580:5%{count}crwdne97580:5 + one: crwdns100666:1crwdne100666:1 + other: crwdns100666:5%{count}crwdne100666:5 zero: no comments label_x_open_work_packages_abbr: - one: crwdns97581:1crwdne97581:1 - other: crwdns97581:5%{count}crwdne97581:5 + one: crwdns100667:1crwdne100667:1 + other: crwdns100667:5%{count}crwdne100667:5 zero: 0 open label_x_open_work_packages_abbr_on_total: - one: crwdns97582:1%{total}crwdne97582:1 - other: crwdns97582:5%{count}crwdnd97582:5%{total}crwdne97582:5 + one: crwdns100668:1%{total}crwdne100668:1 + other: crwdns100668:5%{count}crwdnd100668:5%{total}crwdne100668:5 zero: 0 open / %{total} label_x_projects: - one: crwdns97583:1crwdne97583:1 - other: crwdns97583:5%{count}crwdne97583:5 + one: crwdns100669:1crwdne100669:1 + other: crwdns100669:5%{count}crwdne100669:5 zero: no projects - label_year: crwdns97584:0crwdne97584:0 - label_yesterday: crwdns97585:0crwdne97585:0 - label_keyboard_function: crwdns97586:0crwdne97586:0 - label_keyboard_shortcut: crwdns97587:0crwdne97587:0 - label_keyboard_accesskey: crwdns97588:0crwdne97588:0 - label_keyboard_shortcut_help_heading: crwdns97589:0crwdne97589:0 - label_keyboard_shortcut_within_project: crwdns97590:0crwdne97590:0 - label_keyboard_shortcut_global_shortcuts: crwdns97591:0crwdne97591:0 - label_keyboard_shortcut_some_pages_only: crwdns97592:0crwdne97592:0 - label_keyboard_shortcut_search_global: crwdns97593:0crwdne97593:0 - label_keyboard_shortcut_search_project: crwdns97594:0crwdne97594:0 - label_keyboard_shortcut_go_my_page: crwdns97595:0crwdne97595:0 - label_keyboard_shortcut_show_help: crwdns97596:0crwdne97596:0 - label_keyboard_shortcut_go_overview: crwdns97597:0crwdne97597:0 - label_keyboard_shortcut_go_work_package: crwdns97598:0crwdne97598:0 - label_keyboard_shortcut_go_wiki: crwdns97599:0crwdne97599:0 - label_keyboard_shortcut_go_activity: crwdns97600:0crwdne97600:0 - label_keyboard_shortcut_go_calendar: crwdns97601:0crwdne97601:0 - label_keyboard_shortcut_go_news: crwdns97602:0crwdne97602:0 - label_keyboard_shortcut_go_timelines: crwdns97603:0crwdne97603:0 - label_keyboard_shortcut_new_work_package: crwdns97604:0crwdne97604:0 - label_keyboard_shortcut_details_package: crwdns97605:0crwdne97605:0 - label_keyboard_shortcut_go_edit: crwdns97606:0crwdne97606:0 - label_keyboard_shortcut_open_more_menu: crwdns97607:0crwdne97607:0 - label_keyboard_shortcut_go_preview: crwdns97608:0crwdne97608:0 - label_keyboard_shortcut_focus_previous_item: crwdns97609:0crwdne97609:0 - label_keyboard_shortcut_focus_next_item: crwdns97610:0crwdne97610:0 - label_visible_elements: crwdns97611:0crwdne97611:0 + label_year: crwdns100670:0crwdne100670:0 + label_yesterday: crwdns100671:0crwdne100671:0 + label_keyboard_function: crwdns100672:0crwdne100672:0 + label_keyboard_shortcut: crwdns100673:0crwdne100673:0 + label_keyboard_accesskey: crwdns100674:0crwdne100674:0 + label_keyboard_shortcut_help_heading: crwdns100675:0crwdne100675:0 + label_keyboard_shortcut_within_project: crwdns100676:0crwdne100676:0 + label_keyboard_shortcut_global_shortcuts: crwdns100677:0crwdne100677:0 + label_keyboard_shortcut_some_pages_only: crwdns100678:0crwdne100678:0 + label_keyboard_shortcut_search_global: crwdns100679:0crwdne100679:0 + label_keyboard_shortcut_search_project: crwdns100680:0crwdne100680:0 + label_keyboard_shortcut_go_my_page: crwdns100681:0crwdne100681:0 + label_keyboard_shortcut_show_help: crwdns100682:0crwdne100682:0 + label_keyboard_shortcut_go_overview: crwdns100683:0crwdne100683:0 + label_keyboard_shortcut_go_work_package: crwdns100684:0crwdne100684:0 + label_keyboard_shortcut_go_wiki: crwdns100685:0crwdne100685:0 + label_keyboard_shortcut_go_activity: crwdns100686:0crwdne100686:0 + label_keyboard_shortcut_go_calendar: crwdns100687:0crwdne100687:0 + label_keyboard_shortcut_go_news: crwdns100688:0crwdne100688:0 + label_keyboard_shortcut_go_timelines: crwdns100689:0crwdne100689:0 + label_keyboard_shortcut_new_work_package: crwdns100690:0crwdne100690:0 + label_keyboard_shortcut_details_package: crwdns100691:0crwdne100691:0 + label_keyboard_shortcut_go_edit: crwdns100692:0crwdne100692:0 + label_keyboard_shortcut_open_more_menu: crwdns100693:0crwdne100693:0 + label_keyboard_shortcut_go_preview: crwdns100694:0crwdne100694:0 + label_keyboard_shortcut_focus_previous_item: crwdns100695:0crwdne100695:0 + label_keyboard_shortcut_focus_next_item: crwdns100696:0crwdne100696:0 + label_visible_elements: crwdns100697:0crwdne100697:0 auth_source: - using_abstract_auth_source: crwdns97612:0crwdne97612:0 - ldap_error: crwdns97613:0%{error_message}crwdne97613:0 - ldap_auth_failed: crwdns97614:0crwdne97614:0 - macro_execution_error: crwdns97615:0%{macro_name}crwdne97615:0 - macro_unavailable: crwdns97616:0%{macro_name}crwdne97616:0 + using_abstract_auth_source: crwdns100698:0crwdne100698:0 + ldap_error: crwdns100699:0%{error_message}crwdne100699:0 + ldap_auth_failed: crwdns100700:0crwdne100700:0 + macro_execution_error: crwdns100701:0%{macro_name}crwdne100701:0 + macro_unavailable: crwdns100702:0%{macro_name}crwdne100702:0 macros: - placeholder: crwdns99112:0[Placeholder]crwdnd99112:0%{macro_name}crwdne99112:0 + placeholder: crwdns100703:0[Placeholder]crwdnd100703:0%{macro_name}crwdne100703:0 errors: - missing_or_invalid_parameter: crwdns99015:0crwdne99015:0 + missing_or_invalid_parameter: crwdns100704:0crwdne100704:0 legacy_warning: - timeline: crwdns99012:0crwdne99012:0 + timeline: crwdns100705:0crwdne100705:0 include_wiki_page: errors: - page_not_found: crwdns99016:0%{name}crwdne99016:0 - circular_inclusion: crwdns99017:0crwdne99017:0 + page_not_found: crwdns100706:0%{name}crwdne100706:0 + circular_inclusion: crwdns100707:0crwdne100707:0 create_work_package_link: errors: - no_project_context: crwdns97617:0crwdne97617:0 - invalid_type: crwdns97618:0%{type}crwdnd97618:0%{project}crwdne97618:0 - link_name: crwdns97619:0crwdne97619:0 - link_name_type: crwdns97620:0%{type_name}crwdne97620:0 + no_project_context: crwdns100708:0crwdne100708:0 + invalid_type: crwdns100709:0%{type}crwdnd100709:0%{project}crwdne100709:0 + link_name: crwdns100710:0crwdne100710:0 + link_name_type: crwdns100711:0%{type_name}crwdne100711:0 mail: - actions: crwdns97621:0crwdne97621:0 - mail_body_account_activation_request: crwdns97622:0%{value}crwdne97622:0 - mail_body_account_information: crwdns97623:0crwdne97623:0 - mail_body_account_information_external: crwdns97624:0%{value}crwdne97624:0 - mail_body_lost_password: crwdns97625:0crwdne97625:0 - mail_body_register: crwdns97626:0crwdne97626:0 - mail_body_reminder: crwdns97627:0%{count}crwdnd97627:0%{days}crwdne97627:0 - mail_body_wiki_content_added: crwdns97628:0%{id}crwdnd97628:0%{author}crwdne97628:0 - mail_body_wiki_content_updated: crwdns97629:0%{id}crwdnd97629:0%{author}crwdne97629:0 - mail_subject_account_activation_request: crwdns97630:0%{value}crwdne97630:0 - mail_subject_lost_password: crwdns97631:0%{value}crwdne97631:0 - mail_subject_register: crwdns97632:0%{value}crwdne97632:0 - mail_subject_reminder: crwdns97633:0%{count}crwdnd97633:0%{days}crwdne97633:0 - mail_subject_wiki_content_added: crwdns97634:0%{id}crwdne97634:0 - mail_subject_wiki_content_updated: crwdns97635:0%{id}crwdne97635:0 + actions: crwdns100712:0crwdne100712:0 + mail_body_account_activation_request: crwdns100713:0%{value}crwdne100713:0 + mail_body_account_information: crwdns100714:0crwdne100714:0 + mail_body_account_information_external: crwdns100715:0%{value}crwdne100715:0 + mail_body_lost_password: crwdns100716:0crwdne100716:0 + mail_body_register: crwdns100717:0crwdne100717:0 + mail_body_reminder: crwdns100718:0%{count}crwdnd100718:0%{days}crwdne100718:0 + mail_body_wiki_content_added: crwdns100719:0%{id}crwdnd100719:0%{author}crwdne100719:0 + mail_body_wiki_content_updated: crwdns100720:0%{id}crwdnd100720:0%{author}crwdne100720:0 + mail_subject_account_activation_request: crwdns100721:0%{value}crwdne100721:0 + mail_subject_lost_password: crwdns100722:0%{value}crwdne100722:0 + mail_subject_register: crwdns100723:0%{value}crwdne100723:0 + mail_subject_reminder: crwdns100724:0%{count}crwdnd100724:0%{days}crwdne100724:0 + mail_subject_wiki_content_added: crwdns100725:0%{id}crwdne100725:0 + mail_subject_wiki_content_updated: crwdns100726:0%{id}crwdne100726:0 mail_user_activation_limit_reached: - subject: crwdns99029:0crwdne99029:0 - message: 'crwdns99030:0%{email}crwdnd99030:0%{host}crwdne99030:0 + subject: crwdns100727:0crwdne100727:0 + message: 'crwdns100728:0%{email}crwdnd100728:0%{host}crwdne100728:0 ' steps: - label: crwdns99031:0crwdne99031:0 - a: crwdns99032:0[here]crwdne99032:0 - b: crwdns99033:0[here]crwdne99033:0 - more_actions: crwdns97636:0crwdne97636:0 - noscript_description: crwdns97637:0crwdne97637:0 - noscript_heading: crwdns97638:0crwdne97638:0 - noscript_learn_more: crwdns97639:0crwdne97639:0 - notice_accessibility_mode: crwdns97640:0crwdne97640:0 - notice_account_activated: crwdns97641:0crwdne97641:0 - notice_account_already_activated: crwdns97642:0crwdne97642:0 - notice_account_invalid_token: crwdns97643:0crwdne97643:0 - notice_account_invalid_credentials: crwdns97644:0crwdne97644:0 - notice_account_invalid_credentials_or_blocked: crwdns97645:0crwdne97645:0 - notice_account_lost_email_sent: crwdns97646:0crwdne97646:0 - notice_account_new_password_forced: crwdns97647:0crwdne97647:0 - notice_account_password_expired: crwdns97648:0%{days}crwdne97648:0 - notice_account_password_updated: crwdns97649:0crwdne97649:0 - notice_account_pending: crwdns97650:0crwdne97650:0 - notice_account_register_done: crwdns97651:0crwdne97651:0 - notice_account_unknown_email: crwdns97652:0crwdne97652:0 - notice_account_update_failed: crwdns97653:0crwdne97653:0 - notice_account_updated: crwdns97654:0crwdne97654:0 - notice_account_wrong_password: crwdns97655:0crwdne97655:0 - notice_account_registered_and_logged_in: crwdns97656:0crwdne97656:0 - notice_activation_failed: crwdns97657:0crwdne97657:0 - notice_auth_stage_verification_error: crwdns97658:0%{stage}crwdne97658:0 - notice_auth_stage_wrong_stage: crwdns97659:0%{expected}crwdnd97659:0%{actual}crwdne97659:0 - notice_auth_stage_error: crwdns97660:0%{stage}crwdne97660:0 - notice_can_t_change_password: crwdns97661:0crwdne97661:0 - notice_custom_options_deleted: crwdns97662:0%{option_value}crwdnd97662:0%{num_deleted}crwdne97662:0 - notice_email_error: crwdns97663:0%{value}crwdne97663:0 - notice_email_sent: crwdns97664:0%{value}crwdne97664:0 - notice_failed_to_save_work_packages: crwdns97665:0%{count}crwdnd97665:0%{total}crwdnd97665:0%{ids}crwdne97665:0 - notice_failed_to_save_members: crwdns97666:0%{errors}crwdne97666:0 - notice_file_not_found: crwdns97667:0crwdne97667:0 - notice_forced_logout: crwdns97668:0%{ttl_time}crwdne97668:0 - notice_internal_server_error: crwdns97669:0%{app_title}crwdne97669:0 - notice_work_package_done_ratios_updated: crwdns97670:0crwdne97670:0 - notice_locking_conflict: crwdns97671:0crwdne97671:0 - notice_locking_conflict_additional_information: crwdns97672:0%{users}crwdne97672:0 - notice_locking_conflict_reload_page: crwdns97673:0crwdne97673:0 - notice_member_added: crwdns97674:0%{name}crwdne97674:0 - notice_members_added: crwdns97675:0%{number}crwdne97675:0 - notice_member_removed: crwdns97676:0%{user}crwdne97676:0 - notice_member_deleted: crwdns97677:0%{user}crwdne97677:0 - notice_no_principals_found: crwdns97678:0crwdne97678:0 - notice_bad_request: crwdns97679:0crwdne97679:0 - notice_not_authorized: crwdns97680:0crwdne97680:0 - notice_not_authorized_archived_project: crwdns97681:0crwdne97681:0 - notice_password_confirmation_failed: crwdns97682:0crwdne97682:0 - notice_principals_found_multiple: crwdns97683:0%{number}crwdne97683:0 - notice_principals_found_single: crwdns97684:0crwdne97684:0 - notice_project_not_deleted: crwdns97685:0crwdne97685:0 - notice_successful_connection: crwdns97686:0crwdne97686:0 - notice_successful_create: crwdns97687:0crwdne97687:0 - notice_successful_delete: crwdns97688:0crwdne97688:0 - notice_successful_update: crwdns97689:0crwdne97689:0 - notice_to_many_principals_to_display: crwdns97690:0crwdne97690:0 - notice_unable_delete_time_entry: crwdns97691:0crwdne97691:0 - notice_unable_delete_version: crwdns97692:0crwdne97692:0 - notice_user_missing_authentication_method: crwdns97693:0crwdne97693:0 - notice_user_invitation_resent: crwdns97694:0%{email}crwdne97694:0 - present_access_key_value: crwdns97695:0%{key_name}crwdnd97695:0%{value}crwdne97695:0 - notice_automatic_set_of_standard_type: crwdns97696:0crwdne97696:0 - notice_logged_out: crwdns97697:0crwdne97697:0 - notice_wont_delete_auth_source: crwdns97698:0crwdne97698:0 - notice_project_cannot_update_custom_fields: crwdns97699:0%{errors}crwdne97699:0 - notice_attachment_migration_wiki_page: 'crwdns97700:0%{container_type}crwdnd97700:0%{container_name}crwdne97700:0 + label: crwdns100729:0crwdne100729:0 + a: crwdns100730:0[here]crwdne100730:0 + b: crwdns100731:0[here]crwdne100731:0 + more_actions: crwdns100732:0crwdne100732:0 + noscript_description: crwdns100733:0crwdne100733:0 + noscript_heading: crwdns100734:0crwdne100734:0 + noscript_learn_more: crwdns100735:0crwdne100735:0 + notice_accessibility_mode: crwdns100736:0crwdne100736:0 + notice_account_activated: crwdns100737:0crwdne100737:0 + notice_account_already_activated: crwdns100738:0crwdne100738:0 + notice_account_invalid_token: crwdns100739:0crwdne100739:0 + notice_account_invalid_credentials: crwdns100740:0crwdne100740:0 + notice_account_invalid_credentials_or_blocked: crwdns100741:0crwdne100741:0 + notice_account_lost_email_sent: crwdns100742:0crwdne100742:0 + notice_account_new_password_forced: crwdns100743:0crwdne100743:0 + notice_account_password_expired: crwdns100744:0%{days}crwdne100744:0 + notice_account_password_updated: crwdns100745:0crwdne100745:0 + notice_account_pending: crwdns100746:0crwdne100746:0 + notice_account_register_done: crwdns100747:0crwdne100747:0 + notice_account_unknown_email: crwdns100748:0crwdne100748:0 + notice_account_update_failed: crwdns100749:0crwdne100749:0 + notice_account_updated: crwdns100750:0crwdne100750:0 + notice_account_wrong_password: crwdns100751:0crwdne100751:0 + notice_account_registered_and_logged_in: crwdns100752:0crwdne100752:0 + notice_activation_failed: crwdns100753:0crwdne100753:0 + notice_auth_stage_verification_error: crwdns100754:0%{stage}crwdne100754:0 + notice_auth_stage_wrong_stage: crwdns100755:0%{expected}crwdnd100755:0%{actual}crwdne100755:0 + notice_auth_stage_error: crwdns100756:0%{stage}crwdne100756:0 + notice_can_t_change_password: crwdns100757:0crwdne100757:0 + notice_custom_options_deleted: crwdns100758:0%{option_value}crwdnd100758:0%{num_deleted}crwdne100758:0 + notice_email_error: crwdns100759:0%{value}crwdne100759:0 + notice_email_sent: crwdns100760:0%{value}crwdne100760:0 + notice_failed_to_save_work_packages: crwdns100761:0%{count}crwdnd100761:0%{total}crwdnd100761:0%{ids}crwdne100761:0 + notice_failed_to_save_members: crwdns100762:0%{errors}crwdne100762:0 + notice_file_not_found: crwdns100763:0crwdne100763:0 + notice_forced_logout: crwdns100764:0%{ttl_time}crwdne100764:0 + notice_internal_server_error: crwdns100765:0%{app_title}crwdne100765:0 + notice_work_package_done_ratios_updated: crwdns100766:0crwdne100766:0 + notice_locking_conflict: crwdns100767:0crwdne100767:0 + notice_locking_conflict_additional_information: crwdns100768:0%{users}crwdne100768:0 + notice_locking_conflict_reload_page: crwdns100769:0crwdne100769:0 + notice_member_added: crwdns100770:0%{name}crwdne100770:0 + notice_members_added: crwdns100771:0%{number}crwdne100771:0 + notice_member_removed: crwdns100772:0%{user}crwdne100772:0 + notice_member_deleted: crwdns100773:0%{user}crwdne100773:0 + notice_no_principals_found: crwdns100774:0crwdne100774:0 + notice_bad_request: crwdns100775:0crwdne100775:0 + notice_not_authorized: crwdns100776:0crwdne100776:0 + notice_not_authorized_archived_project: crwdns100777:0crwdne100777:0 + notice_password_confirmation_failed: crwdns100778:0crwdne100778:0 + notice_principals_found_multiple: crwdns100779:0%{number}crwdne100779:0 + notice_principals_found_single: crwdns100780:0crwdne100780:0 + notice_project_not_deleted: crwdns100781:0crwdne100781:0 + notice_successful_connection: crwdns100782:0crwdne100782:0 + notice_successful_create: crwdns100783:0crwdne100783:0 + notice_successful_delete: crwdns100784:0crwdne100784:0 + notice_successful_update: crwdns100785:0crwdne100785:0 + notice_to_many_principals_to_display: crwdns100786:0crwdne100786:0 + notice_unable_delete_time_entry: crwdns100787:0crwdne100787:0 + notice_unable_delete_version: crwdns100788:0crwdne100788:0 + notice_user_missing_authentication_method: crwdns100789:0crwdne100789:0 + notice_user_invitation_resent: crwdns100790:0%{email}crwdne100790:0 + present_access_key_value: crwdns100791:0%{key_name}crwdnd100791:0%{value}crwdne100791:0 + notice_automatic_set_of_standard_type: crwdns100792:0crwdne100792:0 + notice_logged_out: crwdns100793:0crwdne100793:0 + notice_wont_delete_auth_source: crwdns100794:0crwdne100794:0 + notice_project_cannot_update_custom_fields: crwdns100795:0%{errors}crwdne100795:0 + notice_attachment_migration_wiki_page: 'crwdns100796:0%{container_type}crwdnd100796:0%{container_name}crwdne100796:0 ' number: format: - delimiter: crwdns97701:0crwdne97701:0 + delimiter: crwdns100797:0crwdne100797:0 precision: 0 - separator: crwdns97703:0crwdne97703:0 + separator: crwdns100799:0crwdne100799:0 human: format: - delimiter: crwdns97704:0crwdne97704:0 + delimiter: crwdns100800:0crwdne100800:0 precision: 0 storage_units: - format: crwdns97706:0%ncrwdnd97706:0%ucrwdne97706:0 + format: crwdns100802:0%ncrwdnd100802:0%ucrwdne100802:0 units: byte: - one: crwdns97707:1crwdne97707:1 - other: crwdns97707:5crwdne97707:5 - gb: crwdns97708:0crwdne97708:0 - kb: crwdns97709:0crwdne97709:0 - mb: crwdns97710:0crwdne97710:0 - tb: crwdns97711:0crwdne97711:0 + one: crwdns100803:1crwdne100803:1 + other: crwdns100803:5crwdne100803:5 + gb: crwdns100804:0crwdne100804:0 + kb: crwdns100805:0crwdne100805:0 + mb: crwdns100806:0crwdne100806:0 + tb: crwdns100807:0crwdne100807:0 onboarding: - heading_getting_started: crwdns97712:0crwdne97712:0 - text_getting_started_description: crwdns97713:0crwdne97713:0 - text_show_again: crwdns97714:0crwdne97714:0 - welcome: crwdns97715:0crwdne97715:0 - select_language: crwdns99028:0crwdne99028:0 - permission_add_work_package_notes: crwdns97716:0crwdne97716:0 - permission_add_work_packages: crwdns98979:0crwdne98979:0 - permission_add_messages: crwdns97718:0crwdne97718:0 - permission_add_project: crwdns97719:0crwdne97719:0 - permission_add_subprojects: crwdns97720:0crwdne97720:0 - permission_add_work_package_watchers: crwdns97721:0crwdne97721:0 - permission_browse_repository: crwdns97722:0crwdne97722:0 - permission_change_wiki_parent_page: crwdns97723:0crwdne97723:0 - permission_comment_news: crwdns97724:0crwdne97724:0 - permission_commit_access: crwdns97725:0crwdne97725:0 - permission_copy_projects: crwdns97726:0crwdne97726:0 - permission_delete_work_package_watchers: crwdns97727:0crwdne97727:0 - permission_delete_work_packages: crwdns97728:0crwdne97728:0 - permission_delete_messages: crwdns97729:0crwdne97729:0 - permission_delete_own_messages: crwdns97730:0crwdne97730:0 - permission_delete_reportings: crwdns97731:0crwdne97731:0 - permission_delete_timelines: crwdns97732:0crwdne97732:0 - permission_delete_wiki_pages: crwdns97733:0crwdne97733:0 - permission_delete_wiki_pages_attachments: crwdns97734:0crwdne97734:0 - permission_edit_work_package_notes: crwdns97735:0crwdne97735:0 - permission_edit_work_packages: crwdns97736:0crwdne97736:0 - permission_edit_messages: crwdns97737:0crwdne97737:0 - permission_edit_own_work_package_notes: crwdns97738:0crwdne97738:0 - permission_edit_own_messages: crwdns97739:0crwdne97739:0 - permission_edit_own_time_entries: crwdns97740:0crwdne97740:0 - permission_edit_project: crwdns97741:0crwdne97741:0 - permission_edit_reportings: crwdns97742:0crwdne97742:0 - permission_edit_time_entries: crwdns97743:0crwdne97743:0 - permission_edit_timelines: crwdns97744:0crwdne97744:0 - permission_edit_wiki_pages: crwdns97745:0crwdne97745:0 - permission_export_work_packages: crwdns97746:0crwdne97746:0 - permission_export_wiki_pages: crwdns97747:0crwdne97747:0 - permission_list_attachments: crwdns97748:0crwdne97748:0 - permission_log_time: crwdns97749:0crwdne97749:0 - permission_manage_boards: crwdns97750:0crwdne97750:0 - permission_manage_categories: crwdns97751:0crwdne97751:0 - permission_manage_work_package_relations: crwdns97752:0crwdne97752:0 - permission_manage_members: crwdns97753:0crwdne97753:0 - permission_manage_news: crwdns97754:0crwdne97754:0 - permission_manage_project_activities: crwdns97755:0crwdne97755:0 - permission_manage_public_queries: crwdns99121:0crwdne99121:0 - permission_manage_repository: crwdns97757:0crwdne97757:0 - permission_manage_subtasks: crwdns97758:0crwdne97758:0 - permission_manage_versions: crwdns97759:0crwdne97759:0 - permission_manage_wiki: crwdns97760:0crwdne97760:0 - permission_manage_wiki_menu: crwdns97761:0crwdne97761:0 - permission_move_work_packages: crwdns97762:0crwdne97762:0 - permission_protect_wiki_pages: crwdns97763:0crwdne97763:0 - permission_rename_wiki_pages: crwdns97764:0crwdne97764:0 - permission_save_queries: crwdns99122:0crwdne99122:0 - permission_select_project_modules: crwdns97766:0crwdne97766:0 - permission_manage_types: crwdns97767:0crwdne97767:0 - permission_view_calendar: crwdns97768:0crwdne97768:0 - permission_view_changesets: crwdns97769:0crwdne97769:0 - permission_view_commit_author_statistics: crwdns97770:0crwdne97770:0 - permission_view_work_package_watchers: crwdns97771:0crwdne97771:0 - permission_view_work_packages: crwdns97772:0crwdne97772:0 - permission_view_messages: crwdns97773:0crwdne97773:0 - permission_view_members: crwdns97774:0crwdne97774:0 - permission_view_reportings: crwdns97775:0crwdne97775:0 - permission_view_time_entries: crwdns97776:0crwdne97776:0 - permission_view_timelines: crwdns97777:0crwdne97777:0 - permission_view_wiki_edits: crwdns97778:0crwdne97778:0 - permission_view_wiki_pages: crwdns97779:0crwdne97779:0 + heading_getting_started: crwdns100808:0crwdne100808:0 + text_getting_started_description: crwdns100809:0crwdne100809:0 + text_show_again: crwdns100810:0crwdne100810:0 + welcome: crwdns100811:0crwdne100811:0 + select_language: crwdns109126:0crwdne109126:0 + permission_add_work_package_notes: crwdns100813:0crwdne100813:0 + permission_add_work_packages: crwdns100814:0crwdne100814:0 + permission_add_messages: crwdns100815:0crwdne100815:0 + permission_add_project: crwdns100816:0crwdne100816:0 + permission_add_subprojects: crwdns100817:0crwdne100817:0 + permission_add_work_package_watchers: crwdns100818:0crwdne100818:0 + permission_browse_repository: crwdns100819:0crwdne100819:0 + permission_change_wiki_parent_page: crwdns100820:0crwdne100820:0 + permission_comment_news: crwdns100821:0crwdne100821:0 + permission_commit_access: crwdns100822:0crwdne100822:0 + permission_copy_projects: crwdns100823:0crwdne100823:0 + permission_delete_work_package_watchers: crwdns100824:0crwdne100824:0 + permission_delete_work_packages: crwdns100825:0crwdne100825:0 + permission_delete_messages: crwdns100826:0crwdne100826:0 + permission_delete_own_messages: crwdns100827:0crwdne100827:0 + permission_delete_reportings: crwdns100828:0crwdne100828:0 + permission_delete_timelines: crwdns100829:0crwdne100829:0 + permission_delete_wiki_pages: crwdns100830:0crwdne100830:0 + permission_delete_wiki_pages_attachments: crwdns100831:0crwdne100831:0 + permission_edit_work_package_notes: crwdns100832:0crwdne100832:0 + permission_edit_work_packages: crwdns100833:0crwdne100833:0 + permission_edit_messages: crwdns100834:0crwdne100834:0 + permission_edit_own_work_package_notes: crwdns100835:0crwdne100835:0 + permission_edit_own_messages: crwdns100836:0crwdne100836:0 + permission_edit_own_time_entries: crwdns100837:0crwdne100837:0 + permission_edit_project: crwdns100838:0crwdne100838:0 + permission_edit_reportings: crwdns100839:0crwdne100839:0 + permission_edit_time_entries: crwdns100840:0crwdne100840:0 + permission_edit_timelines: crwdns100841:0crwdne100841:0 + permission_edit_wiki_pages: crwdns100842:0crwdne100842:0 + permission_export_work_packages: crwdns100843:0crwdne100843:0 + permission_export_wiki_pages: crwdns100844:0crwdne100844:0 + permission_list_attachments: crwdns100845:0crwdne100845:0 + permission_log_time: crwdns100846:0crwdne100846:0 + permission_manage_boards: crwdns100847:0crwdne100847:0 + permission_manage_categories: crwdns100848:0crwdne100848:0 + permission_manage_work_package_relations: crwdns100849:0crwdne100849:0 + permission_manage_members: crwdns100850:0crwdne100850:0 + permission_manage_news: crwdns100851:0crwdne100851:0 + permission_manage_project_activities: crwdns100852:0crwdne100852:0 + permission_manage_public_queries: crwdns100853:0crwdne100853:0 + permission_manage_repository: crwdns100854:0crwdne100854:0 + permission_manage_subtasks: crwdns100855:0crwdne100855:0 + permission_manage_versions: crwdns100856:0crwdne100856:0 + permission_manage_wiki: crwdns100857:0crwdne100857:0 + permission_manage_wiki_menu: crwdns100858:0crwdne100858:0 + permission_move_work_packages: crwdns100859:0crwdne100859:0 + permission_protect_wiki_pages: crwdns100860:0crwdne100860:0 + permission_rename_wiki_pages: crwdns100861:0crwdne100861:0 + permission_save_queries: crwdns100862:0crwdne100862:0 + permission_select_project_modules: crwdns100863:0crwdne100863:0 + permission_manage_types: crwdns100864:0crwdne100864:0 + permission_view_calendar: crwdns100865:0crwdne100865:0 + permission_view_changesets: crwdns100866:0crwdne100866:0 + permission_view_commit_author_statistics: crwdns100867:0crwdne100867:0 + permission_view_work_package_watchers: crwdns100868:0crwdne100868:0 + permission_view_work_packages: crwdns100869:0crwdne100869:0 + permission_view_messages: crwdns100870:0crwdne100870:0 + permission_view_members: crwdns100871:0crwdne100871:0 + permission_view_reportings: crwdns100872:0crwdne100872:0 + permission_view_time_entries: crwdns100873:0crwdne100873:0 + permission_view_timelines: crwdns100874:0crwdne100874:0 + permission_view_wiki_edits: crwdns100875:0crwdne100875:0 + permission_view_wiki_pages: crwdns100876:0crwdne100876:0 placeholders: - default: crwdns97780:0crwdne97780:0 + default: crwdns100877:0crwdne100877:0 project: destroy: - confirmation: crwdns97781:0%{identifier}crwdne97781:0 - info: crwdns97782:0crwdne97782:0 - project_verification: crwdns97783:0%{name}crwdne97783:0 - subprojects_confirmation: crwdns97784:0%{value}crwdne97784:0 - title: crwdns97785:0%{name}crwdne97785:0 + confirmation: crwdns100878:0%{identifier}crwdne100878:0 + info: crwdns100879:0crwdne100879:0 + project_verification: crwdns100880:0%{name}crwdne100880:0 + subprojects_confirmation: crwdns100881:0%{value}crwdne100881:0 + title: crwdns100882:0%{name}crwdne100882:0 identifier: - warning_one: crwdns97786:0crwdne97786:0 - warning_two: crwdns97787:0crwdne97787:0 - title: crwdns97788:0crwdne97788:0 + warning_one: crwdns100883:0crwdne100883:0 + warning_two: crwdns100884:0crwdne100884:0 + title: crwdns100885:0crwdne100885:0 archive: - are_you_sure: crwdns97789:0%{name}crwdne97789:0 - project_module_activity: crwdns97790:0crwdne97790:0 - project_module_boards: crwdns97791:0crwdne97791:0 - project_module_calendar: crwdns97792:0crwdne97792:0 - project_module_work_package_tracking: crwdns97793:0crwdne97793:0 - project_module_news: crwdns97794:0crwdne97794:0 - project_module_repository: crwdns97795:0crwdne97795:0 - project_module_time_tracking: crwdns97796:0crwdne97796:0 - project_module_timelines: crwdns97797:0crwdne97797:0 - project_module_wiki: crwdns97798:0crwdne97798:0 + are_you_sure: crwdns100886:0%{name}crwdne100886:0 + project_module_activity: crwdns100887:0crwdne100887:0 + project_module_boards: crwdns100888:0crwdne100888:0 + project_module_calendar: crwdns100889:0crwdne100889:0 + project_module_work_package_tracking: crwdns100890:0crwdne100890:0 + project_module_news: crwdns100891:0crwdne100891:0 + project_module_repository: crwdns100892:0crwdne100892:0 + project_module_time_tracking: crwdns100893:0crwdne100893:0 + project_module_timelines: crwdns100894:0crwdne100894:0 + project_module_wiki: crwdns100895:0crwdne100895:0 query: - attribute_and_direction: crwdns97799:0%{attribute}crwdnd97799:0%{direction}crwdne97799:0 + attribute_and_direction: crwdns100896:0%{attribute}crwdnd100896:0%{direction}crwdne100896:0 query_fields: - active_or_archived: crwdns97800:0crwdne97800:0 - assigned_to_role: crwdns97801:0crwdne97801:0 - member_of_group: crwdns97802:0crwdne97802:0 - assignee_or_group: crwdns97803:0crwdne97803:0 - subproject_id: crwdns97804:0crwdne97804:0 - name_or_identifier: crwdns97805:0crwdne97805:0 + active_or_archived: crwdns100897:0crwdne100897:0 + assigned_to_role: crwdns100898:0crwdne100898:0 + member_of_group: crwdns100899:0crwdne100899:0 + assignee_or_group: crwdns100900:0crwdne100900:0 + subproject_id: crwdns100901:0crwdne100901:0 + name_or_identifier: crwdns100902:0crwdne100902:0 repositories: - at_identifier: crwdns97806:0%{identifier}crwdne97806:0 - atom_revision_feed: crwdns97807:0crwdne97807:0 - autofetch_information: crwdns97808:0crwdne97808:0 + at_identifier: crwdns100903:0%{identifier}crwdne100903:0 + atom_revision_feed: crwdns100904:0crwdne100904:0 + autofetch_information: crwdns100905:0crwdne100905:0 checkout: access: - readwrite: crwdns97809:0crwdne97809:0 - read: crwdns97810:0crwdne97810:0 - none: crwdns97811:0crwdne97811:0 - access_permission: crwdns97812:0crwdne97812:0 - url: crwdns97813:0crwdne97813:0 - base_url_text: crwdns97814:0crwdne97814:0 + readwrite: crwdns100906:0crwdne100906:0 + read: crwdns100907:0crwdne100907:0 + none: crwdns100908:0crwdne100908:0 + access_permission: crwdns100909:0crwdne100909:0 + url: crwdns100910:0crwdne100910:0 + base_url_text: crwdns100911:0crwdne100911:0 default_instructions: - git: crwdns97815:0crwdne97815:0 - subversion: crwdns97816:0crwdne97816:0 - enable_instructions_text: crwdns97817:0crwdne97817:0 - instructions: crwdns97818:0crwdne97818:0 - show_instructions: crwdns97819:0crwdne97819:0 - text_instructions: crwdns97820:0crwdne97820:0 - not_available: crwdns97821:0crwdne97821:0 - create_managed_delay: crwdns97822:0crwdne97822:0 - create_successful: crwdns97823:0crwdne97823:0 - delete_sucessful: crwdns97824:0crwdne97824:0 + git: crwdns100912:0crwdne100912:0 + subversion: crwdns100913:0crwdne100913:0 + enable_instructions_text: crwdns100914:0crwdne100914:0 + instructions: crwdns100915:0crwdne100915:0 + show_instructions: crwdns100916:0crwdne100916:0 + text_instructions: crwdns100917:0crwdne100917:0 + not_available: crwdns100918:0crwdne100918:0 + create_managed_delay: crwdns100919:0crwdne100919:0 + create_successful: crwdns100920:0crwdne100920:0 + delete_sucessful: crwdns100921:0crwdne100921:0 destroy: - confirmation: crwdns97825:0crwdne97825:0 - info: crwdns97826:0crwdne97826:0 - info_not_managed: crwdns97827:0crwdne97827:0 - managed_path_note: crwdns97828:0%{path}crwdne97828:0 - repository_verification: crwdns97829:0%{identifier}crwdne97829:0 - subtitle: crwdns97830:0%{repository_type}crwdnd97830:0%{project_name}crwdne97830:0 - subtitle_not_managed: crwdns97831:0%{repository_type}crwdnd97831:0%{url}crwdnd97831:0%{project_name}crwdne97831:0 - title: crwdns97832:0%{repository_type}crwdne97832:0 - title_not_managed: crwdns97833:0%{repository_type}crwdne97833:0 + confirmation: crwdns100922:0crwdne100922:0 + info: crwdns100923:0crwdne100923:0 + info_not_managed: crwdns100924:0crwdne100924:0 + managed_path_note: crwdns100925:0%{path}crwdne100925:0 + repository_verification: crwdns100926:0%{identifier}crwdne100926:0 + subtitle: crwdns100927:0%{repository_type}crwdnd100927:0%{project_name}crwdne100927:0 + subtitle_not_managed: crwdns100928:0%{repository_type}crwdnd100928:0%{url}crwdnd100928:0%{project_name}crwdne100928:0 + title: crwdns100929:0%{repository_type}crwdne100929:0 + title_not_managed: crwdns100930:0%{repository_type}crwdne100930:0 errors: - build_failed: crwdns97834:0%{reason}crwdne97834:0 - managed_delete: crwdns97835:0crwdne97835:0 - managed_delete_local: crwdns97836:0%{path}crwdnd97836:0%{error_message}crwdne97836:0 - empty_repository: crwdns97837:0crwdne97837:0 - exists_on_filesystem: crwdns97838:0crwdne97838:0 - filesystem_access_failed: crwdns97839:0%{message}crwdne97839:0 - not_manageable: crwdns97840:0crwdne97840:0 - path_permission_failed: crwdns97841:0%{path}crwdne97841:0 - unauthorized: crwdns97842:0crwdne97842:0 - unavailable: crwdns97843:0crwdne97843:0 - exception_title: crwdns97844:0%{message}crwdne97844:0 - disabled_or_unknown_type: crwdns97845:0%{type}crwdnd97845:0%{vendor}crwdne97845:0 - disabled_or_unknown_vendor: crwdns97846:0%{vendor}crwdne97846:0 - remote_call_failed: crwdns97847:0%{message}crwdnd97847:0%{code}crwdne97847:0 - remote_invalid_response: crwdns97848:0crwdne97848:0 - remote_save_failed: crwdns97849:0crwdne97849:0 + build_failed: crwdns100931:0%{reason}crwdne100931:0 + managed_delete: crwdns100932:0crwdne100932:0 + managed_delete_local: crwdns100933:0%{path}crwdnd100933:0%{error_message}crwdne100933:0 + empty_repository: crwdns100934:0crwdne100934:0 + exists_on_filesystem: crwdns100935:0crwdne100935:0 + filesystem_access_failed: crwdns100936:0%{message}crwdne100936:0 + not_manageable: crwdns100937:0crwdne100937:0 + path_permission_failed: crwdns100938:0%{path}crwdne100938:0 + unauthorized: crwdns100939:0crwdne100939:0 + unavailable: crwdns100940:0crwdne100940:0 + exception_title: crwdns100941:0%{message}crwdne100941:0 + disabled_or_unknown_type: crwdns100942:0%{type}crwdnd100942:0%{vendor}crwdne100942:0 + disabled_or_unknown_vendor: crwdns100943:0%{vendor}crwdne100943:0 + remote_call_failed: crwdns100944:0%{message}crwdnd100944:0%{code}crwdne100944:0 + remote_invalid_response: crwdns100945:0crwdne100945:0 + remote_save_failed: crwdns100946:0crwdne100946:0 git: instructions: - managed_url: crwdns97850:0crwdne97850:0 - path: crwdns97851:0%{example_path}crwdne97851:0 - path_encoding: crwdns97852:0crwdne97852:0 - local_title: crwdns97853:0crwdne97853:0 - local_url: crwdns97854:0crwdne97854:0 - local_introduction: crwdns97855:0crwdne97855:0 - managed_introduction: crwdns97856:0crwdne97856:0 - managed_title: crwdns97857:0crwdne97857:0 - managed_url: crwdns97858:0crwdne97858:0 - path: crwdns97859:0crwdne97859:0 - path_encoding: crwdns97860:0crwdne97860:0 - go_to_revision: crwdns97861:0crwdne97861:0 - managed_remote: crwdns97862:0crwdne97862:0 - managed_remote_note: crwdns97863:0crwdne97863:0 - managed_url: crwdns97864:0crwdne97864:0 + managed_url: crwdns100947:0crwdne100947:0 + path: crwdns100948:0%{example_path}crwdne100948:0 + path_encoding: crwdns100949:0crwdne100949:0 + local_title: crwdns100950:0crwdne100950:0 + local_url: crwdns100951:0crwdne100951:0 + local_introduction: crwdns100952:0crwdne100952:0 + managed_introduction: crwdns100953:0crwdne100953:0 + managed_title: crwdns100954:0crwdne100954:0 + managed_url: crwdns100955:0crwdne100955:0 + path: crwdns100956:0crwdne100956:0 + path_encoding: crwdns100957:0crwdne100957:0 + go_to_revision: crwdns100958:0crwdne100958:0 + managed_remote: crwdns100959:0crwdne100959:0 + managed_remote_note: crwdns100960:0crwdne100960:0 + managed_url: crwdns100961:0crwdne100961:0 settings: - automatic_managed_repos_disabled: crwdns97865:0crwdne97865:0 - automatic_managed_repos: crwdns97866:0crwdne97866:0 - automatic_managed_repos_text: crwdns97867:0crwdne97867:0 - scm_vendor: crwdns97868:0crwdne97868:0 - scm_type: crwdns97869:0crwdne97869:0 + automatic_managed_repos_disabled: crwdns100962:0crwdne100962:0 + automatic_managed_repos: crwdns100963:0crwdne100963:0 + automatic_managed_repos_text: crwdns100964:0crwdne100964:0 + scm_vendor: crwdns100965:0crwdne100965:0 + scm_type: crwdns100966:0crwdne100966:0 scm_types: - local: crwdns97870:0crwdne97870:0 - existing: crwdns97871:0crwdne97871:0 - managed: crwdns97872:0crwdne97872:0 + local: crwdns100967:0crwdne100967:0 + existing: crwdns100968:0crwdne100968:0 + managed: crwdns100969:0crwdne100969:0 storage: - not_available: crwdns97873:0crwdne97873:0 - update_timeout: crwdns97874:0crwdne97874:0 + not_available: crwdns100970:0crwdne100970:0 + update_timeout: crwdns100971:0crwdne100971:0 subversion: - existing_title: crwdns97875:0crwdne97875:0 - existing_introduction: crwdns97876:0crwdne97876:0 - existing_url: crwdns97877:0crwdne97877:0 + existing_title: crwdns100972:0crwdne100972:0 + existing_introduction: crwdns100973:0crwdne100973:0 + existing_url: crwdns100974:0crwdne100974:0 instructions: - managed_url: crwdns97878:0crwdne97878:0 - url: crwdns97879:0%{local_proto}crwdne97879:0 - managed_title: crwdns97880:0crwdne97880:0 - managed_introduction: crwdns97881:0crwdne97881:0 - managed_url: crwdns97882:0crwdne97882:0 - password: crwdns97883:0crwdne97883:0 - username: crwdns97884:0crwdne97884:0 - truncated: crwdns97885:0%{limit}crwdnd97885:0%{truncated}crwdne97885:0 - named_repository: crwdns97886:0%{vendor_name}crwdne97886:0 - update_settings_successful: crwdns97887:0crwdne97887:0 - url: crwdns97888:0crwdne97888:0 + managed_url: crwdns100975:0crwdne100975:0 + url: crwdns100976:0%{local_proto}crwdne100976:0 + managed_title: crwdns100977:0crwdne100977:0 + managed_introduction: crwdns100978:0crwdne100978:0 + managed_url: crwdns100979:0crwdne100979:0 + password: crwdns100980:0crwdne100980:0 + username: crwdns100981:0crwdne100981:0 + truncated: crwdns100982:0%{limit}crwdnd100982:0%{truncated}crwdne100982:0 + named_repository: crwdns100983:0%{vendor_name}crwdne100983:0 + update_settings_successful: crwdns100984:0crwdne100984:0 + url: crwdns100985:0crwdne100985:0 warnings: - cannot_annotate: crwdns97889:0crwdne97889:0 - search_input_placeholder: crwdns97890:0crwdne97890:0 - setting_email_delivery_method: crwdns97891:0crwdne97891:0 - setting_sendmail_location: crwdns97892:0crwdne97892:0 - setting_smtp_enable_starttls_auto: crwdns97893:0crwdne97893:0 - setting_smtp_ssl: crwdns102529:0crwdne102529:0 - setting_smtp_address: crwdns97894:0crwdne97894:0 - setting_smtp_port: crwdns97895:0crwdne97895:0 - setting_smtp_authentication: crwdns97896:0crwdne97896:0 - setting_smtp_user_name: crwdns97898:0crwdne97898:0 - setting_smtp_password: crwdns97899:0crwdne97899:0 - setting_smtp_domain: crwdns97897:0crwdne97897:0 - setting_activity_days_default: crwdns97900:0crwdne97900:0 - setting_app_subtitle: crwdns97901:0crwdne97901:0 - setting_app_title: crwdns97902:0crwdne97902:0 - setting_attachment_max_size: crwdns97903:0crwdne97903:0 - setting_autofetch_changesets: crwdns97904:0crwdne97904:0 - setting_autologin: crwdns97905:0crwdne97905:0 - setting_available_languages: crwdns97906:0crwdne97906:0 - setting_bcc_recipients: crwdns97907:0crwdne97907:0 - setting_brute_force_block_after_failed_logins: crwdns97908:0crwdne97908:0 - setting_brute_force_block_minutes: crwdns97909:0crwdne97909:0 - setting_cache_formatted_text: crwdns97910:0crwdne97910:0 - setting_use_wysiwyg_description: crwdns98896:0crwdne98896:0 - setting_column_options: crwdns97911:0crwdne97911:0 - setting_commit_fix_keywords: crwdns97912:0crwdne97912:0 - setting_commit_logs_encoding: crwdns97913:0crwdne97913:0 - setting_commit_logtime_activity_id: crwdns97914:0crwdne97914:0 - setting_commit_logtime_enabled: crwdns97915:0crwdne97915:0 - setting_commit_ref_keywords: crwdns97916:0crwdne97916:0 - setting_consent_time: crwdns98965:0crwdne98965:0 - setting_consent_info: crwdns98966:0crwdne98966:0 - setting_consent_required: crwdns98967:0crwdne98967:0 - setting_consent_decline_mail: crwdns98968:0crwdne98968:0 - setting_cross_project_work_package_relations: crwdns97917:0crwdne97917:0 - setting_date_format: crwdns97918:0crwdne97918:0 - setting_default_language: crwdns97919:0crwdne97919:0 - setting_default_notification_option: crwdns97920:0crwdne97920:0 - setting_default_projects_modules: crwdns97921:0crwdne97921:0 - setting_default_projects_public: crwdns97922:0crwdne97922:0 - setting_diff_max_lines_displayed: crwdns97923:0crwdne97923:0 - setting_display_subprojects_work_packages: crwdns97924:0crwdne97924:0 - setting_emails_footer: crwdns97925:0crwdne97925:0 - setting_emails_header: crwdns97926:0crwdne97926:0 - setting_email_login: crwdns97927:0crwdne97927:0 - setting_enabled_scm: crwdns97928:0crwdne97928:0 - setting_feeds_enabled: crwdns97929:0crwdne97929:0 - setting_feeds_limit: crwdns97930:0crwdne97930:0 - setting_file_max_size_displayed: crwdns97931:0crwdne97931:0 - setting_host_name: crwdns97932:0crwdne97932:0 - setting_invitation_expiration_days: crwdns98855:0crwdne98855:0 - setting_work_package_done_ratio: crwdns97933:0crwdne97933:0 - setting_work_package_done_ratio_field: crwdns97934:0crwdne97934:0 - setting_work_package_done_ratio_status: crwdns97935:0crwdne97935:0 - setting_work_package_done_ratio_disabled: crwdns97936:0crwdne97936:0 - setting_work_package_list_default_columns: crwdns97937:0crwdne97937:0 - setting_work_package_list_summable_columns: crwdns97938:0crwdne97938:0 - setting_work_package_properties: crwdns97939:0crwdne97939:0 - setting_work_package_startdate_is_adddate: crwdns97940:0crwdne97940:0 - setting_work_packages_export_limit: crwdns97941:0crwdne97941:0 - setting_journal_aggregation_time_minutes: crwdns97942:0crwdne97942:0 - setting_log_requesting_user: crwdns97943:0crwdne97943:0 - setting_login_required: crwdns97944:0crwdne97944:0 - setting_mail_from: crwdns97945:0crwdne97945:0 - setting_mail_handler_api_enabled: crwdns97946:0crwdne97946:0 - setting_mail_handler_api_description: crwdns97947:0crwdne97947:0 - setting_mail_handler_api_key: crwdns97948:0crwdne97948:0 - setting_mail_handler_body_delimiters: crwdns97949:0crwdne97949:0 - setting_mail_handler_body_delimiter_regex: crwdns97950:0crwdne97950:0 - setting_new_project_user_role_id: crwdns97951:0crwdne97951:0 - setting_password_active_rules: crwdns97952:0crwdne97952:0 - setting_password_count_former_banned: crwdns97953:0crwdne97953:0 - setting_password_days_valid: crwdns97954:0crwdne97954:0 - setting_password_min_length: crwdns97955:0crwdne97955:0 - setting_password_min_adhered_rules: crwdns97956:0crwdne97956:0 - setting_per_page_options: crwdns97957:0crwdne97957:0 - setting_plain_text_mail: crwdns97958:0crwdne97958:0 - setting_protocol: crwdns97959:0crwdne97959:0 - setting_registration_footer: crwdns97960:0crwdne97960:0 - setting_repositories_automatic_managed_vendor: crwdns97961:0crwdne97961:0 - setting_repositories_encodings: crwdns97962:0crwdne97962:0 - setting_repository_authentication_caching_enabled: crwdns97963:0crwdne97963:0 - setting_repository_storage_cache_minutes: crwdns97964:0crwdne97964:0 - setting_repository_checkout_display: crwdns97965:0crwdne97965:0 - setting_repository_checkout_base_url: crwdns97966:0crwdne97966:0 - setting_repository_checkout_text: crwdns97967:0crwdne97967:0 - setting_repository_log_display_limit: crwdns97968:0crwdne97968:0 - setting_repository_truncate_at: crwdns97969:0crwdne97969:0 - setting_rest_api_enabled: crwdns97970:0crwdne97970:0 - setting_self_registration: crwdns97971:0crwdne97971:0 - setting_sequential_project_identifiers: crwdns97972:0crwdne97972:0 - setting_session_ttl: crwdns97973:0crwdne97973:0 - setting_session_ttl_hint: crwdns97974:0crwdne97974:0 - setting_session_ttl_enabled: crwdns97975:0crwdne97975:0 - setting_start_of_week: crwdns97976:0crwdne97976:0 - setting_sys_api_enabled: crwdns97977:0crwdne97977:0 - setting_sys_api_description: crwdns97978:0crwdne97978:0 - setting_time_format: crwdns97980:0crwdne97980:0 - setting_accessibility_mode_for_anonymous: crwdns97981:0crwdne97981:0 - setting_user_format: crwdns97982:0crwdne97982:0 - setting_user_default_timezone: crwdns98865:0crwdne98865:0 - setting_users_deletable_by_admins: crwdns97983:0crwdne97983:0 - setting_users_deletable_by_self: crwdns97984:0crwdne97984:0 - setting_welcome_text: crwdns97985:0crwdne97985:0 - setting_welcome_title: crwdns97986:0crwdne97986:0 - setting_welcome_on_homescreen: crwdns97987:0crwdne97987:0 - setting_wiki_compression: crwdns97989:0crwdne97989:0 - setting_work_package_group_assignment: crwdns97990:0crwdne97990:0 - setting_work_package_list_default_highlighting_mode: crwdns99257:0crwdne99257:0 + cannot_annotate: crwdns100986:0crwdne100986:0 + search_input_placeholder: crwdns100987:0crwdne100987:0 + setting_email_delivery_method: crwdns100988:0crwdne100988:0 + setting_sendmail_location: crwdns100989:0crwdne100989:0 + setting_smtp_enable_starttls_auto: crwdns100990:0crwdne100990:0 + setting_smtp_ssl: crwdns102531:0crwdne102531:0 + setting_smtp_address: crwdns100991:0crwdne100991:0 + setting_smtp_port: crwdns100992:0crwdne100992:0 + setting_smtp_authentication: crwdns100993:0crwdne100993:0 + setting_smtp_user_name: crwdns100994:0crwdne100994:0 + setting_smtp_password: crwdns100995:0crwdne100995:0 + setting_smtp_domain: crwdns100996:0crwdne100996:0 + setting_activity_days_default: crwdns100997:0crwdne100997:0 + setting_app_subtitle: crwdns100998:0crwdne100998:0 + setting_app_title: crwdns100999:0crwdne100999:0 + setting_attachment_max_size: crwdns101000:0crwdne101000:0 + setting_autofetch_changesets: crwdns101001:0crwdne101001:0 + setting_autologin: crwdns101002:0crwdne101002:0 + setting_available_languages: crwdns101003:0crwdne101003:0 + setting_bcc_recipients: crwdns101004:0crwdne101004:0 + setting_brute_force_block_after_failed_logins: crwdns101005:0crwdne101005:0 + setting_brute_force_block_minutes: crwdns101006:0crwdne101006:0 + setting_cache_formatted_text: crwdns101007:0crwdne101007:0 + setting_use_wysiwyg_description: crwdns101008:0crwdne101008:0 + setting_column_options: crwdns101009:0crwdne101009:0 + setting_commit_fix_keywords: crwdns101010:0crwdne101010:0 + setting_commit_logs_encoding: crwdns101011:0crwdne101011:0 + setting_commit_logtime_activity_id: crwdns101012:0crwdne101012:0 + setting_commit_logtime_enabled: crwdns101013:0crwdne101013:0 + setting_commit_ref_keywords: crwdns101014:0crwdne101014:0 + setting_consent_time: crwdns101015:0crwdne101015:0 + setting_consent_info: crwdns101016:0crwdne101016:0 + setting_consent_required: crwdns101017:0crwdne101017:0 + setting_consent_decline_mail: crwdns101018:0crwdne101018:0 + setting_cross_project_work_package_relations: crwdns101019:0crwdne101019:0 + setting_date_format: crwdns101020:0crwdne101020:0 + setting_default_language: crwdns101021:0crwdne101021:0 + setting_default_notification_option: crwdns101022:0crwdne101022:0 + setting_default_projects_modules: crwdns101023:0crwdne101023:0 + setting_default_projects_public: crwdns101024:0crwdne101024:0 + setting_diff_max_lines_displayed: crwdns101025:0crwdne101025:0 + setting_display_subprojects_work_packages: crwdns101026:0crwdne101026:0 + setting_emails_footer: crwdns101027:0crwdne101027:0 + setting_emails_header: crwdns101028:0crwdne101028:0 + setting_email_login: crwdns101029:0crwdne101029:0 + setting_enabled_scm: crwdns101030:0crwdne101030:0 + setting_feeds_enabled: crwdns101031:0crwdne101031:0 + setting_feeds_limit: crwdns101032:0crwdne101032:0 + setting_file_max_size_displayed: crwdns101033:0crwdne101033:0 + setting_host_name: crwdns101034:0crwdne101034:0 + setting_invitation_expiration_days: crwdns101035:0crwdne101035:0 + setting_work_package_done_ratio: crwdns101036:0crwdne101036:0 + setting_work_package_done_ratio_field: crwdns101037:0crwdne101037:0 + setting_work_package_done_ratio_status: crwdns101038:0crwdne101038:0 + setting_work_package_done_ratio_disabled: crwdns101039:0crwdne101039:0 + setting_work_package_list_default_columns: crwdns101040:0crwdne101040:0 + setting_work_package_list_summable_columns: crwdns101041:0crwdne101041:0 + setting_work_package_properties: crwdns101042:0crwdne101042:0 + setting_work_package_startdate_is_adddate: crwdns101043:0crwdne101043:0 + setting_work_packages_export_limit: crwdns101044:0crwdne101044:0 + setting_journal_aggregation_time_minutes: crwdns101045:0crwdne101045:0 + setting_log_requesting_user: crwdns101046:0crwdne101046:0 + setting_login_required: crwdns101047:0crwdne101047:0 + setting_mail_from: crwdns101048:0crwdne101048:0 + setting_mail_handler_api_enabled: crwdns101049:0crwdne101049:0 + setting_mail_handler_api_description: crwdns101050:0crwdne101050:0 + setting_mail_handler_api_key: crwdns101051:0crwdne101051:0 + setting_mail_handler_body_delimiters: crwdns101052:0crwdne101052:0 + setting_mail_handler_body_delimiter_regex: crwdns101053:0crwdne101053:0 + setting_new_project_user_role_id: crwdns101054:0crwdne101054:0 + setting_password_active_rules: crwdns101055:0crwdne101055:0 + setting_password_count_former_banned: crwdns101056:0crwdne101056:0 + setting_password_days_valid: crwdns101057:0crwdne101057:0 + setting_password_min_length: crwdns101058:0crwdne101058:0 + setting_password_min_adhered_rules: crwdns101059:0crwdne101059:0 + setting_per_page_options: crwdns101060:0crwdne101060:0 + setting_plain_text_mail: crwdns101061:0crwdne101061:0 + setting_protocol: crwdns101062:0crwdne101062:0 + setting_registration_footer: crwdns101063:0crwdne101063:0 + setting_repositories_automatic_managed_vendor: crwdns101064:0crwdne101064:0 + setting_repositories_encodings: crwdns101065:0crwdne101065:0 + setting_repository_authentication_caching_enabled: crwdns101066:0crwdne101066:0 + setting_repository_storage_cache_minutes: crwdns101067:0crwdne101067:0 + setting_repository_checkout_display: crwdns101068:0crwdne101068:0 + setting_repository_checkout_base_url: crwdns101069:0crwdne101069:0 + setting_repository_checkout_text: crwdns101070:0crwdne101070:0 + setting_repository_log_display_limit: crwdns101071:0crwdne101071:0 + setting_repository_truncate_at: crwdns101072:0crwdne101072:0 + setting_rest_api_enabled: crwdns101073:0crwdne101073:0 + setting_self_registration: crwdns101074:0crwdne101074:0 + setting_sequential_project_identifiers: crwdns101075:0crwdne101075:0 + setting_session_ttl: crwdns101076:0crwdne101076:0 + setting_session_ttl_hint: crwdns101077:0crwdne101077:0 + setting_session_ttl_enabled: crwdns101078:0crwdne101078:0 + setting_start_of_week: crwdns101079:0crwdne101079:0 + setting_sys_api_enabled: crwdns101080:0crwdne101080:0 + setting_sys_api_description: crwdns101081:0crwdne101081:0 + setting_time_format: crwdns101082:0crwdne101082:0 + setting_accessibility_mode_for_anonymous: crwdns101083:0crwdne101083:0 + setting_user_format: crwdns101084:0crwdne101084:0 + setting_user_default_timezone: crwdns101085:0crwdne101085:0 + setting_users_deletable_by_admins: crwdns101086:0crwdne101086:0 + setting_users_deletable_by_self: crwdns101087:0crwdne101087:0 + setting_welcome_text: crwdns101088:0crwdne101088:0 + setting_welcome_title: crwdns101089:0crwdne101089:0 + setting_welcome_on_homescreen: crwdns101090:0crwdne101090:0 + setting_wiki_compression: crwdns101091:0crwdne101091:0 + setting_work_package_group_assignment: crwdns101092:0crwdne101092:0 + setting_work_package_list_default_highlighting_mode: crwdns102542:0crwdne102542:0 + setting_work_package_list_default_highlighted_attributes: crwdns102544:0crwdne102544:0 settings: - general: crwdns97991:0crwdne97991:0 - other: crwdns97992:0crwdne97992:0 - passwords: crwdns97993:0crwdne97993:0 - session: crwdns97994:0crwdne97994:0 - brute_force_prevention: crwdns97995:0crwdne97995:0 + general: crwdns101094:0crwdne101094:0 + other: crwdns101095:0crwdne101095:0 + passwords: crwdns101096:0crwdne101096:0 + session: crwdns101097:0crwdne101097:0 + brute_force_prevention: crwdns101098:0crwdne101098:0 user: - default_preferences: crwdns98999:0crwdne98999:0 - deletion: crwdns99000:0crwdne99000:0 + default_preferences: crwdns101099:0crwdne101099:0 + deletion: crwdns101100:0crwdne101100:0 + highlighting: + mode_long: + inline: crwdns102546:0crwdne102546:0 + none: crwdns102548:0crwdne102548:0 + status: crwdns102550:0crwdne102550:0 + type: crwdns102552:0crwdne102552:0 + priority: crwdns102554:0crwdne102554:0 text_formatting: - markdown: crwdns98898:0crwdne98898:0 - plain: crwdns98899:0crwdne98899:0 - status_active: crwdns97997:0crwdne97997:0 - status_archived: crwdns97998:0crwdne97998:0 - status_invited: crwdns97999:0crwdne97999:0 - status_locked: crwdns98000:0crwdne98000:0 - status_registered: crwdns98001:0crwdne98001:0 + markdown: crwdns101101:0crwdne101101:0 + plain: crwdns101102:0crwdne101102:0 + status_active: crwdns101103:0crwdne101103:0 + status_archived: crwdns101104:0crwdne101104:0 + status_invited: crwdns101105:0crwdne101105:0 + status_locked: crwdns101106:0crwdne101106:0 + status_registered: crwdns101107:0crwdne101107:0 support: array: - sentence_connector: crwdns98002:0crwdne98002:0 - skip_last_comma: crwdns98003:0crwdne98003:0 - text_accessibility_hint: crwdns98004:0crwdne98004:0 - text_access_token_hint: crwdns98005:0crwdne98005:0 - text_analyze: crwdns98006:0%{subject}crwdne98006:0 - text_are_you_sure: crwdns98007:0crwdne98007:0 - text_are_you_sure_with_children: crwdns98008:0crwdne98008:0 - text_assign_to_project: crwdns98009:0crwdne98009:0 - text_form_configuration: 'crwdns98010:0crwdne98010:0 + sentence_connector: crwdns101108:0crwdne101108:0 + skip_last_comma: crwdns101109:0crwdne101109:0 + text_accessibility_hint: crwdns101110:0crwdne101110:0 + text_access_token_hint: crwdns101111:0crwdne101111:0 + text_analyze: crwdns101112:0%{subject}crwdne101112:0 + text_are_you_sure: crwdns101113:0crwdne101113:0 + text_are_you_sure_with_children: crwdns101114:0crwdne101114:0 + text_assign_to_project: crwdns101115:0crwdne101115:0 + text_form_configuration: 'crwdns101116:0crwdne101116:0 ' - text_form_configuration_drag_to_activate: crwdns98011:0crwdne98011:0 - text_form_configuration_required_attribute: crwdns98012:0crwdne98012:0 - text_caracters_maximum: crwdns98013:0%{count}crwdne98013:0 - text_caracters_minimum: crwdns98014:0%{count}crwdne98014:0 - text_comma_separated: crwdns98015:0crwdne98015:0 - text_comment_wiki_page: crwdns98016:0%{page}crwdne98016:0 - text_custom_field_possible_values_info: crwdns98017:0crwdne98017:0 - text_custom_field_hint_activate_per_project: 'crwdns98018:0crwdne98018:0 + text_form_configuration_drag_to_activate: crwdns101117:0crwdne101117:0 + text_form_configuration_required_attribute: crwdns101118:0crwdne101118:0 + text_caracters_maximum: crwdns101119:0%{count}crwdne101119:0 + text_caracters_minimum: crwdns101120:0%{count}crwdne101120:0 + text_comma_separated: crwdns101121:0crwdne101121:0 + text_comment_wiki_page: crwdns101122:0%{page}crwdne101122:0 + text_custom_field_possible_values_info: crwdns101123:0crwdne101123:0 + text_custom_field_hint_activate_per_project: 'crwdns101124:0crwdne101124:0 ' - text_custom_field_hint_activate_per_project_and_type: 'crwdns98019:0crwdne98019:0 + text_custom_field_hint_activate_per_project_and_type: 'crwdns101125:0crwdne101125:0 ' - text_custom_logo_instructions: 'crwdns98020:0crwdne98020:0 + text_custom_logo_instructions: 'crwdns101126:0crwdne101126:0 ' - text_custom_favicon_instructions: 'crwdns98021:0crwdne98021:0 + text_custom_favicon_instructions: 'crwdns101127:0crwdne101127:0 ' - text_custom_touch_icon_instructions: 'crwdns98022:0crwdne98022:0 + text_custom_touch_icon_instructions: 'crwdns101128:0crwdne101128:0 ' - text_database_allows_tsv: crwdns98866:0crwdne98866:0 - text_default_administrator_account_changed: crwdns98023:0crwdne98023:0 - text_default_encoding: crwdns98024:0crwdne98024:0 - text_destroy: crwdns98025:0crwdne98025:0 - text_destroy_with_associated: crwdns98026:0crwdne98026:0 - text_destroy_what_to_do: crwdns98027:0crwdne98027:0 - text_diff_truncated: crwdns98028:0crwdne98028:0 - text_email_delivery_not_configured: crwdns98029:0crwdne98029:0 - text_enumeration_category_reassign_to: crwdns98030:0crwdne98030:0 - text_enumeration_destroy_question: crwdns98031:0%{count}crwdne98031:0 - text_file_repository_writable: crwdns98032:0crwdne98032:0 - text_git_repo_example: crwdns98033:0crwdne98033:0 - text_hint_date_format: crwdns98034:0crwdne98034:0 - text_hint_disable_with_0: crwdns98035:0crwdne98035:0 - text_hours_between: crwdns98036:0%{min}crwdnd98036:0%{max}crwdne98036:0 - text_work_package_added: crwdns98037:0%{id}crwdnd98037:0%{author}crwdne98037:0 - text_work_package_category_destroy_assignments: crwdns98038:0crwdne98038:0 - text_work_package_category_destroy_question: crwdns98039:0%{count}crwdne98039:0 - text_work_package_category_reassign_to: crwdns98040:0crwdne98040:0 - text_work_package_updated: crwdns98041:0%{id}crwdnd98041:0%{author}crwdne98041:0 - text_work_package_watcher_added: crwdns98042:0%{id}crwdnd98042:0%{watcher_setter}crwdne98042:0 - text_work_packages_destroy_confirmation: crwdns98043:0crwdne98043:0 - text_work_packages_ref_in_commit_messages: crwdns98044:0crwdne98044:0 - text_journal_added: crwdns98045:0%{label}crwdnd98045:0%{value}crwdne98045:0 - text_journal_aggregation_time_explanation: crwdns98046:0crwdne98046:0 - text_journal_changed: crwdns99114:0%{label}crwdnd99114:0%{old}crwdnd99114:0%{new}crwdne99114:0 - text_journal_changed_plain: crwdns99115:0%{label}crwdnd99115:0%{old}crwdnd99115:0%{new}crwdne99115:0 - text_journal_changed_no_detail: crwdns98048:0%{label}crwdne98048:0 - text_journal_changed_with_diff: crwdns98049:0%{label}crwdnd98049:0%{link}crwdne98049:0 - text_journal_deleted: crwdns98050:0%{label}crwdnd98050:0%{old}crwdne98050:0 - text_journal_deleted_with_diff: crwdns98051:0%{label}crwdnd98051:0%{link}crwdne98051:0 - text_journal_set_to: crwdns98052:0%{label}crwdnd98052:0%{value}crwdne98052:0 - text_journal_set_with_diff: crwdns98053:0%{label}crwdnd98053:0%{link}crwdne98053:0 - text_latest_note: crwdns98054:0%{note}crwdne98054:0 - text_length_between: crwdns98055:0%{min}crwdnd98055:0%{max}crwdne98055:0 - text_line_separated: crwdns98056:0crwdne98056:0 - text_load_default_configuration: crwdns98057:0crwdne98057:0 - text_min_max_length_info: crwdns98058:0crwdne98058:0 - text_no_roles_defined: crwdns98059:0crwdne98059:0 - text_no_access_tokens_configurable: crwdns98060:0crwdne98060:0 - text_no_configuration_data: crwdns98061:0crwdne98061:0 - text_no_notes: crwdns98062:0crwdne98062:0 - text_notice_too_many_values_are_inperformant: crwdns98063:0crwdne98063:0 - text_own_membership_delete_confirmation: crwdns98064:0crwdne98064:0 - text_plugin_assets_writable: crwdns98065:0crwdne98065:0 - text_powered_by: crwdns98066:0%{link}crwdne98066:0 - text_project_identifier_info: crwdns98067:0crwdne98067:0 - text_reassign: crwdns98068:0crwdne98068:0 - text_regexp_info: crwdns98069:0[A-Z0-9]crwdne98069:0 - text_regexp_multiline: crwdns98070:0crwdne98070:0 - text_repository_usernames_mapping: crwdns98071:0crwdne98071:0 - text_select_mail_notifications: crwdns98072:0crwdne98072:0 - text_status_changed_by_changeset: crwdns98073:0%{value}crwdne98073:0 - text_table_difference_description: crwdns98074:0%{entries}crwdne98074:0 - text_time_logged_by_changeset: crwdns98075:0%{value}crwdne98075:0 - text_tip_work_package_begin_day: crwdns98076:0crwdne98076:0 - text_tip_work_package_begin_end_day: crwdns98077:0crwdne98077:0 - text_tip_work_package_end_day: crwdns98078:0crwdne98078:0 - text_type_no_workflow: crwdns98079:0crwdne98079:0 - text_unallowed_characters: crwdns98080:0crwdne98080:0 - text_user_invited: crwdns98081:0crwdne98081:0 - text_user_wrote: crwdns98082:0%{value}crwdne98082:0 - text_warn_on_leaving_unsaved: crwdns98083:0crwdne98083:0 - text_what_did_you_change_click_to_add_comment: crwdns99080:0crwdne99080:0 - text_wiki_destroy_confirmation: crwdns98084:0crwdne98084:0 - text_wiki_page_destroy_children: crwdns98085:0crwdne98085:0 - text_wiki_page_destroy_question: crwdns98086:0%{descendants}crwdne98086:0 - text_wiki_page_nullify_children: crwdns98087:0crwdne98087:0 - text_wiki_page_reassign_children: crwdns98088:0crwdne98088:0 - text_workflow_edit: crwdns98089:0crwdne98089:0 - text_zoom_in: crwdns98090:0crwdne98090:0 - text_zoom_out: crwdns98091:0crwdne98091:0 - text_setup_mail_configuration: crwdns98092:0crwdne98092:0 + text_database_allows_tsv: crwdns101129:0crwdne101129:0 + text_default_administrator_account_changed: crwdns101130:0crwdne101130:0 + text_default_encoding: crwdns101131:0crwdne101131:0 + text_destroy: crwdns101132:0crwdne101132:0 + text_destroy_with_associated: crwdns101133:0crwdne101133:0 + text_destroy_what_to_do: crwdns101134:0crwdne101134:0 + text_diff_truncated: crwdns101135:0crwdne101135:0 + text_email_delivery_not_configured: crwdns101136:0crwdne101136:0 + text_enumeration_category_reassign_to: crwdns101137:0crwdne101137:0 + text_enumeration_destroy_question: crwdns101138:0%{count}crwdne101138:0 + text_file_repository_writable: crwdns101139:0crwdne101139:0 + text_git_repo_example: crwdns101140:0crwdne101140:0 + text_hint_date_format: crwdns101141:0crwdne101141:0 + text_hint_disable_with_0: crwdns101142:0crwdne101142:0 + text_hours_between: crwdns101143:0%{min}crwdnd101143:0%{max}crwdne101143:0 + text_work_package_added: crwdns101144:0%{id}crwdnd101144:0%{author}crwdne101144:0 + text_work_package_category_destroy_assignments: crwdns101145:0crwdne101145:0 + text_work_package_category_destroy_question: crwdns101146:0%{count}crwdne101146:0 + text_work_package_category_reassign_to: crwdns101147:0crwdne101147:0 + text_work_package_updated: crwdns101148:0%{id}crwdnd101148:0%{author}crwdne101148:0 + text_work_package_watcher_added: crwdns101149:0%{id}crwdnd101149:0%{watcher_setter}crwdne101149:0 + text_work_packages_destroy_confirmation: crwdns101150:0crwdne101150:0 + text_work_packages_ref_in_commit_messages: crwdns101151:0crwdne101151:0 + text_journal_added: crwdns101152:0%{label}crwdnd101152:0%{value}crwdne101152:0 + text_journal_aggregation_time_explanation: crwdns101153:0crwdne101153:0 + text_journal_changed: crwdns101154:0%{label}crwdnd101154:0%{old}crwdnd101154:0%{new}crwdne101154:0 + text_journal_changed_plain: crwdns101155:0%{label}crwdnd101155:0%{old}crwdnd101155:0%{new}crwdne101155:0 + text_journal_changed_no_detail: crwdns101156:0%{label}crwdne101156:0 + text_journal_changed_with_diff: crwdns101157:0%{label}crwdnd101157:0%{link}crwdne101157:0 + text_journal_deleted: crwdns101158:0%{label}crwdnd101158:0%{old}crwdne101158:0 + text_journal_deleted_with_diff: crwdns101159:0%{label}crwdnd101159:0%{link}crwdne101159:0 + text_journal_set_to: crwdns101160:0%{label}crwdnd101160:0%{value}crwdne101160:0 + text_journal_set_with_diff: crwdns101161:0%{label}crwdnd101161:0%{link}crwdne101161:0 + text_latest_note: crwdns101162:0%{note}crwdne101162:0 + text_length_between: crwdns101163:0%{min}crwdnd101163:0%{max}crwdne101163:0 + text_line_separated: crwdns101164:0crwdne101164:0 + text_load_default_configuration: crwdns101165:0crwdne101165:0 + text_min_max_length_info: crwdns101166:0crwdne101166:0 + text_no_roles_defined: crwdns101167:0crwdne101167:0 + text_no_access_tokens_configurable: crwdns101168:0crwdne101168:0 + text_no_configuration_data: crwdns101169:0crwdne101169:0 + text_no_notes: crwdns101170:0crwdne101170:0 + text_notice_too_many_values_are_inperformant: crwdns101171:0crwdne101171:0 + text_own_membership_delete_confirmation: crwdns101172:0crwdne101172:0 + text_plugin_assets_writable: crwdns101173:0crwdne101173:0 + text_powered_by: crwdns101174:0%{link}crwdne101174:0 + text_project_identifier_info: crwdns101175:0crwdne101175:0 + text_reassign: crwdns101176:0crwdne101176:0 + text_regexp_info: crwdns101177:0[A-Z0-9]crwdne101177:0 + text_regexp_multiline: crwdns101178:0crwdne101178:0 + text_repository_usernames_mapping: crwdns101179:0crwdne101179:0 + text_select_mail_notifications: crwdns101180:0crwdne101180:0 + text_status_changed_by_changeset: crwdns101181:0%{value}crwdne101181:0 + text_table_difference_description: crwdns101182:0%{entries}crwdne101182:0 + text_time_logged_by_changeset: crwdns101183:0%{value}crwdne101183:0 + text_tip_work_package_begin_day: crwdns101184:0crwdne101184:0 + text_tip_work_package_begin_end_day: crwdns101185:0crwdne101185:0 + text_tip_work_package_end_day: crwdns101186:0crwdne101186:0 + text_type_no_workflow: crwdns101187:0crwdne101187:0 + text_unallowed_characters: crwdns101188:0crwdne101188:0 + text_user_invited: crwdns101189:0crwdne101189:0 + text_user_wrote: crwdns101190:0%{value}crwdne101190:0 + text_warn_on_leaving_unsaved: crwdns101191:0crwdne101191:0 + text_what_did_you_change_click_to_add_comment: crwdns101192:0crwdne101192:0 + text_wiki_destroy_confirmation: crwdns101193:0crwdne101193:0 + text_wiki_page_destroy_children: crwdns101194:0crwdne101194:0 + text_wiki_page_destroy_question: crwdns101195:0%{descendants}crwdne101195:0 + text_wiki_page_nullify_children: crwdns101196:0crwdne101196:0 + text_wiki_page_reassign_children: crwdns101197:0crwdne101197:0 + text_workflow_edit: crwdns101198:0crwdne101198:0 + text_zoom_in: crwdns101199:0crwdne101199:0 + text_zoom_out: crwdns101200:0crwdne101200:0 + text_setup_mail_configuration: crwdns101201:0crwdne101201:0 time: - am: crwdns98093:0crwdne98093:0 + am: crwdns101202:0crwdne101202:0 formats: - default: crwdns98094:0%mcrwdnd98094:0%dcrwdnd98094:0%Y %Icrwdnd98094:0%Mcrwdnd98094:0%pcrwdne98094:0 - long: crwdns98095:0%Bcrwdnd98095:0%dcrwdnd98095:0%Ycrwdnd98095:0%H:%Mcrwdne98095:0 - short: crwdns98096:0%dcrwdnd98096:0%bcrwdnd98096:0%H:%Mcrwdne98096:0 - time: crwdns98097:0%I:%Mcrwdnd98097:0%pcrwdne98097:0 - pm: crwdns98098:0crwdne98098:0 + default: crwdns101203:0%mcrwdnd101203:0%dcrwdnd101203:0%Y %Icrwdnd101203:0%Mcrwdnd101203:0%pcrwdne101203:0 + long: crwdns101204:0%Bcrwdnd101204:0%dcrwdnd101204:0%Ycrwdnd101204:0%H:%Mcrwdne101204:0 + short: crwdns101205:0%dcrwdnd101205:0%bcrwdnd101205:0%H:%Mcrwdne101205:0 + time: crwdns101206:0%I:%Mcrwdnd101206:0%pcrwdne101206:0 + pm: crwdns101207:0crwdne101207:0 timeframe: - show: crwdns98099:0crwdne98099:0 - end: crwdns98100:0crwdne98100:0 - start: crwdns98101:0crwdne98101:0 + show: crwdns101208:0crwdne101208:0 + end: crwdns101209:0crwdne101209:0 + start: crwdns101210:0crwdne101210:0 timelines: admin_menu: - color: crwdns98102:0crwdne98102:0 - colors: crwdns98103:0crwdne98103:0 - associations: crwdns98109:0crwdne98109:0 - board_could_not_be_saved: crwdns98110:0crwdne98110:0 - button_delete_all: crwdns98111:0crwdne98111:0 - change: crwdns98112:0crwdne98112:0 - children: crwdns98113:0crwdne98113:0 - color_could_not_be_saved: crwdns98114:0crwdne98114:0 - current_planning: crwdns98115:0crwdne98115:0 - dates: crwdns98116:0crwdne98116:0 - dates_are_calculated_based_on_sub_elements: crwdns98117:0crwdne98117:0 - delete_all: crwdns98118:0crwdne98118:0 - delete_thing: crwdns98119:0crwdne98119:0 - duration: crwdns98120:0crwdne98120:0 + color: crwdns101211:0crwdne101211:0 + colors: crwdns101212:0crwdne101212:0 + associations: crwdns101213:0crwdne101213:0 + board_could_not_be_saved: crwdns101214:0crwdne101214:0 + button_delete_all: crwdns101215:0crwdne101215:0 + change: crwdns101216:0crwdne101216:0 + children: crwdns101217:0crwdne101217:0 + color_could_not_be_saved: crwdns101218:0crwdne101218:0 + current_planning: crwdns101219:0crwdne101219:0 + dates: crwdns101220:0crwdne101220:0 + dates_are_calculated_based_on_sub_elements: crwdns101221:0crwdne101221:0 + delete_all: crwdns101222:0crwdne101222:0 + delete_thing: crwdns101223:0crwdne101223:0 + duration: crwdns101224:0crwdne101224:0 duration_days: - one: crwdns98121:1crwdne98121:1 - other: crwdns98121:5%{count}crwdne98121:5 - edit_color: crwdns98122:0crwdne98122:0 - edit_thing: crwdns98124:0crwdne98124:0 - edit_timeline: crwdns98125:0%{timeline}crwdne98125:0 - delete_timeline: crwdns98126:0%{timeline}crwdne98126:0 - empty: crwdns98127:0crwdne98127:0 - enable_type_in_project: crwdns98128:0%{type}crwdne98128:0 - end: crwdns98129:0crwdne98129:0 + one: crwdns101225:1crwdne101225:1 + other: crwdns101225:5%{count}crwdne101225:5 + edit_color: crwdns101226:0crwdne101226:0 + edit_thing: crwdns101227:0crwdne101227:0 + edit_timeline: crwdns101228:0%{timeline}crwdne101228:0 + delete_timeline: crwdns101229:0%{timeline}crwdne101229:0 + empty: crwdns101230:0crwdne101230:0 + enable_type_in_project: crwdns101231:0%{type}crwdne101231:0 + end: crwdns101232:0crwdne101232:0 errors: - not_implemented: crwdns98130:0crwdne98130:0 - report_comparison: crwdns98131:0crwdne98131:0 - report_epicfail: crwdns98132:0crwdne98132:0 - report_timeout: crwdns98133:0crwdne98133:0 + not_implemented: crwdns101233:0crwdne101233:0 + report_comparison: crwdns101234:0crwdne101234:0 + report_epicfail: crwdns101235:0crwdne101235:0 + report_timeout: crwdns101236:0crwdne101236:0 filter: errors: - timeframe_start: crwdns98134:0crwdne98134:0 - timeframe_end: crwdns98135:0crwdne98135:0 - compare_to_relative: crwdns98136:0crwdne98136:0 - compare_to_absolute: crwdns98137:0crwdne98137:0 - planning_element_time_relative_one: crwdns98138:0crwdne98138:0 - planning_element_time_relative_two: crwdns98139:0crwdne98139:0 - planning_element_time_absolute_one: crwdns98140:0crwdne98140:0 - planning_element_time_absolute_two: crwdns98141:0crwdne98141:0 + timeframe_start: crwdns101237:0crwdne101237:0 + timeframe_end: crwdns101238:0crwdne101238:0 + compare_to_relative: crwdns101239:0crwdne101239:0 + compare_to_absolute: crwdns101240:0crwdne101240:0 + planning_element_time_relative_one: crwdns101241:0crwdne101241:0 + planning_element_time_relative_two: crwdns101242:0crwdne101242:0 + planning_element_time_absolute_one: crwdns101243:0crwdne101243:0 + planning_element_time_absolute_two: crwdns101244:0crwdne101244:0 sort: - sortation: crwdns98142:0crwdne98142:0 - alphabet: crwdns98143:0crwdne98143:0 - explicit_order: crwdns98144:0crwdne98144:0 - project_sortation: crwdns98145:0crwdne98145:0 - date: crwdns98146:0crwdne98146:0 - default: crwdns98147:0crwdne98147:0 + sortation: crwdns101245:0crwdne101245:0 + alphabet: crwdns101246:0crwdne101246:0 + explicit_order: crwdns101247:0crwdne101247:0 + project_sortation: crwdns101248:0crwdne101248:0 + date: crwdns101249:0crwdne101249:0 + default: crwdns101250:0crwdne101250:0 column: - assigned_to: crwdns98148:0crwdne98148:0 - type: crwdns98149:0crwdne98149:0 - due_date: crwdns98150:0crwdne98150:0 - name: crwdns98151:0crwdne98151:0 - status: crwdns98152:0crwdne98152:0 - start_date: crwdns98154:0crwdne98154:0 - columns: crwdns98155:0crwdne98155:0 - comparisons: crwdns98156:0crwdne98156:0 + assigned_to: crwdns101251:0crwdne101251:0 + type: crwdns101252:0crwdne101252:0 + due_date: crwdns101253:0crwdne101253:0 + name: crwdns101254:0crwdne101254:0 + status: crwdns101255:0crwdne101255:0 + start_date: crwdns101256:0crwdne101256:0 + columns: crwdns101257:0crwdne101257:0 + comparisons: crwdns101258:0crwdne101258:0 comparison: - absolute: crwdns98157:0crwdne98157:0 - none: crwdns98158:0crwdne98158:0 - relative: crwdns98159:0crwdne98159:0 - compare_relative_prefix: crwdns98160:0crwdne98160:0 - compare_relative_suffix: crwdns98161:0crwdne98161:0 - compare_absolute: crwdns98162:0%{date}crwdne98162:0 + absolute: crwdns101259:0crwdne101259:0 + none: crwdns101260:0crwdne101260:0 + relative: crwdns101261:0crwdne101261:0 + compare_relative_prefix: crwdns101262:0crwdne101262:0 + compare_relative_suffix: crwdns101263:0crwdne101263:0 + compare_absolute: crwdns101264:0%{date}crwdne101264:0 time_relative: - days: crwdns98163:0crwdne98163:0 - weeks: crwdns98164:0crwdne98164:0 - months: crwdns98165:0crwdne98165:0 - exclude_own_work_packages: crwdns98166:0crwdne98166:0 - exclude_reporters: crwdns98167:0crwdne98167:0 - exclude_empty: crwdns98168:0crwdne98168:0 - grouping: crwdns98169:0crwdne98169:0 - grouping_hide_group: crwdns98170:0%{group}crwdne98170:0 - grouping_one: crwdns98171:0crwdne98171:0 - grouping_one_phrase: crwdns98172:0crwdne98172:0 - grouping_other: crwdns98173:0crwdne98173:0 - hide_chart: crwdns98174:0crwdne98174:0 - noneElement: crwdns98175:0crwdne98175:0 - noneSelection: crwdns98176:0crwdne98176:0 - outline: crwdns98177:0crwdne98177:0 - parent: crwdns98178:0crwdne98178:0 - work_package_filters: crwdns98179:0crwdne98179:0 - work_package_responsible: crwdns99077:0crwdne99077:0 - work_package_assignee: crwdns98181:0crwdne98181:0 - types: crwdns98182:0crwdne98182:0 - status: crwdns98183:0crwdne98183:0 - project_time_filter: crwdns98184:0crwdne98184:0 - project_time_filter_timeframe: crwdns98185:0crwdne98185:0 - project_time_filter_historical_from: crwdns98186:0crwdne98186:0 - project_time_filter_historical_to: crwdns98187:0crwdne98187:0 - project_time_filter_historical: crwdns98188:0%{start_label}crwdnd98188:0%{startdate}crwdnd98188:0%{end_label}crwdnd98188:0%{enddate}crwdne98188:0 - project_time_filter_relative: crwdns98189:0%{start_label}crwdnd98189:0%{startspan}crwdnd98189:0%{startspanunit}crwdnd98189:0%{end_label}crwdnd98189:0%{endspan}crwdnd98189:0%{endspanunit}crwdne98189:0 - project_filters: crwdns98190:0crwdne98190:0 - project_responsible: crwdns99078:0crwdne99078:0 - project_status: crwdns98192:0crwdne98192:0 - timeframe: crwdns98194:0crwdne98194:0 - timeframe_end: crwdns98195:0crwdne98195:0 - timeframe_start: crwdns98196:0crwdne98196:0 - timeline: crwdns98197:0crwdne98197:0 - zoom: crwdns98198:0crwdne98198:0 - history: crwdns98199:0crwdne98199:0 - new_color: crwdns98200:0crwdne98200:0 - new_association: crwdns98201:0crwdne98201:0 - new_work_package: crwdns98202:0crwdne98202:0 - new_reporting: crwdns98204:0crwdne98204:0 - new_timeline: crwdns98205:0crwdne98205:0 - no_projects_for_reporting_available: crwdns98206:0crwdne98206:0 - no_right_to_view_timeline: crwdns98207:0crwdne98207:0 - no_timeline_for_id: crwdns98208:0%{id}crwdne98208:0 - notice_successful_deleted_all_elements: crwdns98209:0crwdne98209:0 - outline: crwdns98210:0crwdne98210:0 + days: crwdns101265:0crwdne101265:0 + weeks: crwdns101266:0crwdne101266:0 + months: crwdns101267:0crwdne101267:0 + exclude_own_work_packages: crwdns101268:0crwdne101268:0 + exclude_reporters: crwdns101269:0crwdne101269:0 + exclude_empty: crwdns101270:0crwdne101270:0 + grouping: crwdns101271:0crwdne101271:0 + grouping_hide_group: crwdns101272:0%{group}crwdne101272:0 + grouping_one: crwdns101273:0crwdne101273:0 + grouping_one_phrase: crwdns101274:0crwdne101274:0 + grouping_other: crwdns101275:0crwdne101275:0 + hide_chart: crwdns101276:0crwdne101276:0 + noneElement: crwdns101277:0crwdne101277:0 + noneSelection: crwdns101278:0crwdne101278:0 + outline: crwdns101279:0crwdne101279:0 + parent: crwdns101280:0crwdne101280:0 + work_package_filters: crwdns101281:0crwdne101281:0 + work_package_responsible: crwdns101282:0crwdne101282:0 + work_package_assignee: crwdns101283:0crwdne101283:0 + types: crwdns101284:0crwdne101284:0 + status: crwdns101285:0crwdne101285:0 + project_time_filter: crwdns101286:0crwdne101286:0 + project_time_filter_timeframe: crwdns101287:0crwdne101287:0 + project_time_filter_historical_from: crwdns101288:0crwdne101288:0 + project_time_filter_historical_to: crwdns101289:0crwdne101289:0 + project_time_filter_historical: crwdns101290:0%{start_label}crwdnd101290:0%{startdate}crwdnd101290:0%{end_label}crwdnd101290:0%{enddate}crwdne101290:0 + project_time_filter_relative: crwdns101291:0%{start_label}crwdnd101291:0%{startspan}crwdnd101291:0%{startspanunit}crwdnd101291:0%{end_label}crwdnd101291:0%{endspan}crwdnd101291:0%{endspanunit}crwdne101291:0 + project_filters: crwdns101292:0crwdne101292:0 + project_responsible: crwdns101293:0crwdne101293:0 + project_status: crwdns101294:0crwdne101294:0 + timeframe: crwdns101295:0crwdne101295:0 + timeframe_end: crwdns101296:0crwdne101296:0 + timeframe_start: crwdns101297:0crwdne101297:0 + timeline: crwdns101298:0crwdne101298:0 + zoom: crwdns101299:0crwdne101299:0 + history: crwdns101300:0crwdne101300:0 + new_color: crwdns101301:0crwdne101301:0 + new_association: crwdns101302:0crwdne101302:0 + new_work_package: crwdns101303:0crwdne101303:0 + new_reporting: crwdns101304:0crwdne101304:0 + new_timeline: crwdns101305:0crwdne101305:0 + no_projects_for_reporting_available: crwdns101306:0crwdne101306:0 + no_right_to_view_timeline: crwdns101307:0crwdne101307:0 + no_timeline_for_id: crwdns101308:0%{id}crwdne101308:0 + notice_successful_deleted_all_elements: crwdns101309:0crwdne101309:0 + outline: crwdns101310:0crwdne101310:0 outlines: - aggregation: crwdns98211:0crwdne98211:0 - level1: crwdns98212:0crwdne98212:0 - level2: crwdns98213:0crwdne98213:0 - level3: crwdns98214:0crwdne98214:0 - level4: crwdns98215:0crwdne98215:0 - level5: crwdns98216:0crwdne98216:0 - all: crwdns98217:0crwdne98217:0 + aggregation: crwdns101311:0crwdne101311:0 + level1: crwdns101312:0crwdne101312:0 + level2: crwdns101313:0crwdne101313:0 + level3: crwdns101314:0crwdne101314:0 + level4: crwdns101315:0crwdne101315:0 + level5: crwdns101316:0crwdne101316:0 + all: crwdns101317:0crwdne101317:0 reporting_for_project: - show: crwdns98218:0%{title}crwdne98218:0 - edit_delete: crwdns98219:0%{title}crwdne98219:0 - history: crwdns98220:0%{title}crwdne98220:0 + show: crwdns101318:0%{title}crwdne101318:0 + edit_delete: crwdns101319:0%{title}crwdne101319:0 + history: crwdns101320:0%{title}crwdne101320:0 reporting: - delete: crwdns98221:0%{comment}crwdne98221:0 - edit: crwdns98222:0%{comment}crwdne98222:0 - show: crwdns98223:0%{comment}crwdne98223:0 - planning_element_update: crwdns98224:0%{title}crwdne98224:0 - type_could_not_be_saved: crwdns98227:0crwdne98227:0 - reporting_could_not_be_saved: crwdns98228:0crwdne98228:0 - properties: crwdns98229:0crwdne98229:0 - really_delete_color: 'crwdns98230:0crwdne98230:0 + delete: crwdns101321:0%{comment}crwdne101321:0 + edit: crwdns101322:0%{comment}crwdne101322:0 + show: crwdns101323:0%{comment}crwdne101323:0 + planning_element_update: crwdns101324:0%{title}crwdne101324:0 + type_could_not_be_saved: crwdns101325:0crwdne101325:0 + reporting_could_not_be_saved: crwdns101326:0crwdne101326:0 + properties: crwdns101327:0crwdne101327:0 + really_delete_color: 'crwdns101328:0crwdne101328:0 ' - really_delete_reporting: 'crwdns98233:0crwdne98233:0 + really_delete_reporting: 'crwdns101329:0crwdne101329:0 ' - start: crwdns98234:0crwdne98234:0 - timeline: crwdns98235:0crwdne98235:0 - timelines: crwdns98236:0crwdne98236:0 - settings: crwdns98237:0crwdne98237:0 - vertical_work_package: crwdns98238:0crwdne98238:0 - you_are_viewing_the_selected_timeline: crwdns98240:0crwdne98240:0 + start: crwdns101330:0crwdne101330:0 + timeline: crwdns101331:0crwdne101331:0 + timelines: crwdns101332:0crwdne101332:0 + settings: crwdns101333:0crwdne101333:0 + vertical_work_package: crwdns101334:0crwdne101334:0 + you_are_viewing_the_selected_timeline: crwdns101335:0crwdne101335:0 zoom: - in: crwdns98241:0crwdne98241:0 - out: crwdns98242:0crwdne98242:0 - days: crwdns98243:0crwdne98243:0 - weeks: crwdns98244:0crwdne98244:0 - months: crwdns98245:0crwdne98245:0 - quarters: crwdns98246:0crwdne98246:0 - years: crwdns98247:0crwdne98247:0 - title_remove_and_delete_user: crwdns98248:0crwdne98248:0 - title_enterprise_upgrade: crwdns98984:0crwdne98984:0 - tooltip_user_default_timezone: 'crwdns98867:0crwdne98867:0 + in: crwdns101336:0crwdne101336:0 + out: crwdns101337:0crwdne101337:0 + days: crwdns101338:0crwdne101338:0 + weeks: crwdns101339:0crwdne101339:0 + months: crwdns101340:0crwdne101340:0 + quarters: crwdns101341:0crwdne101341:0 + years: crwdns101342:0crwdne101342:0 + title_remove_and_delete_user: crwdns101343:0crwdne101343:0 + title_enterprise_upgrade: crwdns101344:0crwdne101344:0 + tooltip_user_default_timezone: 'crwdns101345:0crwdne101345:0 ' - tooltip_resend_invitation: 'crwdns98249:0crwdne98249:0 + tooltip_resend_invitation: 'crwdns101346:0crwdne101346:0 ' tooltip: - setting_email_login: 'crwdns98250:0crwdne98250:0 + setting_email_login: 'crwdns101347:0crwdne101347:0 ' queries: - apply_filter: crwdns98251:0crwdne98251:0 + apply_filter: crwdns101348:0crwdne101348:0 top_menu: - additional_resources: crwdns98252:0crwdne98252:0 - getting_started: crwdns98253:0crwdne98253:0 - help_and_support: crwdns98254:0crwdne98254:0 - total_progress: crwdns98255:0crwdne98255:0 + additional_resources: crwdns101349:0crwdne101349:0 + getting_started: crwdns101350:0crwdne101350:0 + help_and_support: crwdns101351:0crwdne101351:0 + total_progress: crwdns101352:0crwdne101352:0 user: - all: crwdns98256:0crwdne98256:0 - active: crwdns98257:0crwdne98257:0 - activate: crwdns98258:0crwdne98258:0 - activate_and_reset_failed_logins: crwdns98259:0crwdne98259:0 - authentication_provider: crwdns98260:0crwdne98260:0 - authentication_settings_disabled_due_to_external_authentication: 'crwdns98261:0crwdne98261:0 + all: crwdns101353:0crwdne101353:0 + active: crwdns101354:0crwdne101354:0 + activate: crwdns101355:0crwdne101355:0 + activate_and_reset_failed_logins: crwdns101356:0crwdne101356:0 + authentication_provider: crwdns101357:0crwdne101357:0 + authentication_settings_disabled_due_to_external_authentication: 'crwdns101358:0crwdne101358:0 ' - authorization_rejected: crwdns98262:0crwdne98262:0 - assign_random_password: crwdns98263:0crwdne98263:0 - blocked: crwdns98264:0crwdne98264:0 + authorization_rejected: crwdns101359:0crwdne101359:0 + assign_random_password: crwdns101360:0crwdne101360:0 + blocked: crwdns101361:0crwdne101361:0 blocked_num_failed_logins: - one: crwdns98265:1crwdne98265:1 - other: crwdns98265:5%{count}crwdne98265:5 - confirm_status_change: crwdns98266:0%{name}crwdne98266:0 - deleted: crwdns98267:0crwdne98267:0 - error_status_change_failed: crwdns98268:0%{errors}crwdne98268:0 - invite: crwdns98269:0crwdne98269:0 - invited: crwdns98270:0crwdne98270:0 - lock: crwdns98271:0crwdne98271:0 - locked: crwdns98272:0crwdne98272:0 - no_login: crwdns98273:0crwdne98273:0 - password_change_unsupported: crwdns98274:0crwdne98274:0 - registered: crwdns98275:0crwdne98275:0 - reset_failed_logins: crwdns98276:0crwdne98276:0 + one: crwdns101362:1crwdne101362:1 + other: crwdns101362:5%{count}crwdne101362:5 + confirm_status_change: crwdns101363:0%{name}crwdne101363:0 + deleted: crwdns101364:0crwdne101364:0 + error_status_change_failed: crwdns101365:0%{errors}crwdne101365:0 + invite: crwdns101366:0crwdne101366:0 + invited: crwdns101367:0crwdne101367:0 + lock: crwdns101368:0crwdne101368:0 + locked: crwdns101369:0crwdne101369:0 + no_login: crwdns101370:0crwdne101370:0 + password_change_unsupported: crwdns101371:0crwdne101371:0 + registered: crwdns101372:0crwdne101372:0 + reset_failed_logins: crwdns101373:0crwdne101373:0 settings: - mail_notifications: crwdns98277:0crwdne98277:0 - mail_project_explanaition: crwdns98278:0crwdne98278:0 - mail_self_notified: crwdns98279:0crwdne98279:0 - status_user_and_brute_force: crwdns98280:0%{user}crwdnd98280:0%{brute_force}crwdne98280:0 - status_change: crwdns98281:0crwdne98281:0 - unlock: crwdns98282:0crwdne98282:0 - unlock_and_reset_failed_logins: crwdns98283:0crwdne98283:0 - version_status_closed: crwdns98284:0crwdne98284:0 - version_status_locked: crwdns98285:0crwdne98285:0 - version_status_open: crwdns98286:0crwdne98286:0 - note: crwdns98287:0crwdne98287:0 - note_password_login_disabled: crwdns98288:0%{configuration}crwdne98288:0 - warning: crwdns98289:0crwdne98289:0 - warning_attachments_not_saved: crwdns98290:0%{count}crwdne98290:0 - warning_imminent_user_limit: 'crwdns99034:0%{upgrade_url}crwdne99034:0 + mail_notifications: crwdns101374:0crwdne101374:0 + mail_project_explanaition: crwdns101375:0crwdne101375:0 + mail_self_notified: crwdns101376:0crwdne101376:0 + status_user_and_brute_force: crwdns101377:0%{user}crwdnd101377:0%{brute_force}crwdne101377:0 + status_change: crwdns101378:0crwdne101378:0 + unlock: crwdns101379:0crwdne101379:0 + unlock_and_reset_failed_logins: crwdns101380:0crwdne101380:0 + version_status_closed: crwdns101381:0crwdne101381:0 + version_status_locked: crwdns101382:0crwdne101382:0 + version_status_open: crwdns101383:0crwdne101383:0 + note: crwdns101384:0crwdne101384:0 + note_password_login_disabled: crwdns101385:0%{configuration}crwdne101385:0 + warning: crwdns101386:0crwdne101386:0 + warning_attachments_not_saved: crwdns101387:0%{count}crwdne101387:0 + warning_imminent_user_limit: 'crwdns101388:0%{upgrade_url}crwdne101388:0 ' - warning_registration_token_expired: 'crwdns98856:0%{email}crwdne98856:0 + warning_registration_token_expired: 'crwdns101389:0%{email}crwdne101389:0 ' - warning_user_limit_reached: 'crwdns99035:0%{upgrade_url}crwdne99035:0 + warning_user_limit_reached: 'crwdns101390:0%{upgrade_url}crwdne101390:0 ' - warning_user_limit_reached_instructions: 'crwdns99036:0%{current}crwdnd99036:0%{max}crwdne99036:0 + warning_user_limit_reached_instructions: 'crwdns101391:0%{current}crwdnd101391:0%{max}crwdne101391:0 ' - menu_item: crwdns98291:0crwdne98291:0 - menu_item_setting: crwdns98292:0crwdne98292:0 - wiki_menu_item_for: crwdns98293:0%{title}crwdne98293:0 - wiki_menu_item_setting: crwdns98294:0crwdne98294:0 - wiki_menu_item_new_main_item_explanation: 'crwdns98295:0crwdne98295:0 + menu_item: crwdns101392:0crwdne101392:0 + menu_item_setting: crwdns101393:0crwdne101393:0 + wiki_menu_item_for: crwdns101394:0%{title}crwdne101394:0 + wiki_menu_item_setting: crwdns101395:0crwdne101395:0 + wiki_menu_item_new_main_item_explanation: 'crwdns101396:0crwdne101396:0 ' - wiki_menu_item_delete_not_permitted: crwdns98296:0crwdne98296:0 - query_menu_item_for: crwdns98297:0%{title}crwdne98297:0 + wiki_menu_item_delete_not_permitted: crwdns101397:0crwdne101397:0 + query_menu_item_for: crwdns101398:0%{title}crwdne101398:0 work_package: - updated_automatically_by_child_changes: 'crwdns98298:0%{child}crwdne98298:0 + updated_automatically_by_child_changes: 'crwdns101399:0%{child}crwdne101399:0 ' destroy: - info: crwdns98299:0crwdne98299:0 - title: crwdns98300:0crwdne98300:0 - nothing_to_preview: crwdns98301:0crwdne98301:0 + info: crwdns101400:0crwdne101400:0 + title: crwdns101401:0crwdne101401:0 + nothing_to_preview: crwdns101402:0crwdne101402:0 api_v3: attributes: - lock_version: crwdns98302:0crwdne98302:0 + lock_version: crwdns101403:0crwdne101403:0 errors: - code_401: crwdns98303:0crwdne98303:0 - code_401_wrong_credentials: crwdns98304:0crwdne98304:0 - code_403: crwdns98305:0crwdne98305:0 - code_404: crwdns98306:0crwdne98306:0 - code_409: crwdns102538:0crwdne102538:0 - code_500: crwdns98308:0crwdne98308:0 + code_401: crwdns101404:0crwdne101404:0 + code_401_wrong_credentials: crwdns101405:0crwdne101405:0 + code_403: crwdns101406:0crwdne101406:0 + code_404: crwdns101407:0crwdne101407:0 + code_409: crwdns102537:0crwdne102537:0 + code_500: crwdns101409:0crwdne101409:0 expected: - date: crwdns98309:0crwdne98309:0 - duration: crwdns98310:0crwdne98310:0 - invalid_content_type: crwdns98311:0%{content_type}crwdnd98311:0%{actual}crwdne98311:0 - invalid_format: crwdns98312:0%{property}crwdnd98312:0%{expected_format}crwdnd98312:0%{actual}crwdne98312:0 - invalid_json: crwdns98313:0crwdne98313:0 - invalid_relation: crwdns98314:0crwdne98314:0 - invalid_resource: crwdns98315:0%{property}crwdnd98315:0%{expected}crwdnd98315:0%{actual}crwdne98315:0 - invalid_user_status_transition: crwdns98316:0crwdne98316:0 - missing_content_type: crwdns98317:0crwdne98317:0 - missing_request_body: crwdns98318:0crwdne98318:0 - missing_or_malformed_parameter: crwdns98319:0%{parameter}crwdne98319:0 - multipart_body_error: crwdns98320:0crwdne98320:0 - multiple_errors: crwdns98321:0crwdne98321:0 - unable_to_create_attachment: crwdns98322:0crwdne98322:0 + date: crwdns101410:0crwdne101410:0 + duration: crwdns101411:0crwdne101411:0 + invalid_content_type: crwdns101412:0%{content_type}crwdnd101412:0%{actual}crwdne101412:0 + invalid_format: crwdns101413:0%{property}crwdnd101413:0%{expected_format}crwdnd101413:0%{actual}crwdne101413:0 + invalid_json: crwdns101414:0crwdne101414:0 + invalid_relation: crwdns101415:0crwdne101415:0 + invalid_resource: crwdns101416:0%{property}crwdnd101416:0%{expected}crwdnd101416:0%{actual}crwdne101416:0 + invalid_user_status_transition: crwdns101417:0crwdne101417:0 + missing_content_type: crwdns101418:0crwdne101418:0 + missing_request_body: crwdns101419:0crwdne101419:0 + missing_or_malformed_parameter: crwdns101420:0%{parameter}crwdne101420:0 + multipart_body_error: crwdns101421:0crwdne101421:0 + multiple_errors: crwdns101422:0crwdne101422:0 + unable_to_create_attachment: crwdns101423:0crwdne101423:0 render: - context_not_parsable: crwdns98323:0crwdne98323:0 - unsupported_context: crwdns98324:0crwdne98324:0 - context_object_not_found: crwdns98325:0crwdne98325:0 + context_not_parsable: crwdns101424:0crwdne101424:0 + unsupported_context: crwdns101425:0crwdne101425:0 + context_object_not_found: crwdns101426:0crwdne101426:0 validation: - done_ratio: crwdns98326:0crwdne98326:0 - due_date: crwdns99246:0crwdne99246:0 - estimated_hours: crwdns98328:0crwdne98328:0 - invalid_user_assigned_to_work_package: crwdns98329:0%{property}crwdne98329:0 - start_date: crwdns98330:0crwdne98330:0 - writing_read_only_attributes: crwdns98331:0crwdne98331:0 + done_ratio: crwdns101427:0crwdne101427:0 + due_date: crwdns101428:0crwdne101428:0 + estimated_hours: crwdns101429:0crwdne101429:0 + invalid_user_assigned_to_work_package: crwdns101430:0%{property}crwdne101430:0 + start_date: crwdns101431:0crwdne101431:0 + writing_read_only_attributes: crwdns101432:0crwdne101432:0 resources: - schema: crwdns98332:0crwdne98332:0 + schema: crwdns101433:0crwdne101433:0 diff --git a/config/locales/crowdin/lt.yml b/config/locales/crowdin/lt.yml index 9ffa2bc0e3..03b39b782e 100644 --- a/config/locales/crowdin/lt.yml +++ b/config/locales/crowdin/lt.yml @@ -1065,6 +1065,7 @@ lt: ' error_external_authentication_failed: Įvyko klaida vykstant išorinei autentikacijai. Bandykite dar kartą. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projektas redaguotas changeset: Pakeitimų paketas redaguotas @@ -1114,7 +1115,7 @@ lt: upsale: become_hero: Tapti didvyriu! title: Patobulinti į „Enterprise Edition“ versiją - description: Padidinkite savo produktyvumą su „Enterprise Edition“ + description: What are the benefits? more_info: Daugiau informacijos additional_features: Papildomos galingos premium funkcijos professional_support: Profesionali parama iš OpenProject expertų @@ -1910,7 +1911,7 @@ lt: ir komandos bendradarbiavimą naudojant OpenProject. text_show_again: Jūs galite paleisti šį video iš naujo iš pagalbos meniu welcome: Sveiki atvykę į OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Pridėti pastabų permission_add_work_packages: Pridėti darbų paketų permission_add_messages: Skelbti pranešimus @@ -2279,8 +2280,9 @@ lt: setting_welcome_on_homescreen: Rodyti pasisveikinimo bloką namų lange setting_wiki_compression: Wiki istorijos suspaudimas setting_work_package_group_assignment: Leisti priskyrimus grupėms - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Bendra other: Kita @@ -2290,6 +2292,13 @@ lt: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/lv.yml b/config/locales/crowdin/lv.yml index c27172ad33..8d8a0e86cd 100644 --- a/config/locales/crowdin/lv.yml +++ b/config/locales/crowdin/lv.yml @@ -1043,6 +1043,7 @@ lv: ' error_external_authentication_failed: An error occured during external authentication. Please try again. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Project edited changeset: Changeset edited @@ -1092,7 +1093,7 @@ lv: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1868,7 +1869,7 @@ lv: team collaboration with OpenProject. text_show_again: You can restart this video from the help menu welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Add notes permission_add_work_packages: Add work packages permission_add_messages: Post messages @@ -2223,8 +2224,9 @@ lv: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Wiki history compression setting_work_package_group_assignment: Allow assignment to groups - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: General other: Other @@ -2234,6 +2236,13 @@ lv: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/nl.yml b/config/locales/crowdin/nl.yml index 67b00f91c8..3ec4bbb657 100644 --- a/config/locales/crowdin/nl.yml +++ b/config/locales/crowdin/nl.yml @@ -1051,6 +1051,7 @@ nl: ' error_external_authentication_failed: Er heeft zich een fout voorgedaan bij de externe authenticatie. Probeer het opnieuw. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Project bewerkt changeset: Wijzigingsset bewerkt @@ -1100,7 +1101,7 @@ nl: upsale: become_hero: Word een held! title: Upgrade naar Enterprise Edition - description: Uw productiviteit met de Enterprise Edition verbeteren + description: What are the benefits? more_info: Meer informatie additional_features: Extra krachtige premium functies professional_support: Professionele ondersteuning van de OpenProject experts @@ -1887,7 +1888,7 @@ nl: team samenwerking met OpenProject. text_show_again: U kunt deze video van het helpmenu opnieuw starten welcome: Welkom bij OpenProject - select_language: Selecteer uw taal voor OpenProject + select_language: Please select your language permission_add_work_package_notes: Notities toevoegen permission_add_work_packages: Werkpakketten toevoegen permission_add_messages: Berichten posten @@ -2256,7 +2257,9 @@ nl: setting_welcome_on_homescreen: Toon het Welkom blok op thuisscherm setting_wiki_compression: Compressie van wiki geschiedenis setting_work_package_group_assignment: Sta toewijzingen een groepen toe - setting_work_package_list_default_highlighting_mode: Standaart werkpakket markeringsmode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Algemeen other: Overig @@ -2266,6 +2269,13 @@ nl: user: default_preferences: Standaardvoorkeuren deletion: Verwijdering + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: Geen markering + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Onopgemaakte tekst diff --git a/config/locales/crowdin/no.yml b/config/locales/crowdin/no.yml index 0b4010c8a7..c98458d022 100644 --- a/config/locales/crowdin/no.yml +++ b/config/locales/crowdin/no.yml @@ -1030,6 +1030,7 @@ ' error_external_authentication_failed: Det oppstod en feil i forbindelse med ekstern autentisering. Vennligst forsøk igjen. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Prosjektet er redigert changeset: Changeset ble redigert @@ -1079,7 +1080,7 @@ upsale: become_hero: Bli en helt! title: Oppgrader til bedriftsversjonen - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: Mer informasjon additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1851,7 +1852,7 @@ team collaboration with OpenProject. text_show_again: You can restart this video from the help menu welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Legg til notater permission_add_work_packages: Legg til arbeidspakker permission_add_messages: Skriv meldinger @@ -2208,8 +2209,9 @@ setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Komprimering av wiki-historikk setting_work_package_group_assignment: Tillat tildeling til grupper - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Generell other: Øvrig @@ -2219,6 +2221,13 @@ user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/pl.yml b/config/locales/crowdin/pl.yml index fe76e612d1..c6135f0c46 100644 --- a/config/locales/crowdin/pl.yml +++ b/config/locales/crowdin/pl.yml @@ -1069,6 +1069,7 @@ pl: ' error_external_authentication_failed: Wystąpił błąd podczas autoryzacji zewnętrznej. Proszę spróbować ponownie. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projekt edytowany changeset: Komentarze edytowane @@ -1118,7 +1119,7 @@ pl: upsale: become_hero: Zostań bohaterem! title: Aktualizuj do wersji Enterprise - description: Zwiększ swoją produktywność dzięki Enterprise Edition + description: What are the benefits? more_info: Więcej informacji additional_features: Potężne dodatkowe funkcje premium professional_support: Profesjonalne wsparcie od ekspertów OpenProject @@ -1916,7 +1917,7 @@ pl: i pracą zespołową w OpenProject. text_show_again: Możesz zresetować to wideo w menu pomocy welcome: Witamy w OpenProject - select_language: Wybierz żądany język OpenProject + select_language: Please select your language permission_add_work_package_notes: Dodawanie notatek permission_add_work_packages: Dodawanie pakietów roboczych permission_add_messages: Wysyłanie wiadomości @@ -2281,8 +2282,9 @@ pl: setting_welcome_on_homescreen: Wyświetl wiadomość powitalną na ekranie głównym setting_wiki_compression: Kompresja historii wiki setting_work_package_group_assignment: Allow assignment to groups - setting_work_package_list_default_highlighting_mode: Domyślny tryb wyróżniania pakietu - roboczego + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Ogólne other: Inne @@ -2292,6 +2294,13 @@ pl: user: default_preferences: Ustawienia domyślne deletion: Usunięcie + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: Bez wyróżniania + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Zwykły tekst diff --git a/config/locales/crowdin/pt-BR.yml b/config/locales/crowdin/pt-BR.yml index e25cb18d9e..cc269200bb 100644 --- a/config/locales/crowdin/pt-BR.yml +++ b/config/locales/crowdin/pt-BR.yml @@ -1038,6 +1038,7 @@ pt-BR: ' error_external_authentication_failed: Ocorreu um erro durante a autenticação externa. Por favor, tente novamente. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projeto editado changeset: Conjunto de alterações editadas @@ -1087,7 +1088,7 @@ pt-BR: upsale: become_hero: Torne-se um herói! title: Atualizar para a versão Enterprise Edition - description: Aumente sua produtividade com a versão Enterprise Edition + description: Quais são os benefícios? more_info: Mais informações additional_features: Poderosos recursos adicionais professional_support: Suporte profissional dos peritos da OpenProject @@ -1871,7 +1872,7 @@ pt-BR: e colaboração de equipe com o OpenProject. text_show_again: Você pode reiniciar este vídeo através do menu ajuda welcome: Bem-vindo ao OpenProject - select_language: Por favor, selecione seu idioma para o OpenProject + select_language: Please select your language permission_add_work_package_notes: Adicionar anotações permission_add_work_packages: Adicionar pacotes de trabalho permission_add_messages: Postar mensagens @@ -2122,7 +2123,7 @@ pt-BR: setting_smtp_authentication: Autenticação SMTP setting_smtp_user_name: Usuário SMTP setting_smtp_password: Senha SMTP - setting_smtp_domain: Domínio SMTP + setting_smtp_domain: Olá domínio SMTP setting_activity_days_default: Dias exibidos na atividade de projeto setting_app_subtitle: Subtítulo do aplicativo setting_app_title: Título da aplicação @@ -2238,8 +2239,9 @@ pt-BR: setting_welcome_on_homescreen: Exibir bloco de boas-vindas na tela inicial setting_wiki_compression: Compactação de histórico do wiki setting_work_package_group_assignment: Permitir a atribuição de grupos - setting_work_package_list_default_highlighting_mode: Modo padrão de destaque do - pacote de trabalho + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Geral other: Outro @@ -2249,6 +2251,13 @@ pt-BR: user: default_preferences: Preferências padrão deletion: Exclusão + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: Sem destaque + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Texto simples @@ -2325,7 +2334,7 @@ pt-BR: text_enumeration_destroy_question: "% {count} objetos estão atribuídos a esse valor." text_file_repository_writable: Diretório de anexos graváveis text_git_repo_example: um repositório e local (por exemplo, /gitrepo, c:\gitrepo) - text_hint_date_format: Digite uma data no formato YYYY-MM-DD. Outros formatos podem + text_hint_date_format: Insira uma data no formato YYYY-MM-DD. Outros formatos podem ser alterados para uma data não desejada. text_hint_disable_with_0: 'Nota: Desabilitar com 0' text_hours_between: Entre %{min} e %{max} horas. diff --git a/config/locales/crowdin/pt.yml b/config/locales/crowdin/pt.yml index 3cb8841f40..68af3d2663 100644 --- a/config/locales/crowdin/pt.yml +++ b/config/locales/crowdin/pt.yml @@ -1050,6 +1050,7 @@ pt: ' error_external_authentication_failed: Ocorreu um erro durante a autenticação externa. Por favor, tente novamente. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projeto alterado changeset: Changeset editado @@ -1099,7 +1100,7 @@ pt: upsale: become_hero: Torne-se um herói! title: Atualizar para a versão Enterprise - description: Aumente sua produtividade com a versão Enterprise + description: What are the benefits? more_info: Mais informação additional_features: Poderosas funcionalidades Premium adicionais professional_support: Apoio profissional dos especialistas da OpenProject @@ -1884,7 +1885,7 @@ pt: colaboração da equipa com o OpenProject. text_show_again: Pode reiniciar este vídeo através do menu de ajuda welcome: Bem-vindo ao OpenProject - select_language: Por favor selecione o seu idioma para OpenProject + select_language: Please select your language permission_add_work_package_notes: Adicionar notas permission_add_work_packages: Adicionar tarefas permission_add_messages: Publicar mensagens @@ -2257,8 +2258,9 @@ pt: setting_welcome_on_homescreen: Exibir o bloco de boas-vindas no ecrã inicial setting_wiki_compression: Compressão do histórico da wiki setting_work_package_group_assignment: Permitir atribuição de grupos - setting_work_package_list_default_highlighting_mode: Modo de destaque padrão do - pacote de trabalho + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Geral other: Outro @@ -2268,6 +2270,13 @@ pt: user: default_preferences: Preferências por Omissão deletion: Eliminação + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: Sem destaque + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Texto Simples diff --git a/config/locales/crowdin/ro.yml b/config/locales/crowdin/ro.yml index c4b0185924..cef27c9602 100644 --- a/config/locales/crowdin/ro.yml +++ b/config/locales/crowdin/ro.yml @@ -1061,6 +1061,7 @@ ro: ' error_external_authentication_failed: A apărut o eroare în timpul autentificării externe. Încercați din nou. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Proiect editat changeset: Set de schimbări editat @@ -1111,7 +1112,7 @@ ro: upsale: become_hero: Become a hero! title: Achiziționați versiunea Enterprise - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1898,7 +1899,7 @@ ro: unui proiect și a activității echipelor folosind OpenProject. text_show_again: Poate reporni acest videoclip din meniul de ajutor welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Adăugare note permission_add_work_packages: Adăugare pachete de lucru permission_add_messages: Publicare mesaje @@ -2271,8 +2272,9 @@ ro: setting_welcome_on_homescreen: Afişare bloc "bun venit" pe ecranul de start setting_wiki_compression: Comprimare istoric wiki setting_work_package_group_assignment: Atribuire la grupuri permisă - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: General other: Altele @@ -2282,6 +2284,13 @@ ro: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/ru.yml b/config/locales/crowdin/ru.yml index 6d4930d91c..f8cf1256d0 100644 --- a/config/locales/crowdin/ru.yml +++ b/config/locales/crowdin/ru.yml @@ -1073,6 +1073,7 @@ ru: ' error_external_authentication_failed: Ошибка внешней аутентификации. Пожалуйста, попробуйте еще раз. + error_attribute_not_highlightable: 'Атрибуты не выделяются: %{attributes}' events: project: Проект отредактирован changeset: Набор изменений отредактирован @@ -1122,7 +1123,7 @@ ru: upsale: become_hero: Станьте героем! title: Обновите до корпоративной версии - description: Повысьте эффективность работы с корпоративной версией + description: Каковы преимущества? more_info: Больше информации additional_features: Дополнительные мощные возможности professional_support: Помощь от экспертов OpenProject @@ -1917,7 +1918,7 @@ ru: сопровождения с OpenProject. text_show_again: Вы можете перезапустить это видео из меню «Справка» welcome: Добро пожаловать в OpenProject - select_language: Пожалуйста, выберите язык для OpenProject + select_language: Please select your language permission_add_work_package_notes: Добавить заметки permission_add_work_packages: Добавление пакетов работ permission_add_messages: Написать сообщения @@ -2282,8 +2283,9 @@ ru: setting_welcome_on_homescreen: Показывать приветствие на домашней странице setting_wiki_compression: Сжатие истории изменений wiki setting_work_package_group_assignment: Разрешить назначения группам - setting_work_package_list_default_highlighting_mode: Режим подсветки пакетов работ - по умолчанию + setting_work_package_list_default_highlighting_mode: Способ выделения по умолчанию + setting_work_package_list_default_highlighted_attributes: Выделенные встроенные + атрибуты по умолчанию settings: general: Общие other: Другие @@ -2293,6 +2295,13 @@ ru: user: default_preferences: Предпочтения по умолчанию deletion: Удаление + highlighting: + mode_long: + inline: Выделите один или несколько встроенных атрибутов + none: Без подсветки + status: Вся строка по статусу + type: Вся строка по типу + priority: Вся строка по приоритету text_formatting: markdown: Markdown plain: Обычный текст diff --git a/config/locales/crowdin/sk.yml b/config/locales/crowdin/sk.yml index 49868238bd..fc39086eca 100644 --- a/config/locales/crowdin/sk.yml +++ b/config/locales/crowdin/sk.yml @@ -1076,6 +1076,7 @@ sk: ' error_external_authentication_failed: Vyskytla sa chyba počas externej autentifikácie. Prosím skúste to znova. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projekt upravený changeset: Sada zmien upravená @@ -1125,7 +1126,7 @@ sk: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1915,7 +1916,7 @@ sk: team collaboration with OpenProject. text_show_again: Môžete spustiť toto video z ponuky Pomocník welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Pridať poznámky permission_add_work_packages: Pridať pracovné balíky permission_add_messages: Post messages @@ -2272,8 +2273,9 @@ sk: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Wiki history compression setting_work_package_group_assignment: Povoliť priradenie skupinám - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Všeobecné other: Ostatné @@ -2283,6 +2285,13 @@ sk: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/sv-SE.yml b/config/locales/crowdin/sv-SE.yml index eaf1050d24..43fd743c6a 100644 --- a/config/locales/crowdin/sv-SE.yml +++ b/config/locales/crowdin/sv-SE.yml @@ -1032,6 +1032,7 @@ sv-SE: ' error_external_authentication_failed: Ett fel uppstod under extern autentisering. Försök igen. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Projektet redigerades changeset: Uppdatering redigerades @@ -1081,7 +1082,7 @@ sv-SE: upsale: become_hero: Bli en hjälte! title: Uppgradera till Enterprise Edition - description: Öka produktiviteten med Enterprise Edition + description: What are the benefits? more_info: Mer information additional_features: Ytterligare kraftfulla premium-funktioner professional_support: Professionell support från OpenProject-experterna @@ -1854,7 +1855,7 @@ sv-SE: samarbete med OpenProject. text_show_again: Du kan starta om denna video från hjälpmenyn welcome: Välkommen till OpenProject - select_language: Vänligen välj språk för OpenProject + select_language: Please select your language permission_add_work_package_notes: Lägg till anteckningar permission_add_work_packages: Lägg till arbetspaket permission_add_messages: Publicera meddelanden @@ -2211,8 +2212,9 @@ sv-SE: setting_welcome_on_homescreen: Visa välkomstblocket på hemsidan setting_wiki_compression: Wiki komprimera historia setting_work_package_group_assignment: Tillåt tilldelning till grupper - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Allmänt other: Andra @@ -2222,6 +2224,13 @@ sv-SE: user: default_preferences: Förvalda inställningar deletion: Borttagning + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Oformaterad text diff --git a/config/locales/crowdin/th.yml b/config/locales/crowdin/th.yml index 71a849de62..336d39e188 100644 --- a/config/locales/crowdin/th.yml +++ b/config/locales/crowdin/th.yml @@ -1020,6 +1020,7 @@ th: ' error_external_authentication_failed: พบข้อผิดพลาดระหว่างการตรวจสอบตัวตนภายนอก กรุณาลองใหม่อีกครั้ง + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: โครงการได้รับการแก้ไขแล้ว changeset: แก้ไขชุดการเปลี่ยนแปลงแล้ว @@ -1069,7 +1070,7 @@ th: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1826,7 +1827,7 @@ th: team collaboration with OpenProject. text_show_again: คุณสามารถเริ่มเล่นวิดีโอนี้ใหม่ได้จากเมนูวิธีใช้ welcome: Welcome to OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: เพิ่มหมายเหตุ permission_add_work_packages: เพิ่มลำดับภารกิจ permission_add_messages: โพสต์ข้อความ @@ -2177,8 +2178,9 @@ th: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: การบีบอัดไฟล์ประวัติของวิกิ setting_work_package_group_assignment: อนุญาตให้มอบหมายไปยังกลุ่ม - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: ทั่วไป other: อื่น ๆ @@ -2188,6 +2190,13 @@ th: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/tr.yml b/config/locales/crowdin/tr.yml index 01be77bcc3..14a3886681 100644 --- a/config/locales/crowdin/tr.yml +++ b/config/locales/crowdin/tr.yml @@ -1031,6 +1031,7 @@ tr: ' error_external_authentication_failed: Harici doğrulama sırasında bir hata oluştu. Lütfen tekrar deneyin. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Proje düzenlendi changeset: Değişiklikler düzenlendi @@ -1080,7 +1081,7 @@ tr: upsale: become_hero: Kahraman olun! title: Enterprise Edition sürümüne yükseltme - description: Enterprise Edition ile verimliliğinizi artırın + description: Avantajı nedir? more_info: Daha fazla bilgi additional_features: Ek güçlü premium özellikler professional_support: OpenProject uzmanlarından profesyonel destek @@ -1853,7 +1854,7 @@ tr: konusuna genel bir bakış. text_show_again: Bu videoyu Yardım menüsünden yeniden başlatabilirsiniz welcome: OpenProject'e hoş geldiniz - select_language: OpenProject için dilinizi seçin + select_language: Please select your language permission_add_work_package_notes: Not eklemek permission_add_work_packages: İş paketi eklemek permission_add_messages: İleti göndermek @@ -2213,8 +2214,9 @@ tr: setting_welcome_on_homescreen: Hoşgeldiniz bloğunu ana ekranda göster setting_wiki_compression: Wiki geçmişini sıkıştır setting_work_package_group_assignment: Gruplara iş atanmasına izin ver - setting_work_package_list_default_highlighting_mode: Varsayılan iş paketi vurgulama - modu + setting_work_package_list_default_highlighting_mode: Varsayılan vurgulama modu + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Genel other: Diğer @@ -2224,6 +2226,13 @@ tr: user: default_preferences: Varsayılan Tercihler deletion: Silme + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: Vurgulama + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Düz yazı diff --git a/config/locales/crowdin/uk.yml b/config/locales/crowdin/uk.yml index e59d58df5e..93736c7e77 100644 --- a/config/locales/crowdin/uk.yml +++ b/config/locales/crowdin/uk.yml @@ -1067,6 +1067,7 @@ uk: ' error_external_authentication_failed: An error occured during external authentication. Please try again. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Project edited changeset: Changeset edited @@ -1116,7 +1117,7 @@ uk: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1904,7 +1905,7 @@ uk: team collaboration with OpenProject. text_show_again: You can restart this video from the help menu welcome: Ласкаво просимо до OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: Add notes permission_add_work_packages: Add work packages permission_add_messages: Post messages @@ -2259,8 +2260,9 @@ uk: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Вікі історії cтиснення setting_work_package_group_assignment: Дозволити віднесення до груп - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: General other: Other @@ -2270,6 +2272,13 @@ uk: user: default_preferences: Default preferences deletion: Deletion + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: Plain text diff --git a/config/locales/crowdin/vi.yml b/config/locales/crowdin/vi.yml index 72b1a8c3f1..9903f2fd3d 100644 --- a/config/locales/crowdin/vi.yml +++ b/config/locales/crowdin/vi.yml @@ -1033,6 +1033,7 @@ vi: ' error_external_authentication_failed: Lỗi xuất hiện trong khi xác thực bên ngoài. Xin vui lòng thử lại. + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: Đã chỉnh sửa dự án changeset: Đã chỉnh sửa Changeset (bộ thay đổi) @@ -1083,7 +1084,7 @@ vi: upsale: become_hero: Become a hero! title: Upgrade to Enterprise Edition - description: Boost your productivity with the Enterprise Edition + description: What are the benefits? more_info: More information additional_features: Additional powerful premium features professional_support: Professional support from the OpenProject experts @@ -1859,7 +1860,7 @@ vi: team collaboration with OpenProject. text_show_again: Bạn có thể khởi động lại video này từ trình đơn trợ giúp welcome: Welcome to OpenProject - select_language: Vui lòng lựa chọn ngôn ngữ của OpenProject + select_language: Please select your language permission_add_work_package_notes: Add notes permission_add_work_packages: Thêm mới Gói công việc permission_add_messages: Đăng tin nhắn @@ -2215,8 +2216,9 @@ vi: setting_welcome_on_homescreen: Display welcome block on homescreen setting_wiki_compression: Wiki history compression setting_work_package_group_assignment: Allow assignment to groups - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: Tổng quan other: Khác @@ -2226,6 +2228,13 @@ vi: user: default_preferences: Cấu hình mặc định deletion: Xóa + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Gạch dưới plain: Văn bản thuần diff --git a/config/locales/crowdin/zh-TW.yml b/config/locales/crowdin/zh-TW.yml index 36095037c6..9aa8670f93 100644 --- a/config/locales/crowdin/zh-TW.yml +++ b/config/locales/crowdin/zh-TW.yml @@ -951,6 +951,7 @@ zh-TW: ' error_external_authentication_failed: 外部身份驗證錯誤。請再次一次。 + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: 專案已編輯 changeset: 已編輯變更 @@ -1000,7 +1001,7 @@ zh-TW: upsale: become_hero: 成為英雄! title: 升級到企業版 - description: 使用企業版提高您的生產率 + description: What are the benefits? more_info: 更多資訊 additional_features: 其他強大的高級功能 professional_support: 由 OpenProject 專家提供專業支援 @@ -1734,7 +1735,7 @@ zh-TW: text_getting_started_description: 用 OpenProject 取得專案管理和團隊協作的快速概覽。 text_show_again: 您可以從 "説明" 功能表中重新開啟此影片 welcome: 歡迎來到 OpenProject - select_language: Please select your language for OpenProject + select_language: Please select your language permission_add_work_package_notes: 增加註釋 permission_add_work_packages: 新增工作項目 permission_add_messages: 張貼訊息 @@ -2049,8 +2050,9 @@ zh-TW: setting_welcome_on_homescreen: 在主頁面上顯示歡迎區塊 setting_wiki_compression: 維基歷史壓縮 setting_work_package_group_assignment: 允許分配給群組 - setting_work_package_list_default_highlighting_mode: Default work package highlighting - mode + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: 一般 other: 其他 @@ -2060,6 +2062,13 @@ zh-TW: user: default_preferences: 默認偏好設置 deletion: 消除 + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: No highlighting + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: 純文字 diff --git a/config/locales/crowdin/zh.yml b/config/locales/crowdin/zh.yml index c7bdb3c35f..2e72eb645b 100644 --- a/config/locales/crowdin/zh.yml +++ b/config/locales/crowdin/zh.yml @@ -940,6 +940,7 @@ zh: ' error_external_authentication_failed: 在外部身份验证期间出错。请再试一次。 + error_attribute_not_highlightable: 'Attribute(s) not highlightable: %{attributes}' events: project: 编辑项目 changeset: 编辑变更集 @@ -989,7 +990,7 @@ zh: upsale: become_hero: 成为英雄! title: 升级到企业版 - description: 使用企业版提高您的生产率 + description: What are the benefits? more_info: 更多信息 additional_features: 其他强大的高级功能 professional_support: 由 OpenProject 专家提供专业支持 @@ -1722,7 +1723,7 @@ zh: text_getting_started_description: 开放项目的项目部门和合作团队概览 text_show_again: 您可以从帮助菜单重新启动此视频 welcome: 欢迎来到 OpenProject - select_language: 请选择您的 OpenProject 语言 + select_language: Please select your language permission_add_work_package_notes: 添加注释 permission_add_work_packages: 添加工作包 permission_add_messages: 发布消息 @@ -2029,7 +2030,9 @@ zh: setting_welcome_on_homescreen: 在主屏幕上显示欢迎信息 setting_wiki_compression: Wiki 历史压缩 setting_work_package_group_assignment: 允许分配到组 - setting_work_package_list_default_highlighting_mode: 默认工作包突出显示模式 + setting_work_package_list_default_highlighting_mode: Default highlighting mode + setting_work_package_list_default_highlighted_attributes: Default inline highlighted + attributes settings: general: 通用 other: 其他 @@ -2039,6 +2042,13 @@ zh: user: default_preferences: 默认偏好设置 deletion: 删除 + highlighting: + mode_long: + inline: Highlight attribute(s) inline + none: 无突出显示 + status: Entire row by Status + type: Entire row by Type + priority: Entire row by Priority text_formatting: markdown: Markdown plain: 纯文本 diff --git a/config/locales/en.seeders.yml b/config/locales/en.seeders.yml index 3f2ec647b3..62bd74e122 100644 --- a/config/locales/en.seeders.yml +++ b/config/locales/en.seeders.yml @@ -28,18 +28,32 @@ en: seeders: demo_data: + welcome: + title: "Welcome to OpenProject!" + text: | + Select one of the demo projects to get started with some demo data we have prepared for you. + + * [Demo project](%{base_url}/projects/demo-project): to get an overview about classical project management. + * [Scrum project](%{base_url}/projects/your-scrum-project): to learn about Agile and Scrum project management. + + Also, you can create a blank [new project](%{base_url}/projects/new). + + Never stop collaborating. With open source and open mind. + + You can change this welcome text [here](%{base_url}/settings). projects: demo-project: name: Demo project identifier: demo-project description: > **This is a demo project**. You can edit the description in - the [Project settings -> Description](/projects/demo-project/settings). + the [Project settings -> Description](%{base_url}/projects/demo-project/settings). timeline: name: Timeline modules: - work_package_tracking - news + - wiki news: - title: Welcome to your demo project summary: > @@ -58,7 +72,7 @@ en: - name: Bugs status: open type: :default_type_bug - - name: Gantt chart + - name: Project plan status: open timeline: true sort_by: id @@ -80,6 +94,13 @@ en: type: :default_type_task hierarchy: true sort_by: id + columns: + - id + - subject + - priority + - type + - status + - assigned_to work_packages: - subject: Project kick-off description: Plan and execute the project kick-off. @@ -110,7 +131,7 @@ en: children: - subject: Create a new project description: | - Please [create a new project](/projects/new) from the project drop down menu in the left hand header navigation. + Please [create a new project](%{base_url}/projects/new) from the project drop down menu in the left hand header navigation. **You can:** * give your project a name, @@ -119,7 +140,7 @@ en: * set a project to public. **Visuals:** - ![new project](##attachment:"new_project.png") + ![new project](##attachment:"new_project.jpg") **Find out more:** * https://www.openproject.org/help/administration/manage-projects/ @@ -128,10 +149,10 @@ en: start: 0 duration: 0 attachments: - - new_project.png + - new_project.jpg - subject: Customize project overview page description: | - You can [customize your project overview page](/my_projects_overview/demo-project/page_layout) to add important information, such as project description, important links, work packages overview, news, and much more. + You can [customize your project overview page](%{base_url}/my_projects_overview/demo-project/page_layout) to add important information, such as project description, important links, work packages overview, news, and much more. **You can:** * edit the project overview by clicking on the gear icon, @@ -141,7 +162,7 @@ en: * and much more. **Visuals:** - ![project overview](##attachment:"project_overview.png") + ![project overview](##attachment:"project_overview.jpg") **Find out more:** * https://www.openproject.org/help/project-setup/ @@ -150,10 +171,10 @@ en: start: 0 duration: 0 attachments: - - project_overview.png + - project_overview.jpg - subject: Activate further modules description: | - Please activate further [Modules](/projects/demo-project/settings/modules) in the Project settings in order to have more features in your project. + Please activate further [Modules](%{base_url}/projects/demo-project/settings/modules) in the Project settings in order to have more features in your project. **You can:** * add a Scrum module (Backlogs), @@ -163,7 +184,7 @@ en: * and more. **Visuals:** - ![project modules](##attachment:"project_modules.png") + ![project modules](##attachment:"project_modules.jpg") **Find out more:** * https://www.openproject.org/help/activate-deactivate-modules/ @@ -172,10 +193,10 @@ en: start: 0 duration: 0 attachments: - - project_modules.png + - project_modules.jpg - subject: Invite new team members description: | - Please invite new team members by going to [Members](/projects/demo-project/members) in the project navigation. + Please invite new team members by going to [Members](%{base_url}/projects/demo-project/members) in the project navigation. **You can:** * add existing users to a project by typing in their names, @@ -183,7 +204,7 @@ en: * assign a certain role in this project for each user. **Visuals:** - ![project members](##attachment:"project_members.png") + ![project members](##attachment:"project_members.jpg") **Find out more:** * https://www.openproject.org/help/add-project-members/ @@ -193,10 +214,10 @@ en: duration: 1 priority: :default_priority_high attachments: - - project_members.png + - project_members.jpg - subject: Create work packages description: | - Please create work packages for your project. Go to [Work package](/projects/demo-project/work_packages) and click the green +Create button. + Please create work packages for your project. Go to [Work package](%{base_url}/projects/demo-project/work_packages) and click the green +Create button. **You can**: * create any type of work, e.g. features, tasks, bugs, risks, ideas, @@ -206,7 +227,7 @@ en: * insert any custom field to the forms. **Visuals**: - ![create work package](##attachment:"create_work_package.png") + ![create work package](##attachment:"create_work_package.jpg") **Find out more**: * https://www.openproject.org/help/work-packages/create-new-work-package/ @@ -216,10 +237,10 @@ en: duration: 1 priority: :default_priority_high attachments: - - create_work_package.png + - create_work_package.jpg - subject: Create a project plan description: | - Please create a project plan by going to [Gantt chart](##query:"Gantt chart") in the project navigation. + Please create a project plan by going to [Project plan](##query:"Project plan") in the project navigation. **You can:** * create new phases and milestones by simply clicking in the project plan, @@ -229,7 +250,7 @@ en: * custom columns, group, filter and save timeline reports to have them at your fingertips. **Visuals:** - ![gantt chart](##attachment:"gantt_chart.png") + ![gantt chart](##attachment:"gantt_chart.jpg") **Find out more:** * https://www.openproject.org/help/timelines/integrated-timeline-work-package-page/ @@ -239,10 +260,10 @@ en: duration: 1 priority: :default_priority_high attachments: - - gantt_chart.png + - gantt_chart.jpg - subject: Edit a work package description: | - [Edit a work package](/projects/demo-project/work_packages/41/activity) by double clicking on a row in the list view or open the split screen with the "i". + [Edit a work package](%{base_url}/projects/demo-project/work_packages/41/activity) by double clicking on a row in the list view or open the split screen with the "i". **You can**: * change title or description, @@ -254,7 +275,7 @@ en: * change forms in the Administration settings. **Visuals**: - ![edit work package](##attachment:"edit_work_package.png") + ![edit work package](##attachment:"edit_work_package.jpg") **Find out more**: * https://www.openproject.org/help/work-packages/ @@ -264,7 +285,7 @@ en: duration: 0 priority: :default_priority_high attachments: - - edit_work_package.png + - edit_work_package.jpg - subject: Develop v1.0 status: :default_status_scheduled type: :default_type_phase @@ -327,12 +348,43 @@ en: relations: - to: Develop v1.1 type: follows + wiki: + - title: Wiki + content: | + In this wiki you can collaboratively create and edit pages and sub-pages to create a project wiki. + + **You can:** + + * insert text and format it with the toolbar, + * insert text and images with copy and paste, + * paste formatted text directly from MSOffice documents, + * create a page hierarchy by inserting parent pages, + * use makros to include, e.g. table of contents, work packages lists or Gantt charts, + * include wiki pages in other text fields, e.g. project overview or meetings, + * reference tickets with one, two or three "#"+ticket number, depending on what information should be displayed, + * include links to other documents, + * view the change history, + * view as Mardown. + + **More information:** + https://www.openproject.org/help/wiki/ + children: + - title: Project documentation + content: | + This is a sub-page of the wiki. You can change this by editing the Parent page (Click the _EDIT_ button and see bottom of the page). + + ## Project scope + + ## Deliverables + children: + - title: Project manual + content: '' scrum-project: name: Scrum project identifier: your-scrum-project description: | *This is a Scrum demo project.* - You can edit the project description in the [Project settings -> Description](/projects/your-scrum-project/settings). + You can edit the project description in the [Project settings -> Description](%{base_url}/projects/your-scrum-project/settings). timeline: name: Timeline modules: @@ -372,8 +424,8 @@ en: * Divided into two additional time boxes of 4 h: - * The Product Owner presents the team the [Product Backlog](/projects/your-scrum-project/backlogs) and the priorities and explanes the Sprint Goal, to which the team must agree. Together, they prioritize the topics from the Product Backlog which the team will take care of in the next sprint. The team committs to the discussed delivery. - * The team plans autonomously (without the Product Owner) in detail and breaks down the tasks from the discussed requirements to consolidate a [Sprint Backlog](/projects/your-scrum-project/backlogs). + * The Product Owner presents the team the [Product Backlog](%{base_url}/projects/your-scrum-project/backlogs) and the priorities and explanes the Sprint Goal, to which the team must agree. Together, they prioritize the topics from the Product Backlog which the team will take care of in the next sprint. The team committs to the discussed delivery. + * The team plans autonomously (without the Product Owner) in detail and breaks down the tasks from the discussed requirements to consolidate a [Sprint Backlog](%{base_url}/projects/your-scrum-project/backlogs). ### Daily Scrum meeting @@ -382,10 +434,10 @@ en: * Short, daily status meeting of the team. * Time boxed (max. 15 min). - * Stand-up meeting to discuss the following topics from the [Task board](/projects/your-scrum-project/sprints/38/taskboard). + * Stand-up meeting to discuss the following topics from the [Task board](##sprint:"Sprint 1"). * What do I plan to do until the next Daily Scrum? * What has blocked my work (Impediments)? - * Scrum Master moderates and notes down [Sprint Impediments](/projects/your-scrum-project/sprints/38/taskboard). + * Scrum Master moderates and notes down [Sprint Impediments](##sprint:"Sprint 1"). * Product Owner may participate may participate in order to stay informed. ### Sprint Review meeting @@ -420,7 +472,7 @@ en: categories: - Category 1 (to be changed in Project settings) queries: - - name: Gantt chart + - name: Project plan status: open sort_by: id type: @@ -619,8 +671,8 @@ en: * Divided into two additional time boxes of 4 h: - * The Product Owner presents the team the [Product Backlog](/projects/your-scrum-project/backlogs) and the priorities and explanes the Sprint Goal, to which the team must agree. Together, they prioritize the topics from the Product Backlog which the team will take care of in the next sprint. The team committs to the discussed delivery. - * The team plans autonomously (without the Product Owner) in detail and breaks down the tasks from the discussed requirements to consolidate a [Sprint Backlog](/projects/your-scrum-project/backlogs). + * The Product Owner presents the team the [Product Backlog](%{base_url}/projects/your-scrum-project/backlogs) and the priorities and explanes the Sprint Goal, to which the team must agree. Together, they prioritize the topics from the Product Backlog which the team will take care of in the next sprint. The team committs to the discussed delivery. + * The team plans autonomously (without the Product Owner) in detail and breaks down the tasks from the discussed requirements to consolidate a [Sprint Backlog](%{base_url}/projects/your-scrum-project/backlogs). ### Daily Scrum meeting @@ -629,10 +681,10 @@ en: * Short, daily status meeting of the team. * Time boxed (max. 15 min). - * Stand-up meeting to discuss the following topics from the [Task board](/projects/your-scrum-project/sprints/38/taskboard). + * Stand-up meeting to discuss the following topics from the Task board. * What do I plan to do until the next Daily Scrum? * What has blocked my work (Impediments)? - * Scrum Master moderates and notes down [Sprint Impediments](/projects/your-scrum-project/sprints/38/taskboard). + * Scrum Master moderates and notes down Sprint Impediments. * Product Owner may participate may participate in order to stay informed. ### Sprint Review meeting diff --git a/config/locales/en.yml b/config/locales/en.yml index 2afafee329..768d5d4f3f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -985,6 +985,7 @@ en: with the existing menu item "%{existing_caption}" (%{existing_identifier}). error_external_authentication_failed: "An error occured during external authentication. Please try again." + error_attribute_not_highlightable: "Attribute(s) not highlightable: %{attributes}" events: project: 'Project edited' @@ -1040,7 +1041,7 @@ en: upsale: become_hero: "Become a hero!" title: "Upgrade to Enterprise Edition" - description: "Boost your productivity with the Enterprise Edition" + description: "What are the benefits?" more_info: "More information" additional_features: "Additional powerful premium features" professional_support: "Professional support from the OpenProject experts" @@ -1784,7 +1785,7 @@ en: text_getting_started_description: "Get a quick overview of project management and team collaboration with OpenProject." text_show_again: "You can restart this video from the help menu" welcome: "Welcome to OpenProject" - select_language: "Please select your language for OpenProject" + select_language: "Please select your language" permission_add_work_package_notes: "Add notes" permission_add_work_packages: "Add work packages" @@ -2105,7 +2106,8 @@ en: setting_welcome_on_homescreen: "Display welcome block on homescreen" setting_wiki_compression: "Wiki history compression" setting_work_package_group_assignment: "Allow assignment to groups" - setting_work_package_list_default_highlighting_mode: "Default work package highlighting mode" + setting_work_package_list_default_highlighting_mode: "Default highlighting mode" + setting_work_package_list_default_highlighted_attributes: "Default inline highlighted attributes" settings: general: "General" @@ -2116,6 +2118,13 @@ en: user: default_preferences: "Default preferences" deletion: "Deletion" + highlighting: + mode_long: + inline: "Highlight attribute(s) inline" + none: "No highlighting" + status: "Entire row by Status" + type: "Entire row by Type" + priority: "Entire row by Priority" text_formatting: markdown: 'Markdown' diff --git a/config/locales/js-en.yml b/config/locales/js-en.yml index bd0e8a211b..ec8f3b54ad 100644 --- a/config/locales/js-en.yml +++ b/config/locales/js-en.yml @@ -132,6 +132,11 @@ en: button: 'Embed work package table' text: '[Placeholder] Embedded work package table' + custom_actions: + date: + specific: 'on' + current_date: 'Current date' + error: internal: "An internal error has occurred." cannot_save_changes_with_message: "Cannot save your changes due to the following error: %{error}" @@ -298,6 +303,27 @@ en: help_texts: show_modal: 'Show attribute help text entry' + onboarding: + steps: + welcome: 'Take a three minutes introduction tour to learn the most important features.
    We recommend to complete the steps until the end. You can restart the tour any time.' + project_selection: 'Please select one of the projects with useful demo data to get started.
    The Demo project suits best for classical project management, while the Scrum project is better for Agile project management.' + sidebar_arrow: "With the arrow you can navigate back to the project's Main menu." + members: 'Invite new Members to join your project.' + wiki: 'Within the Wiki you can document and share knowledge together with your team.' + backlogs_overview: "Manage your work in the Backlogs view.
    Here you can create epics, user stories, and bugs, prioritize via drag'n'drop and add them to a sprint." + backlogs_task_board_arrow: 'To see your Task board, open on the Sprint drop-down...' + backlogs_task_board_select: '... and select the Task board entry.' + backlogs_task_board: "The Task board visualizes the progress for this sprint. Add new tasks or impediments with the + icon next to a user story. Via drag'n'drop you can update the status." + wp_toggler: "Now let's have a look at the Work package section, which gives you a more detailed view of your work." + wp_list: 'This is the Work package list with the important work within your project, such as tasks, features, milestones, bugs, and more.
    You can create or edit a work package directly within this list. To see its details you can double click on a row.' + wp_full_view: 'Within the Work package details you find all relevant information, such as description, status and priority, activities or comments.' + wp_back_button: 'With the arrow you can navigate back to the work package list.' + wp_create_button: 'The Create button will add a new work package to your project.' + wp_timeline_button: 'You can activate the Gantt chart to create a timeline for your project.' + wp_timeline: 'Here you can edit your project plan. Create new phases, milestones, and add dependencies. All team members can see and update the latest plan at any time.' + help_menu: 'In the Help menu you will find a user guide and additional help resources.
    Enjoy your work with OpenProject!' + got_it: 'Got it' + password_confirmation: field_description: 'You need to enter your account password to confirm this change.' title: 'Confirm your password to continue' @@ -489,6 +515,8 @@ en: update_ie_user: "Please switch to Mozilla Firefox or Google Chrome, or upgrade to Microsoft Edge." learn_more: "Learn more" close_warning: "Ignore this warning." + upsale: + ee_only: 'Enterprise Edition only feature' wiki_formatting: strong: "Strong" italic: "Italic" @@ -648,13 +676,14 @@ en: highlighting_mode: description: "Highlight with color" none: "No highlighting" - inline: 'Overdue dates, "Status", "Type", and "Priority" attribute' + inline: 'Highlighted attribute(s)' + inline_all: 'All attributes' entire_row_by: 'Entire row by' status: 'Status' priority: 'Priority' + type: 'Type' columns_help_text: "Use the input above to add or remove columns to your table view. You can drag and drop the columns to reorder them." upsale: - ee_only: 'Enterprise Edition only feature' attribute_highlighting: 'Need certain work packages to stand out from the mass?' relation_columns: 'Need to see relations in the work package list?' check_out_link: 'Check out the Enterprise Edition.' diff --git a/config/locales/media/en/create_work_package.jpg b/config/locales/media/en/create_work_package.jpg new file mode 100644 index 0000000000..397057ba21 Binary files /dev/null and b/config/locales/media/en/create_work_package.jpg differ diff --git a/config/locales/media/en/create_work_package.png b/config/locales/media/en/create_work_package.png deleted file mode 100644 index 2b0e7d1d52..0000000000 Binary files a/config/locales/media/en/create_work_package.png and /dev/null differ diff --git a/config/locales/media/en/edit_work_package.jpg b/config/locales/media/en/edit_work_package.jpg new file mode 100644 index 0000000000..d150eea198 Binary files /dev/null and b/config/locales/media/en/edit_work_package.jpg differ diff --git a/config/locales/media/en/edit_work_package.png b/config/locales/media/en/edit_work_package.png deleted file mode 100644 index 78c67fea84..0000000000 Binary files a/config/locales/media/en/edit_work_package.png and /dev/null differ diff --git a/config/locales/media/en/gantt_chart.jpg b/config/locales/media/en/gantt_chart.jpg new file mode 100644 index 0000000000..3ed562d11c Binary files /dev/null and b/config/locales/media/en/gantt_chart.jpg differ diff --git a/config/locales/media/en/gantt_chart.png b/config/locales/media/en/gantt_chart.png deleted file mode 100644 index 967f4d8354..0000000000 Binary files a/config/locales/media/en/gantt_chart.png and /dev/null differ diff --git a/config/locales/media/en/new_project.jpg b/config/locales/media/en/new_project.jpg new file mode 100644 index 0000000000..25d4cbfc33 Binary files /dev/null and b/config/locales/media/en/new_project.jpg differ diff --git a/config/locales/media/en/new_project.png b/config/locales/media/en/new_project.png deleted file mode 100644 index 56e99dece0..0000000000 Binary files a/config/locales/media/en/new_project.png and /dev/null differ diff --git a/config/locales/media/en/project_members.jpg b/config/locales/media/en/project_members.jpg new file mode 100644 index 0000000000..65dbcb3dc8 Binary files /dev/null and b/config/locales/media/en/project_members.jpg differ diff --git a/config/locales/media/en/project_members.png b/config/locales/media/en/project_members.png deleted file mode 100644 index 732ed607db..0000000000 Binary files a/config/locales/media/en/project_members.png and /dev/null differ diff --git a/config/locales/media/en/project_modules.jpg b/config/locales/media/en/project_modules.jpg new file mode 100644 index 0000000000..05a94465d6 Binary files /dev/null and b/config/locales/media/en/project_modules.jpg differ diff --git a/config/locales/media/en/project_modules.png b/config/locales/media/en/project_modules.png deleted file mode 100644 index 9d59e21138..0000000000 Binary files a/config/locales/media/en/project_modules.png and /dev/null differ diff --git a/config/locales/media/en/project_overview.jpg b/config/locales/media/en/project_overview.jpg new file mode 100644 index 0000000000..462a94eaf3 Binary files /dev/null and b/config/locales/media/en/project_overview.jpg differ diff --git a/config/locales/media/en/project_overview.png b/config/locales/media/en/project_overview.png deleted file mode 100644 index e8e57cacab..0000000000 Binary files a/config/locales/media/en/project_overview.png and /dev/null differ diff --git a/config/settings.yml b/config/settings.yml index 9ef56e30f4..d9e62fd97f 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -265,6 +265,9 @@ work_package_list_default_columns: - updated_on work_package_list_default_highlighting_mode: default: 'inline' +work_package_list_default_highlighted_attributes: + serialized: true + default: [] work_package_list_summable_columns: serialized: true default: @@ -356,3 +359,5 @@ repository_checkout_data: api_max_page_size: format: int default: 500 +demo_projects_available: + default: false diff --git a/db/migrate/20180510184732_rename_planning_elemnt_type_colors_to_colors.rb b/db/migrate/20180510184732_rename_planning_elemnt_type_colors_to_colors.rb index 9887693793..1762b5f2e5 100644 --- a/db/migrate/20180510184732_rename_planning_elemnt_type_colors_to_colors.rb +++ b/db/migrate/20180510184732_rename_planning_elemnt_type_colors_to_colors.rb @@ -1,9 +1,9 @@ class RenamePlanningElemntTypeColorsToColors < ActiveRecord::Migration[5.1] def up - # Fix existing indexes due to old migration away from timeline_colors - if table_exists? :timelines_colors_pkey - rename_table :timelines_colors_pkey, :planning_element_type_colors_pkey + # This hasn't happened automatically in Rails < 4 with the 2013 migration of timelines_colors + if index_name_exists?(:planning_element_type_colors, :timelines_colors_pkey) + rename_index :planning_element_type_colors, :timelines_colors_pkey, :planning_element_type_colors_pkey end rename_table :planning_element_type_colors, :colors diff --git a/db/migrate/20180924141838_add_highlighted_attributes_to_query.rb b/db/migrate/20180924141838_add_highlighted_attributes_to_query.rb new file mode 100644 index 0000000000..43c1d66c0b --- /dev/null +++ b/db/migrate/20180924141838_add_highlighted_attributes_to_query.rb @@ -0,0 +1,5 @@ +class AddHighlightedAttributesToQuery < ActiveRecord::Migration[5.1] + def change + add_column :queries, :highlighted_attributes, :text + end +end diff --git a/docs/README.md b/docs/README.md index 2d9a5f5932..bd09a54aa1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5,21 +5,21 @@ Get started with installing and upgrading OpenProject using [our Installation Guide starting point](https://www.openproject.org/open-source/download/). -The guides for manual and Docker-based installations [are located here](./installing/README.md). +The guides for [manual](./installation/manual/README.md), [packaged](./installation/packaged/) and [Docker-based](./installation/docker/README.md) installations are provided. ## Upgrading The detailed upgrade instructions for our packaged installer are located on the [official website](https://www.openproject.org/download/upgrade-guides/). -The guides for manual and Docker-based installations [are located here](./upgrading/README.md). +The guides for [manual](./operations/upgrading/manual/upgrading.md), [packaged](./operations/upgrading/packaged/upgrading.md) and [Docker-based](./operations/upgrading/docker/upgrading.md) upgrading are provided. ## Operation -* [Backup guide](./backup/README.md) -* [Alter configuration of OpenProject](./configuration/README.md) +* Backup guides for [manual](./operations/backup/manual/backup.md), [packaged](./operations/backup/packaged/backup.md) and [Docker-based](./operations/backup/docker/backup.md) installations +* [Alter configuration of OpenProject](./configuration/configuration.md) * [Manual repository integration for Git and Subversion](./repositories/README.md) -* [Configure incoming mails](./incoming-mails/README.md) -* [Install custom plugins](./plugins/README.md) +* [Configure incoming mails](./configuration/incoming-emails.md) +* [Install custom plugins](./plugins/plugins.md) ## User Guides @@ -30,7 +30,7 @@ Please see our [User Guide pages](https://www.openproject.org/help/user-guides/) ## Development * [Quick Start for developers](./development/quick-start.md) -* [Full development environment for developers](./development/setting-up-development-environment.md) +* [Full development environment for developers on Ubuntu](./development/development-environment-ubuntu.md) and [Mac OS X](./development/development-environment-osx.md) * [Developing plugins](./development/create-openproject-plugin.md) * [Developing OmniAuth Plugins](./development/create-omniauth-plugin.md) * [Running tests](./development/running-tests.md) diff --git a/docs/api/apiv3/endpoints/queries.apib b/docs/api/apiv3/endpoints/queries.apib index b47ecfeccc..8978dcb5fb 100644 --- a/docs/api/apiv3/endpoints/queries.apib +++ b/docs/api/apiv3/endpoints/queries.apib @@ -13,17 +13,18 @@ A query defines how work packages can be filtered and displayed. Clients can def ## Linked Properties -| Property | Description | Type | Constraints | Supported operations | -| :--------------: | ------------------------------------------------------ | ----------- | -------------------------------- | -------------------- | -| self | This query | Query | not null | READ | -| user | The user that owns this query | User | not null | READ | -| project | The project on which this query operates | Project | | READ | -| columns | Ordered list of QueryColumns. The columns, when maped to WorkPackage properties determine which WorkPackage properties to display | []QueryColumn | | READ | -| sortBy | Ordered list of QuerySortBys. Indicates the WorkPackage property the results will be ordered by as well as the direction | []QuerySortBy | | READ | -| groupBy | The WorkPackage property results of this query are grouped by | String | | READ | -| results | The list of work packages returned by applying the filters, sorting and grouping defined in the query | WorkPackageCollection | | READ | -| schema | This query's schema | Schema | | READ | - +| Property | Description | Type | Constraints | Supported operations | +| :--------------------: | ------------------------------------------------------ | --------------------- | ------------------------------------------- | -------------------- | +| self | This query | Query | not null | READ | +| user | The user that owns this query | User | not null | READ | +| project | The project on which this query operates | Project | | READ | +| columns | Ordered list of QueryColumns. The columns, when maped to WorkPackage properties determine which WorkPackage properties to display | []QueryColumn | | READ | +| highlightedAttributes | **Only with valid Enterprise Token available:** List of QueryColumns that should get highlighted when `highlightingMode` is set to `inline`. | []QueryColumn | | READ | +| sortBy | Ordered list of QuerySortBys. Indicates the WorkPackage property the results will be ordered by as well as the direction | []QuerySortBy | | READ | +| groupBy | The WorkPackage property results of this query are grouped by | String | | READ | +| results | The list of work packages returned by applying the filters, sorting and grouping defined in the query | WorkPackageCollection | | READ | +| schema | This query's schema | Schema | | READ | + Please note, that all the properties listed above will also be embedded when individual queries are returned but will not be embedded when a list of queries is returned. Whether the properties are embedded or not may be subject to change in the future. ## Local Properties @@ -37,7 +38,7 @@ Please note, that all the properties listed above will also be embedded when ind | timelineVisible | Should the timeline mode be shown? | Boolean | | READ | | timelineLabels | Which labels are shown in the timeline, empty when default | QueryTimelineLabels | | READ | | timelineZoomLevel| Which zoom level should the timeline be rendered in? | String | days, weeks, months, quarters, years | READ | -| highlightingMode | Which highlighting mode should the table have? | String | none, inline, status, priority | READ | +| highlightingMode | Which highlighting mode should the table have? | String | none, inline, status, priority, type | READ | | showHierarchies | Should the hierarchy mode be enabled? | Boolean | | READ | | public | Can users besides the owner see the query? | Boolean | | READ | | starred | Should the query be highlighted to the user? | Boolean | | READ | @@ -104,7 +105,7 @@ If the values are nonprimitive (e.g. User, Project), they will be listed as obje ``` -## Query [/api/v3/queries/{id}{?offset,pageSize,filters,sortBy,groupBy,showSums,timelineVisible,timelineLabels,timelineZoomLevel,highlightingMode,showHierarchies}] +## Query [/api/v3/queries/{id}{?offset,pageSize,filters,sortBy,groupBy,showSums,timelineVisible,timelineLabels,timelineZoomLevel,highlightingMode,highlightedAttributes,showHierarchies}] + Model + Body @@ -189,7 +190,8 @@ If the values are nonprimitive (e.g. User, Project), they will be listed as obje "method": "post" } } - } + }, + highlightedAttributes: [] }, "_links": { "self": { @@ -229,6 +231,7 @@ If the values are nonprimitive (e.g. User, Project), they will be listed as obje "title": "Updated on" } ], + highlightedAttributes: [], "groupBy": { "href": null, "title": null @@ -261,12 +264,14 @@ Retreive an individual query as identified by the id parameter. Then end point a All filters also accepted by the work packages endpoint are accepted. If no filter is to be applied, the client should send an empty array (`[]`). + offset = `1` (optional, integer, `25`) ... Page number inside the queries' result collection of work packages. + pageSize = `DEPENDING ON CONFIGURATION` (optional, integer, `25`) ... Number of elements to display per page for the queries' result collection of work packages. + + columns = `['type', 'priority']` (optional, object, `[]`) ... Selected columns for the table view. + sortBy = ["parent", "asc"] (optional, string, `[["status", "asc"]]`) ... JSON specifying sort criteria. The sort criteria is applied to the querie's result collection of work packages overriding the query's persisted sort criteria. + groupBy (optional, string, `status`) ... The column to group by. The grouping criteria is applied to the to the querie's result collection of work packages overriding the query's persisted group criteria. + showSums = `false` (optional, boolean, `true`) ... Indicates whether properties should be summed up if they support it. The showSums parameter is applied to the to the querie's result collection of work packages overriding the query's persisted sums property. + timelineVisible = `false` (optional, boolean, `true`) ... Indicates whether the timeline should be shown. + timelineLabels = `{}` (optional, object, `{}`) ... Overridden labels in the timeline view + highlightingMode = `inline` (optional, object, `inline`) ... Highlighting mode for the table view. + + highlightedAttributes = `['type', 'priority']` (optional, object, `[]`) ... Highlighted attributes mode for the table view when `highlightingMode` is `inline`. When set to `[]` all highlightable attributes will be returned as `highlightedAttributes`. + showHierarchies = `true` (optional, boolean, `true`) ... Indicates whether the hierarchy mode should be enabled. + Response 200 (application/hal+json) @@ -409,7 +414,7 @@ Delete the query identified by the id parameter "message": "The requested resource could not be found." } -## Default Query [/api/v3/queries/default{?offset,pageSize,filters,sortBy,groupBy,showSums,timelineVisible,timelineZoomLevel,showHierarchies}] +## Default Query [/api/v3/queries/default{?offset,pageSize,filters,sortBy,groupBy,showSums,timelineVisible,timelineZoomLevel,showHierarchies,highlightingMode,highlightedAttributes}] + Model + Body @@ -477,7 +482,8 @@ Delete the query identified by the id parameter "href": "/api/v3/work_packages", "method": "post" } - } + }, + highlightedAttributes: [] } }, "_links": { @@ -518,6 +524,7 @@ Delete the query identified by the id parameter "title": "Updated on" } ], + highlightedAttributes: [], "groupBy": { "href": null, "title": null @@ -1478,6 +1485,13 @@ For more details and all possible responses see the general specification of [Fo "hasDefault": true, "writable": true }, + "highlightedAttributes": { + "type": "[]QueryColumn", + "name": "Highlighted attributes", + "required": false, + "hasDefault": true, + "writable": true + }, "showHierarchies": { "type": "Boolean", "name": "Show hierarchies", diff --git a/docs/development/development-environment-ubuntu.md b/docs/development/development-environment-ubuntu.md index 5c92576cd5..0090885be2 100644 --- a/docs/development/development-environment-ubuntu.md +++ b/docs/development/development-environment-ubuntu.md @@ -131,11 +131,11 @@ We will install the latest LTS version of Node.js via [nodenv](https://github.co **Install latest LTS node version** You can find the latest LTS version here: https://nodejs.org/en/download/ -Currently, this is v6.11.0. Install and activate it with: +Currently, this is v8.12.0 Install and activate it with: ```bash -[dev@ubuntu]# nodenv install 6.11.0 -[dev@ubuntu]# nodenv global 6.11.0 +[dev@ubuntu]# nodenv install 8.12.0 +[dev@ubuntu]# nodenv global 8.12.0 ``` ## Verify your installation @@ -150,7 +150,7 @@ ruby 2.5.1p57 (2017-12-25 revision 61468) [x86_64-darwin16] Bundler version 1.16.1 [dev@ubuntu]# npm --version -3.10.10 +6.4.1 ``` # Install OpenProject diff --git a/docs/development/running-tests.md b/docs/development/running-tests.md index d49fea608d..49b2286735 100644 --- a/docs/development/running-tests.md +++ b/docs/development/running-tests.md @@ -269,7 +269,7 @@ you can access both from inside a VM with nat/bridged networking as follows: npm run serve-public # Start your openproject server with the CLI proxy configuration set -OPENPROJECT_CLI_PROXY=':4200' ./bin/rails s -b 0.0.0.0 -p 3000 +OPENPROJECT_CLI_PROXY='http://:4200' ./bin/rails s -b 0.0.0.0 -p 3000 # Now access your server from http://:3000 with code reloading ``` diff --git a/docs/installation/docker/README.md b/docs/installation/docker/README.md index 69fead3957..eea24c5802 100644 --- a/docs/installation/docker/README.md +++ b/docs/installation/docker/README.md @@ -19,7 +19,7 @@ the options that the package-based or manual installation provides. The fastest way to get an OpenProject instance up and running is to run the following command: - docker run -it -p 8080:80 -e SECRET_KEY_BASE=secret openproject/community:7 + docker run -it -p 8080:80 -e SECRET_KEY_BASE=secret openproject/community:8 This will take a bit of time the first time you launch it, but after a few minutes you should see a success message indicating the default administration @@ -35,7 +35,7 @@ the logs to your terminal, which helps with debugging if anything goes wrong. For normal usage you probably want to start it in the background, which can be achieved with the `-d` flag: - docker run -d -p 8080:80 -e SECRET_KEY_BASE=secret openproject/community:7 + docker run -d -p 8080:80 -e SECRET_KEY_BASE=secret openproject/community:8 ### Recommended usage @@ -58,7 +58,7 @@ those directories mounted: -v /var/lib/openproject/pgdata:/var/lib/postgresql/9.6/main \ -v /var/lib/openproject/logs:/var/log/supervisor \ -v /var/lib/openproject/static:/var/db/openproject \ - openproject/community:7 + openproject/community:8 Since we named the container, you can now stop it by running: @@ -143,7 +143,7 @@ Yes. You can simply pass a custom `DATABASE_URL` environment variable on the command-line, which could point to an external database. You can even choose to use MySQL instead of PostgreSQL if you wish. Here is how you would do it: - docker run -d ... -e DATABASE_URL=mysql2://user:pass@host:port/dbname openproject/community:7 + docker run -d ... -e DATABASE_URL=mysql2://user:pass@host:port/dbname openproject/community:8 The container will make sure that the database gets the migrations and demo data as well. diff --git a/docs/installation/manual/README.md b/docs/installation/manual/README.md index 2b8d942249..f92975aa13 100644 --- a/docs/installation/manual/README.md +++ b/docs/installation/manual/README.md @@ -63,7 +63,7 @@ sudo passwd openproject #(enter desired password) We recommend to use the latest MySQL version (>= 5.7) as it supports special charachters such as emojis (emoticons) out of the box. -If your Linux distribution only provides older versions of MySQL it is worth considering +If your Linux distribution only provides older versions of MySQL it is worth considering [adding MySQL as an `apt` source](https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/). Once you have your `apt` sources nicely set up install the packages. @@ -94,8 +94,8 @@ mysql> CREATE DATABASE openproject CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode **On MySQL version 5.6 or older (not recommended)** (!!) No support for emojis (emoticons). See above! If you have to use -5.6 or older and you need to support special unicode characters you can -get there but we don't provide the instructions here as it would bloat +5.6 or older and you need to support special unicode characters you can +get there but we don't provide the instructions here as it would bloat this manual. ```sql @@ -173,7 +173,7 @@ with OpenProject. For more information, see https://github.com/opf/openproject-c ```bash [openproject@host] cd ~ -[openproject@host] git clone https://github.com/opf/openproject-ce.git --branch stable/7 --depth 1 +[openproject@host] git clone https://github.com/opf/openproject-ce.git --branch stable/8 --depth 1 [openproject@host] cd openproject-ce [openproject@host] gem install bundler [openproject@host] bundle install --deployment --without postgres sqlite development test therubyracer docker @@ -196,7 +196,7 @@ you used above: user, database and password): **On MySQL version 5.7 or greater (recommended)** The encoding should be set to `utf8mb4` as we created the DB with that encoding -a few steps ago. +a few steps ago. ```yaml production: @@ -261,7 +261,7 @@ production: #main level Starting with 5.0, OpenProject directly manages your repositories. To use this feature you have to configure OpenProject as shown -[here](./repository-integration.md). +[here](../../repositories/README.md). Add this line into `configuration.yml` file at the end of the file for a better performance of OpenProject: @@ -437,15 +437,15 @@ We do however support an integration with the Apache webserver to create and ser OpenProject ships with support for so-called *managed* repositories, which can be created and maintained directly within OpenProject and are linked to a single project. -The complete guide for the integration of Subversion and Git repositories can be found in the [repository integration guide](repository-integration.md). +The complete guide for the integration of Subversion and Git repositories can be found in the [repository integration guide](../../repositories/README.md). ## Follow-Ups Your OpenProject installation is ready to run. However, there are some things to consider: -* Regularly backup your OpenProject installation. See the [backup guide](backup-guide.md) for details. +* Regularly backup your OpenProject installation. See the [backup guide](../../operations/backup/manual/backup.md) for details. * Serve OpenProject via https -* Watch for OpenProject updates. We advise to always run the latest stable version of OpenProject (especially for security updates). Information on how to perform an update can been found in the [upgrade guide](upgrade-guide.md). You can find out about new OpenProject releases in our [news](https://community.openproject.org/projects/openproject/news), or on [twitter](https://twitter.com/openproject). +* Watch for OpenProject updates. We advise to always run the latest stable version of OpenProject (especially for security updates). Information on how to perform an update can been found in the [upgrade guide](../../operations/upgrading/manual/upgrading.md). You can find out about new OpenProject releases in our [news](https://community.openproject.org/projects/openproject/news), or on [twitter](https://twitter.com/openproject). ## Plug-In installation (Optional) @@ -531,4 +531,3 @@ If you need to restart the server (for example after a configuration change), do If you have any further questions, comments, feedback, or an idea to enhance this guide, please tell us at the appropriate community [forum](https://community.openproject.org/projects/openproject/boards/9). [Follow OpenProject on twitter](https://twitter.com/openproject), and follow the news on [openproject.org](http://openproject.org) to stay up to date. - diff --git a/docs/installation/packaged/0-preparation.md b/docs/installation/packaged/0-preparation.md index 060afa737b..3bde8582dd 100644 --- a/docs/installation/packaged/0-preparation.md +++ b/docs/installation/packaged/0-preparation.md @@ -9,7 +9,7 @@ The package contains an interactive wizard that will configure your environment The installation procedure assumes the following prerequisites: -* A server running one of the Linux distributions listed in the [system requirements](./system-requirements.md). +* A server running one of the Linux distributions listed in the [system requirements](../system-requirements.md). * A mail server that is accessible via SMTP that can be used for sending notification emails. * If you intend to use SSL for OpenProject: A valid SSL certifificate along diff --git a/docs/installation/packaged/4-faq.md b/docs/installation/packaged/4-faq.md index c3ffff4c91..9b651e7993 100644 --- a/docs/installation/packaged/4-faq.md +++ b/docs/installation/packaged/4-faq.md @@ -43,9 +43,9 @@ Yes! We release OpenProject in separate release channels that you can try out. F A closer look at the available branches: -* [stable/7](https://packager.io/gh/opf/openproject-ce/refs/stable/7): Latest stable releases, starting with 7.0.0 until the last minor and patch releases of 7.X.Y are released, this will receive updates. +* [stable/8](https://packager.io/gh/opf/openproject-ce/refs/stable/8): Latest stable releases, starting with 8.0.0 until the last minor and patch releases of 8.X.Y are released, this will receive updates. * [release/8.0](https://packager.io/gh/opf/openproject-ce/refs/release/8.0): Regular (usually daily) release builds for the current next patch release (or for the first release in this version, such as 8.0.0). This will contain early bugfixes before they are being release into stable. **Do not use in production**. But, for upgrading to the next major version, this can be regarded as a _release candidate channel_ that you can use to test your upgrade on a copy of your production environment. -* [stable/6](https://packager.io/gh/opf/openproject-ce/refs/stable/6): Previous stable release, will receive critical updates and bug fixes while enterprise support depends on it. +* [stable/7](https://packager.io/gh/opf/openproject-ce/refs/stable/7): Previous stable release, will receive critical updates and bug fixes while enterprise support depends on it. * [dev](https://packager.io/gh/opf/openproject-ce/refs/dev): Daily builds of the current development build of OpenProject. While we try to keep this operable, this may result in broken code and/or migrations from time to time. Use when you're interested what the next release of OpenProject will look like. **Do not use in production!** For more information, please visit our dedicated [page regarding release candidates and channels](https://www.openproject.org/download-and-installation/release-candidate/). @@ -75,7 +75,7 @@ Here is how you do it using [certbot](https://github.com/certbot/certbot): curl https://dl.eff.org/certbot-auto > /usr/local/bin/certbot-auto chmod a+x /usr/local/bin/certbot-auto - + certbot-auto certonly --webroot --webroot-path /opt/openproject/public -d openprojecct.mydomain.com This requires your OpenProject server to be available from the Internet on port 443 or 80. diff --git a/docs/installation/packaged/centos-7/README.md b/docs/installation/packaged/centos-7/README.md index ac45067f90..d6cf33f84c 100644 --- a/docs/installation/packaged/centos-7/README.md +++ b/docs/installation/packaged/centos-7/README.md @@ -6,7 +6,7 @@ All steps are run with `sudo` to execute as the root user. ``` sudo wget -O /etc/yum.repos.d/openproject-ce.repo \ - https://dl.packager.io/srv/opf/openproject-ce/stable/7/installer/el/7.repo + https://dl.packager.io/srv/opf/openproject-ce/stable/8/installer/el/7.repo ``` **2. Install the OpenProject Community Edition package** diff --git a/docs/installation/packaged/debian-8/README.md b/docs/installation/packaged/debian-8/README.md index 29bfb856ac..d04b669f50 100644 --- a/docs/installation/packaged/debian-8/README.md +++ b/docs/installation/packaged/debian-8/README.md @@ -23,7 +23,7 @@ apt-get install apt-transport-https ``` sudo wget -O /etc/apt/sources.list.d/openproject-ce.list \ - https://dl.packager.io/srv/opf/openproject-ce/stable/7/installer/debian/8.repo + https://dl.packager.io/srv/opf/openproject-ce/stable/8/installer/debian/8.repo ``` diff --git a/docs/installation/packaged/debian-9/README.md b/docs/installation/packaged/debian-9/README.md index 8e516e46a8..a190e2c645 100644 --- a/docs/installation/packaged/debian-9/README.md +++ b/docs/installation/packaged/debian-9/README.md @@ -23,7 +23,7 @@ apt-get install apt-transport-https ``` wget -O /etc/apt/sources.list.d/openproject-ce.list \ - https://dl.packager.io/srv/opf/openproject-ce/stable/7/installer/debian/9.repo + https://dl.packager.io/srv/opf/openproject-ce/stable/8/installer/debian/9.repo ``` diff --git a/docs/installation/packaged/sles-11/README.md b/docs/installation/packaged/sles-11/README.md deleted file mode 100644 index 39eec506fc..0000000000 --- a/docs/installation/packaged/sles-11/README.md +++ /dev/null @@ -1,21 +0,0 @@ -### Steps to install OpenProject on Suse Linux Enterprise Server 11 - -All steps need to be run as `root`. - -**1. Add the OpenProject package source** - -``` -wget -O /etc/zypp/repos.d/openproject-ce.repo \ - https://dl.packager.io/srv/opf/openproject-ce/stable/7/installer/sles/11.repo -``` - -The package source is now registered as `openproject`. - - -**2. Install the OpenProject Community Edition package** - -Using the following command, zypper will install the package and all required dependencies. - -```bash -zypper install openproject -``` diff --git a/docs/installation/packaged/sles-12/README.md b/docs/installation/packaged/sles-12/README.md index 5def91b83c..50895cc745 100644 --- a/docs/installation/packaged/sles-12/README.md +++ b/docs/installation/packaged/sles-12/README.md @@ -6,7 +6,7 @@ All steps need to be run as `root`. ``` wget -O /etc/zypp/repos.d/openproject-ce.repo \ - https://dl.packager.io/srv/opf/openproject-ce/stable/7/installer/sles/12.repo + https://dl.packager.io/srv/opf/openproject-ce/stable/8/installer/sles/12.repo ``` The package source is now registered as `openproject`. diff --git a/docs/installation/packaged/ubuntu-14.04/README.md b/docs/installation/packaged/ubuntu-14.04/README.md index 52398c49ac..2fb0e22cc1 100644 --- a/docs/installation/packaged/ubuntu-14.04/README.md +++ b/docs/installation/packaged/ubuntu-14.04/README.md @@ -18,7 +18,7 @@ Our repository requires apt to have https support. Install this transport method ``` sudo wget -O /etc/apt/sources.list.d/openproject-ce.list \ - https://dl.packager.io/srv/opf/openproject-ce/stable/7/installer/ubuntu/14.04.repo + https://dl.packager.io/srv/opf/openproject-ce/stable/8/installer/ubuntu/14.04.repo ``` **4. Install the OpenProject Community Edition package** diff --git a/docs/installation/packaged/ubuntu-16.04/README.md b/docs/installation/packaged/ubuntu-16.04/README.md index 5002bc952a..19ac786a16 100644 --- a/docs/installation/packaged/ubuntu-16.04/README.md +++ b/docs/installation/packaged/ubuntu-16.04/README.md @@ -18,7 +18,7 @@ Our repository requires apt to have https support. Install this transport method ``` sudo wget -O /etc/apt/sources.list.d/openproject-ce.list \ - https://dl.packager.io/srv/opf/openproject-ce/stable/7/installer/ubuntu/16.04.repo + https://dl.packager.io/srv/opf/openproject-ce/stable/8/installer/ubuntu/16.04.repo ``` diff --git a/docs/installation/packaged/ubuntu-18.04/README.md b/docs/installation/packaged/ubuntu-18.04/README.md new file mode 100644 index 0000000000..ac90a1bd26 --- /dev/null +++ b/docs/installation/packaged/ubuntu-18.04/README.md @@ -0,0 +1,41 @@ +### Steps to install OpenProject package on Ubuntu 18.04 Bionic Beaver + +All steps are prepended with `sudo` to ensure execution as the root user. + +**1. Import the packager.io repository signing key** + +Import the PGP key used to sign our packages. Since we're using the _packager.io_ platform to distribute our packages, both package source and signing key are tied to their service. + +```bash +wget -qO- https://dl.packager.io/srv/opf/openproject-ce/key | sudo apt-key add - +``` + +**2. Ensure that apt-transport-https is installed** + +Our repository requires apt to have https support. Install this transport method with `sudo apt-get install apt-transport-https` if you did not already. + +**3. Ensure that universe package source is added** + +You may run into issues trying to install the `dialog` package in Ubuntu 18.04. To resolve this, please ensure you have the universe APT source + +```bash +sudo add-apt-repository universe +``` + + +**4. Add the OpenProject package source** + +``` +sudo wget -O /etc/apt/sources.list.d/openproject-ce.list \ + https://dl.packager.io/srv/opf/openproject-ce/stable/8/installer/ubuntu/18.04.repo +``` + + +**5. Install the OpenProject Community Edition package** + +Using the following commands, apt will check the new package source and install the package and all required dependencies. + +```bash +apt-get update +apt-get install openproject +``` diff --git a/docs/operations/backup/docker/backup.md b/docs/operations/backup/docker/backup.md index ac2add12b7..a47bb0518c 100644 --- a/docs/operations/backup/docker/backup.md +++ b/docs/operations/backup/docker/backup.md @@ -13,7 +13,7 @@ with Docker: -v /var/lib/openproject/pgdata:/var/lib/postgresql/9.6/main \ -v /var/lib/openproject/logs:/var/log/supervisor \ -v /var/lib/openproject/static:/var/db/openproject \ - openproject/community:7.0 + openproject/community:8 If you're using the same local directories than the above command, then you just need to backup your local `/var/lib/openproject` folder (for instance to @@ -21,4 +21,3 @@ S3 or FTP). If at any point you want to restore from a backup, just put your backup in `/var/lib/openproject` on your local host, and re-launch the docker container. - diff --git a/docs/operations/backup/packaged/backup.md b/docs/operations/backup/packaged/backup.md index 39d6b87826..b1e0261b3a 100644 --- a/docs/operations/backup/packaged/backup.md +++ b/docs/operations/backup/packaged/backup.md @@ -1,19 +1,17 @@ # Backup your OpenProject installation -**Note:** this guide only applies if you've installed OpenProject using our DEB/RPM -packages. +**Note:** this guide only applies if you've installed OpenProject using our DEB/RPM packages. -We advise to backup your OpenProject installation regularly — especially before -upgrading to a newer version. +We advise to backup your OpenProject installation regularly — especially before upgrading to a newer version. ## What should be backed up In general the following parts of your OpenProject installation should be backed up: -* Data stored in the database -* Configuration files -* Uploaded files (attachments) -* Repositories (typically subversion) if applicable +- Data stored in the database +- Configuration files +- Uploaded files (attachments) +- Repositories (typically subversion) if applicable ## How to backup @@ -22,13 +20,17 @@ of the current OpenProject installation. This tool will create a backup of all parts mentioned above. The backup tool is used by executing the following command: - sudo openproject run backup +``` +sudo openproject run backup +``` The command will create backup files in the following location on your system - /var/db/openproject/backup +``` +/var/db/openproject/backup +``` -The content of that directory should look very similar to the following: +The content of that directory should look very similar to the following (depending on your used database, you will see either a `mysql-dump-.sql.gz` or a `postgresql-dump-` file). ```bash root@test-packager-backup:/opt/openproject# ls -l /var/db/openproject/backup/ @@ -39,10 +41,12 @@ total 24 -rw-r----- 1 openproject openproject 116 Apr 8 09:55 svn-repositories-20150408095521.tar.gz ``` + + ## How to restore The backup created with the tool consists of four parts -which are all compressed using `gzip`. Except the MySQL database dump these parts +which are all compressed using `gzip`. Except the database dump these parts can be restored by decompressing the `*.tar.gz` files and copy the content to the proper location. The command to untar and unzip the `*.tar.gz` files looks like this (using sample file names from above): @@ -51,21 +55,45 @@ this (using sample file names from above): tar vxfz attachments-20150408095521.tar.gz ``` -To restore the MySQL dump it is recommended to use the `mysql` command line client. -First the dump has to be extracted (unzipped) and then restored. The command -used should look very similar to this: -```bash -zcat mysql-dump-20150408095521.sql.gz | mysql -u -h -p -``` +### Database The ``, `` and `` variables have to be replaced with the values that are container in the `DATABASE_URL` setting of your installation. This setting can be seen by running: -```bash +``` openproject config:get DATABASE_URL #=> e.g.: mysql2://dbusername:dbpassword@dbhost:dbport/dbname ``` + + +#### PostgreSQL + +To restore the PostgreSQL dump please use the `pg_restore` command utilities. + + + +```bash +pg_restore -h -u -W +``` + + + +First the dump has to be extracted (unzipped) and then restored. The command +used should look very similar to this: + +#### MySQL + + + +To restore the MySQL dump it is recommended to use the `mysql` command line client. + +First the dump has to be extracted (unzipped) and then restored. The command +used should look very similar to this: + +```bash +zcat mysql-dump-20150408095521.sql.gz | mysql -u -h -p +``` diff --git a/docs/operations/migrating/packaged/packaged-migrating.md b/docs/operations/migrating/packaged/packaged-migrating.md index 6e770682aa..19d198a64d 100644 --- a/docs/operations/migrating/packaged/packaged-migrating.md +++ b/docs/operations/migrating/packaged/packaged-migrating.md @@ -1,26 +1,21 @@ # Migrating your packaged OpenProject installation to another environment -**Note:** this guide only applies if you've installed OpenProject using our DEB/RPM -packages. +**Note:** this guide only applies if you've installed OpenProject using our DEB/RPM packages. Migrating your OpenProject packaged installation to another host or environment is trivial and may be combined with, e.g., minor or major package upgrades due to our migration system. ## Backing up -To move and migrate your database, please follow our [backup and restore documentation](https://www.openproject.org/operations/backup/backup-guide-packaged-installation/) for our packaged installation. +To create a dump of all your data in the old installation, please follow our [backup and restore documentation](https://www.openproject.org/operations/backup/backup-guide-packaged-installation/) for our packaged installation. This guide should leave you with a set of archives that you should manually move to your new environment: -- **Database**: mysql-dump-.sql.gz -- **Attachments**: attachments-.tar.gz -- **Custom env configuration**: conf-.tar.gz -- **Repositories**: svn- and git-.tar.gz +- **Database**: mysql-dump-\.sql.gz or postgresql-dump\.pgdump +- **Attachments**: attachments-\.tar.gz +- **Custom env configuration**: conf-\.tar.gz +- **Repositories**: svn- and git-\.tar.gz -Each of these archives can be extracted with -```bash -tar -vxfz .tar.gz -``` ## Migration @@ -47,7 +42,7 @@ You can simply look through the installer.dat and change those values you need. **The conf.d folder** -Additional environment, either generated from the wizard or entered by you through `openproject conifg:set` is written to `/etc/openproject/conf.d/{server,database,other}`. Also look through those and check which contain relevant values for your new installation. +Additional environment, either generated from the wizard or entered by you through `openproject config:set` is written to `/etc/openproject/conf.d/{server,database,other}`. Also look through those and check which contain relevant values for your new installation. ### Database @@ -57,20 +52,31 @@ In the following, the values ``, `` and `` variables hav To read the values from the old installation, you can execute the following command: ```bash - openproject config:get DATABASE_URL #=> e.g.: mysql2://dbusername:dbpassword@dbhost:dbport/dbname ``` First the dump has to be extracted (unzipped) and then restored. The command used should look very similar to this: -```bash +**PostgreSQL** + +``` +# Restore the PostgreSQL dump +pg_restore -h -u -W postgresql-dump-20180408095521.pgdump +``` + + +**MySQL** + +```bash # Extract the mysql dump -zcat mysql-dump-20150408095521.sql.gz | mysql -u -h -p +zcat mysql-dump-20180408095521.sql.gz | mysql -u -h -p ``` + + ### Attachments Your storage path can be shown on the old installation can be shown using the following command: @@ -80,8 +86,9 @@ openproject config:get ATTACHMENTS_STORAGE_PATH #=> e.g., /var/db/openproject/files ``` +Simply extract your attachments dump into that folder with `tar -vxfz .tar.gz`, creating it beforehand if needed. + -Simply extract your attachments dump into that folder, creating it beforehand if needed. ### Repositories @@ -99,9 +106,10 @@ openproject config:get GIT_REPOSITORIES #=> e.g., /var/db/openproject/git ``` - Simply extract your respective repository dumps into ech folder, creating it beforehand if needed. The dumps will only be created if you use that feature in your old installation. + + ## Running openproject configure After you restored all data and updated your installer.dat, all you need to do is run through the configuration process of the packaged installation: @@ -112,4 +120,4 @@ openproject configure It will take all values from your previous installation. *It may ask you additional wizard questions* for new features that did not exist on the old installations, or the ones you removed/left empty in the `installer.dat` file. -This step will also perform database migrations, install and configure all necessary dependencies and start the server. \ No newline at end of file +This step will also perform database migrations, install and configure all necessary dependencies and start the server. diff --git a/docs/operations/upgrading/manual/upgrading.md b/docs/operations/upgrading/manual/upgrading.md index 3371c4c0e3..4d5cf9468b 100644 --- a/docs/operations/upgrading/manual/upgrading.md +++ b/docs/operations/upgrading/manual/upgrading.md @@ -1,3 +1,54 @@ +# OpenProject 7.x to OpenProject 8.x Debian/Ubuntu Upgrade Guide (Manual installation) + +OpenProject 8.x is being released under the branch `stable/8`. Follow the following steps to perform the upgrade: + +First, perform a backup for your current environment + +```bash +[openproject@debian]# cd /home/openproject/openproject +[openproject@debian]# RAILS_ENV="production" bundle exec rake backup:database:create +# Backup will be created under backup/ +``` + +Then, check out the stable version of OpenProject 8.0. + +```bash +[openproject@debian]# cd /home/openproject/openproject +[openproject@debian]# git fetch && git checkout stable/8 +``` + +After upgrading the installation files, you need to migrate the installation to OpenProject 8.0 with the following steps: + +```bash +[openproject@debian]# cd /home/openproject/openproject +[openproject@debian]# rm -rf frontend/node_modules && npm install +[openproject@debian]# RAILS_ENV="production" bundle exec rake db:migrate +[openproject@debian]# RAILS_ENV="production" bundle exec rake db:seed +[openproject@debian]# RAILS_ENV="production" bundle exec rake assets:precompile +[openproject@debian]# touch tmp/restart.txt +``` + +After performing these steps, the server should be running OpenProject 8.0.x. + + +## Upgrade notes + +These following points are some known issues around the update to 8.0. It does not contain the entire list of changes. To see all changes, [please browse the release notes](https://www.openproject.org/release-notes/openproject-8-0/). + +### Migration from Textile to Markdown + +OpenProject 8.0. has removed Textile, all previous content is migrated to GFM Markdown using [pandoc](https://pandoc.org). This will happen automatically during the migration run. A recent pandoc version will be downloaded by OpenProject. + +For more information, please visit this separate guide: https://github.com/opf/openproject/tree/dev/docs/user/textile-to-markdown-migration + +### Frontend changes, Angular is now in production + +OpenProject 8.0. uses Angular for the majority of the frontend application. The `npm install` step should automatically take care of the installation, however in some cases there were leftover `node_modules` entries that resulted in an incomplete frontend application. To ensure the correct versions are installed, we thus recommend you remove `frontend/node_modules` entirely before running `npm install` again. + +### SQL mode changes for MySQL 8.0. + +MySQL 8.0. removes the deprecated SQL mode `no_auto_create_user` that we enforced up until 7.4. You will need to remove this mode from your `config/database.yml` should you have used it. For more information, see https://community.openproject.com/wp/28524 + # OpenProject 6.x to OpenProject 7.x Debian/Ubuntu Upgrade Guide (Manual installation) Please look at the steps in the section about the upgrade to OpenProject 6.0. OpenProject 7.x is being released under the branch `stable/7`. The other steps are identical. @@ -249,4 +300,3 @@ run: If you have any further questions, comments, feedback, or an idea to enhance this guide, please tell us at the appropriate forum. Also, please take a look at the Frequently [Asked Questions](https://www.openproject.org/help/faq/). - diff --git a/docs/operations/upgrading/packaged/upgrading.md b/docs/operations/upgrading/packaged/upgrading.md index 6ae404807b..ebf7491ddf 100644 --- a/docs/operations/upgrading/packaged/upgrading.md +++ b/docs/operations/upgrading/packaged/upgrading.md @@ -50,7 +50,31 @@ Note that this still takes previous values into consideration. Values that shoul Since OpenProject 8.0.0 is a major upgrade, you will need to perform some basic manual steps to upgrade your package. +First, please check that the package repository is correct. Compare your local package repository with the one printed on your matching distribution on [our Download and Installation page](https://www.openproject.org/download-and-installation/) +## Upgrade notes for OpenProject 8.0. + +These following points are some known issues around the update to 8.0. It does not contain the entire list of changes. To see all changes, [please browse the release notes](https://www.openproject.org/release-notes/openproject-8-0/). + +### Upgrades in NPM may result in package inconsistencies + +As has been reported from the community, [there appear to be issues with NPM leftover packages](https://community.openproject.com/projects/openproject/work_packages/28571) upgrading to OpenProject 8.0.0. This is due to the packages applying a delta between your installed version and the to-be-installed 8.0. package. In some cases such as SLES12 and Centos 7, the `frontend/node_modules` folder is not fully correctly replaced. This appears to hint at an issue with yum, the package manager behind both. + +To ensure the package's node_modules folder matches your local version, we recommend you simply remove `/opt/openproject/frontend/node_modules` entirely **before** installing the package + +``` +rm -rf /opt/openproject/frontend/node_modules +# Continue with the installation steps described below +``` + +### Migration from Textile to Markdown + +OpenProject 8.0. has removed Textile, all previous content is migrated to GFM Markdown using [pandoc](https://pandoc.org). This will happen automatically during the migration run. A recent pandoc version will be downloaded by OpenProject. + +For more information, please visit this separate guide: https://github.com/opf/openproject/tree/dev/docs/user/textile-to-markdown-migration + + +## Upgrade steps If you have currently installed the stable 7.x release of OpenProject by using the `stable/7` package source, you will need to adjust that package source. @@ -69,3 +93,5 @@ you will need to adjust that package source. - Update the reference to `stable/7` in `/etc/zypp/repos.d/openproject.repo` to `stable/8`. - Perform the Upgrade steps as mentioned above in *Upgrading your OpenProject installation* + + diff --git a/docs/repositories/README.md b/docs/repositories/README.md index b97402f579..8e7b1473b5 100644 --- a/docs/repositories/README.md +++ b/docs/repositories/README.md @@ -68,7 +68,7 @@ Part of the managed repositories functionality was previously provided with repo Reposman periodically checked for new projects and automatically created a repository of a given type. It never deleted repositories on the filesystem when their associated project was removed in OpenProject. -This script has been integrated into OpenProject and extended. If you previously used reposman, please see the [upgrade guide to 5.0](./upgrade-guide.md) for further guidance on how to migrate to managed repositories. +This script has been integrated into OpenProject and extended. If you previously used reposman, please see the [upgrade guide to 5.0](../operations/upgrading) for further guidance on how to migrate to managed repositories. ### Managing Repositories Remotely diff --git a/frontend/legacy/app/components/wp-custom-actions/date-action.component.html b/frontend/legacy/app/components/wp-custom-actions/date-action.component.html new file mode 100644 index 0000000000..4f34914950 --- /dev/null +++ b/frontend/legacy/app/components/wp-custom-actions/date-action.component.html @@ -0,0 +1,19 @@ + + + + + + + diff --git a/frontend/legacy/app/components/wp-custom-actions/date-action.component.ts b/frontend/legacy/app/components/wp-custom-actions/date-action.component.ts new file mode 100644 index 0000000000..6734e7eaf7 --- /dev/null +++ b/frontend/legacy/app/components/wp-custom-actions/date-action.component.ts @@ -0,0 +1,99 @@ +// -- copyright +// OpenProject is a project management system. +// Copyright (C) 2012-2015 the OpenProject Foundation (OPF) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License version 3. +// +// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +// Copyright (C) 2006-2013 Jean-Philippe Lang +// Copyright (C) 2010-2013 the ChiliProject Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// See doc/COPYRIGHT.rdoc for more details. +// ++ + +import {openprojectLegacyModule} from "core-app/openproject-legacy-app"; + +export class WpCustomActionsAdminDateActionComponent { + public valueVisible = false; + public fieldName:string; + public fieldValue:string; + public visibleValue:string; + public selectedOperator:any; + private i18n:any; + + private onKey = 'on'; + private currentKey = 'current'; + private currentFieldValue = '%CURRENT_DATE%'; + + public operators:{key:string, label:string}[]; + + constructor() { + window.OpenProject.getPluginContext().then((context) => { + this.i18n = context.services.i18n; + + this.initialize(); + }); + } + + // cannot use $onInit as it would be called before the operators gets filled + public initialize() { + this.operators = [{key: this.onKey, label: this.i18n.t('js.custom_actions.date.specific')}, + {key: this.currentKey, label: this.i18n.t('js.custom_actions.date.current_date')}]; + + if (this.fieldValue === this.currentFieldValue) { + this.selectedOperator = this.operators[1]; + } else { + this.selectedOperator = this.operators[0]; + this.visibleValue = this.fieldValue; + } + + this.toggleValueVisibility(); + } + + public toggleValueVisibility() { + this.valueVisible = this.selectedOperator.key === this.onKey; + this.updateDbValue(); + } + + private updateDbValue() { + if (this.selectedOperator.key === this.currentKey) { + this.fieldValue = this.currentFieldValue; + } else { + this.fieldValue = this.visibleValue; + } + } + + public get fieldId() { + // replace all square brackets by underscore + // to match the label's for value + return this.fieldName + .replace(/\[|\]/g, '_') + .replace('__', '_') + .replace(/_$/, ''); + } +} + +openprojectLegacyModule.component('wpCustomActionsAdminDateAction', { + template: require('!!raw-loader!./date-action.component.html'), + controller: WpCustomActionsAdminDateActionComponent, + bindings: { + fieldName: "@", + fieldValue: "@", + } +}); + diff --git a/frontend/npm-shrinkwrap.json b/frontend/npm-shrinkwrap.json index c2773bd445..8ec95d55a0 100644 --- a/frontend/npm-shrinkwrap.json +++ b/frontend/npm-shrinkwrap.json @@ -1287,17 +1287,17 @@ } }, "@angular/compiler": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-6.1.2.tgz", - "integrity": "sha512-IMaqx1gIYMqrori41bITgm22patbde/SRINiSggeUqegVhX4b2wIZ6ALIyT6utD2CC9n7oHQgp/VpMVMOIg0yA==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-6.1.10.tgz", + "integrity": "sha512-FPIb2j3zfoBwb6vo/u0gQeu70h8InGlSisBr3xMACs/35/pwB6kbQR+JQiUr0D7k6QApg7AuMkvq8aFNelg0aw==", "requires": { "tslib": "^1.9.0" } }, "@angular/compiler-cli": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-6.1.2.tgz", - "integrity": "sha512-r3zSbXMc0Uv5kPau+AF7uxps3S8A02Bp2Rw18NnMY+2kXPPKXn/qfAplYidrRrlcW0Kwklt34TSMxd4cxerRuQ==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-6.1.10.tgz", + "integrity": "sha512-GCWdyeNQSnF4RfzO4A0+WHsNEgxKpl5arg4ldLSWMNkj/DrhMD4TnmxhR+IVY+7ieMkUBwpcuWRnjdOdnbmV+w==", "requires": { "chokidar": "^1.4.2", "minimist": "^1.2.0", @@ -1332,7 +1332,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } @@ -1490,6 +1490,11 @@ "assertion-error": "*" } }, + "@types/chart.js": { + "version": "2.7.34", + "resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.7.34.tgz", + "integrity": "sha512-dh0vgrF0oCpeb4AC+eBU7QdKPoaIg4Xd8+D1BtJKT737gNeloc91bmSUwo4PpJwZXM4vKBSNIO/LfLazvss15g==" + }, "@types/codemirror": { "version": "0.0.58", "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.58.tgz", @@ -3315,6 +3320,39 @@ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.5.0.tgz", "integrity": "sha512-9ZTaoBaePSCFvNlNGrsyI8ZVACP2svUtq0DkM7t4K2ClAa96sqOIRjAzDTc8zXzFt1cZR46rRzLTiHFSJ+Qw0g==" }, + "chart.js": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.7.2.tgz", + "integrity": "sha512-90wl3V9xRZ8tnMvMlpcW+0Yg13BelsGS9P9t0ClaDxv/hdypHDr/YAGf+728m11P5ljwyB0ZHfPKCapZFqSqYA==", + "requires": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "chartjs-color": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.2.0.tgz", + "integrity": "sha1-hKL7dVeH7YXDndbdjHsdiEKbrq4=", + "requires": { + "chartjs-color-string": "^0.5.0", + "color-convert": "^0.5.3" + }, + "dependencies": { + "color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" + } + } + }, + "chartjs-color-string": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz", + "integrity": "sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==", + "requires": { + "color-name": "^1.0.0" + } + }, "check-types": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.3.0.tgz", @@ -7817,7 +7855,7 @@ "jquery-mockjax": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/jquery-mockjax/-/jquery-mockjax-2.2.2.tgz", - "integrity": "sha512-stVgUln5bo7g14KjeU45c31nAYlBHAUVBo4JbdoDYIJ3i6Nzlu8mkjKcAviwad9AU1dBEHHpuzA7R6mKcWgvZA==", + "integrity": "sha1-nH0rEDpEz2HJnMeKnueHhQS2CQc=", "dev": true, "requires": { "jquery": ">=1.5.2" @@ -9610,6 +9648,14 @@ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", "integrity": "sha1-ddpKkn7liH45BliABltzNkE7MQ0=" }, + "ng2-charts": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-1.6.0.tgz", + "integrity": "sha512-9w0WH69x5/nuqC1og2WaY39NbaBqTGIP1+5gZaH7/KPN6UEPonNg/pYnsIVklLj1DWPWXKa8+XXIJZ1jy5nLxg==", + "requires": { + "chart.js": "^2.6.0" + } + }, "ng2-rx-componentdestroyed": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ng2-rx-componentdestroyed/-/ng2-rx-componentdestroyed-3.0.0.tgz", @@ -13588,7 +13634,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "source-map": { @@ -13597,9 +13643,9 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.8.tgz", - "integrity": "sha512-WqAEWPdb78u25RfKzOF0swBpY0dKrNdjc4GvLwm7ScX/o9bj8Eh/YL8mcMhBHYDGl87UkkSXDOFnW4G7GhWhGg==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" diff --git a/frontend/package.json b/frontend/package.json index 28d8ee2966..0b20a22f7a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -33,8 +33,8 @@ "@angular/cdk": "6.4.3", "@angular/cli": "6.1.3", "@angular/common": "6.1.2", - "@angular/compiler": "6.1.2", - "@angular/compiler-cli": "6.1.2", + "@angular/compiler": "6.1.10", + "@angular/compiler-cli": "6.1.10", "@angular/core": "6.1.2", "@angular/forms": "6.1.2", "@angular/http": "6.1.2", @@ -43,6 +43,7 @@ "@angular/router": "6.1.2", "@types/angular": "^1.6.45", "@types/assertion-error": "^1.0.30", + "@types/chart.js": "^2.7.34", "@types/codemirror": "0.0.58", "@types/es6-shim": "^0.31.32", "@types/jquery": "^2.0.40", @@ -66,6 +67,7 @@ "bourbon": "~4.2.1", "bowser": "^1.6.1", "bundle-loader": "^0.5.4", + "chart.js": "2.7.2", "clean-webpack-plugin": "^0.1.19", "codemirror": "^5.39.0", "contra": "^1.9.4", @@ -96,6 +98,7 @@ "moment": "^2.17.1", "moment-timezone": "^0.5.11", "mousetrap": "~1.6.0", + "ng2-charts": "^1.1.0", "ng2-rx-componentdestroyed": "3.0.0", "ngtemplate-loader": "^2.0.1", "node-sass": "^4.9.3", diff --git a/frontend/src/app/angular4-modules.ts b/frontend/src/app/angular4-modules.ts index 19535fe85e..22d31f1e29 100644 --- a/frontend/src/app/angular4-modules.ts +++ b/frontend/src/app/angular4-modules.ts @@ -73,6 +73,7 @@ import {UserLinkComponent} from 'core-components/user/user-link/user-link.compon import {WorkPackageCacheService} from 'core-components/work-packages/work-package-cache.service'; import {WorkPackageBreadcrumbComponent} from 'core-components/work-packages/wp-breadcrumb/wp-breadcrumb.component'; import {WorkPackageRelationsCountComponent} from 'core-components/work-packages/wp-relations-count/wp-relations-count.component'; +import {WorkPackageWatchersCountComponent} from 'core-components/work-packages/wp-relations-count/wp-watchers-count.component'; import {WorkPackageSingleViewComponent} from 'core-components/work-packages/wp-single-view/wp-single-view.component'; import {WorkPackageSubjectComponent} from 'core-components/work-packages/wp-subject/wp-subject.component'; import {WorkPackageTypeStatusComponent} from 'core-components/work-packages/wp-type-status/wp-type-status.component'; @@ -215,6 +216,9 @@ import {CurrentUserService} from 'core-components/user/current-user.service'; import {CkeditorAugmentedTextareaComponent} from "core-app/ckeditor/ckeditor-augmented-textarea.component"; import {WpTableConfigurationHighlightingTab} from "core-components/wp-table/configuration-modal/tabs/highlighting-tab.component"; import {WorkPackageTableHighlightingService} from "core-components/wp-fast-table/state/wp-table-highlighting.service"; +import {ChartsModule} from "ng2-charts"; +import {WorkPackageEmbeddedGraphComponent} from "core-components/wp-table/embedded/wp-embedded-graph.component"; +import {WorkPackageByVersionGraphComponent} from "core-components/wp-by-version-graph/wp-by-version-graph.component"; @NgModule({ imports: [ @@ -235,7 +239,8 @@ import {WorkPackageTableHighlightingService} from "core-components/wp-fast-table // Plugin hooks and modules OpenprojectPluginsModule, // Linked plugins dynamically generated by bundler - LinkedPluginsModule + LinkedPluginsModule, + ChartsModule ], providers: [ { @@ -343,8 +348,6 @@ import {WorkPackageTableHighlightingService} from "core-components/wp-fast-table ZenModeButtonComponent, WpResizerDirective, MainMenuResizerComponent, - WpCustomActionComponent, - WpCustomActionsComponent, WorkPackageTableSumsRowController, SortHeaderDirective, @@ -365,6 +368,7 @@ import {WorkPackageTableHighlightingService} from "core-components/wp-fast-table // Split view WorkPackageSplitViewComponent, WorkPackageRelationsCountComponent, + WorkPackageWatchersCountComponent, WorkPackageBreadcrumbComponent, WorkPackageEditFieldGroupComponent, WorkPackageSplitViewToolbarComponent, @@ -439,6 +443,9 @@ import {WorkPackageTableHighlightingService} from "core-components/wp-fast-table // Embedded table WorkPackageEmbeddedTableComponent, WorkPackageEmbeddedTableEntryComponent, + // Embedded graphs + WorkPackageEmbeddedGraphComponent, + // Modals WpTableConfigurationModalComponent, WpTableConfigurationColumnsTab, @@ -477,11 +484,18 @@ import {WorkPackageTableHighlightingService} from "core-components/wp-fast-table EmbeddedTablesMacroComponent, CkeditorAugmentedTextareaComponent, + // CustomActions + WpCustomActionComponent, + WpCustomActionsComponent, + // Attachments AttachmentsComponent, AttachmentListComponent, AttachmentListItemComponent, AttachmentsUploadComponent, + + // Work package graphs on version page + WorkPackageByVersionGraphComponent, ], entryComponents: [ WorkPackagesBaseComponent, @@ -489,7 +503,6 @@ import {WorkPackageTableHighlightingService} from "core-components/wp-fast-table WorkPackageTablePaginationComponent, WorkPackagesTableController, TablePaginationComponent, - WpCustomActionsComponent, // Split view WorkPackageSplitViewComponent, @@ -562,11 +575,17 @@ import {WorkPackageTableHighlightingService} from "core-components/wp-fast-table CkeditorAugmentedTextareaComponent, EmbeddedTablesMacroComponent, + // CustomActions + WpCustomActionsComponent, + // Attachments AttachmentsComponent, // Zen mode button ZenModeButtonComponent, + + // Work package graphs on version page + WorkPackageByVersionGraphComponent, ] }) export class OpenProjectModule { diff --git a/frontend/src/app/components/angular/tracking-functions.ts b/frontend/src/app/components/angular/tracking-functions.ts index 6ecbc23ce1..4ae5e13f63 100644 --- a/frontend/src/app/components/angular/tracking-functions.ts +++ b/frontend/src/app/components/angular/tracking-functions.ts @@ -6,8 +6,14 @@ export namespace AngularTrackingHelpers { } export function compareByName(a:T|undefined|null, b:T|undefined|null):boolean { - const bothNil = !a && !b; - return bothNil || (!!a && !!b && a.name === b.name); + return compareByAttribute('name')(a, b); + } + + export function compareByAttribute(attribute:string) { + return (a:any, b:any) => { + const bothNil = !a && !b; + return bothNil || (!!a && !!b && a[attribute] === b[attribute]); + }; } export function trackByName(i:number, item:any) { @@ -18,6 +24,15 @@ export namespace AngularTrackingHelpers { return _.get(item, 'href'); } + export function trackByHrefAndProperty(propertyName:string) { + return (i:number, item:HalResource) => { + let href = _.get(item, 'href'); + let prop = _.get(item, propertyName, 'none'); + + return `${href}#${propertyName}=${prop}`; + }; + } + export function trackByTrackingIdentifier(i:number, item:any) { return _.get(item, 'trackingIdentifier', item && item.href); } diff --git a/frontend/src/app/components/filters/filter-toggled-multiselect-value/filter-toggled-multiselect-value.component.spec.ts b/frontend/src/app/components/filters/filter-toggled-multiselect-value/filter-toggled-multiselect-value.component.spec.ts index 3aee9d03fe..a9a74942f6 100644 --- a/frontend/src/app/components/filters/filter-toggled-multiselect-value/filter-toggled-multiselect-value.component.spec.ts +++ b/frontend/src/app/components/filters/filter-toggled-multiselect-value/filter-toggled-multiselect-value.component.spec.ts @@ -105,7 +105,7 @@ describe('FilterToggledMultiselectValueComponent', () => { fixture.detectChanges(); }); - describe('app.isValueMulti()', function () { + describe('app.hasMultipleSelectedOptions()', function () { it('is true', () => { expect(app.isValueMulti()).toBeTruthy(); }); @@ -177,7 +177,7 @@ describe('FilterToggledMultiselectValueComponent', () => { fixture.detectChanges(); }); - describe('app.isValueMulti()', function () { + describe('app.hasMultipleSelectedOptions()', function () { it('is false', () => { expect(app.isValueMulti()).toBeFalsy(); }); @@ -209,7 +209,7 @@ describe('FilterToggledMultiselectValueComponent', () => { fixture.detectChanges(); }); - describe('app.isValueMulti()', function () { + describe('app.hasMultipleSelectedOptions()', function () { it('is false', () => { expect(app.isValueMulti()).toBeFalsy(); }); diff --git a/frontend/src/app/components/projects/project-menu-autocomplete/project-menu-autocomplete.component.ts b/frontend/src/app/components/projects/project-menu-autocomplete/project-menu-autocomplete.component.ts index 6e809b74eb..1a391b2b58 100644 --- a/frontend/src/app/components/projects/project-menu-autocomplete/project-menu-autocomplete.component.ts +++ b/frontend/src/app/components/projects/project-menu-autocomplete/project-menu-autocomplete.component.ts @@ -37,6 +37,7 @@ import {I18nService} from "core-app/modules/common/i18n/i18n.service"; import {HttpClient} from "@angular/common/http"; import {ChangeDetectorRef, Component, ElementRef, OnInit} from "@angular/core"; import {DynamicBootstrapper} from "core-app/globals/dynamic-bootstrapper"; +import {CurrentProjectService} from "core-components/projects/current-project.service"; export interface IProjectMenuEntry { id:number; @@ -73,7 +74,8 @@ export class ProjectMenuAutocompleteComponent extends ILazyAutocompleterBridge({}); public changeData$ = this.changeData.asObservable(); + private resizeObservable$:Observable; + private resizeSubscription$:Subscription; + constructor(protected I18n:I18nService, protected injector:Injector) { } @@ -74,9 +81,12 @@ export class MainMenuToggleService { } // mobile version default: hide menu on initialization - if (this.isMobile()) { + if (this.isMobile) { this.closeMenu(); } + + // Listen on changes of the screen size + this.onWindowResize(); } // click on arrow or hamburger icon @@ -86,8 +96,8 @@ export class MainMenuToggleService { event.preventDefault(); } - if (!this.showNavigation()) { // sidebar is hidden -> show menu - if (this.isMobile()) { // mobile version + if (!this.showNavigation) { // sidebar is hidden -> show menu + if (this.isMobile) { // mobile version this.setWidth(window.innerWidth); // On mobile the main menu shall close whenever you click outside the menu. this.setupAutocloseMainMenu(); @@ -109,18 +119,22 @@ export class MainMenuToggleService { } public closeMenu():void { - this.saveWidth(0); + if (this.isMobile) { + this.saveWidth(0); // save 0 in localStorage to open menu automatically on onWindowResize + } else { + this.setWidth(0); + } this.hideElements.addClass('hidden-navigation'); } public closeWhenOnMobile():void { - if (this.isMobile()) { + if (this.isMobile) { this.closeMenu() }; } private setToggleTitle():void { - if (this.showNavigation()) { + if (this.showNavigation) { this.toggleTitle = this.I18n.t('js.label_hide_project_menu'); } else { this.toggleTitle = this.I18n.t('js.label_expand_project_menu'); @@ -129,7 +143,7 @@ export class MainMenuToggleService { } private addRemoveClassHidden():void { - this.hideElements.toggleClass('hidden-navigation', !this.showNavigation()); + this.hideElements.toggleClass('hidden-navigation', !this.showNavigation); } public saveWidth(width?:number):void { @@ -151,7 +165,7 @@ export class MainMenuToggleService { this.snapBack(); this.ensureContentVisibility(); - this.global.showNavigation = this.showNavigation(); + this.global.showNavigation = this.showNavigation; this.addRemoveClassHidden(); this.htmlNode.style.setProperty("--main-menu-width", this.elementWidth + 'px'); } @@ -162,7 +176,7 @@ export class MainMenuToggleService { jQuery('#main-menu').on('focusout.main_menu', function (event) { // Check that main menu is not closed and that the `focusout` event is not a click on an element // that tries to close the menu anyways. - if (!that.showNavigation() || document.getElementById('main-menu-toggle') === event.relatedTarget) { + if (!that.showNavigation || document.getElementById('main-menu-toggle') === event.relatedTarget) { return; } else { @@ -191,11 +205,34 @@ export class MainMenuToggleService { } } - private isMobile():boolean { + public get isMobile():boolean { return (window.innerWidth < 680); } - public showNavigation():boolean { + public get showNavigation():boolean { return (this.elementWidth > 10); } + + private get isGlobalPage():boolean { + return this.currentProject.id? false : true; + } + + // Listen on changes of the window size on all global pages + // Expand menu automatically on desktop + private onWindowResize() { + if (!this.isGlobalPage) { // Listen only on global pages + return; + } + this.resizeObservable$ = fromEvent(window, 'resize') + this.resizeSubscription$ = this.resizeObservable$.subscribe( evt => { + if (!this.isMobile) { + let localStorage = parseInt(window.OpenProject.guardedLocalStorage(this.localStorageKey) as string); + if (localStorage > 0 && this.elementWidth > 10) { // Mobile menu is open and should stay open on desktop + this.setWidth(localStorage); + } else if (localStorage === 0 && this.elementWidth === 0) { // Mobile menu is closed and should expand on desktop + this.saveWidth(this.defaultWidth); + } + } + }); + } } diff --git a/frontend/src/app/components/routing/wp-full-view/wp-full-view.html b/frontend/src/app/components/routing/wp-full-view/wp-full-view.html index 87430e1c1b..d26049486a 100644 --- a/frontend/src/app/components/routing/wp-full-view/wp-full-view.html +++ b/frontend/src/app/components/routing/wp-full-view/wp-full-view.html @@ -57,10 +57,6 @@
    -
    - -
    @@ -83,12 +79,18 @@ [uiParams]="{workPackageId: workPackage.id}" uiSrefActive="selected"> +
    + +
    + +
    diff --git a/frontend/src/app/components/routing/wp-split-view/wp-split-view.html b/frontend/src/app/components/routing/wp-split-view/wp-split-view.html index 9bd4918da4..bc5d034c7b 100644 --- a/frontend/src/app/components/routing/wp-split-view/wp-split-view.html +++ b/frontend/src/app/components/routing/wp-split-view/wp-split-view.html @@ -22,6 +22,7 @@ uiSref="work-packages.list.details.watchers" uiSrefActive="selected"> +
  • { - this.count = _.size(relations); - }); - } + combineLatest( + this.wpRelations.state(this.wpId.toString()).values$(), + this.wpCacheService.loadWorkPackage(this.wpId.toString()).values$() + ).pipe( + takeUntil(componentDestroyed(this)) + ).subscribe(([relations, workPackage]) => { + let relationCount = _.size(relations); + let parentCount = workPackage.parent ? 1 : 0; + let childrenCount = _.size(workPackage.children); + + this.count = relationCount + parentCount + childrenCount; + }); +} ngOnDestroy():void { // Nothing to do diff --git a/frontend/src/app/components/work-packages/wp-relations-count/wp-relations-count.html b/frontend/src/app/components/work-packages/wp-relations-count/wp-relations-count.html index 809ed7724a..81c5204928 100644 --- a/frontend/src/app/components/work-packages/wp-relations-count/wp-relations-count.html +++ b/frontend/src/app/components/work-packages/wp-relations-count/wp-relations-count.html @@ -1,3 +1,3 @@ - diff --git a/frontend/src/app/components/work-packages/wp-relations-count/wp-watchers-count.component.ts b/frontend/src/app/components/work-packages/wp-relations-count/wp-watchers-count.component.ts new file mode 100644 index 0000000000..78082c41d5 --- /dev/null +++ b/frontend/src/app/components/work-packages/wp-relations-count/wp-watchers-count.component.ts @@ -0,0 +1,30 @@ +import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {componentDestroyed} from 'ng2-rx-componentdestroyed'; +import {takeUntil} from 'rxjs/operators'; +import {WorkPackageCacheService} from '../../work-packages/work-package-cache.service'; +import {combineLatest} from 'rxjs'; + +@Component({ + templateUrl: './wp-relations-count.html', + selector: 'wp-watchers-count', +}) +export class WorkPackageWatchersCountComponent implements OnInit, OnDestroy { + @Input('wpId') wpId:string; + public count:number = 0; + + constructor(protected wpCacheService:WorkPackageCacheService) { + } + + ngOnInit():void { + this.wpCacheService.loadWorkPackage(this.wpId.toString()).values$() + .pipe( + takeUntil(componentDestroyed(this)) + ).subscribe((workPackage) => { + this.count = _.size(workPackage.watchers.elements); + }); +} + + ngOnDestroy():void { + // Nothing to do + } +} diff --git a/frontend/src/app/components/wp-by-version-graph/wp-by-version-graph.component.ts b/frontend/src/app/components/wp-by-version-graph/wp-by-version-graph.component.ts new file mode 100644 index 0000000000..6ac06a4522 --- /dev/null +++ b/frontend/src/app/components/wp-by-version-graph/wp-by-version-graph.component.ts @@ -0,0 +1,104 @@ +import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core'; +import { WorkPackageTableConfigurationObject } from 'core-components/wp-table/wp-table-configuration'; +import {DynamicBootstrapper} from "core-app/globals/dynamic-bootstrapper"; +import { + WorkPackageEmbeddedGraphComponent, + WorkPackageEmbeddedGraphDataset +} from "core-components/wp-table/embedded/wp-embedded-graph.component"; +import {I18nService} from "core-app/modules/common/i18n/i18n.service"; + +@Component({ + selector: 'wp-by-version-graph', + templateUrl: './wp-by-version-graph.template.html', +}) + +export class WorkPackageByVersionGraphComponent implements OnInit { + @Input() versionId:number; + @ViewChild('wpEmbeddedGraphMulti') private embeddedGraphMulti:WorkPackageEmbeddedGraphComponent; + @ViewChild('wpEmbeddedGraphSingle') private embeddedGraphSingle:WorkPackageEmbeddedGraphComponent; + public groupBy:string = 'status'; + public datasets:WorkPackageEmbeddedGraphDataset[] = []; + public displayModeSingle = true; + public availableGroupBy:{label:string, key:string}[]; + + constructor(readonly elementRef:ElementRef, + readonly I18n:I18nService) { + this.availableGroupBy = [{label: I18n.t('js.work_packages.properties.category'), key: 'category'}, + {label: I18n.t('js.work_packages.properties.type'), key: 'type'}, + {label: I18n.t('js.work_packages.properties.status'), key: 'status'}, + {label: I18n.t('js.work_packages.properties.priority'), key: 'priority'}, + {label: I18n.t('js.work_packages.properties.author'), key: 'author'}, + {label: I18n.t('js.work_packages.properties.assignee'), key: 'assignee'}]; + } + + ngOnInit() { + const element = this.elementRef.nativeElement; + this.versionId = JSON.parse(element.getAttribute('version-id')); + + this.setQueryProps(); + } + + public setQueryProps() { + this.datasets.length = 0; + + if (this.groupBy === 'status') { + this.displayModeSingle = true; + this.datasets.push({ label: this.I18n.t('js.label_all'), queryProps: this.propsBoth }); + } else { + this.displayModeSingle = false; + this.datasets.push({ label: this.I18n.t('js.label_open_work_packages'), queryProps: this.propsOpen }); + this.datasets.push({ label: this.I18n.t('js.label_closed_work_packages'), queryProps: this.propsClosed }); + } + + if (this.currentGraph) { + this.currentGraph.tableState.refreshRequired.putValue([false, false], ''); + } + } + + public get propsBoth() { + return this.baseProps(); + } + + public get propsOpen() { + return this.baseProps({status: { operator: 'o', values: []}}); + } + + public get propsClosed() { + return this.baseProps({status: { operator: 'c', values: []}}); + } + + private baseProps(filter?:any) { + let filters = [{ version: { operator: '=', values: [this.versionId] }}, + { subprojectId: { operator: '*', values: []}}]; + + if (filter) { + filters.push(filter); + } + + return { + 'columns[]': [], + filters: JSON.stringify(filters), + group_by: this.groupBy, + pageSize: 0 + }; + } + + public get displaySingle() { + return this.displayModeSingle; + } + + public get displayMulti() { + return !this.displayModeSingle; + } + + private get currentGraph() { + if (this.displaySingle) { + return this.embeddedGraphSingle; + } else { + return this.embeddedGraphMulti; + } + + } +} + +DynamicBootstrapper.register({ selector: 'wp-by-version-graph', cls: WorkPackageByVersionGraphComponent }); diff --git a/frontend/src/app/components/wp-by-version-graph/wp-by-version-graph.template.html b/frontend/src/app/components/wp-by-version-graph/wp-by-version-graph.template.html new file mode 100644 index 0000000000..a8c017cea6 --- /dev/null +++ b/frontend/src/app/components/wp-by-version-graph/wp-by-version-graph.template.html @@ -0,0 +1,16 @@ + + + + + + + diff --git a/frontend/src/app/components/wp-custom-actions/wp-custom-actions/wp-custom-action.component.html b/frontend/src/app/components/wp-custom-actions/wp-custom-actions/wp-custom-action.component.html index a61202b11c..804630fe29 100644 --- a/frontend/src/app/components/wp-custom-actions/wp-custom-actions/wp-custom-action.component.html +++ b/frontend/src/app/components/wp-custom-actions/wp-custom-actions/wp-custom-action.component.html @@ -1,6 +1,6 @@ diff --git a/frontend/src/app/components/wp-edit-form/work-package-changeset.ts b/frontend/src/app/components/wp-edit-form/work-package-changeset.ts index 839b939b83..2db9831738 100644 --- a/frontend/src/app/components/wp-edit-form/work-package-changeset.ts +++ b/frontend/src/app/components/wp-edit-form/work-package-changeset.ts @@ -196,6 +196,11 @@ export class WorkPackageChangeset { } this.wpActivity.clear(this.workPackage.id); + + // If there is a parent, its view has to be updated as well + if (this.workPackage.parent) { + this.wpCacheService.loadWorkPackage(this.workPackage.parent.id.toString(), true); + } this.wpCacheService.updateWorkPackage(this.workPackage); this.resource = null; this.clear(); @@ -357,4 +362,3 @@ export class WorkPackageChangeset { this.wpEditing.updateValue(this.workPackage.id, this); } } - diff --git a/frontend/src/app/components/wp-fast-table/builders/cell-builder.ts b/frontend/src/app/components/wp-fast-table/builders/cell-builder.ts index 4999764d5e..0cf48e6f66 100644 --- a/frontend/src/app/components/wp-fast-table/builders/cell-builder.ts +++ b/frontend/src/app/components/wp-fast-table/builders/cell-builder.ts @@ -19,6 +19,10 @@ export class CellBuilder { const td = document.createElement('td'); td.classList.add(tdClassName, wpCellTdClassName, attribute); + if (attribute === 'subject') { + td.classList.add('-max'); + } + const container = document.createElement('span'); container.classList.add(editCellContainer, editFieldContainerClass, attribute); const displayElement = this.fieldRenderer.render(workPackage, attribute, null); diff --git a/frontend/src/app/components/wp-fast-table/builders/highlighting/row-highlight-render-pass.ts b/frontend/src/app/components/wp-fast-table/builders/highlighting/row-highlight-render-pass.ts index ba7bd45c63..aa469f86c9 100644 --- a/frontend/src/app/components/wp-fast-table/builders/highlighting/row-highlight-render-pass.ts +++ b/frontend/src/app/components/wp-fast-table/builders/highlighting/row-highlight-render-pass.ts @@ -21,7 +21,7 @@ export class HighlightingRenderPass { return; } - const highlightAttribute = this.wpTableHighlighting.current; + const highlightAttribute = this.wpTableHighlighting.current.mode; // Get the computed style to identify bright properties const styles = window.getComputedStyle(document.body); diff --git a/frontend/src/app/components/wp-fast-table/state/wp-table-hierarchy.service.ts b/frontend/src/app/components/wp-fast-table/state/wp-table-hierarchy.service.ts index 43bdb5a74f..3a064fceec 100644 --- a/frontend/src/app/components/wp-fast-table/state/wp-table-hierarchy.service.ts +++ b/frontend/src/app/components/wp-fast-table/state/wp-table-hierarchy.service.ts @@ -42,11 +42,16 @@ export class WorkPackageTableHierarchiesService extends WorkPackageTableBaseServ state.current = active; state.last = null; - // hierarchies and group by are mutually exclusive if (active) { + // hierarchies and group by are mutually exclusive var groupBy = this.tableState.groupBy.value!; groupBy.current = undefined; this.tableState.groupBy.putValue(groupBy); + + // hierarchies and sort by are mutually exclusive + var sortBy = this.tableState.sortBy.value!; + sortBy.current = []; + this.tableState.sortBy.putValue(sortBy); } this.state.putValue(state); diff --git a/frontend/src/app/components/wp-fast-table/state/wp-table-highlighting.service.ts b/frontend/src/app/components/wp-fast-table/state/wp-table-highlighting.service.ts index 0a6a0a4976..0119673107 100644 --- a/frontend/src/app/components/wp-fast-table/state/wp-table-highlighting.service.ts +++ b/frontend/src/app/components/wp-fast-table/state/wp-table-highlighting.service.ts @@ -5,36 +5,58 @@ import {Injectable} from '@angular/core'; import {States} from 'core-components/states.service'; import {HighlightingMode} from "core-components/wp-fast-table/builders/highlighting/highlighting-mode.const"; import {DynamicCssService} from "../../../modules/common/dynamic-css/dynamic-css.service"; +import {WorkPackageTableHighlight} from "core-components/wp-fast-table/wp-table-highlight"; +import {BannersService} from "core-app/modules/common/enterprise/banners.service"; +import {HalResource} from "core-app/modules/hal/resources/hal-resource"; @Injectable() -export class WorkPackageTableHighlightingService extends WorkPackageTableBaseService implements WorkPackageQueryStateService { - public eeShowBanners:boolean = false; - +export class WorkPackageTableHighlightingService extends WorkPackageTableBaseService implements WorkPackageQueryStateService { public constructor(readonly states:States, + readonly Banners:BannersService, readonly dynamicCssService:DynamicCssService, readonly tableState:TableState) { super(tableState); - this.eeShowBanners = jQuery('body').hasClass('ee-banners-visible'); + } + + /** + * Decides whether we want to inline highlight the given field name. + * + * @param name A display field name such as 'status', 'priority'. + */ + public shouldHighlightInline(name:string):boolean { + // 1. Are we in inline mode or unable to render? + if (!this.isInline || this.Banners.eeShowBanners) { + return false; + } + + // 2. Is selected attributes === undefined or empty Array? + if (this.current.selectedAttributes === undefined || this.current.selectedAttributes === []) { + return true; + } + + // 3. Is name in selected attributes ? + return !!_.find(this.current.selectedAttributes, (attr:HalResource) => attr.id === name); } public get state() { return this.tableState.highlighting; } - public get current():HighlightingMode { - return this.filteredMode(this.state.getValueOr('inline')); + public get current():WorkPackageTableHighlight { + let value = this.state.getValueOr(new WorkPackageTableHighlight('inline')); + return this.filteredValue(value); } public get isInline() { - return this.current === 'inline'; + return this.current.mode === 'inline'; } public get isDisabled() { - return this.current === 'none'; + return this.current.mode === 'none'; } - public update(value:HighlightingMode) { - super.update(this.filteredMode(value)); + public update(value:WorkPackageTableHighlight) { + super.update(this.filteredValue(value)); // Load dynamic highlighting CSS if enabled if (!this.isDisabled) { @@ -42,25 +64,29 @@ export class WorkPackageTableHighlightingService extends WorkPackageTableBaseSer } } - public valueFromQuery(query:QueryResource):HighlightingMode { - return query.highlightingMode || this.filteredMode('inline'); + public valueFromQuery(query:QueryResource):WorkPackageTableHighlight { + return this.filteredValue(new WorkPackageTableHighlight(query.highlightingMode, query.highlightedAttributes)); } public hasChanged(query:QueryResource) { - return query.highlightingMode !== this.current; + return query.highlightingMode !== this.current.mode || + !_.isEqual(query.highlightedAttributes, this.current.selectedAttributes); } public applyToQuery(query:QueryResource):boolean { - query.highlightingMode = this.current; + const current = this.current; + query.highlightingMode = current.mode; + + query.highlightedAttributes = current.selectedAttributes; return false; } - private filteredMode(mode:HighlightingMode):HighlightingMode { - if (this.eeShowBanners) { - return 'none'; - } else { - return mode; - } + private filteredValue(value:WorkPackageTableHighlight):WorkPackageTableHighlight { + this.Banners.conditional(() => { + value.mode = 'none'; + value.selectedAttributes = undefined; + }); + return value; } } diff --git a/frontend/src/app/components/wp-fast-table/state/wp-table-sort-by.service.ts b/frontend/src/app/components/wp-fast-table/state/wp-table-sort-by.service.ts index 2188c18152..4536718023 100644 --- a/frontend/src/app/components/wp-fast-table/state/wp-table-sort-by.service.ts +++ b/frontend/src/app/components/wp-fast-table/state/wp-table-sort-by.service.ts @@ -77,6 +77,14 @@ export class WorkPackageTableSortByService extends WorkPackageTableBaseService 0) { + // hierarchies and sort by are mutually exclusive + var hierarchies = this.tableState.hierarchies.value!; + hierarchies.current = false; + hierarchies.last = null; + this.tableState.hierarchies.putValue(hierarchies); + query.hierarchies = hierarchies.current; + } query.sortBy = cloneHalResourceCollection(this.current.current); return true; } diff --git a/frontend/src/app/components/wp-fast-table/wp-table-highlight.ts b/frontend/src/app/components/wp-fast-table/wp-table-highlight.ts new file mode 100644 index 0000000000..3a86105948 --- /dev/null +++ b/frontend/src/app/components/wp-fast-table/wp-table-highlight.ts @@ -0,0 +1,63 @@ +// -- copyright +// OpenProject is a project management system. +// Copyright (C) 2012-2015 the OpenProject Foundation (OPF) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License version 3. +// +// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +// Copyright (C) 2006-2013 Jean-Philippe Lang +// Copyright (C) 2010-2013 the ChiliProject Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// See doc/COPYRIGHT.rdoc for more details. +// ++ + +import {QueryResource} from 'core-app/modules/hal/resources/query-resource'; +import {HighlightingMode} from "core-components/wp-fast-table/builders/highlighting/highlighting-mode.const"; +import {HalResource} from "core-app/modules/hal/resources/hal-resource"; + +export class WorkPackageTableHighlight { + private _selectedAttributes:HalResource[]|undefined; + + constructor(public mode:HighlightingMode = 'inline', + selected:HalResource[]|undefined = undefined) { + this.selectedAttributes = selected; + } + + public get selectedAttributes() { + return this._selectedAttributes; + } + + public set selectedAttributes(val:HalResource[]|undefined) { + if (_.isEmpty(val)) { + this._selectedAttributes = undefined; + } else { + this._selectedAttributes = val; + } + } + + public update(query:QueryResource|null) { + if (!query) { + this.mode = 'inline'; + this.selectedAttributes = undefined; + return; + } + + this.mode = query.highlightingMode; + this.selectedAttributes = query.selectedAttributes; + } +} diff --git a/frontend/src/app/components/wp-query-select/wp-query-select-dropdown.component.ts b/frontend/src/app/components/wp-query-select/wp-query-select-dropdown.component.ts index f44976eec8..2722cabc6c 100644 --- a/frontend/src/app/components/wp-query-select/wp-query-select-dropdown.component.ts +++ b/frontend/src/app/components/wp-query-select/wp-query-select-dropdown.component.ts @@ -32,7 +32,7 @@ import {WorkPackagesListService} from '../wp-list/wp-list.service'; import {WorkPackagesListChecksumService} from '../wp-list/wp-list-checksum.service'; import {WorkPackagesListComponent} from 'core-components/routing/wp-list/wp-list.component'; import {StateService, TransitionService} from '@uirouter/core'; -import {Component, ElementRef, OnDestroy, OnInit, ViewChild} from "@angular/core"; +import {Component, ElementRef, OnDestroy, OnInit, ViewChild, ChangeDetectorRef} from "@angular/core"; import {QueryDmService} from 'core-app/modules/hal/dm-services/query-dm.service'; import {LoadingIndicatorService} from "core-app/modules/common/loading-indicator/loading-indicator.service"; import {I18nService} from "core-app/modules/common/i18n/i18n.service"; @@ -107,7 +107,8 @@ export class WorkPackageQuerySelectDropdownComponent implements OnInit, OnDestro private initialized = false; - constructor(readonly element:ElementRef, + constructor(readonly ref:ChangeDetectorRef, + readonly element:ElementRef, readonly QueryDm:QueryDmService, readonly $state:StateService, readonly $transitions:TransitionService, @@ -233,7 +234,6 @@ export class WorkPackageQuerySelectDropdownComponent implements OnInit, OnDestro private loadQueries() { return this.loadingPromise = this.QueryDm .all(this.CurrentProject.identifier); - } private set loadingPromise(promise:Promise) { @@ -413,6 +413,8 @@ export class WorkPackageQuerySelectDropdownComponent implements OnInit, OnDestro let thisCategory:string = jQuery(category).attr("category"); this.expandCollapseCategory(thisCategory); }); + // Update view + this.ref.detectChanges(); }); }); } diff --git a/frontend/src/app/components/wp-query/url-params-helper.ts b/frontend/src/app/components/wp-query/url-params-helper.ts index 2f49a70a48..39f329fcb8 100644 --- a/frontend/src/app/components/wp-query/url-params-helper.ts +++ b/frontend/src/app/components/wp-query/url-params-helper.ts @@ -63,31 +63,54 @@ export class UrlParamsHelperService { } public encodeQueryJsonParams(query:QueryResource, additional:any = {}) { - var paramsData:any = { - c: query.columns.map(function (column) { - return column.id; - }) - }; - if (!!query.sums) { - paramsData.s = query.sums; - } + let paramsData:any = {}; - if (!!query.timelineVisible) { - paramsData.tv = query.timelineVisible; + paramsData = this.encodeColumns(paramsData, query); + paramsData = this.encodeSums(paramsData, query); + paramsData = this.encodeTimelineVisible(paramsData, query); + paramsData = this.encodeHighlightingMode(paramsData, query); + paramsData = this.encodeHighlightedAttributes(paramsData, query); + paramsData.hi = !!query.showHierarchies; + paramsData.g = _.get(query.groupBy, 'id', ''); + paramsData = this.encodeSortBy(paramsData, query); + paramsData = this.encodeFilters(paramsData, query); + paramsData.pa = additional.page; + paramsData.pp = additional.perPage; - if (!_.isEmpty(query.timelineLabels)) { - paramsData.tll = JSON.stringify(query.timelineLabels); - } + return JSON.stringify(paramsData); + } - paramsData.tzl = query.timelineZoomLevel; + private encodeColumns(paramsData:any, query:QueryResource) { + paramsData.c = query.columns.map(function (column) { + return column.id; + }) + return paramsData; + } + + private encodeSums(paramsData:any, query:QueryResource) { + if (!!query.sums) { + paramsData.s = query.sums; } + return paramsData; + } + private encodeHighlightingMode(paramsData:any, query:QueryResource) { if (query.highlightingMode && query.highlightingMode !== 'inline') { paramsData.hl = query.highlightingMode; } + return paramsData; + } - paramsData.hi = !!query.showHierarchies; - paramsData.g = _.get(query.groupBy, 'id', ''); + private encodeHighlightedAttributes(paramsData:any, query:QueryResource) { + if (query.highlightingMode === 'inline') { + if (Array.isArray(query.highlightedAttributes) && query.highlightedAttributes.length > 0) { + paramsData.hla = query.highlightedAttributes.map(el => el.id); + } + } + return paramsData; + } + + private encodeSortBy(paramsData:any, query:QueryResource) { if (query.sortBy) { paramsData.t = query .sortBy @@ -96,6 +119,10 @@ export class UrlParamsHelperService { }) .join(); } + return paramsData; + } + + private encodeFilters(paramsData:any, query:QueryResource) { if (query.filters && query.filters.length) { paramsData.f = query .filters @@ -113,13 +140,28 @@ export class UrlParamsHelperService { } else { paramsData.f = []; } + return paramsData; + } - paramsData.pa = additional.page; - paramsData.pp = additional.perPage; + private encode(paramsData:any, query:QueryResource) { - return JSON.stringify(paramsData); + return paramsData; + } + + private encodeTimelineVisible(paramsData:any, query:QueryResource) { + if (!!query.timelineVisible) { + paramsData.tv = query.timelineVisible; + + if (!_.isEmpty(query.timelineLabels)) { + paramsData.tll = JSON.stringify(query.timelineLabels); + } + + paramsData.tzl = query.timelineZoomLevel; + } + return paramsData; } + public buildV3GetQueryFromJsonParams(updateJson:string|null) { var queryData:any = { pageSize: this.paginationService.getPerPage() @@ -153,6 +195,10 @@ export class UrlParamsHelperService { queryData.highlightingMode = properties.hl; } + if (properties.hla) { + queryData["highlightedAttributes[]"] = properties.hla.map((column:any) => column); + } + if (properties.hi === false || properties.hi === true) { queryData.showHierarchies = properties.hi; } @@ -212,6 +258,10 @@ export class UrlParamsHelperService { queryData.highlightingMode = query.highlightingMode; } + if (query.highlightedAttributes && query.highlightingMode === 'inline') { + queryData.highlightedAttributes = query.highlightedAttributes.map(el => el.href); + } + queryData.showHierarchies = !!query.showHierarchies; queryData.groupBy = _.get(query.groupBy, 'id', ''); diff --git a/frontend/src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.directive.ts b/frontend/src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.directive.ts index 229d16aabb..892c3ee5c1 100644 --- a/frontend/src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.directive.ts +++ b/frontend/src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.directive.ts @@ -83,7 +83,7 @@ export class WorkPackageRelationsHierarchyComponent implements OnInit, OnDestroy let toLoad:string[] = []; if (this.workPackage.parent) { - toLoad.push(this.workPackage.parent.id); + toLoad.push(this.workPackage.parent.id.toString()); this.wpCacheService.loadWorkPackage(this.workPackage.parent.id).values$() .pipe( diff --git a/frontend/src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service.ts b/frontend/src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service.ts index c822176f25..b99ee0528c 100644 --- a/frontend/src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service.ts +++ b/frontend/src/app/components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service.ts @@ -117,6 +117,7 @@ export class WorkPackageRelationsHierarchyService { public removeChild(childWorkPackage:WorkPackageResource) { return childWorkPackage.$load().then(() => { + let parentWorkPackage = childWorkPackage.parent; return childWorkPackage.changeParent({ _links: { parent: { @@ -125,6 +126,7 @@ export class WorkPackageRelationsHierarchyService { }, lockVersion: childWorkPackage.lockVersion }).then(wp => { + this.wpCacheService.loadWorkPackage(parentWorkPackage.id.toString(), true); this.wpCacheService.updateWorkPackage(wp); }) .catch((error) => { diff --git a/frontend/src/app/components/wp-single-view-tabs/activity-panel/activity-entry-info.ts b/frontend/src/app/components/wp-single-view-tabs/activity-panel/activity-entry-info.ts index be9f093b3c..f63bbb2d9b 100644 --- a/frontend/src/app/components/wp-single-view-tabs/activity-panel/activity-entry-info.ts +++ b/frontend/src/app/components/wp-single-view-tabs/activity-panel/activity-entry-info.ts @@ -55,6 +55,10 @@ export class ActivityEntryInfo { return this.activity.href; } + public get version() { + return this.activity.version; + } + public get isNextDate() { return this.date !== this.dateOfPrevious; } diff --git a/frontend/src/app/components/wp-single-view-tabs/activity-panel/activity-tab.component.ts b/frontend/src/app/components/wp-single-view-tabs/activity-panel/activity-tab.component.ts index 556cb515cf..461acfd299 100644 --- a/frontend/src/app/components/wp-single-view-tabs/activity-panel/activity-tab.component.ts +++ b/frontend/src/app/components/wp-single-view-tabs/activity-panel/activity-tab.component.ts @@ -42,7 +42,7 @@ import {AngularTrackingHelpers} from "core-components/angular/tracking-functions export class WorkPackageActivityTabComponent extends ActivityPanelBaseController implements OnDestroy { public workPackage:WorkPackageResource; public tabName = this.I18n.t('js.work_packages.tabs.activity'); - public trackByHref = AngularTrackingHelpers.trackByHref; + public trackByHref = AngularTrackingHelpers.trackByHrefAndProperty('version'); constructor(readonly wpCacheService:WorkPackageCacheService, readonly $transition:Transition, diff --git a/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.html b/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.html index 662f132ace..451b185bb7 100644 --- a/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.html +++ b/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.html @@ -21,7 +21,13 @@ (change)="updateMode($event.target.value)" value="inline" name="highlighting_mode_switch"> - + {{ text.highlighting_mode.inline }} +   + +
  • diff --git a/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.ts b/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.ts index 092f8dcb03..239de6299b 100644 --- a/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.ts +++ b/frontend/src/app/components/wp-table/configuration-modal/tabs/highlighting-tab.component.ts @@ -1,10 +1,13 @@ import {Component, Injector} from '@angular/core'; import {TabComponent} from 'core-components/wp-table/configuration-modal/tab-portal-outlet'; -import { - WorkPackageTableHighlightingService -} from 'core-components/wp-fast-table/state/wp-table-highlighting.service'; +import {WorkPackageTableHighlightingService} from 'core-components/wp-fast-table/state/wp-table-highlighting.service'; import {I18nService} from "core-app/modules/common/i18n/i18n.service"; import {HighlightingMode} from "core-components/wp-fast-table/builders/highlighting/highlighting-mode.const"; +import {MultiToggledSelectOption} from "core-app/modules/common/multi-toggled-select/multi-toggled-select.component"; +import {HalResource} from "core-app/modules/hal/resources/hal-resource"; +import {States} from "core-app/components/states.service"; +import {WorkPackageTableHighlight} from "core-components/wp-fast-table/wp-table-highlight"; +import {BannersService} from "core-app/modules/common/enterprise/banners.service"; @Component({ templateUrl: './highlighting-tab.component.html' @@ -12,34 +15,63 @@ import {HighlightingMode} from "core-components/wp-fast-table/builders/highlight export class WpTableConfigurationHighlightingTab implements TabComponent { // Display mode - public highlightingMode:HighlightingMode|'entire-row' = 'inline'; + public highlightingMode:HighlightingMode = 'inline'; public entireRowMode:boolean = false; public lastEntireRowAttribute:HighlightingMode = 'status'; public eeShowBanners:boolean = false; + public availableMappedHighlightedAttributes:MultiToggledSelectOption[] = []; + + public selectedAttributes:MultiToggledSelectOption[] = []; + public text = { title: this.I18n.t('js.work_packages.table_configuration.highlighting'), highlighting_mode: { description: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.description'), none: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.none'), inline: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.inline'), + inline_all_attributes: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.inline_all'), status: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.status'), type: this.I18n.t('js.work_packages.properties.type'), priority: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.priority'), entire_row_by: this.I18n.t('js.work_packages.table_configuration.highlighting_mode.entire_row_by'), }, - upsaleEnterpriseOnly: this.I18n.t('js.work_packages.table_configuration.upsale.ee_only'), + upsaleEnterpriseOnly: this.I18n.t('js.upsale.ee_only'), upsaleAttributeHighlighting: this.I18n.t('js.work_packages.table_configuration.upsale.attribute_highlighting'), upsaleCheckOutLink: this.I18n.t('js.work_packages.table_configuration.upsale.check_out_link') }; constructor(readonly injector:Injector, readonly I18n:I18nService, + readonly states:States, + readonly Banners:BannersService, readonly wpTableHighlight:WorkPackageTableHighlightingService) { } public onSave() { - this.wpTableHighlight.update(this.highlightingMode as HighlightingMode); + let mode = this.highlightingMode; + let highlightedAttributes:HalResource[] = this.selectedAttributesAsHal(); + + const newValue = new WorkPackageTableHighlight(mode, highlightedAttributes); + this.wpTableHighlight.update(newValue); + } + + private selectedAttributesAsHal() { + if (this.isAllOptionSelected()) { + return []; + } else { + return this.multiToggleValuesToHal(this.selectedAttributes); + } + } + + private multiToggleValuesToHal(values:MultiToggledSelectOption[]) { + return values.map(el => { + return _.find(this.availableHighlightedAttributes, (column) => column.href === el.value)!; + }); + } + + private isAllOptionSelected() { + return this.selectedAttributes.length === 1 && _.get(this.selectedAttributes[0], 'value') === 'all'; } public updateMode(mode:HighlightingMode|'entire-row') { @@ -62,10 +94,47 @@ export class WpTableConfigurationHighlightingTab implements TabComponent { } ngOnInit() { - this.eeShowBanners = jQuery('body').hasClass('ee-banners-visible'); - this.updateMode(this.wpTableHighlight.current); + this.availableMappedHighlightedAttributes = + [this.allAttributesOption].concat(this.getAvailableAttributes()); + + this.setSelectedValues(); + + this.eeShowBanners = this.Banners.eeShowBanners; + this.updateMode(this.wpTableHighlight.current.mode); + if (this.eeShowBanners) { this.updateMode('none'); } } + + private setSelectedValues() { + const currentValues = this.wpTableHighlight.current.selectedAttributes; + if (currentValues === undefined) { + this.selectedAttributes = [this.allAttributesOption]; + } else { + this.selectedAttributes = this.mapAttributes(currentValues); + } + } + + public get availableHighlightedAttributes():HalResource[] { + const schema = this.states.query.form.value!.schema; + return schema.highlightedAttributes.allowedValues; + } + + public getAvailableAttributes():MultiToggledSelectOption[] { + return this.mapAttributes(this.availableHighlightedAttributes); + } + + private mapAttributes(input:HalResource[]):MultiToggledSelectOption[] { + return input.map((el:HalResource) => ({ name: el.name, value: el.$href! })); + } + + private get allAttributesOption():MultiToggledSelectOption { + return { + name: this.text.highlighting_mode.inline_all_attributes, + singleOnly: true, + selectWhenEmptySelection: true, + value: 'all' + }; + } } diff --git a/frontend/src/app/components/wp-table/embedded/wp-embedded-base.component.ts b/frontend/src/app/components/wp-table/embedded/wp-embedded-base.component.ts new file mode 100644 index 0000000000..be67cefe5f --- /dev/null +++ b/frontend/src/app/components/wp-table/embedded/wp-embedded-base.component.ts @@ -0,0 +1,99 @@ +import {AfterViewInit, Input, OnDestroy, OnInit} from '@angular/core'; +import {CurrentProjectService} from '../../projects/current-project.service'; +import {TableState} from '../table-state/table-state'; +import {WorkPackageStatesInitializationService} from '../../wp-list/wp-states-initialization.service'; +import {untilComponentDestroyed} from 'ng2-rx-componentdestroyed'; +import { + WorkPackageTableConfiguration, + WorkPackageTableConfigurationObject +} from 'core-components/wp-table/wp-table-configuration'; +import {LoadingIndicatorService} from 'core-app/modules/common/loading-indicator/loading-indicator.service'; +import {QueryDmService} from 'core-app/modules/hal/dm-services/query-dm.service'; +import {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper'; +import {I18nService} from "core-app/modules/common/i18n/i18n.service"; + +export abstract class WorkPackageEmbeddedBaseComponent implements OnInit, AfterViewInit, OnDestroy { + @Input('configuration') protected providedConfiguration:WorkPackageTableConfigurationObject; + @Input() public uniqueEmbeddedTableName:string = `embedded-table-${Date.now()}`; + @Input() public initialLoadingIndicator:boolean = true; + + public tableInformationLoaded = false; + public showTablePagination = false; + public configuration:WorkPackageTableConfiguration; + public error:string|null = null; + + protected constructor(readonly QueryDm:QueryDmService, + readonly tableState:TableState, + readonly I18n:I18nService, + readonly urlParamsHelper:UrlParamsHelperService, + readonly loadingIndicatorService:LoadingIndicatorService, + readonly wpStatesInitialization:WorkPackageStatesInitializationService, + readonly currentProject:CurrentProjectService) { + } + + ngOnInit() { + this.configuration = new WorkPackageTableConfiguration(this.providedConfiguration); + // Set embedded status in configuration + this.configuration.isEmbedded = true; + } + + ngAfterViewInit():void { + // Load initially + this.refresh(this.initialLoadingIndicator); + + // Reload results on refresh requests + this.tableState.refreshRequired + .values$() + .pipe(untilComponentDestroyed(this)) + .subscribe(() => this.refresh(false)); + } + + ngOnDestroy():void { + // noting to do + } + + get projectIdentifier() { + let identifier:string|null = null; + + if (this.configuration.projectContext) { + identifier = this.currentProject.identifier; + } else { + identifier = this.configuration.projectIdentifier; + } + + return identifier || undefined; + } + + public buildQueryProps() { + const query = this.tableState.query.value!; + this.wpStatesInitialization.applyToQuery(query); + + return this.urlParamsHelper.buildV3GetQueryFromQueryResource(query); + } + + protected setLoaded() { + this.tableInformationLoaded = this.configuration.tableVisible; + } + + public refresh(visible:boolean = true):Promise { + return this.loadQuery(visible); + } + + public set loadingIndicator(promise:Promise) { + if (this.configuration.tableVisible) { + this.loadingIndicatorService + .indicator(this.uniqueEmbeddedTableName) + .promise = promise; + } + } + + protected abstract loadQuery(visible:boolean):Promise; + + protected get queryProjectScope() { + if (!this.configuration.projectContext) { + return undefined; + } else { + return this.projectIdentifier; + } + } +} diff --git a/frontend/src/app/components/wp-table/embedded/wp-embedded-graph.component.ts b/frontend/src/app/components/wp-table/embedded/wp-embedded-graph.component.ts new file mode 100644 index 0000000000..2091a0d61c --- /dev/null +++ b/frontend/src/app/components/wp-table/embedded/wp-embedded-graph.component.ts @@ -0,0 +1,168 @@ +import {AfterViewInit, Component, Injector, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; +import {CurrentProjectService} from 'core-components/projects/current-project.service'; +import {TableState} from 'core-components/wp-table/table-state/table-state'; +import {WorkPackageStatesInitializationService} from 'core-components/wp-list/wp-states-initialization.service'; +import {WorkPackageTableRelationColumnsService} from 'core-components/wp-fast-table/state/wp-table-relation-columns.service'; +import {WorkPackageTableHierarchiesService} from 'core-components/wp-fast-table/state/wp-table-hierarchy.service'; +import {WorkPackageTableTimelineService} from 'core-components/wp-fast-table/state/wp-table-timeline.service'; +import {WorkPackageTablePaginationService} from 'core-components/wp-fast-table/state/wp-table-pagination.service'; +import {WorkPackageTableGroupByService} from 'core-components/wp-fast-table/state/wp-table-group-by.service'; +import {WorkPackageTableSortByService} from 'core-components/wp-fast-table/state/wp-table-sort-by.service'; +import {WorkPackageTableFiltersService} from 'core-components/wp-fast-table/state/wp-table-filters.service'; +import {WorkPackageTableColumnsService} from 'core-components/wp-fast-table/state/wp-table-columns.service'; +import {WorkPackageTableSumService} from 'core-components/wp-fast-table/state/wp-table-sum.service'; +import {WorkPackageTableAdditionalElementsService} from 'core-components/wp-fast-table/state/wp-table-additional-elements.service'; +import { WorkPackageTableConfiguration } from 'core-components/wp-table/wp-table-configuration'; +import {WorkPackageTableRefreshService} from 'core-components/wp-table/wp-table-refresh-request.service'; +import {OpTableActionsService} from 'core-components/wp-table/table-actions/table-actions.service'; +import {LoadingIndicatorService} from 'core-app/modules/common/loading-indicator/loading-indicator.service'; +import {WorkPackageTableSelection} from 'core-components/wp-fast-table/state/wp-table-selection.service'; +import {QueryDmService} from 'core-app/modules/hal/dm-services/query-dm.service'; +import {GroupObject} from 'core-app/modules/hal/resources/wp-collection-resource'; +import {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper'; +import {I18nService} from "core-app/modules/common/i18n/i18n.service"; +import { Chart } from 'chart.js'; +import {WorkPackageEmbeddedBaseComponent} from "core-components/wp-table/embedded/wp-embedded-base.component"; + +export interface WorkPackageEmbeddedGraphDataset { + label:string; + queryProps:any; + queryId?:number; + groups?:GroupObject[]; +} + +@Component({ + selector: 'wp-embedded-graph', + templateUrl: './wp-embedded-graph.html', + providers: [ + TableState, + OpTableActionsService, + WorkPackageStatesInitializationService, + WorkPackageTableRelationColumnsService, + WorkPackageTablePaginationService, + WorkPackageTableGroupByService, + WorkPackageTableHierarchiesService, + WorkPackageTableSortByService, + WorkPackageTableColumnsService, + WorkPackageTableFiltersService, + WorkPackageTableTimelineService, + WorkPackageTableSelection, + WorkPackageTableSumService, + WorkPackageTableAdditionalElementsService, + WorkPackageTableRefreshService, + ] +}) + +export class WorkPackageEmbeddedGraphComponent extends WorkPackageEmbeddedBaseComponent implements OnInit, AfterViewInit, OnDestroy { + @Input() public datasets:WorkPackageEmbeddedGraphDataset[]; + + public tableInformationLoaded = false; + public showTablePagination = false; + public configuration:WorkPackageTableConfiguration; + public error:string|null = null; + + public chartLabels:string[] = []; + public chartData:any = []; + public chartType:string = 'horizontalBar'; + public chartOptions = { + responsive: true, + scales: { + xAxes: [{ + stacked: true, + ticks: { + callback: (value:number) => { + if (Math.floor(value) === value) { + return value; + } else { + return null; + } + } + } + }], + yAxes: [{ + stacked: true + }] + } + }; + + constructor(readonly QueryDm:QueryDmService, + readonly tableState:TableState, + readonly I18n:I18nService, + readonly urlParamsHelper:UrlParamsHelperService, + readonly loadingIndicatorService:LoadingIndicatorService, + readonly wpStatesInitialization:WorkPackageStatesInitializationService, + readonly currentProject:CurrentProjectService) { + super(QueryDm, tableState, I18n, urlParamsHelper, loadingIndicatorService, wpStatesInitialization, currentProject); + } + + public refresh(visible:boolean = true):Promise { + return super.refresh(visible).then(() => this.updateChartData()); + } + + private updateChartData() { + let uniqLabels = _.uniq(this.datasets.reduce((array, dataset) => { + return array.concat(dataset.groups!.map((group) => group.value) as any); + }, [])) as string[]; + + let labelCountMaps = this.datasets.map((dataset) => { + let countMap = dataset.groups!.reduce((hash, group) => { + hash[group.value] = group.count; + return hash; + }, {} as any); + + return { + label: dataset.label, + data: uniqLabels.map((label) => { return countMap[label] || 0; }) + }; + }); + + uniqLabels = uniqLabels.map((label) => { + if (!label) { + return this.I18n.t('js.placeholders.default'); + } else { + return label; + } + }); + + // keep the array in order to update the labels + this.chartLabels.length = 0; + this.chartLabels.push(...uniqLabels); + this.chartData = labelCountMaps; + } + + protected loadQuery(visible:boolean = false) { + this.error = null; + + let queries = this.datasets.map((dataset:any) => { + return this.QueryDm + .find( + dataset.queryProps, + dataset.queryId, + this.queryProjectScope + ) + .then(query => { + dataset.groups = query.results.groups; + return dataset; + }) + ; + }); + + const promise = Promise.all(queries) + .then((datasets) => { + this.setLoaded(); + return datasets; + }) + .catch((error) => { + this.error = this.I18n.t( + 'js.error.embedded_table_loading', + { message: _.get(error, 'message', error) } + ); + }); + + if (visible) { + this.loadingIndicator = promise; + } + + return promise; + } +} diff --git a/frontend/src/app/components/wp-table/embedded/wp-embedded-graph.html b/frontend/src/app/components/wp-table/embedded/wp-embedded-graph.html new file mode 100644 index 0000000000..38d68abbde --- /dev/null +++ b/frontend/src/app/components/wp-table/embedded/wp-embedded-graph.html @@ -0,0 +1,15 @@ +
    + + + + +
    + +
    +
    + diff --git a/frontend/src/app/components/wp-table/embedded/wp-embedded-table.component.ts b/frontend/src/app/components/wp-table/embedded/wp-embedded-table.component.ts index b31e79dfd5..19c0f3fad1 100644 --- a/frontend/src/app/components/wp-table/embedded/wp-embedded-table.component.ts +++ b/frontend/src/app/components/wp-table/embedded/wp-embedded-table.component.ts @@ -14,10 +14,7 @@ import {WorkPackageTableSumService} from 'core-components/wp-fast-table/state/wp import {WorkPackageTableAdditionalElementsService} from 'core-components/wp-fast-table/state/wp-table-additional-elements.service'; import {withLatestFrom} from 'rxjs/operators'; import {untilComponentDestroyed} from 'ng2-rx-componentdestroyed'; -import { - WorkPackageTableConfiguration, - WorkPackageTableConfigurationObject -} from 'core-components/wp-table/wp-table-configuration'; +import { WorkPackageTableConfiguration } from 'core-components/wp-table/wp-table-configuration'; import {OpTableActionFactory} from 'core-components/wp-table/table-actions/table-action'; import {WorkPackageTableRefreshService} from 'core-components/wp-table/wp-table-refresh-request.service'; import {OpTableActionsService} from 'core-components/wp-table/table-actions/table-actions.service'; @@ -30,6 +27,7 @@ import {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper import {WpTableConfigurationModalComponent} from 'core-components/wp-table/configuration-modal/wp-table-configuration.modal'; import {OpModalService} from 'core-components/op-modals/op-modal.service'; import {I18nService} from "core-app/modules/common/i18n/i18n.service"; +import {WorkPackageEmbeddedBaseComponent} from "core-components/wp-table/embedded/wp-embedded-base.component"; @Component({ selector: 'wp-embedded-table', @@ -52,16 +50,12 @@ import {I18nService} from "core-app/modules/common/i18n/i18n.service"; WorkPackageTableRefreshService, ] }) -export class WorkPackageEmbeddedTableComponent implements OnInit, AfterViewInit, OnDestroy { +export class WorkPackageEmbeddedTableComponent extends WorkPackageEmbeddedBaseComponent implements OnInit, AfterViewInit, OnDestroy { @Input('queryId') public queryId?:number; @Input('queryProps') public queryProps:any = {}; - @Input('configuration') private providedConfiguration:WorkPackageTableConfigurationObject; - @Input() public uniqueEmbeddedTableName:string = `embedded-table-${Date.now()}`; - @Input() public initialLoadingIndicator:boolean = true; @Input() public tableActions:OpTableActionFactory[] = []; @Input() public compactTableStyle:boolean = false; - private query:QueryResource; public tableInformationLoaded = false; public showTablePagination = false; public configuration:WorkPackageTableConfiguration; @@ -79,31 +73,17 @@ export class WorkPackageEmbeddedTableComponent implements OnInit, AfterViewInit, readonly wpTablePagination:WorkPackageTablePaginationService, readonly wpStatesInitialization:WorkPackageStatesInitializationService, readonly currentProject:CurrentProjectService) { - - } - - ngOnInit() { - this.configuration = new WorkPackageTableConfiguration(this.providedConfiguration); - // Set embedded status in configuration - this.configuration.isEmbedded = true; + super(QueryDm, tableState, I18n, urlParamsHelper, loadingIndicatorService, wpStatesInitialization, currentProject); } ngAfterViewInit():void { + super.ngAfterViewInit(); // Provision embedded table actions if (this.tableActions) { this.tableActionsService.setActions(...this.tableActions); } - // Load initial query - this.loadQuery(this.initialLoadingIndicator); - - // Reload results on refresh requests - this.tableState.refreshRequired - .values$() - .pipe(untilComponentDestroyed(this)) - .subscribe(() => this.refresh(false)); - // Reload results on changes to pagination this.tableState.ready.fireOnStateChange(this.wpTablePagination.state, 'Query loaded').values$().pipe( @@ -115,9 +95,6 @@ export class WorkPackageEmbeddedTableComponent implements OnInit, AfterViewInit, }); } - ngOnDestroy():void { - } - public openConfigurationModal(onUpdated:() => void) { this.tableState.query .valuesPromise() @@ -130,25 +107,6 @@ export class WorkPackageEmbeddedTableComponent implements OnInit, AfterViewInit, }); } - get projectIdentifier() { - let identifier:string|null = null; - - if (this.configuration.projectContext) { - identifier = this.currentProject.identifier; - } else { - identifier = this.configuration.projectIdentifier; - } - - return identifier || undefined; - } - - public buildQueryProps() { - const query = this.tableState.query.value!; - this.wpStatesInitialization.applyToQuery(query); - - return this.urlParamsHelper.buildV3GetQueryFromQueryResource(query); - } - private initializeStates(query:QueryResource, results:WorkPackageCollectionResource) { this.tableState.ready.doAndTransition('Query loaded', () => { this.wpStatesInitialization.clearStates(); @@ -158,7 +116,7 @@ export class WorkPackageEmbeddedTableComponent implements OnInit, AfterViewInit, return this.tableState.tableRendering.onQueryUpdated.valuesPromise() .then(() => { this.showTablePagination = results.total > results.count; - this.tableInformationLoaded = this.configuration.tableVisible; + this.setLoaded(); // Disable compact mode when timeline active if (this.wpTableTimeline.isVisible) { @@ -168,19 +126,7 @@ export class WorkPackageEmbeddedTableComponent implements OnInit, AfterViewInit, }); } - public refresh(visible:boolean = true):Promise { - return this.loadQuery(visible); - } - - public set loadingIndicator(promise:Promise) { - if (this.configuration.tableVisible) { - this.loadingIndicatorService - .indicator(this.uniqueEmbeddedTableName) - .promise = promise; - } - } - - private loadQuery(visible:boolean = true) { + protected loadQuery(visible:boolean = true) { // HACK: Decrease loading time of queries when results are not needed. // We should allow the backend to disable results embedding instead. @@ -195,7 +141,10 @@ export class WorkPackageEmbeddedTableComponent implements OnInit, AfterViewInit, this.queryId, this.queryProjectScope ) - .then((query:QueryResource) => this.initializeStates(query, query.results)) + .then((query:QueryResource) => { + this.initializeStates(query, query.results); + return query; + }) .catch((error) => { this.error = this.I18n.t( 'js.error.embedded_table_loading', @@ -209,12 +158,4 @@ export class WorkPackageEmbeddedTableComponent implements OnInit, AfterViewInit, return promise; } - - private get queryProjectScope() { - if (!this.configuration.projectContext) { - return undefined; - } else { - return this.projectIdentifier; - } - } } diff --git a/frontend/src/app/components/wp-table/table-state/table-state.ts b/frontend/src/app/components/wp-table/table-state/table-state.ts index f08c188155..817bed7822 100644 --- a/frontend/src/app/components/wp-table/table-state/table-state.ts +++ b/frontend/src/app/components/wp-table/table-state/table-state.ts @@ -21,6 +21,7 @@ import { } from 'core-app/modules/hal/resources/wp-collection-resource'; import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource'; import {HighlightingMode} from "core-components/wp-fast-table/builders/highlighting/highlighting-mode.const"; +import {WorkPackageTableHighlight} from "core-components/wp-fast-table/wp-table-highlight"; @Injectable() export class TableState extends StatesGroup { @@ -60,7 +61,7 @@ export class TableState extends StatesGroup { // Hierarchies of table hierarchies = input(); // Highlighting mode - highlighting = input(); + highlighting = input(); // State to be updated when the table is up to date rendered = input(); diff --git a/frontend/src/app/globals/unsupported-browsers.ts b/frontend/src/app/globals/unsupported-browsers.ts index bb81260493..49ee155d6a 100644 --- a/frontend/src/app/globals/unsupported-browsers.ts +++ b/frontend/src/app/globals/unsupported-browsers.ts @@ -37,6 +37,7 @@ declare const I18n:GlobalI18n; // As we don't support ANY version of msie, so treat 11 (last ie before edge) as unsupported const minimumSupported = { msie: '12', + safari: '12', firefox: '60' }; let additionalMessage = I18n.t("js.unsupported_browser.update_message"); diff --git a/frontend/src/app/modules/common/enterprise/banners.service.ts b/frontend/src/app/modules/common/enterprise/banners.service.ts new file mode 100644 index 0000000000..c106081974 --- /dev/null +++ b/frontend/src/app/modules/common/enterprise/banners.service.ts @@ -0,0 +1,53 @@ +// -- copyright +// OpenProject is a project management system. +// Copyright (C) 2012-2015 the OpenProject Foundation (OPF) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License version 3. +// +// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +// Copyright (C) 2006-2013 Jean-Philippe Lang +// Copyright (C) 2010-2013 the ChiliProject Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// See doc/COPYRIGHT.rdoc for more details. +// ++ + +import {Inject, Injectable} from '@angular/core'; +import {DOCUMENT} from "@angular/common"; +import {PathHelperService} from "../path-helper/path-helper.service"; + +@Injectable() +export class BannersService { + + private readonly _banners:boolean = true; + + constructor(@Inject(DOCUMENT) protected documentElement:Document) { + this._banners = documentElement.body.classList.contains('ee-banners-visible'); + } + + public get eeShowBanners():boolean { + return this._banners; + } + + public conditional(bannersVisible?:() => void, bannersNotVisible?:() => void) { + this._banners ? this.callMaybe(bannersVisible) : this.callMaybe(bannersNotVisible); + } + + private callMaybe(func?:Function) { + func && func(); + } +} diff --git a/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.html b/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.html new file mode 100644 index 0000000000..6fa902212e --- /dev/null +++ b/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.html @@ -0,0 +1,69 @@ +
    + + + + + + + + +
    diff --git a/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.ts b/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.ts new file mode 100644 index 0000000000..181aa9fff2 --- /dev/null +++ b/frontend/src/app/modules/common/multi-toggled-select/multi-toggled-select.component.ts @@ -0,0 +1,143 @@ +// -- copyright +// OpenProject is a project management system. +// Copyright (C) 2012-2015 the OpenProject Foundation (OPF) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License version 3. +// +// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +// Copyright (C) 2006-2013 Jean-Philippe Lang +// Copyright (C) 2010-2013 the ChiliProject Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// See doc/COPYRIGHT.rdoc for more details. +// ++ + +import {Component, EventEmitter, Input, OnInit, Output} from "@angular/core"; +import {I18nService} from "core-app/modules/common/i18n/i18n.service"; +import {AngularTrackingHelpers} from "core-components/angular/tracking-functions"; + +export interface MultiToggledSelectOption { + name:string; + singleOnly?:true; + selectWhenEmptySelection?:true; + value:any; +} + +@Component({ + selector: 'multi-toggled-select', + templateUrl: './multi-toggled-select.component.html' +}) +export class MultiToggledSelectComponent implements OnInit { + @Input() availableOptions:T[]; + @Input() initialSelection:T[]|undefined; + @Input() selectHtmlId:string|undefined; + @Input() isRequired:boolean = false; + @Input() isDisabled:boolean = false; + @Input() currentValueInvalid:boolean = false; + + @Output() onValueChange = new EventEmitter(); + @Output() onMultiToggle = new EventEmitter(); + @Output() onValueKeydown = new EventEmitter(); + + public text = { + requiredPlaceholder: this.I18n.t('js.placeholders.selection'), + placeholder: this.I18n.t('js.placeholders.default'), + switch_to_single_select: this.I18n.t('js.work_packages.label_switch_to_single_select'), + switch_to_multi_select: this.I18n.t('js.work_packages.label_switch_to_multi_select'), + }; + + /** Whether we're currently multi-selecting */ + public isMultiselect = false; + + /** Comparer function for values */ + public compareByValue = AngularTrackingHelpers.compareByAttribute('value'); + + /** Current selected option */ + private _selectedOption:T|T[]|undefined; + + constructor(protected readonly I18n:I18nService) { + } + + ngOnInit() { + this.ensureSingleInitialSelectionIsNotArray(); + this.isMultiselect = this.hasMultipleSelectedOptions(); + } + + public hasMultipleSelectedOptions() { + return (this.selectedOption instanceof Array) && this.selectedOption.length > 1; + } + + public emitValueChange() { + this.onValueChange.emit(_.castArray(this.selectedOption || [])); + } + + public toggleMultiselect() { + this.isMultiselect = !this.isMultiselect; + + if (this.isMultiselect ) { + /** Switching to multi select. + * Ensure selectedOption is either an empty Array or the selectedOption, + * Preventing cases such as `[undefined]`. **/ + this._selectedOption = _.castArray(this.selectedOption || []); + } else { + /** Switching to single select. **/ + if (Array.isArray(this.selectedOption)) { + if (this.selectedOption.length === 0) { + this.onEmptySelection(); + } else { + this._selectedOption = (this.selectedOption as T[])[0]; + } + this.emitValueChange(); + } + } + } + + public get availableMultiOptions() { + return this.availableOptions.filter(el => el.singleOnly !== true); + } + + public get selectedOption():T|T[]|undefined { + return this._selectedOption; + } + + public set selectedOption(val:T|T[]|undefined) { + this._selectedOption = val; + } + + public get nullOption():T { + return { name: this.text.placeholder, value: '' } as T; + } + + /** Ensure that the initialSelection becomes an Array. + * `undefined` becomes an empty Array. **/ + private ensureSingleInitialSelectionIsNotArray():void { + if (Array.isArray(this.initialSelection)) { + if (this.initialSelection.length === 1) { + this.selectedOption = this.initialSelection[0]; + } else { + this.selectedOption = this.initialSelection; + } + } + } + + private onEmptySelection():void { + const newSelection = _.find(this.availableOptions, option => option.selectWhenEmptySelection === true); + if (newSelection) { + this.selectedOption = newSelection; + } + } +} diff --git a/frontend/src/app/modules/common/openproject-common.module.ts b/frontend/src/app/modules/common/openproject-common.module.ts index d4f299a982..c4205f38ef 100644 --- a/frontend/src/app/modules/common/openproject-common.module.ts +++ b/frontend/src/app/modules/common/openproject-common.module.ts @@ -30,7 +30,7 @@ import {FormsModule} from "@angular/forms"; import {BrowserModule} from "@angular/platform-browser"; -import {APP_INITIALIZER, Injector, NgModule} from "@angular/core"; +import {APP_INITIALIZER, Injector, Input, NgModule} from "@angular/core"; import {AuthoringComponent} from 'core-app/modules/common/authoring/authoring.component'; import {ConfigurationService} from 'core-app/modules/common/config/configuration.service'; @@ -63,6 +63,8 @@ import {CKEditorSetupService} from "core-app/modules/common/ckeditor/ckeditor-se import {CKEditorPreviewService} from "core-app/modules/common/ckeditor/ckeditor-preview.service"; import {ColorsAutocompleter} from "core-app/modules/common/colors/colors-autocompleter.component"; import {DynamicCssService} from "./dynamic-css/dynamic-css.service"; +import {MultiToggledSelectComponent} from "core-app/modules/common/multi-toggled-select/multi-toggled-select.component"; +import {BannersService} from "core-app/modules/common/enterprise/banners.service"; export function bootstrapModule(injector:Injector) { return () => { @@ -105,6 +107,9 @@ export function bootstrapModule(injector:Injector) { // Table highlight HighlightColDirective, + // Multi select component + MultiToggledSelectComponent, + // CKEditor OpCkeditorComponent, ], @@ -140,6 +145,8 @@ export function bootstrapModule(injector:Injector) { CopyToClipboardDirective, ColorsAutocompleter, + + MultiToggledSelectComponent, ], entryComponents: [ OpDateTimeComponent, @@ -153,6 +160,7 @@ export function bootstrapModule(injector:Injector) { { provide: APP_INITIALIZER, useFactory: bootstrapModule, deps: [Injector], multi: true }, I18nService, DynamicCssService, + BannersService, NotificationsService, FocusHelperService, LoadingIndicatorService, diff --git a/frontend/src/app/modules/fields/display/field-types/wp-display-highlightable-field.module.ts b/frontend/src/app/modules/fields/display/field-types/wp-display-highlightable-field.module.ts index 8d9eb33339..e1038fd357 100644 --- a/frontend/src/app/modules/fields/display/field-types/wp-display-highlightable-field.module.ts +++ b/frontend/src/app/modules/fields/display/field-types/wp-display-highlightable-field.module.ts @@ -33,6 +33,6 @@ export class HighlightableDisplayField extends DisplayField { protected readonly wpTableHighlighting:WorkPackageTableHighlightingService = this.$injector.get(WorkPackageTableHighlightingService); public get shouldHighlight() { - return this.context.options.colorize !== false && (this.context.container !== 'table' || this.wpTableHighlighting.isInline); + return this.context.options.colorize !== false && (this.context.container !== 'table' || this.wpTableHighlighting.shouldHighlightInline(this.name)); } } diff --git a/frontend/src/app/modules/hal/hal-link/hal-link.ts b/frontend/src/app/modules/hal/hal-link/hal-link.ts index f7af705988..584da05094 100644 --- a/frontend/src/app/modules/hal/hal-link/hal-link.ts +++ b/frontend/src/app/modules/hal/hal-link/hal-link.ts @@ -42,6 +42,11 @@ export interface HalLinkInterface { identifier?:string; } +export interface HalLinkSource { + href:string|null; + title:string; +} + export interface CallableHalLink extends HalLinkInterface { $link:this; data?:Promise; diff --git a/frontend/src/app/modules/hal/resources/query-resource.ts b/frontend/src/app/modules/hal/resources/query-resource.ts index 8bd763f37a..c9caafd0af 100644 --- a/frontend/src/app/modules/hal/resources/query-resource.ts +++ b/frontend/src/app/modules/hal/resources/query-resource.ts @@ -66,6 +66,7 @@ export class QueryResource extends HalResource { public timelineVisible:boolean; public timelineZoomLevel:TimelineZoomLevel; public highlightingMode:HighlightingMode; + public highlightedAttributes:HalResource[]|undefined; public timelineLabels:TimelineLabels; public showHierarchies:boolean; public public:boolean; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index d87f2a43f1..ec532f0e87 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -22,7 +22,7 @@ "noFallthroughCasesInSwitch": true, "strictNullChecks": true, "skipLibCheck": true, - "baseUrl": "./", + "baseUrl": "./src/", "typeRoots": [ "node_modules/@types" ], diff --git a/lib/api/v3/queries/query_representer.rb b/lib/api/v3/queries/query_representer.rb index 87b18a3192..a9fe2fada4 100644 --- a/lib/api/v3/queries/query_representer.rb +++ b/lib/api/v3/queries/query_representer.rb @@ -217,6 +217,30 @@ class QueryRepresenter < ::API::Decorators::Single end } + resources :highlighted_attributes, + getter: ->(*) { + represented.highlighted_columns.map do |column| + ::API::V3::Queries::Columns::QueryColumnsFactory.create(column) + end + }, + setter: ->(fragment:, **) { + columns = Array(fragment).map do |column| + name = id_from_href "queries/columns", column['href'] + + ::API::Utilities::PropertyNameConverter.to_ar_name(name, context: WorkPackage.new) if name + end + + represented.highlighted_attributes = columns.map(&:to_sym).compact if fragment + }, + link: ->(*) { + represented.highlighted_columns.map do |column| + { + href: api_v3_paths.query_column(convert_attribute(column.name)), + title: column.caption + } + end + } + property :starred, writeable: true diff --git a/lib/api/v3/queries/schemas/query_schema_representer.rb b/lib/api/v3/queries/schemas/query_schema_representer.rb index 6400ea77e6..cb2159dbaf 100644 --- a/lib/api/v3/queries/schemas/query_schema_representer.rb +++ b/lib/api/v3/queries/schemas/query_schema_representer.rb @@ -186,6 +186,26 @@ def self.filters_schema } } + schema_with_allowed_collection :highlighted_attributes, + type: '[]QueryColumn', + required: false, + writable: true, + has_default: true, + visibility: false, + values_callback: -> { represented.available_highlighting_columns }, + value_representer: ->(column) { + Columns::QueryColumnsFactory.representer(column) + }, + link_factory: ->(column) { + converted_name = convert_attribute(column.name) + + { + href: api_v3_paths.query_column(converted_name), + id: converted_name, + title: column.caption + } + } + schema_with_allowed_collection :sort_by, type: '[]QuerySortBy', required: false, diff --git a/lib/open_project/configuration.rb b/lib/open_project/configuration.rb index ad9134726c..607ad26807 100644 --- a/lib/open_project/configuration.rb +++ b/lib/open_project/configuration.rb @@ -46,6 +46,7 @@ module Configuration 'database_cipher_key' => nil, 'force_help_link' => nil, 'force_formatting_help_link' => nil, + 'log_level' => 'info', 'scm_git_command' => nil, 'scm_subversion_command' => nil, 'scm_local_checkout_path' => 'repositories', # relative to OpenProject directory diff --git a/lib/open_project/design.rb b/lib/open_project/design.rb index 524af6884b..a0808ae6f0 100644 --- a/lib/open_project/design.rb +++ b/lib/open_project/design.rb @@ -143,8 +143,8 @@ class Design 'drop-down-unselected-font-color' => "$body-font-color", 'drop-down-selected-font-color' => "$primary-color", 'drop-down-hover-font-color' => "$drop-down-selected-font-color", - 'drop-down-selected-bg-color' => "#EFEFEF", - 'drop-down-hover-bg-color' => "$drop-down-selected-bg-color", + 'drop-down-selected-bg-color' => "#E7E7E7", + 'drop-down-hover-bg-color' => "#EFEFEF", 'context-menu-unselected-font-color' => "$drop-down-unselected-font-color", 'context-menu-hover-font-color' => "$drop-down-hover-font-color", 'content-box-border' => "1px solid $content-default-border-color", diff --git a/lib/open_project/version.rb b/lib/open_project/version.rb index c4e97c26e0..9551cbe820 100644 --- a/lib/open_project/version.rb +++ b/lib/open_project/version.rb @@ -33,8 +33,8 @@ module OpenProject module VERSION #:nodoc: MAJOR = 8 - MINOR = 0 - PATCH = 2 + MINOR = 1 + PATCH = 0 TINY = PATCH # Redmine compat # Used by semver to define the special version (if any). diff --git a/spec/controllers/versions_controller_spec.rb b/spec/controllers/versions_controller_spec.rb index 65a05d52cc..c25bccea5b 100644 --- a/spec/controllers/versions_controller_spec.rb +++ b/spec/controllers/versions_controller_spec.rb @@ -248,33 +248,4 @@ expect { Version.find(@deleted) }.to raise_error ActiveRecord::RecordNotFound end end - - describe '#status_by' do - before do - login_as(user) - end - - context 'status by version' do - before do - get :status_by, - xhr: true, - params: { id: version2.id }, format: :js - end - - it { expect(response).to be_success } - it { expect(response).to render_template('versions/_work_package_counts') } - end - - context 'status by version with status_by' do - before do - get :status_by, - xhr: true, - params: { id: version2.id, status_by: 'status' }, - format: :js - end - - it { expect(response).to be_success } - it { expect(response).to render_template('versions/_work_package_counts') } - end - end end diff --git a/spec/features/auth/consent_auth_stage_spec.rb b/spec/features/auth/consent_auth_stage_spec.rb index 8a59fbdeb5..5939d8880d 100644 --- a/spec/features/auth/consent_auth_stage_spec.rb +++ b/spec/features/auth/consent_auth_stage_spec.rb @@ -99,6 +99,12 @@ def expect_not_logged_in context 'when enabled, but consent exists', with_settings: { consent_info: { en: '# Consent header!' } } do let(:consent_required) { true } + + after do + # Clear session to avoid that the onboarding tour starts + page.execute_script("window.sessionStorage.clear();") + end + it 'should show consent' do expect(Setting.consent_time).to be_blank login_with user.login, user_password diff --git a/spec/features/custom_fields/activate_in_project_spec.rb b/spec/features/custom_fields/activate_in_project_spec.rb index 49b2a29133..22ec23c883 100644 --- a/spec/features/custom_fields/activate_in_project_spec.rb +++ b/spec/features/custom_fields/activate_in_project_spec.rb @@ -42,7 +42,7 @@ wp end let(:wp_page) { Pages::FullWorkPackage.new(work_package) } - let(:project_settings_page) { Pages::ProjectSettings.new(work_package.project) } + let(:project_settings_page) { Pages::Projects::Settings.new(work_package.project) } before do login_as(user) diff --git a/spec/features/onboarding/onboarding_tour_spec.rb b/spec/features/onboarding/onboarding_tour_spec.rb new file mode 100644 index 0000000000..bbf9f876a6 --- /dev/null +++ b/spec/features/onboarding/onboarding_tour_spec.rb @@ -0,0 +1,149 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe 'onboarding tour for new users', js: true do + let(:user) { FactoryBot.create :admin } + let(:project) { FactoryBot.create :project, name: 'Demo project', identifier: 'demo-project', is_public: true, enabled_module_names: %w[work_package_tracking wiki] } + let(:scrum_project) {FactoryBot.create :project, name: 'Scrum project', identifier: 'your-scrum-project', is_public: true, enabled_module_names: %w[work_package_tracking] } + let!(:wp_1) { FactoryBot.create(:work_package, project: project) } + let(:next_button) { find('.enjoyhint_next_btn') } + + context 'as a new user' do + before do + login_as user + allow(Setting).to receive(:demo_projects_available).and_return(true) + allow(Setting).to receive(:welcome_title).and_return('Hey ho!') + allow(Setting).to receive(:welcome_on_homescreen?).and_return(true) + end + + it 'I can select a language' do + visit home_path first_time_user: true + expect(page).to have_text 'Please select your language' + + select 'Deutsch', :from => 'user_language' + click_button 'Save' + + expect(page).to have_text 'Projekt auswählen' + end + + context 'the tutorial does not start' do + before do + allow(Setting).to receive(:welcome_text).and_return(" #{project.name} ") + visit home_path first_time_user: true + + select 'English', :from => 'user_language' + click_button 'Save' + end + + it 'when the welcome block does not include the demo projects' do + expect(page).not_to have_text 'Take a three minutes introduction tour to learn the most important features.' + expect(page).not_to have_selector '.enjoyhint_next_btn' + end + end + + context 'the tutorial starts' do + before do + allow(Setting).to receive(:welcome_text).and_return(" #{project.name} #{scrum_project.name} ") + visit home_path first_time_user: true + + select 'English', :from => 'user_language' + click_button 'Save' + end + + after do + # Clear session to avoid that the onboarding tour starts + page.execute_script("window.sessionStorage.clear();") + end + + it 'directly after the language selection' do + # The tutorial appears + expect(page).to have_text 'Take a three minutes introduction tour to learn the most important features.' + expect(page).to have_selector '.enjoyhint_next_btn:not(.enjoyhint_hide)' + end + + it 'and I skip the tutorial' do + find('.enjoyhint_skip_btn').click + + # The tutorial disappears + expect(page).not_to have_text 'Take a three minutes introduction tour to learn the most important features.' + expect(page).not_to have_selector '.enjoyhint_next_btn' + + page.driver.browser.navigate.refresh + + # The tutorial did not start again + expect(page).not_to have_text 'Take a three minutes introduction tour to learn the most important features.' + expect(page).not_to have_selector '.enjoyhint_next_btn' + end + + it 'and I continue the tutorial' do + next_button.click + expect(page).to have_text 'Please select one of the projects with useful demo data to get started.' + + find('.welcome').click_link 'Demo project' + expect(page).to have_current_path "/projects/#{project.identifier}/work_packages/?start_onboarding_tour=true" + expect(page).not_to have_selector('.loading-indicator') + expect(page).to have_text 'This is the Work package list' + + next_button.click + expect(page).to have_current_path project_work_package_path(project, wp_1.id, 'activity') + expect(page).to have_text 'Within the Work package details you find all relevant information' + + next_button.click + expect(page).to have_text 'With the arrow you can navigate back to the work package list.' + + next_button.click + expect(page).to have_text 'The Create button will add a new work package to your project' + + next_button.click + expect(page).to have_text 'You can activate the Gantt chart to create a timeline for your project.' + + next_button.click + expect(page).to have_text 'Here you can edit your project plan. Create new phases, milestones, and add dependencies.' + + next_button.click + expect(page).to have_text "With the arrow you can navigate back to the project's Main menu." + + next_button.click + expect(page).to have_text 'Invite new Members to join your project.' + + next_button.click + expect(page).to have_text 'Within the Wiki you can document and share knowledge together with your team.' + + next_button.click + expect(page).to have_text 'In the Help menu you will find a user guide and additional help resources.' + + next_button.click + expect(page).not_to have_selector '.enjoy_hint_label' + end + end + end +end + + diff --git a/spec/features/projects/copy_spec.rb b/spec/features/projects/copy_spec.rb index 7a0787b8bd..ce0a84fc19 100644 --- a/spec/features/projects/copy_spec.rb +++ b/spec/features/projects/copy_spec.rb @@ -115,7 +115,7 @@ end it 'copies projects and the associated objects' do - original_settings_page = Pages::ProjectSettings.new(project) + original_settings_page = Pages::Projects::Settings.new(project) original_settings_page.visit! click_link 'Copy' @@ -137,7 +137,7 @@ expect(copied_project) .to be_present - copied_settings_page = Pages::ProjectSettings.new(copied_project) + copied_settings_page = Pages::Projects::Settings.new(copied_project) copied_settings_page.visit! # has the parent of the original project diff --git a/spec/features/projects/project_autocomplete_spec.rb b/spec/features/projects/project_autocomplete_spec.rb index f3c5404262..3c0765c8ef 100644 --- a/spec/features/projects/project_autocomplete_spec.rb +++ b/spec/features/projects/project_autocomplete_spec.rb @@ -27,7 +27,6 @@ #++ require 'spec_helper' -require 'features/projects/projects_page' describe 'Projects autocomplete page', type: :feature, js: true do let!(:user) { FactoryBot.create :user } diff --git a/spec/features/projects/projects_custom_fields_spec.rb b/spec/features/projects/projects_custom_fields_spec.rb index 6cede01774..b9dc897d20 100644 --- a/spec/features/projects/projects_custom_fields_spec.rb +++ b/spec/features/projects/projects_custom_fields_spec.rb @@ -27,7 +27,6 @@ #++ require 'spec_helper' -require 'features/projects/projects_page' describe 'Projects custom fields', type: :feature do let(:current_user) { FactoryBot.create(:admin) } diff --git a/spec/features/projects/projects_index_spec.rb b/spec/features/projects/projects_index_spec.rb index 67cac6638e..05c3aeed0d 100644 --- a/spec/features/projects/projects_index_spec.rb +++ b/spec/features/projects/projects_index_spec.rb @@ -27,7 +27,6 @@ #++ require 'spec_helper' -require 'features/projects/projects_page' describe 'Projects index page', type: :feature, diff --git a/spec/features/projects/projects_spec.rb b/spec/features/projects/projects_spec.rb index fe1970413e..64ab055b9e 100644 --- a/spec/features/projects/projects_spec.rb +++ b/spec/features/projects/projects_spec.rb @@ -27,7 +27,6 @@ #++ require 'spec_helper' -require 'features/projects/projects_page' describe 'Projects', type: :feature do let(:current_user) { FactoryBot.create(:admin) } @@ -117,10 +116,10 @@ describe 'deletion', js: true do let(:project) { FactoryBot.create(:project) } - let(:projects_page) { ProjectsPage.new(project) } + let(:projects_page) { Pages::Projects::Destroy.new(project) } before do - projects_page.visit_confirm_destroy + projects_page.visit! end describe 'disable delete w/o confirm' do diff --git a/spec/features/types/activate_in_project_spec.rb b/spec/features/types/activate_in_project_spec.rb new file mode 100644 index 0000000000..9f2061fa53 --- /dev/null +++ b/spec/features/types/activate_in_project_spec.rb @@ -0,0 +1,80 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' +require 'support/pages/custom_fields' + +describe 'types', js: true do + let(:user) do + FactoryBot.create :user, + member_in_project: project, + member_with_permissions: %i(edit_project manage_types add_work_packages view_work_packages) + end + let!(:active_type) { FactoryBot.create(:type) } + let!(:type) { FactoryBot.create(:type) } + let!(:project) { FactoryBot.create(:project, types: [active_type]) } + let(:project_settings_page) { Pages::Projects::Settings.new(project) } + let(:work_packages_page) { Pages::WorkPackagesTable.new(project) } + + before do + login_as(user) + end + + it 'is only visible in the project if it has been activated' do + # the currently active types are available for work package creation + work_packages_page.visit! + + work_packages_page.expect_type_available_for_create(active_type) + work_packages_page.expect_type_not_available_for_create(type) + + project_settings_page.visit_tab!('types') + + expect(page) + .to have_unchecked_field(type.name) + expect(page) + .to have_checked_field(active_type.name) + + # switch enabled types + check(type.name) + uncheck(active_type.name) + + project_settings_page.save! + + expect(page) + .to have_checked_field(type.name) + expect(page) + .to have_unchecked_field(active_type.name) + + # the newly activated types are available for work package creation + # disabled ones are not + work_packages_page.visit! + + work_packages_page.expect_type_available_for_create(type) + work_packages_page.expect_type_not_available_for_create(active_type) + end +end diff --git a/spec/features/types/form_configuration_query_spec.rb b/spec/features/types/form_configuration_query_spec.rb index 0ad1445ad9..fe92f5a1a2 100644 --- a/spec/features/types/form_configuration_query_spec.rb +++ b/spec/features/types/form_configuration_query_spec.rb @@ -27,7 +27,6 @@ #++ require 'spec_helper' -require 'features/projects/project_settings_page' describe 'form subelements configuration', type: :feature, js: true do let(:admin) { FactoryBot.create :admin } diff --git a/spec/features/types/form_configuration_spec.rb b/spec/features/types/form_configuration_spec.rb index 803c0eb9d7..4919d2ff28 100644 --- a/spec/features/types/form_configuration_spec.rb +++ b/spec/features/types/form_configuration_spec.rb @@ -27,7 +27,6 @@ #++ require 'spec_helper' -require 'features/projects/project_settings_page' describe 'form configuration', type: :feature, js: true do let(:admin) { FactoryBot.create :admin } @@ -248,7 +247,7 @@ end describe 'custom fields' do - let(:project_settings_page) { ProjectSettingsPage.new(project) } + let(:project_settings_page) { Pages::Projects::Settings.new(project) } let(:custom_fields) { [custom_field] } let(:custom_field) { FactoryBot.create(:integer_issue_custom_field, name: 'MyNumber') } @@ -287,7 +286,7 @@ wp_page.expect_attribute_hidden(cf_identifier_api) # Enable in project, should then be visible - project_settings_page.visit_settings_tab('custom_fields') + project_settings_page.visit_tab!('custom_fields') expect(page).to have_selector(".custom-field-#{custom_field.id} td", text: 'MyNumber') expect(page).to have_selector(".custom-field-#{custom_field.id} td", text: type.name) @@ -326,7 +325,7 @@ end # Ensure CF is checked - project_settings_page.visit_settings_tab('custom_fields') + project_settings_page.visit_tab!('custom_fields') expect(page).to have_selector(".custom-field-#{custom_field.id} td", text: 'MyNumber') expect(page).to have_selector(".custom-field-#{custom_field.id} td", text: type.name) expect(page).to have_selector("#project_work_package_custom_field_ids_#{custom_field.id}[checked]") diff --git a/spec/features/types/reset_form_configuration_spec.rb b/spec/features/types/reset_form_configuration_spec.rb index c30a9f4836..c34029bc90 100644 --- a/spec/features/types/reset_form_configuration_spec.rb +++ b/spec/features/types/reset_form_configuration_spec.rb @@ -27,7 +27,6 @@ #++ require 'spec_helper' -require 'features/projects/project_settings_page' describe 'Reset form configuration', type: :feature, js: true do let(:admin) { FactoryBot.create :admin } diff --git a/spec/features/users/create_spec.rb b/spec/features/users/create_spec.rb index febece00cf..df87dccc91 100644 --- a/spec/features/users/create_spec.rb +++ b/spec/features/users/create_spec.rb @@ -96,17 +96,23 @@ context 'with external authentication', js: true do before do auth_source.save! - new_user_page.visit! + new_user_page.fill_in! first_name: 'bobfirst', last_name: 'boblast', email: 'bob@mail.com', login: 'bob', auth_source: auth_source.name + new_user_page.submit! end + after do + # Clear session to avoid that the onboarding tour starts + page.execute_script("window.sessionStorage.clear();") + end + it_behaves_like 'successful user creation' do describe 'activation', js: true do before do diff --git a/spec/features/users/delete_spec.rb b/spec/features/users/delete_spec.rb index 08430a4d5b..7bb3d3187c 100644 --- a/spec/features/users/delete_spec.rb +++ b/spec/features/users/delete_spec.rb @@ -27,7 +27,6 @@ #++ require 'spec_helper' -require 'features/projects/projects_page' describe 'user deletion: ', type: :feature, js: true do let(:dialog) { ::Components::PasswordConfirmationDialog.new } diff --git a/spec/features/users/edit_users_spec.rb b/spec/features/users/edit_users_spec.rb index 20263746ab..e99fe62d5f 100644 --- a/spec/features/users/edit_users_spec.rb +++ b/spec/features/users/edit_users_spec.rb @@ -27,7 +27,6 @@ #++ require 'spec_helper' -require 'features/projects/projects_page' describe 'edit users', type: :feature, js: true do let(:current_user) { FactoryBot.create :admin } diff --git a/spec/features/users/my_spec.rb b/spec/features/users/my_spec.rb index 60faab56d3..81d898637c 100644 --- a/spec/features/users/my_spec.rb +++ b/spec/features/users/my_spec.rb @@ -27,7 +27,6 @@ #++ require 'spec_helper' -require 'features/projects/projects_page' describe 'my', type: :feature, js: true do let(:user_password) { 'bob' * 4 } diff --git a/spec/features/work_packages/custom_actions_spec.rb b/spec/features/work_packages/custom_actions_spec.rb index 9926509931..1927115326 100644 --- a/spec/features/work_packages/custom_actions_spec.rb +++ b/spec/features/work_packages/custom_actions_spec.rb @@ -271,9 +271,11 @@ retry_block do new_ca_page.visit! new_ca_page.set_name('Move project') + # Add date custom action which has a different admin layout + select date_custom_field.name, from: 'Add action' + select 'on', from: date_custom_field.name date = (Date.today + 5.days).to_s - new_ca_page.add_action(date_custom_field.name, date) - page.find_field("custom_action_actions_custom_field_#{date_custom_field.id}", with: date) + fill_in "custom_action_actions_custom_field_#{date_custom_field.id}_visible", with: date # Close autocompleter if page.has_selector? '.ui-datepicker-close' diff --git a/spec/features/work_packages/details/relations/hierarchy_spec.rb b/spec/features/work_packages/details/relations/hierarchy_spec.rb index 6996f87739..ec1385d829 100644 --- a/spec/features/work_packages/details/relations/hierarchy_spec.rb +++ b/spec/features/work_packages/details/relations/hierarchy_spec.rb @@ -1,15 +1,16 @@ require 'spec_helper' -describe 'Work package relations tab', js: true, selenium: true do +shared_examples 'work package relations tab', js: true, selenium: true do include_context 'ui-autocomplete helpers' let(:user) { FactoryBot.create :admin } let(:project) { FactoryBot.create(:project) } let(:work_package) { FactoryBot.create(:work_package, project: project) } - let(:work_packages_page) { ::Pages::SplitWorkPackage.new(work_package) } - let(:full_wp) { ::Pages::FullWorkPackage.new(work_package) } let(:relations) { ::Components::WorkPackages::Relations.new(work_package) } + let(:tabs) { ::Components::WorkPackages::Tabs.new(work_package) } + + let(:relations_tab) { find('.tabrow li.selected', text: 'RELATIONS') } let(:visit) { true } @@ -22,8 +23,9 @@ end def visit_relations - work_packages_page.visit_tab!('relations') - work_packages_page.expect_subject + wp_page.visit_tab!('relations') + expect_angular_frontend_initialized + wp_page.expect_subject loading_indicator_saveguard end @@ -35,7 +37,7 @@ def visit_relations it 'allows to manage hierarchy' do # Shows link parent link expect(page).to have_selector('#hierarchy--add-parent') - find('.work-packages--details .wp-inline-create--add-link', + find('.wp-inline-create--add-link', text: I18n.t('js.relation_buttons.add_parent')).click # Add parent @@ -44,17 +46,20 @@ def visit_relations ## # Add child #1 - find('.work-packages--details .wp-inline-create--add-link', + find('.wp-inline-create--add-link', text: I18n.t('js.relation_buttons.add_existing_child')).click relations.add_existing_child(child) ## # Add child #2 - find('.work-packages--details .wp-inline-create--add-link', + find('.wp-inline-create--add-link', text: I18n.t('js.relation_buttons.add_existing_child')).click relations.add_existing_child(child2) + + # Count parent and child relations in split view + tabs.expect_counter(relations_tab, 3) end describe 'inline create' do @@ -72,6 +77,9 @@ def visit_relations table.expect_work_package_subject 'my new child' work_package.reload expect(work_package.children.count).to eq(1) + + # If new child is inline created, counter should increase + tabs.expect_counter(relations_tab, 1) end end end @@ -103,8 +111,8 @@ def visit_relations before do visit_relations - work_packages_page.visit_tab!('relations') - work_packages_page.expect_subject + wp_page.visit_tab!('relations') + wp_page.expect_subject loading_indicator_saveguard end @@ -140,6 +148,9 @@ def visit_relations # But it should show the linked parent expect(page).to have_selector('.wp-relations-hierarchy-subject', text: parent.subject) + + # And it should count parent and the two relations + tabs.expect_counter(relations_tab, 3) end end @@ -151,34 +162,50 @@ def visit_relations it 'should be able to link parent and children' do # Shows link parent link expect(page).to have_selector('#hierarchy--add-parent') - find('.work-packages--details .wp-inline-create--add-link', + find('.wp-inline-create--add-link', text: I18n.t('js.relation_buttons.add_parent')).click # Add parent relations.add_parent(parent.id, parent) - work_packages_page.expect_and_dismiss_notification(message: 'Successful update.') + wp_page.expect_and_dismiss_notification(message: 'Successful update.') relations.expect_parent(parent) ## # Add child - find('.work-packages--details .wp-inline-create--add-link', + find('.wp-inline-create--add-link', text: I18n.t('js.relation_buttons.add_existing_child')).click relations.add_existing_child(child) - work_packages_page.expect_and_dismiss_notification(message: 'Successful update.') + wp_page.expect_and_dismiss_notification(message: 'Successful update.') relations.expect_child(child) + # Expect counter to add up new parent and child to the existing relations + tabs.expect_counter(relations_tab, 4) + # Remove parent relations.remove_parent(parent) - work_packages_page.expect_and_dismiss_notification(message: 'Successful update.') + wp_page.expect_and_dismiss_notification(message: 'Successful update.') relations.expect_not_parent(parent) # Remove child relations.remove_child(child) # Should also check for successful update but no message is shown, yet. relations.expect_not_child(child) + + # Expect counter to only count the two existing relations + tabs.expect_counter(relations_tab, 2) end end end end end + +context 'Split screen' do + let(:wp_page) { Pages::SplitWorkPackage.new(work_package) } + it_behaves_like 'work package relations tab' +end + +context 'Full screen' do + let(:wp_page) { Pages::FullWorkPackage.new(work_package) } + it_behaves_like 'work package relations tab' +end diff --git a/spec/features/work_packages/details/relations/relations_spec.rb b/spec/features/work_packages/details/relations/relations_spec.rb index 5220f6f0f0..f744e646c7 100644 --- a/spec/features/work_packages/details/relations/relations_spec.rb +++ b/spec/features/work_packages/details/relations/relations_spec.rb @@ -10,6 +10,9 @@ let(:work_packages_page) { ::Pages::SplitWorkPackage.new(work_package) } let(:full_wp) { ::Pages::FullWorkPackage.new(work_package) } let(:relations) { ::Components::WorkPackages::Relations.new(work_package) } + let(:tabs) { ::Components::WorkPackages::Tabs.new(work_package) } + + let(:relations_tab) { find('.tabrow li.selected', text: 'RELATIONS') } let(:visit) { true } @@ -23,6 +26,7 @@ def visit_relations work_packages_page.visit_tab!('relations') + expect_angular_frontend_initialized work_packages_page.expect_subject loading_indicator_saveguard end @@ -147,15 +151,23 @@ def visit_relations it 'should allow to manage relations' do relations.add_relation(type: 'follows', to: relatable) + # Relations counter badge should increase number of relations + tabs.expect_counter(relations_tab, 1) + relations.remove_relation(relatable) expect(page).to have_no_selector('.relation-group--header', text: 'FOLLOWS') + # If there are no relations, the counter badge should not be displayed + tabs.expect_no_counter(relations_tab) + work_package.reload expect(work_package.relations.direct).to be_empty end it 'should allow to move between split and full view (Regression #24194)' do relations.add_relation(type: 'follows', to: relatable) + # Relations counter should increase + tabs.expect_counter(relations_tab, 1) # Switch to full view find('.work-packages--details-fullscreen-icon').click diff --git a/spec/features/work_packages/highlighting_spec.rb b/spec/features/work_packages/highlighting_spec.rb index 072d4f757f..0f7b048412 100644 --- a/spec/features/work_packages/highlighting_spec.rb +++ b/spec/features/work_packages/highlighting_spec.rb @@ -81,8 +81,39 @@ expect(wp1_row).to have_selector('.__hl_date_overdue') expect(wp2_row).to have_selector('.__hl_date_due_today') - # Highlight by status - highlighting.switch_highlight 'Status' + # Highlight only one attribute + highlighting.switch_inline_attribute_highlight "Priority" + + wp1_row = wp_table.row(wp_1) + wp2_row = wp_table.row(wp_2) + + ## Priority should have a dot + expect(SelectorHelpers.get_pseudo_class_property(page, + wp1_row.find('[class^="__hl_dot_priority_"]'), + ':before', + "background-color")).to eq('rgb(18, 52, 86)') + expect(SelectorHelpers.get_pseudo_class_property(page, + wp2_row.find('[class^="__hl_dot_priority_"]'), + ':before', + "background-color")).to eq('rgba(0, 0, 0, 0)') + + ## Status should not have a dot + expect(wp1_row).not_to have_selector('.status [class^="__hl_dot_"]') + + # Highlight multiple attributes + highlighting.switch_inline_attribute_highlight "Priority", "Status" + wp1_row = wp_table.row(wp_1) + expect(SelectorHelpers.get_pseudo_class_property(page, + wp1_row.find('[class^="__hl_dot_priority_"]'), + ':before', + "background-color")).to eq('rgb(18, 52, 86)') + expect(SelectorHelpers.get_pseudo_class_property(page, + wp1_row.find('[class^="__hl_dot_status_"]'), + ':before', + "background-color")).to eq('rgb(255, 0, 0)') + + # Highlight entire row by status + highlighting.switch_entire_row_highlight 'Status' expect(page).to have_selector("#{wp_table.row_selector(wp_1)}.__hl_row_status_#{status1.id}") expect(page).to have_selector("#{wp_table.row_selector(wp_2)}.__hl_row_status_#{status2.id}") @@ -105,13 +136,14 @@ expect(page).to have_no_selector('[class*="__hl_inl_priority"]') expect(page).to have_no_selector('[class*="__hl_date"]') - # Highlight by priority - highlighting.switch_highlight 'Priority' + # Highlight entire row by priority + highlighting.switch_entire_row_highlight 'Priority' expect(page).to have_selector("#{wp_table.row_selector(wp_1)}.__hl_row_priority_#{priority1.id}") expect(page).to have_selector("#{wp_table.row_selector(wp_2)}.__hl_row_priority_#{priority_no_color.id}") + # Remove selection from table row find('body').send_keys [:control, 'd'] - + wp1_row = wp_table.row(wp_1) wp2_row = wp_table.row(wp_2) expect(wp1_row.native.css_value('background-color')).to eq('rgba(18, 52, 86, 1)') @@ -129,7 +161,7 @@ expect(page).to have_no_selector('[class*="__hl_date"]') # No highlighting - highlighting.switch_highlight 'No highlighting' + highlighting.switch_highlighting_mode 'No highlighting' expect(page).to have_no_selector('[class*="__hl_row"]') expect(page).to have_no_selector('[class*="__hl_inl_status"]') expect(page).to have_no_selector('[class*="__hl_inl_priority"]') diff --git a/spec/features/work_packages/new/create_child_spec.rb b/spec/features/work_packages/new/create_child_spec.rb index fa67a6da77..858776139d 100644 --- a/spec/features/work_packages/new/create_child_spec.rb +++ b/spec/features/work_packages/new/create_child_spec.rb @@ -29,6 +29,8 @@ require 'spec_helper' RSpec.feature 'Work package create children', js: true, selenium: true do + let(:tabs) { ::Components::WorkPackages::Tabs.new(original_work_package) } + let(:relations_tab) { find('.tabrow li', text: 'RELATIONS') } let(:user) do FactoryBot.create(:user, member_in_project: project, @@ -41,7 +43,6 @@ old_status: original_work_package.status, new_status: FactoryBot.create(:status)) end - let(:create_role) do FactoryBot.create(:role, permissions: [:view_work_packages, @@ -104,6 +105,8 @@ original_work_package_page = Pages::FullWorkPackage.new(original_work_package) child_work_package_page = original_work_package_page.add_child + expect_angular_frontend_initialized + type_field = child_work_package_page.edit_field :type type_field.expect_active! @@ -119,6 +122,9 @@ expect(page).to have_selector('.notification-box--content', text: I18n.t('js.notice_successful_create')) + # Relations counter in full view should equal 1 + tabs.expect_counter(relations_tab, 1) + child_work_package = WorkPackage.order(created_at: 'desc').first expect(child_work_package).to_not eql original_work_package @@ -136,6 +142,8 @@ original_work_package_page = Pages::SplitWorkPackage.new(original_work_package, project) child_work_package_page = original_work_package_page.add_child + expect_angular_frontend_initialized + type_field = child_work_package_page.edit_field :type expect(type_field.input_element).to have_selector('option[selected]', text: 'Please select') @@ -150,6 +158,9 @@ expect(page).to have_selector('.notification-box--content', text: I18n.t('js.notice_successful_create')) + # # Relations counter in split view should equal 1 + tabs.expect_counter(relations_tab, 1) + child_work_package = WorkPackage.order(created_at: 'desc').first expect(child_work_package).to_not eql original_work_package diff --git a/spec/features/work_packages/tabs/watcher_tab_spec.rb b/spec/features/work_packages/tabs/watcher_tab_spec.rb index cdc7421d32..8df64618ab 100644 --- a/spec/features/work_packages/tabs/watcher_tab_spec.rb +++ b/spec/features/work_packages/tabs/watcher_tab_spec.rb @@ -6,6 +6,7 @@ describe 'Watcher tab', js: true, selenium: true do let(:project) { FactoryBot.create(:project) } let(:work_package) { FactoryBot.create(:work_package, project: project) } + let(:tabs) { ::Components::WorkPackages::Tabs.new(work_package) } let(:user) { FactoryBot.create(:user, member_in_project: project, member_through_role: role) } let(:role) { FactoryBot.create(:role, permissions: permissions) } @@ -17,6 +18,7 @@ } let(:watch_button) { find '#watch-button' } + let(:watchers_tab) { find('.tabrow li.selected', text: 'WATCHERS') } def expect_button_is_watching title = I18n.t('js.label_unwatch_work_package') @@ -54,6 +56,7 @@ def expect_button_is_not_watching before do login_as(user) wp_page.visit_tab! :watchers + expect_angular_frontend_initialized expect(page).to have_selector('.tabrow li.selected', text: 'WATCHERS') end @@ -69,10 +72,16 @@ def expect_button_is_not_watching expect(page).to have_selector('.work-package--watcher-name', count: 1, text: user.name) expect_button_is_watching + # Expect watchers counter to increase + tabs.expect_counter(watchers_tab, 1) + # Remove watcher from list page.find('wp-watcher-entry', text: user.name).hover page.find('.form--selected-value--remover').click + # Watchers counter should not be displayed + tabs.expect_no_counter(watchers_tab) + # Expect the removal of the user to toggle WP watch button expect(page).to have_no_selector('.work-package--watcher-name') expect_button_is_not_watching diff --git a/spec/lib/api/v3/queries/query_representer_generation_spec.rb b/spec/lib/api/v3/queries/query_representer_generation_spec.rb index aa6c437aae..b969f08b13 100644 --- a/spec/lib/api/v3/queries/query_representer_generation_spec.rb +++ b/spec/lib/api/v3/queries/query_representer_generation_spec.rb @@ -517,8 +517,64 @@ def non_empty_to_query(hash) it 'renders the default' do query.highlighting_mode = nil - + query.highlighted_attributes = nil is_expected.to be_json_eql('inline'.to_json).at_path('highlightingMode') + is_expected.to_not have_json_path('highlightedAttributes') + end + + context "inline attribute highlighting" do + let :status do + { + href: '/api/v3/queries/columns/status', + title: 'Status' + } + end + + let :type do + { + href: '/api/v3/queries/columns/type', + title: 'Type' + } + end + + let :priority do + { + href: '/api/v3/queries/columns/priority', + title: 'Priority' + } + end + + let :due_date do + { + href: '/api/v3/queries/columns/dueDate', + title: 'Finish date' + } + end + + let(:query) do + query = FactoryBot.build_stubbed(:query, project: project) + + query.highlighted_attributes = ['status', 'type', 'priority', 'due_date'] + + query + end + + let(:highlighted_attributes) do + [status, type, priority, due_date] + end + + it 'links an array of highlighted attributes' do + is_expected + .to be_json_eql(highlighted_attributes.to_json).at_path('_links/highlightedAttributes') + end + + it 'embeds selected inline attributes' do + query.highlighted_attributes[0..0].each_with_index do |attr, index| + is_expected + .to be_json_eql("/api/v3/queries/columns/#{attr}".to_json) + .at_path("_embedded/highlightedAttributes/#{index}/_links/self/href") + end + end end end diff --git a/spec/lib/api/v3/queries/query_representer_parsing_spec.rb b/spec/lib/api/v3/queries/query_representer_parsing_spec.rb index 1eb9fbeb67..7e4f1766a1 100644 --- a/spec/lib/api/v3/queries/query_representer_parsing_spec.rb +++ b/spec/lib/api/v3/queries/query_representer_parsing_spec.rb @@ -86,4 +86,18 @@ expect(subject).not_to be_grouped end end + + describe 'parsing highlighted_attributes', with_ee: [:conditional_highlighting] do + let(:request_body) do + { + '_links' => { + 'highlightedAttributes' => [{ 'href' => "/api/v3/queries/columns/type" }] + } + } + end + + it 'should set highlighted_attributes' do + expect(subject.highlighted_attributes).to eq(%i{type}) + end + end end diff --git a/spec/lib/api/v3/queries/schemas/query_schema_representer_spec.rb b/spec/lib/api/v3/queries/schemas/query_schema_representer_spec.rb index 8b39d4cea5..ad148fdccf 100644 --- a/spec/lib/api/v3/queries/schemas/query_schema_representer_spec.rb +++ b/spec/lib/api/v3/queries/schemas/query_schema_representer_spec.rb @@ -284,6 +284,20 @@ it_behaves_like 'has no visibility property' end + describe 'highlighting_mode' do + let(:path) { 'highlightingMode' } + + it_behaves_like 'has basic schema properties' do + let(:type) { 'String' } + let(:name) { Query.human_attribute_name('highlighting_mode') } + let(:required) { false } + let(:writable) { true } + let(:has_default) { true } + end + + it_behaves_like 'has no visibility property' + end + describe 'columns' do let(:path) { 'columns' } @@ -332,6 +346,38 @@ end end + describe 'show highlighted_attributes' do + let(:path) { 'highlightedAttributes' } + + it_behaves_like 'has basic schema properties' do + let(:type) { '[]QueryColumn' } + let(:name) { Query.human_attribute_name('highlighted_attributes') } + let(:required) { false } + let(:writable) { true } + let(:has_default) { true } + end + + it_behaves_like 'does not link to allowed values' + + context 'when embedding' do + let(:form_embedded) { true } + let(:type) { FactoryBot.build_stubbed(:type) } + let(:available_values) do + [Queries::WorkPackages::Columns::PropertyColumn.new(:bogus1, highlightable: true), + Queries::WorkPackages::Columns::PropertyColumn.new(:bogus2, highlightable: true)] + end + let(:available_values_method) { :available_columns } + + it_behaves_like 'has a collection of allowed values' do + let(:expected_hrefs) do + available_values.map do |value| + api_v3_paths.query_column(value.name.to_s.camelcase(:lower)) + end + end + end + end + end + describe 'filters' do let(:path) { 'filters' } diff --git a/spec/lib/open_project/text_formatting/markdown/markdown_spec.rb b/spec/lib/open_project/text_formatting/markdown/markdown_spec.rb index 8813dbc6aa..eaffbc57d2 100644 --- a/spec/lib/open_project/text_formatting/markdown/markdown_spec.rb +++ b/spec/lib/open_project/text_formatting/markdown/markdown_spec.rb @@ -231,6 +231,55 @@ def controller it { is_expected.to be_html_eql("

    #{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.

    ") } end + describe 'quickinfo' do + subject { format_text("###{issue.id}") } + + let(:issue) do + FactoryBot.create :work_package, + project: project, + author: project_member, + type: project.types.first, + start_date: start_date, + due_date: due_date + end + + context 'no dates' do + let(:start_date) { nil } + let(:due_date) { nil } + + it 'prints no quickinfo with dates' do + puts subject + end + end + + context 'start date' do + let(:start_date) { Date.today } + let(:due_date) { nil } + + it 'prints no quickinfo with dates' do + expect(subject).to include "(#{start_date.to_s} -)" + end + end + + context 'due date' do + let(:start_date) { nil } + let(:due_date) { Date.today } + + it 'prints quickinfo with start date' do + expect(subject).to include "(- #{due_date.to_s})" + end + end + + context 'both date' do + let(:start_date) { Date.today } + let(:due_date) { Date.today + 1.day } + + it 'prints quickinfo with dates' do + expect(subject).to include "(#{start_date.to_s} - #{due_date.to_s})" + end + end + end + context 'Plain issue link with braces' do subject { format_text("foo (bar ##{issue.id})") } diff --git a/spec/models/custom_actions/actions/custom_field_spec.rb b/spec/models/custom_actions/actions/custom_field_spec.rb index e491c484d2..92720e44e0 100644 --- a/spec/models/custom_actions/actions/custom_field_spec.rb +++ b/spec/models/custom_actions/actions/custom_field_spec.rb @@ -508,9 +508,17 @@ it_behaves_like 'string custom action validations' end + + context 'for a date custom field' do + let(:custom_field) { date_custom_field } + + it_behaves_like 'date custom action validations' + end end describe '#apply' do + let(:work_package) { double('work_package') } + %i[list version bool @@ -523,7 +531,6 @@ list_multi].each do |type| let(:custom_field) { send(:"#{type}_custom_field") } - let(:work_package) { double('work_package') } it "sets the value for #{type} custom fields" do expect(work_package) @@ -535,5 +542,19 @@ instance.apply(work_package) end end + + context 'for a date custom field' do + let(:custom_field) { date_custom_field } + + it "sets the value to today for a dynamic value" do + expect(work_package) + .to receive(:"custom_field_#{custom_field.id}=") + .with(Date.today) + + instance.values = '%CURRENT_DATE%' + + instance.apply(work_package) + end + end end end diff --git a/spec/models/custom_actions/actions/date_spec.rb b/spec/models/custom_actions/actions/date_spec.rb index 0c89bdb7ef..1cd283f2cc 100644 --- a/spec/models/custom_actions/actions/date_spec.rb +++ b/spec/models/custom_actions/actions/date_spec.rb @@ -39,7 +39,18 @@ let(:work_package) { FactoryBot.build_stubbed(:stubbed_work_package) } it 'sets both start and finish date to the action\'s value' do - instance.values = [Date.today] + instance.values = [Date.today + 5] + + instance.apply(work_package) + + expect(work_package.start_date) + .to eql Date.today + 5 + expect(work_package.due_date) + .to eql Date.today + 5 + end + + it 'sets both start and finish date to the current date if so specified' do + instance.values = ['%CURRENT_DATE%'] instance.apply(work_package) diff --git a/spec/models/custom_actions/actions/due_date_spec.rb b/spec/models/custom_actions/actions/due_date_spec.rb index 85e7cddcff..1b7f572ded 100644 --- a/spec/models/custom_actions/actions/due_date_spec.rb +++ b/spec/models/custom_actions/actions/due_date_spec.rb @@ -35,24 +35,15 @@ let(:value) { Date.today } it_behaves_like 'base custom action' do - describe '#apply' do - let(:work_package) { FactoryBot.build_stubbed(:stubbed_work_package) } - - it 'sets the due_date to the action\'s value' do - instance.values = [Date.today] - - instance.apply(work_package) - - expect(work_package.due_date) - .to eql Date.today - end - end - describe '#multi_value?' do it 'is false' do expect(instance) .not_to be_multi_value end end + + it_behaves_like 'date custom action validations' + it_behaves_like 'date values transformation' + it_behaves_like 'date custom action apply' end end diff --git a/spec/models/custom_actions/actions/start_date_spec.rb b/spec/models/custom_actions/actions/start_date_spec.rb index 5df6d4a4d6..4df514fe76 100644 --- a/spec/models/custom_actions/actions/start_date_spec.rb +++ b/spec/models/custom_actions/actions/start_date_spec.rb @@ -35,24 +35,15 @@ let(:value) { Date.today } it_behaves_like 'base custom action' do - describe '#apply' do - let(:work_package) { FactoryBot.build_stubbed(:stubbed_work_package) } - - it 'sets the start_date to the action\'s value' do - instance.values = [Date.today] - - instance.apply(work_package) - - expect(work_package.start_date) - .to eql Date.today - end - end - describe '#multi_value?' do it 'is false' do expect(instance) .not_to be_multi_value end end + + it_behaves_like 'date custom action validations' + it_behaves_like 'date values transformation' + it_behaves_like 'date custom action apply' end end diff --git a/spec/models/custom_actions/shared_expectations.rb b/spec/models/custom_actions/shared_expectations.rb index 23608684a1..56ffcd4ead 100644 --- a/spec/models/custom_actions/shared_expectations.rb +++ b/spec/models/custom_actions/shared_expectations.rb @@ -433,10 +433,10 @@ shared_examples_for 'date values transformation' do describe '#values' do it 'transforms the values to integers' do - instance.values = ["2015-03-29", Date.today, nil, (Date.today - 1.day).to_datetime, 'bogus'] + instance.values = ["2015-03-29", Date.today, nil, (Date.today - 1.day).to_datetime, 'bogus', '%CURRENT_DATE%'] expect(instance.values) - .to match_array [Date.parse("2015-03-29"), Date.today, nil, Date.today - 1.day] + .to match_array [Date.parse("2015-03-29"), Date.today, nil, Date.today - 1.day, '%CURRENT_DATE%'] end end end @@ -507,3 +507,27 @@ end end end + +shared_examples_for 'date custom action apply' do + describe '#apply' do + let(:work_package) { FactoryBot.build_stubbed(:stubbed_work_package) } + + it 'sets the daate to the action\'s value' do + instance.values = [Date.today + 5.days] + + instance.apply(work_package) + + expect(work_package.send(key)) + .to eql Date.today + 5.days + end + + it 'sets the date to the current date if so specified' do + instance.values = ['%CURRENT_DATE%'] + + instance.apply(work_package) + + expect(work_package.send(key)) + .to eql Date.today + end + end +end diff --git a/spec/models/journal/aggregated_journal_spec.rb b/spec/models/journal/aggregated_journal_spec.rb index b735e36648..93a933226d 100644 --- a/spec/models/journal/aggregated_journal_spec.rb +++ b/spec/models/journal/aggregated_journal_spec.rb @@ -63,9 +63,9 @@ def display_sorted_hash(hash) end describe Journal::AggregatedJournal, type: :model do - let(:work_package) { + let(:work_package) do FactoryBot.build(:work_package) - } + end let(:user1) { FactoryBot.create(:user) } let(:user2) { FactoryBot.create(:user) } let(:initial_author) { user1 } @@ -74,8 +74,6 @@ def display_sorted_hash(hash) before do allow(User).to receive(:current).and_return(initial_author) - allow(WorkPackages::UpdateContract).to receive(:new).and_return(NoopContract.new) - allow(WorkPackages::CreateNoteContract).to receive(:new).and_return(NoopContract.new) work_package.save! end @@ -105,9 +103,8 @@ def display_sorted_hash(hash) allow(User).to receive(:current).and_return(new_author) - WorkPackages::UpdateService - .new(user: new_author, work_package: work_package) - .call(attributes: changes) + work_package.attributes = changes + work_package.save! end context 'by author of last change' do @@ -146,9 +143,8 @@ def display_sorted_hash(hash) let(:notes) { 'Another comment, unrelated to the first one.' } before do - AddWorkPackageNoteService - .new(user: new_author, work_package: work_package) - .call(notes) + work_package.add_journal(new_author, notes) + work_package.save! end it 'returns two journals' do @@ -189,9 +185,8 @@ def display_sorted_hash(hash) work_package.reload # need to update the lock_version, avoiding StaleObjectError changes = { subject: 'foo' } - WorkPackages::UpdateService - .new(user: new_author, work_package: work_package) - .call(attributes: changes) + work_package.attributes = changes + work_package.save! end it 'returns a single journal' do @@ -302,9 +297,8 @@ def display_sorted_hash(hash) changes = { subject: 'a new subject!' } - WorkPackages::UpdateService - .new(user: new_author, work_package: work_package) - .call(attributes: changes) + work_package.attributes = changes + work_package.save! end it 'only returns the journals for the requested work package' do @@ -313,9 +307,9 @@ def display_sorted_hash(hash) end context 'specifying a maximum version' do - subject { + subject do described_class.aggregated_journals(journable: work_package, until_version: version) - } + end context 'equal to the latest version' do let(:version) { work_package.journals.last.version } diff --git a/spec/features/projects/project_settings_page.rb b/spec/models/queries/work_packages/columns/work_package_column_spec.rb similarity index 73% rename from spec/features/projects/project_settings_page.rb rename to spec/models/queries/work_packages/columns/work_package_column_spec.rb index b82d21a9bd..0ed44c3329 100644 --- a/spec/features/projects/project_settings_page.rb +++ b/spec/models/queries/work_packages/columns/work_package_column_spec.rb @@ -26,29 +26,14 @@ # See docs/COPYRIGHT.rdoc for more details. #++ -class ProjectSettingsPage - include Rails.application.routes.url_helpers - include Capybara::DSL +require 'spec_helper' - def initialize(project) - @project = project +describe Queries::WorkPackages::Columns::WorkPackageColumn, type: :model do + it "allows to be constructed with attribute highlightable" do + expect(described_class.new('foo', highlightable: true).highlightable?).to eq(true) end - def visit_settings - visit settings_path - end - - def visit_settings_tab(tab) - visit settings_path(tab: tab) - end - - def fieldset_label - find 'fieldset#project_issue_custom_fields label' - end - - private - - def settings_path(options = {}) - settings_project_path(@project, options) + it "allows to be constructed without attribute highlightable" do + expect(described_class.new('foo').highlightable?).to eq(false) end end diff --git a/spec/models/query_spec.rb b/spec/models/query_spec.rb index 330397079a..989b50f77f 100644 --- a/spec/models/query_spec.rb +++ b/spec/models/query_spec.rb @@ -82,25 +82,76 @@ end describe 'highlighting' do - it 'accepts valid values' do - %w(inline none status priority).each do |val| - query.highlighting_mode = val + context 'with EE' do + it '#hightlighted_attrirbutes accepts valid values' do + query.highlighted_attributes = %w(status type priority due_date) expect(query).to be_valid - expect(query.highlighting_mode).to eq(val.to_sym) end - end - it 'accepts non-present values' do - query.highlighting_mode = nil - expect(query).to be_valid + it '#hightlighted_attributes rejects invalid values' do + query.highlighted_attributes = %w(status bogus) + expect(query).not_to be_valid + end - query.highlighting_mode = '' - expect(query).to be_valid + it '#hightlighting_mode accepts non-present values' do + query.highlighting_mode = nil + expect(query).to be_valid + + query.highlighting_mode = '' + expect(query).to be_valid + end + + it '#hightlighting_mode rejects invalid values' do + query.highlighting_mode = 'bogus' + expect(query).not_to be_valid + end + + it '#available_highlighting_columns returns highlightable columns' do + available_columns = { + highlightable1: { + highlightable: true + }, + highlightable2: { + highlightable: true + }, + no_highlight: {} + } + + allow(Queries::WorkPackages::Columns::PropertyColumn).to receive(:property_columns) + .and_return(available_columns) + + expect(query.available_highlighting_columns.map(&:name)).to eq(%i{highlightable1 highlightable2}) + end + + describe '#highlighted_columns returns a valid subset of Columns' do + let(:highlighted_attributes) { %i{status type priority due_date foo} } + + before do + query.highlighted_attributes = highlighted_attributes + end + + it 'removes the offending values' do + query.valid_subset! + + expect(query.highlighted_columns.map(&:name)) + .to match_array %i{status type priority due_date} + end + end end - it 'rejects invalid values' do - query.highlighting_mode = 'bogus' - expect(query).not_to be_valid + context 'without EE' do + let(:conditional_highlighting_allowed) { false } + + it 'always returns :none as highlighting_mode' do + query.highlighting_mode = 'status' + expect(query.highlighting_mode).to eq(:none) + end + + it 'always returns nil as highlighted_attributes' do + query.highlighting_mode = 'inline' + query.highlighted_attributes = ['status'] + expect(query.highlighted_attributes).to be_empty + end end end @@ -531,6 +582,21 @@ end end end + + context 'highlighted_attributes' do + let(:highlighted_attributes) { %i{status type priority due_date foo} } + + before do + query.highlighted_attributes = highlighted_attributes + end + + it 'removes the offending values' do + query.valid_subset! + + expect(query.highlighted_attributes) + .to match_array %i{status type priority due_date} + end + end end describe '#filter_for' do diff --git a/spec/models/setting_spec.rb b/spec/models/setting_spec.rb index 030b9cd5cc..bc1ff49c53 100644 --- a/spec/models/setting_spec.rb +++ b/spec/models/setting_spec.rb @@ -85,6 +85,25 @@ end end + # Check that when reading certain setting values that they get overwritten if needed. + describe "filter saved settings" do + before do + Setting.work_package_list_default_highlighting_mode = "inline" + end + + describe "with EE token", with_ee: [:conditional_highlighting] do + it "returns the value for 'work_package_list_default_highlighting_mode' without changing it" do + expect(Setting.work_package_list_default_highlighting_mode).to eq("inline") + end + end + + describe "without EE" do + it "return 'none' as 'work_package_list_default_highlighting_mode'" do + expect(Setting.work_package_list_default_highlighting_mode).to eq("none") + end + end + end + # tests the serialization feature to store complex data types like arrays in settings describe 'serialized settings' do before do diff --git a/spec/models/work_package/planning_comparison_spec.rb b/spec/models/work_package/planning_comparison_spec.rb deleted file mode 100644 index 5a6825401e..0000000000 --- a/spec/models/work_package/planning_comparison_spec.rb +++ /dev/null @@ -1,146 +0,0 @@ -#-- copyright -# OpenProject is a project management system. -# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2017 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See docs/COPYRIGHT.rdoc for more details. -#++ - -require 'spec_helper' - -describe 'Planning Comparison', type: :model do - let (:project) { FactoryBot.create(:project) } - let (:admin) { FactoryBot.create(:admin) } - - before do - # query implicitly uses the logged in user to check for allowed work_packages/projects - allow(User).to receive(:current).and_return(admin) - end - - describe 'going back in history' do - let(:journalized_work_package) do - # TODO are these actually unit-tests?! - wp = nil - # create 2 journal-entries, to make sure, that the comparison actually picks up the latest one - Timecop.travel(2.weeks.ago) do - wp = FactoryBot.create(:work_package, project: project, start_date: '01/01/2020', due_date: '01/03/2020') - wp.save # triggers the journaling and saves the old due_date, creating the baseline for the comparison - end - - Timecop.travel(1.week.ago) do - wp.reload - wp.due_date = '01/04/2020' - wp.save # triggers the journaling and saves the old due_date, creating the baseline for the comparison - end - - wp.reload - wp.due_date = '01/05/2020' - wp.save # adds another journal-entry - wp - end - - before do wp = journalized_work_package end - - it 'should return the changes as a work_package' do - # beware of these date-conversions: 1.week.ago does not catch the change, as created_at is stored as a timestamp - expect(PlanningComparisonService.compare(project, 5.days.ago).size).to eql 1 - expect(PlanningComparisonService.compare(project, 5.days.ago).first).to be_instance_of WorkPackage - end - - it 'should return the old due_date in the comparison' do - # beware of these date-conversions: 1.week.ago does not catch the change, as created_at is stored as a timestamp - old_work_package = PlanningComparisonService.compare(project, 5.days.ago).first - expect(old_work_package.due_date).to eql Date.parse '01/04/2020' - end - - it 'should return only the latest change when the workpackage was edited on the same day more than once' do - Timecop.travel(1.week.ago) do - journalized_work_package.reload - journalized_work_package.due_date = '01/05/2020' - journalized_work_package.save # triggers the journaling and saves the old due_date, creating the baseline for the comparison - - journalized_work_package.reload - journalized_work_package.due_date = '01/07/2020' - journalized_work_package.save - end - - old_work_packages = PlanningComparisonService.compare(project, 5.days.ago) - expect(old_work_packages.size).to eql 1 - - expect(old_work_packages.first.due_date).to eql Date.parse '01/07/2020' - end - end - - describe 'filtering work_packages also applies to the history' do - let(:assigned_to_user) do - FactoryBot.create(:user, - member_in_project: project, - member_through_role: FactoryBot.build(:role)) - end - let (:filter) do - { f: ['assigned_to_id'], - op: { 'assigned_to_id' => '=' }, - v: { 'assigned_to_id' => ["#{assigned_to_user.id}"] } } - end - - let (:work_package) do - wp = nil - # create 2 journal-entries, to make sure, that the comparison actually picks up the latest one - Timecop.travel(1.week.ago) do - wp = FactoryBot.create(:work_package, project: project, due_date: '01/03/2020', assigned_to_id: assigned_to_user.id) - wp.save # triggers the journaling and saves the old due_date, creating the baseline for the comparison - end - - wp.reload - wp.due_date = '01/05/2020' - wp.save # adds another journal-entry - wp - end - - let (:filtered_work_package) do - other_user = FactoryBot.create(:user) - wp = nil - # create 2 journal-entries, to make sure, that the comparison actually picks up the latest one - Timecop.travel(1.week.ago) do - wp = FactoryBot.create(:work_package, project: project, due_date: '01/03/2020', assigned_to_id: other_user.id) - wp.save # triggers the journaling and saves the old due_date, creating the baseline for the comparison - end - - wp.reload - wp.due_date = '01/05/2020' - wp.save # adds another journal-entry - wp - end - - before do - work_package - filtered_work_package - end - - it 'should filter out the work_package assigned to the wrong person' do - filtered_packages = PlanningComparisonService.compare(project, 5.days.ago, filter) - expect(filtered_packages).to include work_package - expect(filtered_packages).not_to include filtered_work_package - end - end -end diff --git a/spec/routing/activities_spec.rb b/spec/routing/activities_spec.rb new file mode 100644 index 0000000000..aa88aee96b --- /dev/null +++ b/spec/routing/activities_spec.rb @@ -0,0 +1,57 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe ActivitiesController, 'routing', type: :routing do + it { + expect(get('/activity')).to route_to(controller: 'activities', + action: 'index') + } + + it { + expect(get('/activity.atom')).to route_to(controller: 'activities', + action: 'index', + format: 'atom') + } + + context 'project scoped' do + it { + expect(get('/projects/abc/activity')).to route_to(controller: 'activities', + action: 'index', + project_id: 'abc') + } + + it { + expect(get('/projects/abc/activity.atom')).to route_to(controller: 'activities', + action: 'index', + project_id: 'abc', + format: 'atom') + } + end +end diff --git a/spec/requests/attachments_routes_spec.rb b/spec/routing/attachments_spec.rb similarity index 65% rename from spec/requests/attachments_routes_spec.rb rename to spec/routing/attachments_spec.rb index 2643a44c67..7d558c2d96 100644 --- a/spec/requests/attachments_routes_spec.rb +++ b/spec/routing/attachments_spec.rb @@ -28,10 +28,27 @@ require 'spec_helper' -describe 'attachments routes', type: :request do - let(:user) { FactoryBot.create :admin } - let(:attachment) { FactoryBot.create :attachment } +describe AttachmentsController, 'routing', type: :routing do + it { + is_expected.to route(:get, '/attachments/1').to(controller: 'attachments', + action: 'download', + id: '1') + } + it { + is_expected.to route(:get, '/attachments/1/filename.ext').to(controller: 'attachments', + action: 'download', + id: '1', + filename: 'filename.ext') + } + it { + is_expected.to route(:delete, '/attachments/1').to(controller: 'attachments', + action: 'destroy', + id: '1') + } +end + +describe AttachmentsController, 'routing', type: :request do describe 'for backwards compatibility' do it 'redirects /attachments/download with filename to attachments#download' do get '/attachments/download/42/foo.png' diff --git a/spec/routing/boards_routing_spec.rb b/spec/routing/boards_routing_spec.rb index abb0420a1f..7662b4e80c 100644 --- a/spec/routing/boards_routing_spec.rb +++ b/spec/routing/boards_routing_spec.rb @@ -29,6 +29,54 @@ require 'spec_helper' describe BoardsController, type: :routing do + it { + is_expected.to route(:get, '/projects/world_domination/boards').to(controller: 'boards', + action: 'index', + project_id: 'world_domination') + } + it { + is_expected.to route(:get, '/projects/world_domination/boards/new').to(controller: 'boards', + action: 'new', + project_id: 'world_domination') + } + it { + is_expected.to route(:post, '/projects/world_domination/boards').to(controller: 'boards', + action: 'create', + project_id: 'world_domination') + } + it { + is_expected.to route(:get, '/projects/world_domination/boards/44').to(controller: 'boards', + action: 'show', + project_id: 'world_domination', + id: '44') + } + it { + expect(get('/projects/abc/boards/1.atom')) + .to route_to(controller: 'boards', + action: 'show', + project_id: 'abc', + id: '1', + format: 'atom') + } + it { + is_expected.to route(:get, '/projects/world_domination/boards/44/edit').to(controller: 'boards', + action: 'edit', + project_id: 'world_domination', + id: '44') + } + it { + is_expected.to route(:put, '/projects/world_domination/boards/44').to(controller: 'boards', + action: 'update', + project_id: 'world_domination', + id: '44') + } + it { + is_expected.to route(:delete, '/projects/world_domination/boards/44').to(controller: 'boards', + action: 'destroy', + project_id: 'world_domination', + id: '44') + } + it 'should connect GET /projects/:project/boards/:board/move to boards#move' do expect(get('/projects/1/boards/1/move')).to route_to(controller: 'boards', action: 'move', diff --git a/spec/routing/enumerations_spec.rb b/spec/routing/enumerations_spec.rb new file mode 100644 index 0000000000..5401c67f45 --- /dev/null +++ b/spec/routing/enumerations_spec.rb @@ -0,0 +1,66 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2017 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See doc/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe EnumerationsController, 'routing', type: :routing do + context 'admin scoped' do + it { + is_expected.to route(:get, 'admin/enumerations').to(controller: 'enumerations', + action: 'index') + } + + it { + is_expected.to route(:get, 'admin/enumerations/new').to(controller: 'enumerations', + action: 'new') + } + + it { + is_expected.to route(:post, 'admin/enumerations').to(controller: 'enumerations', + action: 'create') + } + + it { + is_expected.to route(:get, 'admin/enumerations/1/edit').to(controller: 'enumerations', + action: 'edit', + id: '1') + } + + it { + is_expected.to route(:put, 'admin/enumerations/1').to(controller: 'enumerations', + action: 'update', + id: '1') + } + + it { + is_expected.to route(:delete, 'admin/enumerations/1').to(controller: 'enumerations', + action: 'destroy', + id: '1') + } + end +end diff --git a/spec/routing/groups_spec.rb b/spec/routing/groups_spec.rb new file mode 100644 index 0000000000..2bdeb01bd5 --- /dev/null +++ b/spec/routing/groups_spec.rb @@ -0,0 +1,109 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe 'groups routes', type: :routing do + it { + is_expected.to route(:get, '/admin/groups').to(controller: 'groups', + action: 'index') + } + + it { + is_expected.to route(:get, '/admin/groups/new').to(controller: 'groups', + action: 'new') + } + + it { + is_expected.to route(:post, '/admin/groups').to(controller: 'groups', + action: 'create') + } + + it { + is_expected.to route(:get, '/admin/groups/4').to(controller: 'groups', + action: 'show', + id: '4') + } + + it { + is_expected.to route(:get, '/admin/groups/4/edit').to(controller: 'groups', + action: 'edit', + id: '4') + } + + it { + is_expected.to route(:put, '/admin/groups/4').to(controller: 'groups', + action: 'update', + id: '4') + } + + it { + is_expected.to route(:delete, '/admin/groups/4').to(controller: 'groups', + action: 'destroy', + id: '4') + } + + it { + is_expected.to route(:get, '/admin/groups/4/autocomplete_for_user').to(controller: 'groups', + action: 'autocomplete_for_user', + id: '4') + } + + it { + is_expected.to route(:post, '/admin/groups/4/members').to(controller: 'groups', + action: 'add_users', + id: '4') + } + + it { + is_expected.to route(:delete, '/admin/groups/4/members/5').to(controller: 'groups', + action: 'remove_user', + id: '4', + user_id: '5') + } + + it { + is_expected.to route(:post, '/admin/groups/4/memberships').to(controller: 'groups', + action: 'create_memberships', + id: '4') + } + + it { + is_expected.to route(:put, '/admin/groups/4/memberships/5').to(controller: 'groups', + action: 'edit_membership', + id: '4', + membership_id: '5') + } + + it { + is_expected.to route(:delete, '/admin/groups/4/memberships/5').to(controller: 'groups', + action: 'destroy_membership', + id: '4', + membership_id: '5') + } +end diff --git a/spec/routing/members_spec.rb b/spec/routing/members_spec.rb index 4a26a78be4..4d2b558314 100644 --- a/spec/routing/members_spec.rb +++ b/spec/routing/members_spec.rb @@ -29,6 +29,33 @@ require 'spec_helper' describe MembersController, type: :routing do + context 'project scoped' do + it { + is_expected.to route(:post, '/projects/5234/members').to(controller: 'members', + action: 'create', + project_id: '5234') + } + + it { + is_expected.to route(:get, '/projects/5234/members/autocomplete_for_member') + .to(controller: 'members', + action: 'autocomplete_for_member', + project_id: '5234') + } + end + + it { + is_expected.to route(:put, '/members/5234').to(controller: 'members', + action: 'update', + id: '5234') + } + + it { + is_expected.to route(:delete, '/members/5234').to(controller: 'members', + action: 'destroy', + id: '5234') + } + it 'connects GET /projects/:project_id/members/paginate_users ' + 'to members#paginate_users' do expect(get('/projects/1/members/paginate_users')) diff --git a/spec/routing/messages_spec.rb b/spec/routing/messages_spec.rb new file mode 100644 index 0000000000..cc65fea2fe --- /dev/null +++ b/spec/routing/messages_spec.rb @@ -0,0 +1,81 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe MessagesController, 'routing', type: :routing do + context 'project scoped' do + it { + is_expected.to route(:get, '/boards/lala/topics/new').to(controller: 'messages', + action: 'new', + board_id: 'lala') + } + + it { + is_expected.to route(:post, '/boards/lala/topics').to(controller: 'messages', + action: 'create', + board_id: 'lala') + } + end + + it { + is_expected.to route(:get, '/topics/2').to(controller: 'messages', + action: 'show', + id: '2') + } + + it { + is_expected.to route(:get, '/topics/22/edit').to(controller: 'messages', + action: 'edit', + id: '22') + } + + it { + is_expected.to route(:put, '/topics/22').to(controller: 'messages', + action: 'update', + id: '22') + } + + it { + is_expected.to route(:delete, '/topics/555').to(controller: 'messages', + action: 'destroy', + id: '555') + } + + it { + is_expected.to route(:get, '/topics/22/quote').to(controller: 'messages', + action: 'quote', + id: '22') + } + + it { + is_expected.to route(:post, '/topics/555/reply').to(controller: 'messages', + action: 'reply', + id: '555') + } +end diff --git a/spec/routing/my_spec.rb b/spec/routing/my_spec.rb index 2113ba9f36..183709e310 100644 --- a/spec/routing/my_spec.rb +++ b/spec/routing/my_spec.rb @@ -56,4 +56,9 @@ it '/my/generate_api_key POST routes to my#generate_api_key' do expect(post('/my/generate_api_key')).to route_to('my#generate_api_key') end + + it { + expect(get('/my/deletion_info')).to route_to(controller: 'users', + action: 'deletion_info') + } end diff --git a/spec/routing/news_comments_spec.rb b/spec/routing/news_comments_spec.rb new file mode 100644 index 0000000000..4a43dc037d --- /dev/null +++ b/spec/routing/news_comments_spec.rb @@ -0,0 +1,45 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe News::CommentsController, 'routing', type: :routing do + context 'news scoped' do + it { + is_expected.to route(:post, '/news/567/comments').to(controller: 'news/comments', + action: 'create', + news_id: '567') + } + end + + it { + is_expected.to route(:delete, '/comments/15').to(controller: 'news/comments', + action: 'destroy', + id: '15') + } +end diff --git a/spec/routing/news_spec.rb b/spec/routing/news_spec.rb new file mode 100644 index 0000000000..c3a431311d --- /dev/null +++ b/spec/routing/news_spec.rb @@ -0,0 +1,101 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe NewsController, 'routing', type: :routing do + context 'project scoped' do + it { + is_expected.to route(:get, '/projects/567/news').to(controller: 'news', + action: 'index', + project_id: '567') + } + + it do + expect(get('/projects/567/news.atom')) + .to route_to(controller: 'news', + action: 'index', + format: 'atom', + project_id: '567') + end + + it { + is_expected.to route(:get, '/projects/567/news/new').to(controller: 'news', + action: 'new', + project_id: '567') + } + + it { + is_expected.to route(:post, '/projects/567/news').to(controller: 'news', + action: 'create', + project_id: '567') + } + end + + it { + is_expected.to route(:get, '/news').to(controller: 'news', + action: 'index') + } + + it do + expect(get('/news.atom')) + .to route_to(controller: 'news', + action: 'index', + format: 'atom') + end + + it { + is_expected.to route(:get, '/news/2').to(controller: 'news', + action: 'show', + id: '2') + } + + it { + is_expected.to route(:get, '/news/234').to(controller: 'news', + action: 'show', + id: '234') + } + + it { + is_expected.to route(:get, '/news/567/edit').to(controller: 'news', + action: 'edit', + id: '567') + } + + it { + is_expected.to route(:put, '/news/567').to(controller: 'news', + action: 'update', + id: '567') + } + + it { + is_expected.to route(:delete, '/news/567').to(controller: 'news', + action: 'destroy', + id: '567') + } +end diff --git a/spec/requests/old_issue_2_wp_spec.rb b/spec/routing/old_issue_2_wp_spec.rb similarity index 100% rename from spec/requests/old_issue_2_wp_spec.rb rename to spec/routing/old_issue_2_wp_spec.rb diff --git a/spec/routing/roles_spec.rb b/spec/routing/roles_spec.rb index b29be7a5e7..14a677021d 100644 --- a/spec/routing/roles_spec.rb +++ b/spec/routing/roles_spec.rb @@ -34,4 +34,49 @@ expect(get('/roles/new')).to route_to('roles#new') end end + + context 'admin scoped' do + it { + is_expected.to route(:get, 'admin/roles').to(controller: 'roles', + action: 'index') + } + + it { + is_expected.to route(:get, 'admin/roles/new').to(controller: 'roles', + action: 'new') + } + + it { + is_expected.to route(:post, 'admin/roles').to(controller: 'roles', + action: 'create') + } + + it { + is_expected.to route(:get, 'admin/roles/1/edit').to(controller: 'roles', + action: 'edit', + id: '1') + } + + it { + is_expected.to route(:put, 'admin/roles/1').to(controller: 'roles', + action: 'update', + id: '1') + } + + it { + is_expected.to route(:delete, 'admin/roles/1').to(controller: 'roles', + action: 'destroy', + id: '1') + } + + it { + is_expected.to route(:get, 'admin/roles/report').to(controller: 'roles', + action: 'report') + } + + it { + is_expected.to route(:put, 'admin/roles').to(controller: 'roles', + action: 'bulk_update') + } + end end diff --git a/spec/requests/short_uri_wp_spec.rb b/spec/routing/short_uri_wp_spec.rb similarity index 100% rename from spec/requests/short_uri_wp_spec.rb rename to spec/routing/short_uri_wp_spec.rb diff --git a/spec/routing/timelog_spec.rb b/spec/routing/timelog_spec.rb index 3d2f1b2434..9a807ff6cb 100644 --- a/spec/routing/timelog_spec.rb +++ b/spec/routing/timelog_spec.rb @@ -29,20 +29,133 @@ require 'spec_helper' describe TimelogController, type: :routing do - it 'should connect GET /work_packages/:work_package_id/time_entries/new to timelog#new' do - expect(get('/work_packages/1/time_entries/new')).to route_to(controller: 'timelog', - action: 'new', - work_package_id: '1') - end - it 'connects GET /time_entries to timelog#index' do expect(get('/time_entries')).to route_to(controller: 'timelog', action: 'index') end - it 'connects GET /projects/:id/time_entries to timelog#index' do - expect(get('/projects/1/time_entries')).to route_to(controller: 'timelog', - action: 'index', - project_id: '1') + it { + expect(get('/time_entries.csv')).to route_to(controller: 'timelog', + action: 'index', + format: 'csv') + } + + it { + expect(get('/time_entries.atom')).to route_to(controller: 'timelog', + action: 'index', + format: 'atom') + } + + it { + is_expected.to route(:get, '/time_entries/new').to(controller: 'timelog', + action: 'new') + } + + it { + is_expected.to route(:get, '/time_entries/22/edit').to(controller: 'timelog', + action: 'edit', + id: '22') + } + + it { + is_expected.to route(:post, '/time_entries').to(controller: 'timelog', + action: 'create') + } + + it { + is_expected.to route(:put, '/time_entries/22').to(controller: 'timelog', + action: 'update', + id: '22') + } + + it { + is_expected.to route(:delete, '/time_entries/55').to(controller: 'timelog', + action: 'destroy', + id: '55') + } + + context 'reports' do + it { + is_expected.to route(:get, '/time_entries/report').to(controller: 'time_entries/reports', + action: 'show') + } + end + + context 'work package scoped' do + it 'should connect GET /work_packages/:work_package_id/time_entries/new to timelog#new' do + expect(get('/work_packages/1/time_entries/new')).to route_to(controller: 'timelog', + action: 'new', + work_package_id: '1') + end + end + + context 'project scoped' do + it 'connects GET /projects/:id/time_entries to timelog#index' do + expect(get('/projects/1/time_entries')).to route_to(controller: 'timelog', + action: 'index', + project_id: '1') + end + + it { + expect(get('/projects/567/time_entries.csv')).to route_to(controller: 'timelog', + action: 'index', + project_id: '567', + format: 'csv') + } + + it { + expect(get('/projects/567/time_entries.atom')).to route_to(controller: 'timelog', + action: 'index', + project_id: '567', + format: 'atom') + } + + it { + is_expected.to route(:get, '/projects/567/time_entries/new').to(controller: 'timelog', + action: 'new', + project_id: '567') + } + + it { + is_expected.to route(:get, '/projects/567/time_entries/22/edit').to(controller: 'timelog', + action: 'edit', + id: '22', + project_id: '567') + } + + it { + is_expected.to route(:post, '/projects/567/time_entries').to(controller: 'timelog', + action: 'create', + project_id: '567') + } + + it { + is_expected.to route(:put, '/projects/567/time_entries/22').to(controller: 'timelog', + action: 'update', + id: '22', + project_id: '567') + } + + it { + is_expected.to route(:delete, '/projects/567/time_entries/55').to(controller: 'timelog', + action: 'destroy', + id: '55', + project_id: '567') + } + + context 'reports' do + it { + is_expected.to route(:get, '/projects/567/time_entries/report').to(controller: 'time_entries/reports', + action: 'show', + project_id: '567') + } + + it { + expect(get('/projects/567/time_entries/report.csv')).to route_to(controller: 'time_entries/reports', + action: 'show', + project_id: '567', + format: 'csv') + } + end end end diff --git a/spec/routing/users_routing_spec.rb b/spec/routing/users_routing_spec.rb index ce1e94ed74..550625a98a 100644 --- a/spec/routing/users_routing_spec.rb +++ b/spec/routing/users_routing_spec.rb @@ -28,40 +28,107 @@ require 'spec_helper' -describe UsersController, type: :routing do - describe 'routing' do - describe 'users' do - it { - expect(get('/users/1/change_status/foobar')) - .to route_to controller: 'users', - action: 'change_status_info', - id: '1', - change_action: 'foobar' - } - it { - expect(get('/users/1/deletion_info')).to route_to(controller: 'users', - action: 'deletion_info', - id: '1') - } - - it { - expect(delete('/users/1')).to route_to(controller: 'users', - action: 'destroy', - id: '1') - } - end - - describe 'my' do - let(:user) { FactoryBot.create(:user) } - - before do - login_as(user) - end - - it { - expect(get('/my/deletion_info')).to route_to(controller: 'users', - action: 'deletion_info') - } - end - end +describe UsersController, 'routing', type: :routing do + it { + is_expected.to route(:get, '/users').to(controller: 'users', + action: 'index') + } + + it { + expect(get('/users.xml')) + .to route_to controller: 'users', + action: 'index', + format: 'xml' + } + + it { + is_expected.to route(:get, '/users/44').to(controller: 'users', + action: 'show', + id: '44') + } + + it { + expect(get('/users/44.xml')) + .to route_to controller: 'users', + action: 'show', + id: '44', + format: 'xml' + } + + it { + is_expected.to route(:get, '/users/current').to(controller: 'users', + action: 'show', + id: 'current') + } + + it { + expect(get('/users/current.xml')) + .to route_to controller: 'users', + action: 'show', + id: 'current', + format: 'xml' + } + + it { + is_expected.to route(:get, '/users/new').to(controller: 'users', + action: 'new') + } + + it { + is_expected.to route(:get, '/users/444/edit').to(controller: 'users', + action: 'edit', + id: '444') + } + + it { + is_expected.to route(:get, '/users/222/edit/membership').to(controller: 'users', + action: 'edit', + id: '222', + tab: 'membership') + } + + it { + is_expected.to route(:post, '/users').to(controller: 'users', + action: 'create') + } + + it { + expect(post('/users.xml')) + .to route_to controller: 'users', + action: 'create', + format: 'xml' + } + + it { + is_expected.to route(:put, '/users/444').to(controller: 'users', + action: 'update', + id: '444') + } + + it { + expect(put('/users/444.xml')) + .to route_to controller: 'users', + action: 'update', + id: '444', + format: 'xml' + } + + it { + expect(get('/users/1/change_status/foobar')) + .to route_to controller: 'users', + action: 'change_status_info', + id: '1', + change_action: 'foobar' + } + it { + expect(get('/users/1/deletion_info')).to route_to(controller: 'users', + action: 'deletion_info', + id: '1') + } + + it { + expect(delete('/users/1')).to route_to(controller: 'users', + action: 'destroy', + id: '1') + } end diff --git a/spec/routing/versions_spec.rb b/spec/routing/versions_spec.rb new file mode 100644 index 0000000000..9f327a065f --- /dev/null +++ b/spec/routing/versions_spec.rb @@ -0,0 +1,87 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe 'versions routing', type: :routing do + it { + is_expected.to route(:get, '/versions/1').to(controller: 'versions', + action: 'show', + id: '1') + } + + it { + is_expected.to route(:get, '/versions/1/edit').to(controller: 'versions', + action: 'edit', + id: '1') + } + + it { + is_expected.to route(:patch, '/versions/1').to(controller: 'versions', + action: 'update', + id: '1') + } + + it { + is_expected.to route(:delete, '/versions/1').to(controller: 'versions', + action: 'destroy', + id: '1') + } + + it { + is_expected.to route(:get, '/versions/1/status_by').to(controller: 'versions', + action: 'status_by', + id: '1') + } + + context 'project scoped' do + it { + is_expected.to route(:get, '/projects/foo/versions/new').to(controller: 'versions', + action: 'new', + project_id: 'foo') + } + + it { + is_expected.to route(:post, '/projects/foo/versions').to(controller: 'versions', + action: 'create', + project_id: 'foo') + } + + it { + is_expected.to route(:put, '/projects/foo/versions/close_completed').to(controller: 'versions', + action: 'close_completed', + project_id: 'foo') + } + + it { + is_expected.to route(:get, '/projects/foo/roadmap').to(controller: 'versions', + action: 'index', + project_id: 'foo') + } + end +end diff --git a/spec/routing/wiki_routing_spec.rb b/spec/routing/wiki_routing_spec.rb index cce724ff8f..41cf618dfc 100644 --- a/spec/routing/wiki_routing_spec.rb +++ b/spec/routing/wiki_routing_spec.rb @@ -30,6 +30,12 @@ describe WikiController, type: :routing do describe 'routing' do + it { + is_expected.to route(:get, '/projects/567/wiki').to(controller: 'wiki', + action: 'show', + project_id: '567') + } + it 'should connect GET /projects/:project_id/wiki/:name (without format) to wiki/show' do expect(get('/projects/abc/wiki/blubs')).to route_to(controller: 'wiki', action: 'show', @@ -46,10 +52,10 @@ it 'should connect GET /projects/:project_id/wiki/:name.html to wiki/show' do expect(get('/projects/abc/wiki/blubs.markdown')).to route_to(controller: 'wiki', - action: 'show', - project_id: 'abc', - id: 'blubs', - format: 'markdown') + action: 'show', + project_id: 'abc', + id: 'blubs', + format: 'markdown') end it 'should connect GET /projects/:project_id/wiki/new to wiki/new' do @@ -71,31 +77,35 @@ project_id: 'abc') end + it { + is_expected.to route(:get, '/projects/567/wiki/my_page/edit').to(controller: 'wiki', + action: 'edit', + project_id: '567', + id: 'my_page') + } + it do - expect(get('/projects/abc/wiki/abc_wiki?version=3')).to route_to( - controller: 'wiki', - action: 'show', - project_id: 'abc', - id: 'abc_wiki', - version: '3') + expect(get('/projects/abc/wiki/abc_wiki?version=3')).to route_to(controller: 'wiki', + action: 'show', + project_id: 'abc', + id: 'abc_wiki', + version: '3') end it 'should connect GET /projects/:project_id/wiki/:id/parent_page to wiki/edit_parent_page' do expect(get('/projects/abc/wiki/abc_wiki/parent_page')) - .to route_to( - controller: 'wiki', - action: 'edit_parent_page', - project_id: 'abc', - id: 'abc_wiki') + .to route_to(controller: 'wiki', + action: 'edit_parent_page', + project_id: 'abc', + id: 'abc_wiki') end it 'should connect PATCH /projects/:project_id/wiki/:id/parent_page to wiki/update_parent_page' do expect(patch('/projects/abc/wiki/abc_wiki/parent_page')) - .to route_to( - controller: 'wiki', - action: 'update_parent_page', - project_id: 'abc', - id: 'abc_wiki') + .to route_to(controller: 'wiki', + action: 'update_parent_page', + project_id: 'abc', + id: 'abc_wiki') end it 'should connect GET /projects/:project_id/wiki/:id/toc to wiki#index' do @@ -104,5 +114,103 @@ project_id: 'abc', id: 'blubs') end + + it { + is_expected.to route(:get, '/projects/1/wiki/CookBook_documentation/history').to(controller: 'wiki', + action: 'history', + project_id: '1', + id: 'CookBook_documentation') + } + it { + is_expected.to route(:get, '/projects/1/wiki/CookBook_documentation/diff').to(controller: 'wiki', + action: 'diff', + project_id: '1', + id: 'CookBook_documentation') + } + + it { + is_expected.to route(:get, '/projects/1/wiki/CookBook_documentation/diff/2').to(controller: 'wiki', + action: 'diff', + project_id: '1', + id: 'CookBook_documentation', + version: '2') + } + + it { + is_expected.to route(:get, '/projects/1/wiki/CookBook_documentation/diff/2/vs/1').to(controller: 'wiki', + action: 'diff', + project_id: '1', + id: 'CookBook_documentation', + version: '2', + version_from: '1') + } + + it { + is_expected.to route(:get, '/projects/1/wiki/CookBook_documentation/annotate/2').to(controller: 'wiki', + action: 'annotate', + project_id: '1', + id: 'CookBook_documentation', + version: '2') + } + + it { + is_expected.to route(:get, '/projects/22/wiki/ladida/rename').to(controller: 'wiki', + action: 'rename', + project_id: '22', + id: 'ladida') + } + + it { + is_expected.to route(:get, '/projects/567/wiki/index').to(controller: 'wiki', + action: 'index', + project_id: '567') + } + + it { + is_expected.to route(:get, '/projects/567/wiki/date_index').to(controller: 'wiki', + action: 'date_index', + project_id: '567') + } + + it { + is_expected.to route(:get, '/projects/567/wiki/export').to(controller: 'wiki', + action: 'export', + project_id: '567') + } + + it { + is_expected.to route(:patch, '/projects/22/wiki/ladida/rename').to(controller: 'wiki', + action: 'rename', + project_id: '22', + id: 'ladida') + } + + it { + is_expected.to route(:post, '/projects/22/wiki/ladida/protect').to(controller: 'wiki', + action: 'protect', + project_id: '22', + id: 'ladida') + } + + it { + is_expected.to route(:post, '/projects/22/wiki/ladida/add_attachment').to(controller: 'wiki', + action: 'add_attachment', + project_id: '22', + id: 'ladida') + } + + it { + is_expected.to route(:put, '/projects/567/wiki/my_page').to(controller: 'wiki', + action: 'update', + project_id: '567', + id: 'my_page') + } + + it { + is_expected.to route(:delete, '/projects/22/wiki/ladida').to(controller: 'wiki', + action: 'destroy', + project_id: '22', + id: 'ladida') + } end end diff --git a/spec/seeders/demo_data_seeder_spec.rb b/spec/seeders/demo_data_seeder_spec.rb index e32b207ebc..4df3072c9a 100644 --- a/spec/seeders/demo_data_seeder_spec.rb +++ b/spec/seeders/demo_data_seeder_spec.rb @@ -47,7 +47,7 @@ expect(User.where(admin: true).count).to eq 1 expect(Project.count).to eq 2 expect(WorkPackage.count).to eq 41 - expect(Wiki.count).to eq 1 + expect(Wiki.count).to eq 2 expect(Query.count).to eq num_queries ensure ActionMailer::Base.perform_deliveries = perform_deliveries diff --git a/spec/services/api/v3/parse_query_params_service_spec.rb b/spec/services/api/v3/parse_query_params_service_spec.rb index 3aee4f6051..3997df199d 100644 --- a/spec/services/api/v3/parse_query_params_service_spec.rb +++ b/spec/services/api/v3/parse_query_params_service_spec.rb @@ -127,6 +127,21 @@ end end + context 'with highlighted_attributes' do + it_behaves_like 'transforms' do + let(:params) { { highlightedAttributes: %w(status type priority dueDate) } } + # Please note, that dueDate is expected to get translated to due_date. + let(:expected) { { highlighted_attributes: %w(status type priority due_date) } } + end + end + + context 'without highlighted_attributes' do + it_behaves_like 'transforms' do + let(:params) { { highlightedAttributes: nil } } + let(:expected) { {} } + end + end + context 'with sort' do context 'as sortBy in comma separated value' do it_behaves_like 'transforms' do diff --git a/spec/services/update_query_from_params_service_spec.rb b/spec/services/update_query_from_params_service_spec.rb index ee53674de8..be14288ded 100644 --- a/spec/services/update_query_from_params_service_spec.rb +++ b/spec/services/update_query_from_params_service_spec.rb @@ -111,5 +111,44 @@ .to match_array(params[:columns].map(&:to_sym)) end end + + context 'highlighting mode', with_ee: %i[conditional_highlighting] do + let(:params) do + { highlighting_mode: 'status' } + end + + it 'sets the highlighting_mode' do + subject + + expect(query.highlighting_mode) + .to eq(:status) + end + end + + context 'default highlighting mode', with_ee: %i[conditional_highlighting] do + let(:params) do + { } + end + + it 'sets the highlighting_mode' do + subject + + expect(query.highlighting_mode) + .to eq(:inline) + end + end + + context 'highlighting mode without EE' do + let(:params) do + { highlighting_mode: 'status' } + end + + it 'sets the highlighting_mode' do + subject + + expect(query.highlighting_mode) + .to eq(:none) + end + end end end diff --git a/spec/support/authentication_helpers.rb b/spec/support/authentication_helpers.rb index f25e1fef6e..d15b6463bb 100644 --- a/spec/support/authentication_helpers.rb +++ b/spec/support/authentication_helpers.rb @@ -43,6 +43,7 @@ def login_as(user) def login_with(login, password, autologin: false) visit signin_path + within('#login-form') do fill_in 'username', with: login fill_in 'password', with: password diff --git a/spec/support/components/work_packages/relations.rb b/spec/support/components/work_packages/relations.rb index e60f2a5841..f25ce0b69c 100644 --- a/spec/support/components/work_packages/relations.rb +++ b/spec/support/components/work_packages/relations.rb @@ -131,7 +131,7 @@ def add_parent(query, work_package) autocomplete = container.find(".wp-relations--autocomplete") select_autocomplete autocomplete, query: query, - results_selector: '.wp-relations-autocomplete--results', + results_selector: '.detail-panel--relations .wp-relations-autocomplete--results', select_text: work_package.id container.find('.wp-create-relation--save').click diff --git a/spec/support/components/work_packages/table_configuration/highlighting.rb b/spec/support/components/work_packages/table_configuration/highlighting.rb index 07777c1c29..0bd921820a 100644 --- a/spec/support/components/work_packages/table_configuration/highlighting.rb +++ b/spec/support/components/work_packages/table_configuration/highlighting.rb @@ -34,13 +34,32 @@ class Highlighting def initialize; end - def switch_highlight(label) + def switch_highlighting_mode(label) modal_open? or open_modal - if %w(Status Priority).include? label - choose "Entire row by" - select label - else - choose label + choose label + + apply + end + + def switch_entire_row_highlight(label) + modal_open? or open_modal + choose "Entire row by" + page.all(".form--field")[1].select label + apply + end + + def switch_inline_attribute_highlight(*labels) + modal_open? or open_modal + choose "Highlighted attribute(s)" + within(page.all(".form--field")[0]) do + if labels.size == 1 + select labels.first + elsif labels.size > 1 + find('[class*="--toggle-multiselect"]').click + labels.each do |label| + select label + end + end end apply end diff --git a/spec/support/components/work_packages/tabs_counter.rb b/spec/support/components/work_packages/tabs_counter.rb new file mode 100644 index 0000000000..8cee286c82 --- /dev/null +++ b/spec/support/components/work_packages/tabs_counter.rb @@ -0,0 +1,27 @@ +require 'features/support/components/ui_autocomplete' + +module Components + module WorkPackages + class Tabs + include Capybara::DSL + include RSpec::Matchers + include ::Components::UIAutocompleteHelpers + + attr_reader :work_package + + def initialize(work_package) + @work_package = work_package + end + + # Check value of counter for the given tab + def expect_counter(tab, content) + expect(tab).to have_selector('.wp-tabs-count', text: "#{content}") + end + + # Counter should not be displayed, if there are no relations or watchers + def expect_no_counter(tab) + expect(tab).to have_no_selector('.wp-tabs-count') + end + end + end +end diff --git a/spec/support/pages/messages/show.rb b/spec/support/pages/messages/show.rb index 3e679b9d52..9bbd8a6b8f 100644 --- a/spec/support/pages/messages/show.rb +++ b/spec/support/pages/messages/show.rb @@ -37,7 +37,7 @@ def initialize(message) end def expect_subject(subject) - expect(page).to have_selector('.message-title', text: subject) + expect(page).to have_selector('.title-container', text: subject) end def expect_content(content) diff --git a/spec/support/pages/project_settings.rb b/spec/support/pages/project_settings.rb deleted file mode 100644 index 084ed74d48..0000000000 --- a/spec/support/pages/project_settings.rb +++ /dev/null @@ -1,90 +0,0 @@ -#-- copyright -# OpenProject is a project management system. -# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2017 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See docs/COPYRIGHT.rdoc for more details. -#++ - -require 'support/pages/page' - -module Pages - class ProjectSettings < Page - attr_accessor :project - - def initialize(project) - super() - - self.project = project - end - - def visit_tab!(name) - visit settings_project_path(project, tab: name) - end - - # only notice is used as opposed to notification-box - def expect_notification(type: :notice, message:) - expect(page).to have_selector(".flash.#{type}", text: message, wait: 10) - end - - def expect_type_active(type) - expect_type(type, true) - end - - def expect_type_inactive(type) - expect_type(type, false) - end - - def expect_type(type, active = true) - expect(page) - .to have_field("project_planning_element_type_ids_#{type.id}", checked: active) - end - - def expect_wp_custom_field_active(custom_field) - expect_wp_custom_field(custom_field, true) - end - - def expect_wp_custom_field_inactive(custom_field) - expect_wp_custom_field(custom_field, false) - end - - def activate_wp_custom_field(custom_field) - check custom_field.name - end - - def save! - click_button 'Save' - end - - def expect_wp_custom_field(custom_field, active = true) - expect(page) - .to have_field(custom_field.name, checked: active) - end - - private - - def path - settings_project_path(project) - end - end -end diff --git a/spec/features/projects/projects_page.rb b/spec/support/pages/projects/destroy.rb similarity index 84% rename from spec/features/projects/projects_page.rb rename to spec/support/pages/projects/destroy.rb index ceb3b22477..7597c7fd96 100644 --- a/spec/features/projects/projects_page.rb +++ b/spec/support/pages/projects/destroy.rb @@ -26,15 +26,18 @@ # See docs/COPYRIGHT.rdoc for more details. #++ -class ProjectsPage - include Rails.application.routes.url_helpers - include Capybara::DSL +module Pages + module Projects + class Destroy < ::Pages::Page + def initialize(project) + @project = project + end - def initialize(project) - @project = project - end + private - def visit_confirm_destroy - visit confirm_destroy_project_path(@project) + def path + confirm_destroy_project_path(@project) + end + end end end diff --git a/spec/support/pages/projects/settings.rb b/spec/support/pages/projects/settings.rb new file mode 100644 index 0000000000..ac6698601a --- /dev/null +++ b/spec/support/pages/projects/settings.rb @@ -0,0 +1,96 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require 'support/pages/page' + +module Pages + module Projects + class Settings < Pages::Page + attr_accessor :project + + def initialize(project) + super() + + self.project = project + end + + def visit_tab!(name) + visit settings_project_path(project, tab: name) + end + + # only notice is used as opposed to notification-box + def expect_notification(type: :notice, message:) + expect(page).to have_selector(".flash.#{type}", text: message, wait: 10) + end + + def expect_type_active(type) + expect_type(type, true) + end + + def expect_type_inactive(type) + expect_type(type, false) + end + + def expect_type(type, active = true) + expect(page) + .to have_field("project_planning_element_type_ids_#{type.id}", checked: active) + end + + def expect_wp_custom_field_active(custom_field) + expect_wp_custom_field(custom_field, true) + end + + def expect_wp_custom_field_inactive(custom_field) + expect_wp_custom_field(custom_field, false) + end + + def activate_wp_custom_field(custom_field) + check custom_field.name + end + + def save! + click_button 'Save' + end + + def expect_wp_custom_field(custom_field, active = true) + expect(page) + .to have_field(custom_field.name, checked: active) + end + + def fieldset_label + find 'fieldset#project_issue_custom_fields label' + end + + private + + def path + settings_project_path(project) + end + end + end +end diff --git a/spec/support/pages/work_packages_table.rb b/spec/support/pages/work_packages_table.rb index 5d10cc5f45..7ef66fdf39 100644 --- a/spec/support/pages/work_packages_table.rb +++ b/spec/support/pages/work_packages_table.rb @@ -117,13 +117,31 @@ def click_inline_create end def create_wp_split_screen(type) - find('.add-work-package:not([disabled])', text: 'Create').click + click_wp_create_button find('#types-context-menu .menu-item', text: type, wait: 10).click SplitWorkPackageCreate.new(project: project) end + def click_wp_create_button + find('.add-work-package:not([disabled])', text: 'Create').click + end + + def expect_type_available_for_create(type) + click_wp_create_button + + expect(page) + .to have_selector('#types-context-menu .menu-item', text: type.name) + end + + def expect_type_not_available_for_create(type) + click_wp_create_button + + expect(page) + .to have_no_selector('#types-context-menu .menu-item', text: type.name) + end + def open_split_view(work_package) split_page = SplitWorkPackage.new(work_package, project) diff --git a/spec_legacy/integration/routing_spec.rb b/spec_legacy/integration/routing_spec.rb deleted file mode 100644 index f72c0b56b3..0000000000 --- a/spec_legacy/integration/routing_spec.rb +++ /dev/null @@ -1,880 +0,0 @@ -#-- encoding: UTF-8 -#-- copyright -# OpenProject is a project management system. -# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2017 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See docs/COPYRIGHT.rdoc for more details. -#++ -require_relative '../legacy_spec_helper' - -describe 'routing', type: :routing do - before do - # shoulda-matchers 3.1 symbolizes the format, breaking these legacy tests - stub_const('Shoulda::Matchers::ActionController::RouteParams::PARAMS_TO_SYMBOLIZE', []) - end - - context 'activities' do - it { - is_expected.to route(:get, '/activity').to(controller: 'activities', - action: 'index') - } - it { - is_expected.to route(:get, '/activity.atom').to(controller: 'activities', - action: 'index', - format: 'atom') - } - - it 'should route /activities to activities#index' do - assert_recognizes({ controller: 'activities', action: 'index' }, '/activities') - end - it 'should route /activites.atom to activities#index' do - assert_recognizes({ controller: 'activities', action: 'index', format: 'atom' }, '/activities.atom') - end - - it { - is_expected.to route(:get, 'projects/eCookbook/activity').to(controller: 'activities', - action: 'index', - project_id: 'eCookbook') - } - - it { - is_expected.to route(:get, 'projects/eCookbook/activity.atom').to(controller: 'activities', - action: 'index', - project_id: 'eCookbook', - format: 'atom') - } - - it 'should route project/eCookbook/activities to activities#index' do - assert_recognizes({ controller: 'activities', action: 'index', project_id: 'eCookbook' }, '/projects/eCookbook/activities') - end - it 'should route project/eCookbook/activites.atom to activities#index' do - assert_recognizes({ controller: 'activities', action: 'index', format: 'atom', project_id: 'eCookbook' }, '/projects/eCookbook/activities.atom') - end - end - - context 'attachments' do - it { - is_expected.to route(:get, '/attachments/1').to(controller: 'attachments', - action: 'download', - id: '1') - } - it { - is_expected.to route(:get, '/attachments/1/filename.ext').to(controller: 'attachments', - action: 'download', - id: '1', - filename: 'filename.ext') - } - - it 'should redirect /atttachments/download/1 to /attachments/1' do - get '/attachments/download/1' - assert_redirected_to '/attachments/1' - end - - it 'should redirect /atttachments/download/1/filename.ext to /attachments/1/filename.ext' do - get '/attachments/download/1/filename.ext' - assert_redirected_to '/attachments/1/filename.ext' - end - - it { - is_expected.to route(:delete, '/attachments/1').to(controller: 'attachments', - action: 'destroy', - id: '1') - } - end - - context 'boards' do - it { - is_expected.to route(:get, '/projects/world_domination/boards').to(controller: 'boards', - action: 'index', - project_id: 'world_domination') - } - it { - is_expected.to route(:get, '/projects/world_domination/boards/new').to(controller: 'boards', - action: 'new', - project_id: 'world_domination') - } - it { - is_expected.to route(:post, '/projects/world_domination/boards').to(controller: 'boards', - action: 'create', - project_id: 'world_domination') - } - it { - is_expected.to route(:get, '/projects/world_domination/boards/44').to(controller: 'boards', - action: 'show', - project_id: 'world_domination', - id: '44') - } - it { - is_expected.to route(:get, '/projects/world_domination/boards/44.atom').to(controller: 'boards', - action: 'show', - project_id: 'world_domination', - id: '44', - format: 'atom') - } - it { - is_expected.to route(:get, '/projects/world_domination/boards/44/edit').to(controller: 'boards', - action: 'edit', - project_id: 'world_domination', - id: '44') - } - it { - is_expected.to route(:put, '/projects/world_domination/boards/44').to(controller: 'boards', - action: 'update', - project_id: 'world_domination', - id: '44') - } - it { - is_expected.to route(:delete, '/projects/world_domination/boards/44').to(controller: 'boards', - action: 'destroy', - project_id: 'world_domination', - id: '44') - } - end - - context 'enumerations' do - context 'within admin' do - it { - is_expected.to route(:get, 'admin/enumerations').to(controller: 'enumerations', - action: 'index') - } - - it { - is_expected.to route(:get, 'admin/enumerations/new').to(controller: 'enumerations', - action: 'new') - } - - it { - is_expected.to route(:post, 'admin/enumerations').to(controller: 'enumerations', - action: 'create') - } - - it { - is_expected.to route(:get, 'admin/enumerations/1/edit').to(controller: 'enumerations', - action: 'edit', - id: '1') - } - - it { - is_expected.to route(:put, 'admin/enumerations/1').to(controller: 'enumerations', - action: 'update', - id: '1') - } - - it { - is_expected.to route(:delete, 'admin/enumerations/1').to(controller: 'enumerations', - action: 'destroy', - id: '1') - } - end - end - - context 'roles' do - context 'witin admin' do - it { - is_expected.to route(:get, 'admin/roles').to(controller: 'roles', - action: 'index') - } - - it { - is_expected.to route(:get, 'admin/roles/new').to(controller: 'roles', - action: 'new') - } - - it { - is_expected.to route(:post, 'admin/roles').to(controller: 'roles', - action: 'create') - } - - it { - is_expected.to route(:get, 'admin/roles/1/edit').to(controller: 'roles', - action: 'edit', - id: '1') - } - - it { - is_expected.to route(:put, 'admin/roles/1').to(controller: 'roles', - action: 'update', - id: '1') - } - - it { - is_expected.to route(:delete, 'admin/roles/1').to(controller: 'roles', - action: 'destroy', - id: '1') - } - - it { - is_expected.to route(:get, 'admin/roles/report').to(controller: 'roles', - action: 'report') - } - - it { - is_expected.to route(:put, 'admin/roles').to(controller: 'roles', - action: 'bulk_update') - } - end - end - - context 'journals' do - it { - is_expected.to route(:get, '/journals/100/diff/description').to(controller: 'journals', - action: 'diff', - id: '100', - field: 'description') - } - end - - context 'members' do - context 'project scoped' do - it { - is_expected.to route(:post, '/projects/5234/members').to(controller: 'members', - action: 'create', - project_id: '5234') - } - - it { - is_expected.to route(:get, '/projects/5234/members/autocomplete_for_member') - .to(controller: 'members', - action: 'autocomplete_for_member', - project_id: '5234') - } - end - - it { - is_expected.to route(:put, '/members/5234').to(controller: 'members', - action: 'update', - id: '5234') - } - - it { - is_expected.to route(:delete, '/members/5234').to(controller: 'members', - action: 'destroy', - id: '5234') - } - end - - context 'messages' do - context 'project scoped' do - it { - is_expected.to route(:get, '/boards/lala/topics/new').to(controller: 'messages', - action: 'new', - board_id: 'lala') - } - - it { - is_expected.to route(:post, '/boards/lala/topics').to(controller: 'messages', - action: 'create', - board_id: 'lala') - } - end - - it { - is_expected.to route(:get, '/topics/2').to(controller: 'messages', - action: 'show', - id: '2') - } - - it { - is_expected.to route(:get, '/topics/22/edit').to(controller: 'messages', - action: 'edit', - id: '22') - } - - it { - is_expected.to route(:put, '/topics/22').to(controller: 'messages', - action: 'update', - id: '22') - } - - it { - is_expected.to route(:delete, '/topics/555').to(controller: 'messages', - action: 'destroy', - id: '555') - } - - it { - is_expected.to route(:get, '/topics/22/quote').to(controller: 'messages', - action: 'quote', - id: '22') - } - - it { - is_expected.to route(:post, '/topics/555/reply').to(controller: 'messages', - action: 'reply', - id: '555') - } - end - - context 'news' do - context 'project scoped' do - it { - is_expected.to route(:get, '/projects/567/news').to(controller: 'news', - action: 'index', - project_id: '567') - } - - it { - is_expected.to route(:get, '/projects/567/news.atom').to(controller: 'news', - action: 'index', - format: 'atom', - project_id: '567') - } - - it { - is_expected.to route(:get, '/projects/567/news/new').to(controller: 'news', - action: 'new', - project_id: '567') - } - - it { - is_expected.to route(:post, '/projects/567/news').to(controller: 'news', - action: 'create', - project_id: '567') - } - end - - it { - is_expected.to route(:get, '/news').to(controller: 'news', - action: 'index') - } - - it { - is_expected.to route(:get, '/news.atom').to(controller: 'news', - action: 'index', - format: 'atom') - } - - it { - is_expected.to route(:get, '/news/2').to(controller: 'news', - action: 'show', - id: '2') - } - - it { - is_expected.to route(:get, '/news/234').to(controller: 'news', - action: 'show', - id: '234') - } - - it { - is_expected.to route(:get, '/news/567/edit').to(controller: 'news', - action: 'edit', - id: '567') - } - - it { - is_expected.to route(:put, '/news/567').to(controller: 'news', - action: 'update', - id: '567') - } - - it { - is_expected.to route(:delete, '/news/567').to(controller: 'news', - action: 'destroy', - id: '567') - } - end - - context 'news/comments' do - context 'news scoped' do - it { - is_expected.to route(:post, '/news/567/comments').to(controller: 'news/comments', - action: 'create', - news_id: '567') - } - end - - it { - is_expected.to route(:delete, '/comments/15').to(controller: 'news/comments', - action: 'destroy', - id: '15') - } - end - - context 'timelogs' do - it { - is_expected.to route(:get, '/time_entries').to(controller: 'timelog', - action: 'index') - } - - it { - is_expected.to route(:get, '/time_entries.csv').to(controller: 'timelog', - action: 'index', - format: 'csv') - } - - it { - is_expected.to route(:get, '/time_entries.atom').to(controller: 'timelog', - action: 'index', - format: 'atom') - } - - it { - is_expected.to route(:get, '/time_entries/new').to(controller: 'timelog', - action: 'new') - } - - it { - is_expected.to route(:get, '/time_entries/22/edit').to(controller: 'timelog', - action: 'edit', - id: '22') - } - - it { - is_expected.to route(:post, '/time_entries').to(controller: 'timelog', - action: 'create') - } - - it { - is_expected.to route(:put, '/time_entries/22').to(controller: 'timelog', - action: 'update', - id: '22') - } - - it { - is_expected.to route(:delete, '/time_entries/55').to(controller: 'timelog', - action: 'destroy', - id: '55') - } - - context 'project scoped' do - it { - is_expected.to route(:get, '/projects/567/time_entries').to(controller: 'timelog', - action: 'index', - project_id: '567') - } - - it { - is_expected.to route(:get, '/projects/567/time_entries.csv').to(controller: 'timelog', - action: 'index', - project_id: '567', - format: 'csv') - } - - it { - is_expected.to route(:get, '/projects/567/time_entries.atom').to(controller: 'timelog', - action: 'index', - project_id: '567', - format: 'atom') - } - - it { - is_expected.to route(:get, '/projects/567/time_entries/new').to(controller: 'timelog', - action: 'new', - project_id: '567') - } - - it { - is_expected.to route(:get, '/projects/567/time_entries/22/edit').to(controller: 'timelog', - action: 'edit', - id: '22', - project_id: '567') - } - - it { - is_expected.to route(:post, '/projects/567/time_entries').to(controller: 'timelog', - action: 'create', - project_id: '567') - } - - it { - is_expected.to route(:put, '/projects/567/time_entries/22').to(controller: 'timelog', - action: 'update', - id: '22', - project_id: '567') - } - - it { - is_expected.to route(:delete, '/projects/567/time_entries/55').to(controller: 'timelog', - action: 'destroy', - id: '55', - project_id: '567') - } - end - end - - context 'time_entries/reports' do - it { - is_expected.to route(:get, '/time_entries/report').to(controller: 'time_entries/reports', - action: 'show') - } - it { - is_expected.to route(:get, '/projects/567/time_entries/report').to(controller: 'time_entries/reports', - action: 'show', - project_id: '567') - } - - it { - is_expected.to route(:get, '/projects/567/time_entries/report.csv').to(controller: 'time_entries/reports', - action: 'show', - project_id: '567', - format: 'csv') - } - end - - context 'users' do - it { - is_expected.to route(:get, '/users').to(controller: 'users', - action: 'index') - } - - it { - is_expected.to route(:get, '/users.xml').to(controller: 'users', - action: 'index', - format: 'xml') - } - - it { - is_expected.to route(:get, '/users/44').to(controller: 'users', - action: 'show', - id: '44') - } - - it { - is_expected.to route(:get, '/users/44.xml').to(controller: 'users', - action: 'show', - id: '44', - format: 'xml') - } - - it { - is_expected.to route(:get, '/users/current').to(controller: 'users', - action: 'show', - id: 'current') - } - - it { - is_expected.to route(:get, '/users/current.xml').to(controller: 'users', - action: 'show', - id: 'current', - format: 'xml') - } - - it { - is_expected.to route(:get, '/users/new').to(controller: 'users', - action: 'new') - } - - it { - is_expected.to route(:get, '/users/444/edit').to(controller: 'users', - action: 'edit', - id: '444') - } - - it { - is_expected.to route(:get, '/users/222/edit/membership').to(controller: 'users', - action: 'edit', - id: '222', - tab: 'membership') - } - - it { - is_expected.to route(:post, '/users').to(controller: 'users', - action: 'create') - } - - it { - is_expected.to route(:post, '/users.xml').to(controller: 'users', - action: 'create', - format: 'xml') - } - - it { - is_expected.to route(:put, '/users/444').to(controller: 'users', - action: 'update', - id: '444') - } - - it { - is_expected.to route(:put, '/users/444.xml').to(controller: 'users', - action: 'update', - id: '444', - format: 'xml') - } - end - - context 'versions' do - it { - is_expected.to route(:get, '/versions/1').to(controller: 'versions', - action: 'show', - id: '1') - } - - it { - is_expected.to route(:get, '/versions/1/edit').to(controller: 'versions', - action: 'edit', - id: '1') - } - - it { - is_expected.to route(:patch, '/versions/1').to(controller: 'versions', - action: 'update', - id: '1') - } - - it { - is_expected.to route(:delete, '/versions/1').to(controller: 'versions', - action: 'destroy', - id: '1') - } - - it { - is_expected.to route(:get, '/versions/1/status_by').to(controller: 'versions', - action: 'status_by', - id: '1') - } - - context 'project' do - it { - is_expected.to route(:get, '/projects/foo/versions/new').to(controller: 'versions', - action: 'new', - project_id: 'foo') - } - - it { - is_expected.to route(:post, '/projects/foo/versions').to(controller: 'versions', - action: 'create', - project_id: 'foo') - } - - it { - is_expected.to route(:put, '/projects/foo/versions/close_completed').to(controller: 'versions', - action: 'close_completed', - project_id: 'foo') - } - - it { - is_expected.to route(:get, '/projects/foo/roadmap').to(controller: 'versions', - action: 'index', - project_id: 'foo') - } - end - end - - context "wiki (singular, project's pages)" do - context 'within project' do - it { - is_expected.to route(:get, '/projects/567/wiki').to(controller: 'wiki', - action: 'show', - project_id: '567') - } - - it { - is_expected.to route(:get, '/projects/567/wiki/lalala').to(controller: 'wiki', - action: 'show', - project_id: '567', - id: 'lalala') - } - - it { - is_expected.to route(:get, '/projects/567/wiki/my_page/edit').to(controller: 'wiki', - action: 'edit', - project_id: '567', - id: 'my_page') - } - - it { - is_expected.to route(:get, '/projects/1/wiki/CookBook_documentation/history').to(controller: 'wiki', - action: 'history', - project_id: '1', - id: 'CookBook_documentation') - } - it { - is_expected.to route(:get, '/projects/1/wiki/CookBook_documentation/diff').to(controller: 'wiki', - action: 'diff', - project_id: '1', - id: 'CookBook_documentation') - } - - it { - is_expected.to route(:get, '/projects/1/wiki/CookBook_documentation/diff/2').to(controller: 'wiki', - action: 'diff', - project_id: '1', - id: 'CookBook_documentation', - version: '2') - } - - it { - is_expected.to route(:get, '/projects/1/wiki/CookBook_documentation/diff/2/vs/1').to(controller: 'wiki', - action: 'diff', - project_id: '1', - id: 'CookBook_documentation', - version: '2', - version_from: '1') - } - - it { - is_expected.to route(:get, '/projects/1/wiki/CookBook_documentation/annotate/2').to(controller: 'wiki', - action: 'annotate', - project_id: '1', - id: 'CookBook_documentation', - version: '2') - } - - it { - is_expected.to route(:get, '/projects/22/wiki/ladida/rename').to(controller: 'wiki', - action: 'rename', - project_id: '22', - id: 'ladida') - } - - it { - is_expected.to route(:get, '/projects/567/wiki/index').to(controller: 'wiki', - action: 'index', - project_id: '567') - } - - it { - is_expected.to route(:get, '/projects/567/wiki/date_index').to(controller: 'wiki', - action: 'date_index', - project_id: '567') - } - - it { - is_expected.to route(:get, '/projects/567/wiki/export').to(controller: 'wiki', - action: 'export', - project_id: '567') - } - - it { - is_expected.to route(:patch, '/projects/22/wiki/ladida/rename').to(controller: 'wiki', - action: 'rename', - project_id: '22', - id: 'ladida') - } - - it { - is_expected.to route(:post, '/projects/22/wiki/ladida/protect').to(controller: 'wiki', - action: 'protect', - project_id: '22', - id: 'ladida') - } - - it { - is_expected.to route(:post, '/projects/22/wiki/ladida/add_attachment').to(controller: 'wiki', - action: 'add_attachment', - project_id: '22', - id: 'ladida') - } - - it { - is_expected.to route(:put, '/projects/567/wiki/my_page').to(controller: 'wiki', - action: 'update', - project_id: '567', - id: 'my_page') - } - - it { - is_expected.to route(:delete, '/projects/22/wiki/ladida').to(controller: 'wiki', - action: 'destroy', - project_id: '22', - id: 'ladida') - } - end - end - - context 'administration panel' do - it { is_expected.to route(:get, '/projects').to(controller: 'projects', action: 'index') } - end - - context 'groups' do - it { - is_expected.to route(:get, '/admin/groups').to(controller: 'groups', - action: 'index') - } - - it { - is_expected.to route(:get, '/admin/groups/new').to(controller: 'groups', - action: 'new') - } - - it { - is_expected.to route(:post, '/admin/groups').to(controller: 'groups', - action: 'create') - } - - it { - is_expected.to route(:get, '/admin/groups/4').to(controller: 'groups', - action: 'show', - id: '4') - } - - it { - is_expected.to route(:get, '/admin/groups/4/edit').to(controller: 'groups', - action: 'edit', - id: '4') - } - - it { - is_expected.to route(:put, '/admin/groups/4').to(controller: 'groups', - action: 'update', - id: '4') - } - - it { - is_expected.to route(:delete, '/admin/groups/4').to(controller: 'groups', - action: 'destroy', - id: '4') - } - - it { - is_expected.to route(:get, '/admin/groups/4/autocomplete_for_user').to(controller: 'groups', - action: 'autocomplete_for_user', - id: '4') - } - - it { - is_expected.to route(:post, '/admin/groups/4/members').to(controller: 'groups', - action: 'add_users', - id: '4') - } - - it { - is_expected.to route(:delete, '/admin/groups/4/members/5').to(controller: 'groups', - action: 'remove_user', - id: '4', - user_id: '5') - } - - it { - is_expected.to route(:post, '/admin/groups/4/memberships').to(controller: 'groups', - action: 'create_memberships', - id: '4') - } - - it { - is_expected.to route(:put, '/admin/groups/4/memberships/5').to(controller: 'groups', - action: 'edit_membership', - id: '4', - membership_id: '5') - } - - it { - is_expected.to route(:delete, '/admin/groups/4/memberships/5').to(controller: 'groups', - action: 'destroy_membership', - id: '4', - membership_id: '5') - } - end -end diff --git a/spec_legacy/unit/wiki_page_spec.rb b/spec_legacy/unit/wiki_page_spec.rb index 32610895ec..9da3e4594b 100644 --- a/spec_legacy/unit/wiki_page_spec.rb +++ b/spec_legacy/unit/wiki_page_spec.rb @@ -50,12 +50,6 @@ assert @wiki.pages.include?(page) end - it 'should sidebar should be protected by default' do - page = @wiki.find_or_new_page('sidebar') - assert page.new_record? - assert page.protected? - end - it 'should find or new page' do page = @wiki.find_or_new_page('CookBook documentation') assert_kind_of WikiPage, page diff --git a/vendored-plugins/openproject-auth_plugins/lib/open_project/auth_plugins/version.rb b/vendored-plugins/openproject-auth_plugins/lib/open_project/auth_plugins/version.rb index f4a40eb039..b6973238ae 100644 --- a/vendored-plugins/openproject-auth_plugins/lib/open_project/auth_plugins/version.rb +++ b/vendored-plugins/openproject-auth_plugins/lib/open_project/auth_plugins/version.rb @@ -29,6 +29,6 @@ module OpenProject module AuthPlugins - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-avatars/app/views/settings/_openproject_avatars.html.erb b/vendored-plugins/openproject-avatars/app/views/settings/_openproject_avatars.html.erb index d52251ef34..e352ac7a28 100644 --- a/vendored-plugins/openproject-avatars/app/views/settings/_openproject_avatars.html.erb +++ b/vendored-plugins/openproject-avatars/app/views/settings/_openproject_avatars.html.erb @@ -6,7 +6,7 @@
    <%= styled_label_tag 'settings[enable_gravatars]', t('avatars.settings.enable_gravatars') %> - <%= hidden_field_tag 'settings[enable_gravatars]', 0 %> + <%= hidden_field_tag 'settings[enable_gravatars][]', 0 %> <%= styled_check_box_tag 'settings[enable_gravatars]', 1, manager.gravatar_enabled?, container_class: '-xslim' %>
    @@ -22,8 +22,8 @@
    <%= t 'avatars.label_local_avatar' %>
    - <%= styled_label_tag :enable_local_avatars, t('avatars.settings.enable_local_avatars') %> - <%= hidden_field_tag 'settings[enable_local_avatars]', 0 %> + <%= styled_label_tag 'settings[enable_local_avatars]', t('avatars.settings.enable_local_avatars') %> + <%= hidden_field_tag 'settings[enable_local_avatars][]', 0 %> <%= styled_check_box_tag 'settings[enable_local_avatars]', 1, manager.local_avatars_enabled?, container_class: '-xslim' %>
    diff --git a/vendored-plugins/openproject-avatars/lib/open_project/avatars/version.rb b/vendored-plugins/openproject-avatars/lib/open_project/avatars/version.rb index 985e98a875..b749145bee 100644 --- a/vendored-plugins/openproject-avatars/lib/open_project/avatars/version.rb +++ b/vendored-plugins/openproject-avatars/lib/open_project/avatars/version.rb @@ -1,5 +1,5 @@ module OpenProject module Avatars - VERSION = "8.0.2".freeze + VERSION = "8.1.0".freeze end end diff --git a/vendored-plugins/openproject-backlogs/app/helpers/rb_master_backlogs_helper.rb b/vendored-plugins/openproject-backlogs/app/helpers/rb_master_backlogs_helper.rb index 86f9e255b2..dca2ae79fd 100644 --- a/vendored-plugins/openproject-backlogs/app/helpers/rb_master_backlogs_helper.rb +++ b/vendored-plugins/openproject-backlogs/app/helpers/rb_master_backlogs_helper.rb @@ -122,10 +122,12 @@ def sprint_backlog_menu_items_for(backlog) items = {} items[:task_board] = link_to(l(:label_task_board), - controller: '/rb_taskboards', - action: 'show', - project_id: @project, - sprint_id: backlog.sprint) + { controller: '/rb_taskboards', + action: 'show', + project_id: @project, + sprint_id: backlog.sprint }, + class: 'show_task_board') + if backlog.sprint.has_burndown? items[:burndown] = content_tag(:a, diff --git a/vendored-plugins/openproject-backlogs/lib/open_project/backlogs/version.rb b/vendored-plugins/openproject-backlogs/lib/open_project/backlogs/version.rb index 4bb885c27c..e05dec8a03 100644 --- a/vendored-plugins/openproject-backlogs/lib/open_project/backlogs/version.rb +++ b/vendored-plugins/openproject-backlogs/lib/open_project/backlogs/version.rb @@ -35,6 +35,6 @@ module OpenProject module Backlogs - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-backlogs/spec/features/onboarding/backogs_onboarding_tour_spec.rb b/vendored-plugins/openproject-backlogs/spec/features/onboarding/backogs_onboarding_tour_spec.rb new file mode 100644 index 0000000000..b07a895df6 --- /dev/null +++ b/vendored-plugins/openproject-backlogs/spec/features/onboarding/backogs_onboarding_tour_spec.rb @@ -0,0 +1,106 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe 'backlogs onboarding tour', js: true do + let(:next_button) { find('.enjoyhint_next_btn') } + let(:user) { FactoryBot.create :admin } + let(:demo_project) { FactoryBot.create :project, name: 'Demo project', identifier: 'demo-project', is_public: true, enabled_module_names: %w[work_package_tracking wiki] } + let(:project) { FactoryBot.create :project, name: 'Scrum project', identifier: 'your-scrum-project', is_public: true, enabled_module_names: %w[work_package_tracking wiki backlogs] } + let(:sprint) { FactoryBot.create(:version, project: project, name: 'Sprint 1') } + let(:status) { FactoryBot.create(:default_status) } + let(:priority) { FactoryBot.create(:default_priority) } + + let(:impediment) do + FactoryBot.build(:impediment, author: user, + fixed_version: sprint, + assigned_to: user, + project: project, + type: type_task, + status: status) + end + + let(:story_type) { FactoryBot.create(:type_feature) } + let(:task_type) do + type = FactoryBot.create(:type_task) + project.types << type + + type + end + + let!(:existing_story) do + FactoryBot.create(:work_package, + type: story_type, + project: project, + status: status, + priority: priority, + position: 1, + story_points: 3, + fixed_version: sprint ) + end + + before do + login_as user + allow(Setting).to receive(:demo_projects_available).and_return(true) + allow(Setting).to receive(:plugin_openproject_backlogs).and_return('story_types' => [story_type.id.to_s], + 'task_type' => task_type.id.to_s) + end + + after do + # Clear session to avoid that the onboarding tour starts + page.execute_script("window.sessionStorage.clear();") + end + + context 'as a new user' do + it 'I see a part of the onboarding tour in the backlogs section' do + # Set the tour parameter so that we can start on the overview page + visit "/projects/#{project.identifier}/backlogs/?start_scrum_onboarding_tour=true" + expect(page).to have_text 'Manage your work in the Backlogs view.' + + next_button.click + expect(page).to have_text 'To see your Task board, open on the Sprint drop-down...' + + next_button.click + expect(page).to have_selector('.backlog .items', visible: true) + expect(page).to have_text '... and select the Task board entry.' + + next_button.click + expect(page).to have_current_path backlogs_project_sprint_taskboard_path(project.identifier, sprint.id) + expect(page).to have_text 'The Task board visualizes the progress for this sprint.' + + next_button.click + expect(page).to have_text "Now let's have a look at the Work package section, which gives you a more detailed view of your work." + + next_button.click + expect(page).to have_current_path project_work_packages_path(project.identifier) + end + end +end + + diff --git a/vendored-plugins/openproject-costs/lib/open_project/costs/version.rb b/vendored-plugins/openproject-costs/lib/open_project/costs/version.rb index 7edbd8b3e9..cd29f53794 100644 --- a/vendored-plugins/openproject-costs/lib/open_project/costs/version.rb +++ b/vendored-plugins/openproject-costs/lib/open_project/costs/version.rb @@ -19,6 +19,6 @@ module OpenProject module Costs - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-costs/package.json b/vendored-plugins/openproject-costs/package.json index 43fa7d12dc..140282ec87 100644 --- a/vendored-plugins/openproject-costs/package.json +++ b/vendored-plugins/openproject-costs/package.json @@ -1,6 +1,5 @@ { "name": "openproject-costs", "version": "0.1.0", - "main": "frontend/app/openproject-costs-app.js", "dependencies": {} } diff --git a/vendored-plugins/openproject-documents/lib/open_project/documents/version.rb b/vendored-plugins/openproject-documents/lib/open_project/documents/version.rb index 8ebb5987ae..5d70139371 100644 --- a/vendored-plugins/openproject-documents/lib/open_project/documents/version.rb +++ b/vendored-plugins/openproject-documents/lib/open_project/documents/version.rb @@ -31,6 +31,6 @@ module OpenProject module Documents - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-github_integration/lib/open_project/github_integration/version.rb b/vendored-plugins/openproject-github_integration/lib/open_project/github_integration/version.rb index 17a6887e7f..d67575e2ef 100644 --- a/vendored-plugins/openproject-github_integration/lib/open_project/github_integration/version.rb +++ b/vendored-plugins/openproject-github_integration/lib/open_project/github_integration/version.rb @@ -14,6 +14,6 @@ module OpenProject module GithubIntegration - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-global_roles/lib/open_project/global_roles/version.rb b/vendored-plugins/openproject-global_roles/lib/open_project/global_roles/version.rb index 39610a9963..9461f6bb2e 100644 --- a/vendored-plugins/openproject-global_roles/lib/open_project/global_roles/version.rb +++ b/vendored-plugins/openproject-global_roles/lib/open_project/global_roles/version.rb @@ -19,6 +19,6 @@ module OpenProject module GlobalRoles - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-ldap_groups/lib/open_project/ldap_groups/version.rb b/vendored-plugins/openproject-ldap_groups/lib/open_project/ldap_groups/version.rb index 12d9897d8f..ef90a3aac4 100644 --- a/vendored-plugins/openproject-ldap_groups/lib/open_project/ldap_groups/version.rb +++ b/vendored-plugins/openproject-ldap_groups/lib/open_project/ldap_groups/version.rb @@ -1,5 +1,5 @@ module OpenProject module LdapGroups - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-meeting/lib/open_project/meeting/version.rb b/vendored-plugins/openproject-meeting/lib/open_project/meeting/version.rb index 01220acdcf..7dd55bee1b 100644 --- a/vendored-plugins/openproject-meeting/lib/open_project/meeting/version.rb +++ b/vendored-plugins/openproject-meeting/lib/open_project/meeting/version.rb @@ -20,6 +20,6 @@ module OpenProject module Meeting - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-my_project_page/app/seeders/my_projects_overview_seeder.rb b/vendored-plugins/openproject-my_project_page/app/seeders/my_projects_overview_seeder.rb index e68555f430..1eeef927b2 100644 --- a/vendored-plugins/openproject-my_project_page/app/seeders/my_projects_overview_seeder.rb +++ b/vendored-plugins/openproject-my_project_page/app/seeders/my_projects_overview_seeder.rb @@ -6,7 +6,7 @@ class MyProjectsOverviewSeeder < Seeder def seed_data! puts "*** Seeding MyProjectsOverview" - Array(I18n.t("seeders.demo_data.projects")).each do |key, project| + Array(translate_with_base_url("seeders.demo_data.projects")).each do |key, project| puts " -Creating overview for #{project[:name]}" if config = project[:"project-overview"] @@ -29,13 +29,22 @@ def seed_data! end def applicable? - MyProjectsOverview.count.zero? + MyProjectsOverview.count.zero? && demo_projects_exist? end private + def demo_projects_exist? + identifiers = Array(I18n.t("seeders.demo_data.projects")) + .map { |_key, project| project[:identifier] } + + identifiers + .all? { |ident| Project.where(identifier: ident).exists? } + end + def area(config, project) return config if config.is_a? String + return config[:block] if config[:block].present? [config[:id], config[:title], with_references(config[:content], project)] end @@ -49,8 +58,14 @@ def create_attachments!(my_project_overview, area, attributes) attachment.save! end - area_with_references = Array(my_project_overview.send(area)).map do |tag, title, content| - [tag, title, link_attachments(content, my_project_overview.attachments)] + area_with_references = Array(my_project_overview.send(area)).map do |data| + if data.is_a? String # single string referring to a block + data + else + tag, title, content = data + + [tag, title, link_attachments(content, my_project_overview.attachments)] + end end my_project_overview.update area => area_with_references diff --git a/vendored-plugins/openproject-my_project_page/config/locales/en.seeders.yml b/vendored-plugins/openproject-my_project_page/config/locales/en.seeders.yml index 0490fbd496..d625b9200c 100644 --- a/vendored-plugins/openproject-my_project_page/config/locales/en.seeders.yml +++ b/vendored-plugins/openproject-my_project_page/config/locales/en.seeders.yml @@ -31,50 +31,68 @@ en: projects: demo-project: project-overview: - left: - - project_description - - work_package_tracking - right: - - members - - news_latest top: + - id: b + title: '' + content: | + ![Teaser](##attachment:"background-teaser-8-0v6.jpg") + attachments: + - background-teaser-8-0v6.jpg + left: - id: a - title: Welcome to your demo project + title: Getting started content: | We are glad you joined! We suggest to try a few things to get started in OpenProject. - *Try the following steps:* - 1. *Invite new members to your project*: -> Go to [Members](/projects/demo-project/members) in the project navigation. - 2. *View the work in your project*: -> Go to [Work packages](/projects/demo-project/work_packages) in the project navigation. - 3. *Create a new work package*: -> Go to [Work packages -> Create](/projects/demo-project/work_packages/new). - 4. *Create and update a project plan*: -> Go to [Gantt charts](/projects/demo-project/work_packages?query_id=##query.id:"Gantt chart") in the project navigation. - 5. *Activate further modules*: -> Go to [Project settings -> Modules](/projects/demo-project/settings/modules). - 6. *Complete your tasks in the project*: -> Go to [Work packages -> Tasks](/projects/demo-project/work_packages/details/##wp.id:"Edit a work package"/overview?query_id=##query.id:"Tasks"). + Discover the most important features with our [Guided Tour](%{base_url}/projects/demo-project/work_packages/?start_onboarding_tour=true). + + _Try the following steps:_ + + 1. *Invite new members to your project*: → Go to [Members](%{base_url}/projects/demo-project/members) in the project navigation. + 2. *View the work in your project*: → Go to [Work packages](%{base_url}/projects/demo-project/work_packages) in the project navigation. + 3. *Create a new work package*: → Go to [Work packages → Create](%{base_url}/projects/demo-project/work_packages/new). + 4. *Create and update a project plan*: → Go to [Project plan](%{base_url}/projects/demo-project/work_packages?query_id=##query.id:"Project plan") in the project navigation. + 5. *Activate further modules*: → Go to [Project settings → Modules](%{base_url}/projects/demo-project/settings/modules). + 6. *Complete your tasks in the project*: → Go to [Work packages → Tasks](%{base_url}/projects/demo-project/work_packages/details/##wp.id:"Edit a work package"/overview?query_id=##query.id:"Tasks"). Here you will find our [User Guides](https://www.openproject.org/help/). Please let us know if you have any questions or need support. Contact us: [support[at]openproject.com](mailto:support@openproject.com). - scrum-project: - project-overview: - left: - - project_description - - work_package_tracking + - block: project_description + - block: work_package_tracking right: - members - news_latest + scrum-project: + project-overview: top: + - id: b + title: '' + content: | + ![Teaser](##attachment:"background-teaser-8-0v6.jpg") + attachments: + - background-teaser-8-0v6.jpg + left: - id: a - title: Welcome to your Scrum demo project + title: Getting started content: | We are glad you joined! We suggest to try a few things to get started in OpenProject. - *Try the following steps:* - 1. *Invite new members to your project*: -> Go to [Members](/projects/your-scrum-project/members) in the project navigation. - 2. *View your Product backlog and Sprint backlogs*: -> Go to [Backlogs](/projects/your-scrum-project/backlogs) in the project navigation. - 3. *View your Task board*: -> Go to [Backlogs](/projects/your-scrum-project/backlogs) -> Click on right arrow on Sprint -> Select [Task Board](##sprint:"Sprint 1"). - 4. *Create a new work package*: -> Go to [Work packages -> Create](/projects/your-scrum-project/work_packages/new). - 5. *Create and update a project plan*: -> Go to [Gantt charts](##query:"Gantt chart") in the project navigation. - 6. *Create a Sprint wiki*: -> Go to [Backlogs](/projects/your-scrum-project/backlogs) and open the sprint wiki from the right drop down menu in a sprint. You can edit the [wiki template](/projects/your-scrum-project/wiki/) based on your needs. - 7. *Activate further modules*: -> Go to [Project settings -> Modules](/projects/your-scrum-project/settings/modules). + Discover the most important features with our [Guided Tour](%{base_url}/projects/your-scrum-project/backlogs?start_scrum_onboarding_tour=true). + + _Try the following steps:_ + + 1. *Invite new members to your project*: → Go to [Members](%{base_url}/projects/your-scrum-project/members) in the project navigation. + 2. *View your Product backlog and Sprint backlogs*: → Go to [Backlogs](%{base_url}/projects/your-scrum-project/backlogs) in the project navigation. + 3. *View your Task board*: → Go to [Backlogs](%{base_url}/projects/your-scrum-project/backlogs) → Click on right arrow on Sprint → Select [Task Board](##sprint:"Sprint 1"). + 4. *Create a new work package*: → Go to [Work packages → Create](%{base_url}/projects/your-scrum-project/work_packages/new). + 5. *Create and update a project plan*: → Go to [Project plan](##query:"Project plan") in the project navigation. + 6. *Create a Sprint wiki*: → Go to [Backlogs](%{base_url}/projects/your-scrum-project/backlogs) and open the sprint wiki from the right drop down menu in a sprint. You can edit the [wiki template](%{base_url}/projects/your-scrum-project/wiki/) based on your needs. + 7. *Activate further modules*: → Go to [Project settings → Modules](%{base_url}/projects/your-scrum-project/settings/modules). Here you will find our [User Guides](https://www.openproject.org/help/). Please let us know if you have any questions or need support. Contact us: [support[at]openproject.com](mailto:support@openproject.com). + - block: project_description + - block: work_package_tracking + right: + - members + - news_latest diff --git a/vendored-plugins/openproject-my_project_page/config/locales/media/en/background-teaser-8-0v6.jpg b/vendored-plugins/openproject-my_project_page/config/locales/media/en/background-teaser-8-0v6.jpg new file mode 100644 index 0000000000..ecb0c237fa Binary files /dev/null and b/vendored-plugins/openproject-my_project_page/config/locales/media/en/background-teaser-8-0v6.jpg differ diff --git a/vendored-plugins/openproject-my_project_page/lib/open_project/my_project_page/version.rb b/vendored-plugins/openproject-my_project_page/lib/open_project/my_project_page/version.rb index 02fe2b87c2..b03d579513 100644 --- a/vendored-plugins/openproject-my_project_page/lib/open_project/my_project_page/version.rb +++ b/vendored-plugins/openproject-my_project_page/lib/open_project/my_project_page/version.rb @@ -20,6 +20,6 @@ module OpenProject module MyProjectPage - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-openid_connect/lib/open_project/openid_connect/engine.rb b/vendored-plugins/openproject-openid_connect/lib/open_project/openid_connect/engine.rb index e816990ecb..d20ccba707 100644 --- a/vendored-plugins/openproject-openid_connect/lib/open_project/openid_connect/engine.rb +++ b/vendored-plugins/openproject-openid_connect/lib/open_project/openid_connect/engine.rb @@ -50,6 +50,20 @@ def configuration end end + #config.to_prepare do + initializer 'openid_connect.form_post_method' do + # If response_mode 'form_post' is chosen, + # the IP sends a POST to the callback. Only if + # the sameSite flag is not set on the session cookie, is the cookie send along with the request. + if OpenProject::Configuration['openid_connect'] && + OpenProject::Configuration['openid_connect'].any? { |_, v| v['response_mode']&.to_s == 'form_post' } + SecureHeaders::Configuration.default.cookies[:samesite][:lax] = false + # Need to reload the secure_headers config to + # avoid having set defaults (e.g. https) when changing the cookie values + load Rails.root + 'config/initializers/secure_headers.rb' + end + end + config.to_prepare do # set a secure cookie in production secure_cookie = !!Rails.configuration.force_ssl diff --git a/vendored-plugins/openproject-openid_connect/lib/open_project/openid_connect/version.rb b/vendored-plugins/openproject-openid_connect/lib/open_project/openid_connect/version.rb index 9147417b3f..371ee0856c 100644 --- a/vendored-plugins/openproject-openid_connect/lib/open_project/openid_connect/version.rb +++ b/vendored-plugins/openproject-openid_connect/lib/open_project/openid_connect/version.rb @@ -1,5 +1,5 @@ module OpenProject module OpenIDConnect - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-pdf_export/lib/open_project/pdf_export/version.rb b/vendored-plugins/openproject-pdf_export/lib/open_project/pdf_export/version.rb index 2bf02d4560..a892e02e4f 100644 --- a/vendored-plugins/openproject-pdf_export/lib/open_project/pdf_export/version.rb +++ b/vendored-plugins/openproject-pdf_export/lib/open_project/pdf_export/version.rb @@ -25,6 +25,6 @@ module OpenProject module PdfExport - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-reporting/lib/open_project/reporting/version.rb b/vendored-plugins/openproject-reporting/lib/open_project/reporting/version.rb index a021447827..e1556f2221 100644 --- a/vendored-plugins/openproject-reporting/lib/open_project/reporting/version.rb +++ b/vendored-plugins/openproject-reporting/lib/open_project/reporting/version.rb @@ -19,6 +19,6 @@ module OpenProject module Reporting - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/fil.yml b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/fil.yml index 4a1eaaf585..7d405efc2d 100644 --- a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/fil.yml +++ b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/fil.yml @@ -30,7 +30,7 @@ fil: notice_pwd_confirmation: "Kailangan mong kumpirmahin ang iyong password sa paggawa ng mga pagbabago sa setting na ito." label_device_type: "Ang uri ng aparato" label_default_device: "I-Default ang 2FA na aparato" - label_device: "Ang 2FA na aparato" + label_device: "2Fa na aparato" label_devices: "Ang 2FA na mga aparato" label_one_time_password: 'Ang isang beses na password' label_2fa_enabled: 'Ang Dalawang-dahilan ng aktibo na pagpapatunay' diff --git a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/fr.yml b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/fr.yml index 47c4a6e535..0f58bb4ac8 100644 --- a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/fr.yml +++ b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/fr.yml @@ -149,7 +149,7 @@ fr: cookie_removed: 'Le cookie de mémorisation à été enlevé.' dont_ask_again: "Créer le cookie de mémorisation de l'authentification 2FA sur ce client pour %{days} jours." field_phone: "Téléphone mobile" - field_otp: "Mot de passe à usage unique" + field_otp: "Mot de passe unique" notice_account_otp_invalid: "Mot de passe à usage unique non valide." notice_account_otp_expired: "Le mot de passe à usage unique que vous avez renseigné a expiré." notice_developer_strategy_otp: "La stratégie de développement à généré le mot de passe à usage unique suivant : %{token} (Channel: %{channel})" diff --git a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/id.yml b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/id.yml index 9e15b5f66b..d5aa52d797 100644 --- a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/id.yml +++ b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/id.yml @@ -2,7 +2,7 @@ id: activerecord: attributes: two_factor_authentication/device: - identifier: 'Pengenal' + identifier: 'Pengidentifikasi' default: 'Digunakan sebagai standar' two_factor_authentication/device/sms: phone_number: "Nomor telepon" @@ -143,13 +143,13 @@ id: required_to_add_device: 'Kebijakan keamanan aktif mengharuskan Anda untuk mengaktifkan otentikasi dua-faktor. Silakan gunakan formulir berikut untuk mendaftar perangkat.' remember: active_session_notice: > - Account Anda telah aktif ingat cookie yang berlaku hingga %{expires_on}. Cookie ini memungkinkan Anda untuk masuk tanpa faktor kedua ke account Anda sehingga waktu itu. + Akun Anda telah aktif ingat cookie yang berlaku hingga %{expires_on}. Cookie ini memungkinkan Anda untuk masuk tanpa faktor kedua ke akun Anda sehingga waktu itu. label: 'ingat' clear_cookie: 'Tekan disini untuk menghapus cookie' cookie_removed: 'Ingat cookie telah dihapus.' - dont_ask_again: "Membuat kue untuk mengingat 2FA otentikasi pada klien ini untuk %{days} hari." + dont_ask_again: "Membuat cookie untuk mengingat 2FA otentikasi pada klien ini untuk %{days} hari." field_phone: "Ponsel" - field_otp: "Satu-kali kata sandi" + field_otp: "One-time password" notice_account_otp_invalid: "Sandi sekali pakai yang tidak valid." notice_account_otp_expired: "Kata sandi satu-kali yang anda masukkan kadaluarsa." notice_developer_strategy_otp: "Pengembang strategi dihasilkan one-time password berikut: %{token} (saluran: %{channel})" diff --git a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/ja.yml b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/ja.yml index 675367aaf5..db9a4bea3d 100644 --- a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/ja.yml +++ b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/ja.yml @@ -17,7 +17,7 @@ ja: models: two_factor_authentication/device: "2FAデバイス" two_factor_authentication/device/sms: "携帯電話" - two_factor_authentication/device/totp: "認証システム アプリケーション" + two_factor_authentication/device/totp: "認証システムアプリケーション" two_factor_authentication: error_2fa_disabled: "2FAの配信が無効になっています。" error_no_device: "このインスタンスに必要であるにもかかわらず、このユーザーに登録された2FAデバイスが見つかりませんでした。" @@ -30,8 +30,8 @@ ja: notice_pwd_confirmation: "これらの設定を変更するにはパスワードを確認する必要があります。" label_device_type: "デバイスタイプ" label_default_device: "規定の2FAデバイス" - label_device: "2ファクターデバイス" - label_devices: "2ファクターデバイス" + label_device: "2FAデバイス" + label_devices: "2FAデバイス" label_one_time_password: 'ワンタイムパスワード' label_2fa_enabled: '2要素認証が有効です' label_2fa_disabled: '2要素認証が有効ではありません' diff --git a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/pt-BR.yml b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/pt-BR.yml index fd2aedda8a..afef7ca0bc 100644 --- a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/pt-BR.yml +++ b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/pt-BR.yml @@ -34,7 +34,7 @@ pt-BR: label_devices: "Dispositivos 2FA" label_one_time_password: 'Senha de uso único' label_2fa_enabled: 'O segundo fator de autenticação está ativo' - label_2fa_disabled: 'O segundo fator de autenticação não está ativo' + label_2fa_disabled: 'Autenticação de dois fatores não está ativa' text_otp_delivery_message_sms: "Sua senha de uso único de %{app_title} é %{token}" text_otp_delivery_message_voice: "Sua senha de uso único de %{app_title} é: %{pause} %{token}. %{pause} repito: %{pause} %{token}" text_enter_2fa: 'Por favor digite a senha de uso único do seu dispositivo.' @@ -134,7 +134,7 @@ pt-BR: delivery_failed: 'Falha ao entregar o SNS:' message_bird: sms_delivery_failed: 'Falha ao enviar o SMS MessageBird.' - voice_delivery_failed: 'Falha ao realizar a chamada de voz MessageBird SMS.' + voice_delivery_failed: 'Falha ao realizar a chamada de voz MessageBird Sms.' restdt: delivery_failed_with_code: 'Falha ao entregar o token. (Código do erro %{code})' strategies: @@ -151,7 +151,7 @@ pt-BR: label: 'Lembrar-me' clear_cookie: 'Clique aqui para remover este cookir' cookie_removed: 'O cookie gravado foi removido.' - dont_ask_again: "Crie um cookie para lembrar a autenticação 2FA para este cliente por %{days} dias." + dont_ask_again: "Crie um cookie para lembrar do 2FA neste cliente por %{days} dias." field_phone: "Celular" field_otp: "Senha de uso único" notice_account_otp_invalid: "Senha de uso único inválida." diff --git a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/pt-PT.yml b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/pt-PT.yml index 99b150f737..e14090a110 100644 --- a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/pt-PT.yml +++ b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/pt-PT.yml @@ -35,7 +35,7 @@ pt: label_one_time_password: 'Palavra-passe de uso único' label_2fa_enabled: 'Autenticação de dois fatores está ativo' label_2fa_disabled: 'Autenticação de dois fatores não ativa' - text_otp_delivery_message_sms: "Sua senha de uso único de %{app_title} é %{token}" + text_otp_delivery_message_sms: "A sua senha de utilização única de %{app_title} é %{token}" text_otp_delivery_message_voice: "A sua senha de utilização única de %{app_title} é: %{pause} %{token}. %{pause} Repito: %{pause} %{token}" text_enter_2fa: 'Digite a palavra-passe de utilização única de seu dispositivo.' text_2fa_enabled: 'Em cada login, você será solicitado a inserir um token OTP do seu dispositivo 2FA padrão.' @@ -49,7 +49,7 @@ pt: current_configuration: 'Configuração atual' label_active_strategies: 'Estratégias 2FA activas' label_enforced: 'Forçar 2FA' - label_remember: 'Lembrar login 2FA' + label_remember: 'Lembrar início de sessão 2FA' text_configuration: | Nota: Estes valores representam a configuração atual em toda a aplicação. Não pode desativar definições forçadas pela configuração, nem alterar as atuais estratégias ativas, uma vez que requerem um reinício do servidor. text_configuration_guide: Para mais informações, consulte o guia de configuração. @@ -149,7 +149,7 @@ pt: active_session_notice: > A sua conta tem um cookie de lembrança válido até %{expires_on}. Este cookie permite que inicie a sessão sem um segundo factor na sua conta até essa altura. label: 'Lembrar' - clear_cookie: 'Clique aqui para remover esta cookie' + clear_cookie: 'Clique aqui para remover este cookie' cookie_removed: 'O cookie de lembrança foi removido.' dont_ask_again: "Criar cookie para lembrar a autenticação 2FA neste cliente durante %{days} dias." field_phone: "Telemóvel" diff --git a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/tr.yml b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/tr.yml index faeb20e5ce..7ad70aaf6d 100644 --- a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/tr.yml +++ b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/tr.yml @@ -30,12 +30,12 @@ tr: notice_pwd_confirmation: "Bu ayarlarda değişiklikler yaptıktan sonra şifrenizi onaylamanız gerekir." label_device_type: "Cihaz türü" label_default_device: "Varsayılan 2FA cihazı" - label_device: "2FA cihazı" + label_device: "2FA aygıtı" label_devices: "2FA cihazları" label_one_time_password: 'Tek kullanımlık şifre' label_2fa_enabled: 'İki faktörlü kimlik doğrulama aktif' label_2fa_disabled: 'İki faktörlü kimlik doğrulama aktif değil' - text_otp_delivery_message_sms: "Your %{app_title} one-time password is %{token}" + text_otp_delivery_message_sms: "Senin %{app_title} one-time şifre %{token}" text_otp_delivery_message_voice: "Your %{app_title} one-time password is: %{pause} %{token}. %{pause} I repeat: %{pause} %{token}" text_enter_2fa: 'Lütfen cihazınızdaki tek kullanımlık şifreyi giriniz.' text_2fa_enabled: 'Her girişte, varsayılan 2FA cihazınızdan bir OTP jetonu girmeniz talep edilir.' @@ -60,7 +60,7 @@ tr: failed_to_save_settings: '2FA ayarları güncelleştirmesi başarısız: %{message}' admin: self_edit_path: 'Kendi 2FA cihazınızı eklemek yada değiştirmek için, lütfen burdan%{self_edit_link}' - self_edit_link_name: 'Hesap sayfanızdaki iki faktörlü kimlik doğrulama' + self_edit_link_name: 'Hesap sayfanızdaki iki faktörlü kimlik doğrulayıcı' self_edit_forbidden: 'Burada kendi 2FA cihazınızı düzenleyemezsiniz. Bunun yerine Hesabım > İki faktörlü kimlik doğrulama.' no_devices_for_user: 'Bu kullanıcı için hiçbir 2FA cihazı kayıtlı değil.' all_devices_deleted: 'Bu kullanıcının tüm 2FA cihazları silindi' @@ -151,7 +151,7 @@ tr: cookie_removed: 'Çerezin kaldırıldığını hatırla.' dont_ask_again: "Bu kullanıcı da 2FA kimlik doğrulamasını %{days} gün boyunca hatırlamak için çerez oluştur." field_phone: "Cep telefonu" - field_otp: "Tek kullanımlık şifre" + field_otp: "Tek-kullanımlık Şifre" notice_account_otp_invalid: "Geçersiz tek kullanımlık şifre." notice_account_otp_expired: "Girdiğiniz tek kullanımlık şifrenin süresi dolmuş." notice_developer_strategy_otp: "Geliştirici stratejisi aşağıdaki tek seferlik şifreyi oluşturdu: %{token} (Kanal: %{channel})" diff --git a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/zh-CN.yml b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/zh-CN.yml index 13ea8d5cea..5d1ceb1c24 100644 --- a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/zh-CN.yml +++ b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/zh-CN.yml @@ -45,11 +45,11 @@ zh-CN: enter_backup_code_text: 请从您的代码列表中输入有效的备份代码,以防您无法再访问已注册的 2FA 设备。 other_device: '使用其他设备或备份代码' settings: - title: '双重身份验证设置' + title: '两步认证设置' current_configuration: '当前配置' - label_active_strategies: '激活双重身份验证策略' - label_enforced: '强制双重身份验证' - label_remember: '记住双重身份验证登录信息' + label_active_strategies: '激活两步认证策略' + label_enforced: '强制两步认证' + label_remember: '记住两步认证登录信息' text_configuration: | 注释:这些值表示当前应用级配置。您无法禁用由配置强制的设置或更改当前的有效策略,因为它们需要重启服务器。 text_configuration_guide: 如需了解更多信息,请参阅配置指南。 diff --git a/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/zh-TW.yml b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/zh-TW.yml new file mode 100644 index 0000000000..20e5ba6f73 --- /dev/null +++ b/vendored-plugins/openproject-two_factor_authentication/config/locales/crowdin/zh-TW.yml @@ -0,0 +1,173 @@ +zh-TW: + activerecord: + attributes: + two_factor_authentication/device: + identifier: '識別碼' + default: '儲存為預設值' + two_factor_authentication/device/sms: + phone_number: "電話號碼" + errors: + models: + two_factor_authentication/device: + default_already_exists: '已為另一個 OTP 設備設置。' + two_factor_authentication/device/sms: + attributes: + phone_number: + error_phone_number_format: "格式必須是 + XX XXXXXXXXX" + models: + two_factor_authentication/device: "2FA 設備" + two_factor_authentication/device/sms: "手機" + two_factor_authentication/device/totp: "驗證程式應用程式" + two_factor_authentication: + error_2fa_disabled: "2FA 發送已被禁用。" + error_no_device: "未為該使用者找到已註冊的2FA 設備, 儘管此實例是必需的。" + error_no_matching_strategy: "沒有匹配的2FA 策略可供此使用者使用。請聯繫您的系統管理員。" + error_is_enforced_not_active: '配置錯誤: 已強制執行雙因素身份驗證, 但不存在有效原則。' + error_invalid_backup_code: '不正確2FA 備份代碼' + channel_unavailable: "傳遞通道 %{channel} 不可用。" + no_valid_phone_number: "不存在有效電話號碼。" + label_pwd_confirmation: "密碼" + notice_pwd_confirmation: "在對這些設置進行更改時, 您需要確認您的密碼。" + label_device_type: "裝置類型" + label_default_device: "預設2FA 設備" + label_device: "2FA 設備" + label_devices: "2FA 設備" + label_one_time_password: '一次性密碼' + label_2fa_enabled: '雙重驗證已啟用' + label_2fa_disabled: '雙重驗證已關閉' + text_otp_delivery_message_sms: "%{app_title} 一次性密碼為 %{token}" + text_otp_delivery_message_voice: "您的 %{app_title} 一次性密碼為: %{pause} %{token}。 %{pause} 重複: %{pause} %{token}" + text_enter_2fa: '請從您的設備取得一次性密碼。' + text_2fa_enabled: '於每次登錄, 您都將被要求從預設的2FA 設備中取得 OTP 密碼。' + text_2fa_disabled: '要啟用雙因素身份驗證, 請使用上面的按鈕註冊新的2FA 設備。如果已有設備, 則需要將其設置為預設值。' + login: + enter_backup_code_title: 輸入備份代碼 + enter_backup_code_text: 請從代碼清單中輸入有效的備份代碼, 以防您無法再訪問已註冊的2FA 設備。 + other_device: '使用其他設備或備份代碼' + settings: + title: '2FA 設置' + current_configuration: '目前設定:' + label_active_strategies: '已套用的 2FA 策略' + label_enforced: '強制使用 2FA' + label_remember: '記住2FA 登錄' + text_configuration: | + 注意: 這些值表示當前應用程式範圍的配置。不能禁用由配置強制執行的設置或更改當前套用的策略, 因為它們需要重新開機伺服器。 + text_configuration_guide: 更多資訊,請參考設定指南. + text_enforced: 'Enable this setting to force all users to register a 2FA device on their next login. Can only be disabled when not enforced by configuration.' + text_remember: | + 將此值設置為大於零, 以允許使用者在給定的天數內記住其2FA 身份驗證。在那段期間, 他們將不被要求重新進入。只能在配置不強制的情況下設置。 + error_invalid_settings: '您選擇的2FA 策略無效' + failed_to_save_settings: '未能更新2FA 設置: %{message}' + admin: + self_edit_path: '要添加或修改您自己的2FA 設備, 請轉到 %{self_edit_link}' + self_edit_link_name: '雙重驗證於您的帳號頁面' + self_edit_forbidden: '無法於此路徑編輯您擁有的2FA設備.請至 我的帳號 > 雙重認證.' + no_devices_for_user: '沒有為該使用者註冊的 2FA 設備。' + all_devices_deleted: '此使用者的所有2FA 設備已被刪除' + delete_all_are_you_sure: '確實要刪除此使用者的所有2FA 設備嗎?' + button_delete_all_devices: '刪除已註冊的2FA 設備' + button_register_mobile_phone_for_user: '註冊手機' + text_2fa_enabled: '每次登錄時, 都會要求該使用者從預設的2FA 設備中取得 OTP 密碼。' + text_2fa_disabled: "The user did not set up a 2FA device through his 'My account page'" + upsale: + title: 'Two-factor authentication is an enterprise feature' + description: 'Strenghten your internal or external authentication mechanisms with a second factor.' + backup_codes: + none_found: No backup codes exist for this account. + singular: Backup code + plural: Backup codes + your_codes: for your %{app_name} account %{login} + overview_description: | + If you are unable to access your two factor devices, you can use a backup code to regain access to your account. + Use the following button to generate a new set of backup codes. + generate: + title: Generate backup codes + keep_safe_as_password: 'Important! Treat these codes as passwords.' + keep_safe_warning: 'Either save them in your password manager, or print this page and put in a safe place.' + regenerate_warning: 'Warning: If you have created backup codes before, they will be invalidated and will no longer work.' + devices: + add_new: 'Add new 2FA device' + register: 'Register device' + confirm_default: 'Confirm changing default device' + confirm_device: 'Confirm device' + confirm_now: 'Not confirmed, click here to activate' + cannot_delete_default: 'Cannot delete default device' + make_default_are_you_sure: 'Are you sure you want to make this 2FA device your default?' + make_default_failed: 'Failed to update the default 2FA device.' + deletion_are_you_sure: 'Are you sure you want to delete this 2FA device?' + registration_complete: '2FA device registration complete!' + registration_failed_token_invalid: '2FA device registration failed, the token was invalid.' + registration_failed_update: '2FA device registration failed, the token was valid but the device could not be updated.' + confirm_send_failed: 'Confirmation of your 2FA device failed.' + button_complete_registration: 'Complete 2FA registration' + text_confirm_to_complete_html: "Please complete the registration of your device %{identifier} by entering a one-time password from your default device." + text_confirm_to_change_default_html: "Please confirm changing your default device to %{new_identifier} by entering a one-time password from your current default device." + text_identifier: 'You can give the device a custom identifier using this field.' + failed_to_delete: 'Failed to delete 2FA device.' + is_default_cannot_delete: 'The device is marked as default and cannot be deleted due to an active security policy. Mark another device as default before deleting.' + not_existing: 'No 2FA device has been registered for your account.' + request_2fa: Please enter the code from your %{device_name} to verify your identity. + totp: + title: 'Use your app-based authenticator' + provisioning_uri: 'Provisioning URI' + secret_key: 'Secret key' + time_based: 'Time based' + account: 'Account name / Issuer' + setup: | + For setting up two-factor authentication with Google Authenticator, download the application from the Apple App store or Google Play Store. + After opening the app, you can scan the following QR code to register the device. + question_cannot_scan: | + Unable to scan the code using your application? + text_cannot_scan: | + If you can't scan the code, you can enter the entry manually using the following details: + description: | + Register an application authenticator for use with OpenProject using the time-based one-time password authentication standard. + Common examples are Google Authenticator or Authy. + sms: + title: 'Use your mobile phone' + redacted_identifier: 'Mobile device (%{redacted_number})' + request_2fa_identifier: '%{redacted_identifier}, we sent you an authentication code via %{delivery_channel}' + description: | + Register your mobile phone number for delivery of OpenProject one-time passwords. + sns: + delivery_failed: 'SNS delivery failed:' + message_bird: + sms_delivery_failed: 'MessageBird SMS delivery failed.' + voice_delivery_failed: 'MessageBird voice call failed.' + restdt: + delivery_failed_with_code: 'Token delivery failed. (Error code %{code})' + strategies: + totp: '驗證程式應用程式' + sns: '亞馬遜 SNS' + resdt: 'SMS Rest API' + mobile_transmit_notification: "已將一次性密碼發送給您的手機。" + label_two_factor_authentication: '雙重身分驗證' + forced_registration: + required_to_add_device: '活動安全性原則要求您啟用雙重身份驗證。請使用以下表格註冊設備。' + remember: + active_session_notice: > + 您的帳戶有一個活動的記住 cookie 有效, 直到 %{expires_on}。此 cookie 允許您在沒有第二個因素的情況下登錄到您的帳戶, 直到該時間。 + label: '記住' + clear_cookie: '按一下此處刪除此 cookie' + cookie_removed: '記住的 cookie 已被刪除。' + dont_ask_again: "創建 cookie,使 %{days} 天內記住此用戶端上的2FA 身份驗證。" + field_phone: "手機" + field_otp: "一次性密碼" + notice_account_otp_invalid: "一次性密碼無效。" + notice_account_otp_expired: "您輸入的一次性密碼已過期。" + notice_developer_strategy_otp: "開發者策略生成了以下一次性密碼: %{token} (通道: %{channel})" + notice_account_otp_send_failed: "無法發送您的一次性密碼。" + notice_account_has_no_phone: "沒有與您的帳戶關聯的手機號碼。" + label_expiration_hint: "%{date} 或登出時" + label_actions: '操作' + label_confirmed: '已確認' + button_continue: '繼續' + button_make_default: '標記為預設值' + label_unverified_phone: "Cell phone not yet verified" + notice_phone_number_format: "請輸入以下格式的號碼: + XX XXXXXXXX。" + text_otp_not_receive: "其他驗證方法" + text_send_otp_again: "通過以下操作,重新發送一次性密碼:" + button_resend_otp_form: "重新發送" + button_otp_by_voice: "語音電話" + button_otp_by_sms: "簡訊" + label_otp_channel: "傳送管道" diff --git a/vendored-plugins/openproject-two_factor_authentication/lib/open_project/two_factor_authentication/version.rb b/vendored-plugins/openproject-two_factor_authentication/lib/open_project/two_factor_authentication/version.rb index 58e34cbe52..f4ed0514d9 100644 --- a/vendored-plugins/openproject-two_factor_authentication/lib/open_project/two_factor_authentication/version.rb +++ b/vendored-plugins/openproject-two_factor_authentication/lib/open_project/two_factor_authentication/version.rb @@ -1,5 +1,5 @@ module OpenProject module TwoFactorAuthentication - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-webhooks/lib/open_project/webhooks/version.rb b/vendored-plugins/openproject-webhooks/lib/open_project/webhooks/version.rb index ace5804101..9bcdf85261 100644 --- a/vendored-plugins/openproject-webhooks/lib/open_project/webhooks/version.rb +++ b/vendored-plugins/openproject-webhooks/lib/open_project/webhooks/version.rb @@ -14,6 +14,6 @@ module OpenProject module Webhooks - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/openproject-xls_export/lib/open_project/xls_export/version.rb b/vendored-plugins/openproject-xls_export/lib/open_project/xls_export/version.rb index 0bbe4a5584..9c3b062aca 100644 --- a/vendored-plugins/openproject-xls_export/lib/open_project/xls_export/version.rb +++ b/vendored-plugins/openproject-xls_export/lib/open_project/xls_export/version.rb @@ -1,5 +1,5 @@ module OpenProject module XlsExport - VERSION = "8.0.2" + VERSION = "8.1.0" end end diff --git a/vendored-plugins/reporting_engine/lib/reporting_engine/version.rb b/vendored-plugins/reporting_engine/lib/reporting_engine/version.rb index 827cafeb0d..a0b62160e1 100644 --- a/vendored-plugins/reporting_engine/lib/reporting_engine/version.rb +++ b/vendored-plugins/reporting_engine/lib/reporting_engine/version.rb @@ -18,5 +18,5 @@ #++ module ReportingEngine - VERSION = "8.0.2" + VERSION = "8.1.0" end